c语言实现语法分析器Word下载.docx
- 文档编号:5787462
- 上传时间:2023-05-05
- 格式:DOCX
- 页数:9
- 大小:50.68KB
c语言实现语法分析器Word下载.docx
《c语言实现语法分析器Word下载.docx》由会员分享,可在线阅读,更多相关《c语言实现语法分析器Word下载.docx(9页珍藏版)》请在冰点文库上搜索。
函数绘图语言的特点,可以将记号设计为如下的数据结构:
StructToken
{Token_Typetype;
----------类别
char*lexeme;
--------------属性,原是输入的字符串
doublevalue;
----------属性,若记号是常数则是常数的值
double(*FuncPtr)(double);
--属性,若记号是函数则是函数指针
};
函数绘图语言的记号类别划分如下:
EnumToken_Type
{ORGIN,SCALE,ROT,IS,------------保留字
TO,STEP,DRAW,FOR,FROM,---------保留字
T,--------------------------------参数
SEMICO,L_BRACKET,R_BRACKET,COMMA--分隔符
PLUS,MINUS,MUL,DIV,POWER,------运算符
FUNC,--------------------------函数
CONST_ID,-------------------常数
NONTOKEN,-----------------空记号
ERRTOKEN-------------------出错记号
2、模式的正规式表示
函数绘图语言的此法可用下是正规式集合表示,其中的letter和digit是辅助定义
描述词法的正规式
Letter=[a-zA-Z]
Digit=[0-9]
COMMENT=“//”|“--”
WHITE_SPACE=(“”|\t|\n)+
SEMICO=“;
”
L_BRACKET=“(”
R_BRACKET=“)”
COMMA=“,”
PLUS=“+”
MINUS=“-”
MUL=“*”
DIV=“/”
POWER=“**”
CONST_ID=digit+(“.”digit*)?
ID=letter+(letter|digit)*
用于我们是手工构造词法分析器,而正规越少越便于程序的编写,因此设计上采用相同模式的记号公用一个正规式的方法。
常数的字面值部分设计为CONST_ID,而常量名则合并到ID
中。
但这却带来一个问题,函数绘图语言中的保留字、常量名、参数名,以及函数名均被识别为ID,当时别出ID时,如何再仔细分它们?
为解决上述问题,我们可以设计一个预定义的符号表
3、区分记号的符号表
将所有符合ID模式的保留字、常量名、参数名和函数名等均放进符号表中,具体内容如下:
staticTokenTokenTab[]=//符号表内容
{
{CONST_ID,"
PI"
3.1415926,NULL},
E"
2.71828,NULL},
{T,"
T"
0.0,NULL},
{FUNC,"
SIN"
0.0,sin},
COS"
0.0,cos},
TAN"
0.0,tan},
LN"
0.0,log},
EXP"
0.0,exp},
SQRT"
0.0,sqrt},
{ORIGIN,"
ORIGIN"
{SCALE,"
SCALE"
{ROT,"
ROT"
{IS,"
IS"
{FOR,"
FOR"
{FROM,"
FROM"
{TO,"
TO"
{STEP,"
STEP"
{DRAW,"
DRAW"
当词法分析器识别出一个ID时,就可以通过查找符号表来确定具体是哪一个记号。
4、正规式的DFA
根据上述的正规式和DFA的构造算法,可以得到最终的简化DFA如图:
三、解决方案
1、词法分析器的程序框架
根据上述DFA,可以得到程序框架如下:
structTokentoken={ERRTOKEN,“”,0.0,NULL};
//用于返回记号
token.lexeme=TokenBuffer;
//记号的字符指针指向字符缓冲区
char=GetChar();
//从源文件中读取一个字符
……//空格、TAB、回车等字符的过滤
AddInTokenString(char);
//将读入的字符放进缓冲区TokenBuffer中
if(isalpha(char)){……}//识别ID
elseif(isdigit(char)){……}//识别数字常量
else
{switch(char)
{case‘;
’:
token.type=SEMICO;
returntoken;
……
}
}
2、与语法分析器的接口
<
1>
词法分析器的测试
#include"
scanner.h"
voidmain(intargc,char*argv[])
{Tokentoken;
if(argc<
2){printf("
pleaseinputSourceFile!
\n"
);
return;
}
if(!
InitScanner(argv[1]))//初始化词法分析器
{printf("
OpenSourceFileError!
\n"
);
printf("
记号类别字符串常数值函数\n"
__________________________________________n"
while
(1)
{token=GetToken();
//通过词法分析器获得一个记号
if(token.type!
=NONTOKEN)//打印记号的内容
printf("
%4d,%12s,%12f,%12x\n"
token.type,token.lexeme,token.value,token.FuncPtr);
elsebreak;
//源程序结束,退出循环
CloseScanner();
//关闭词法分析器
变量:
1、staticFILE*InFile;
作用:
打开绘图语言源程序时,指向该程序的指针
2、unsignedintLineNo:
词法分析器对每个记号的字符串进行分析时,必须记住该字符串在源程序中的位置,LineNo就是用来记录该字符串所在行的行号。
3、staticcharTokenBuffer[TOKEN_LEN];
字符缓冲区,把记号的字符串保留在其中
函数:
1、externboolInitScanner(constchar*FileName);
作用:
检查汉书绘图语言的源程序文件是否存在,如果存在,则打开给文件,并初始化LineNo的值为1,返回true;
否则直接返回false。
2、externvoidCloseScanner(void);
关闭源程序文件。
3、externTokenGetToken(void);
每调用该函数一次仅获得一个记号,要得到源程序的所有记号,就必须重复调用次函数
4、staticcharGetChar(void);
从源程序中读取一个字符
5、staticvoidBackChar(char);
回退多读进的字符。
6、staticvoidAddCharTokenString(char);
将已识别的字符添加到缓冲区中。
7、staticvoidEmptyTokenString(void);
清空缓冲区。
8、staticTokenJudgeKeyToken(constchar*IDString);
根据识别出的字符串在符号表中查找相应的记号,若查找的成功,返回该记号,否则反会出错记号
6.与语法分析器的接口
词法分析器提供记号给语法分析器分析,它们之间的接口关系如下
2>
测试实例与测试结果
词法分析器的测试比较简单,可以分为三个部分:
1.全部合法的输入
2.各种组合的非法输入
【实验结论】
通过对词法分析器的编写,使我将课本中所学的理论知识在实际中得以应用,从而加深了对抽象理论的理解,通过实际操作,让我体会了编写程序的整个过程,令我受益匪浅。
而且在滤掉注释的那部分中,一开始,限于教材的影响,我只实现了滤掉‘//’和‘--’这两种注释。
通过老师检查时候的提醒,也是我认识到可以更加灵活的改变程序的功能,例如滤掉制定符号和字符等等。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 实现 语法 分析器