C词法扫描器及语法分析器实现.docx
- 文档编号:1302564
- 上传时间:2022-10-20
- 格式:DOCX
- 页数:114
- 大小:435.71KB
C词法扫描器及语法分析器实现.docx
《C词法扫描器及语法分析器实现.docx》由会员分享,可在线阅读,更多相关《C词法扫描器及语法分析器实现.docx(114页珍藏版)》请在冰豆网上搜索。
C词法扫描器及语法分析器实现
1课程设计目标
学生在学习《编译原理》课程过程中,结合各章节的构造编译程序的基本理论,要求用C或C++语言描述及上机调试,实现一个C-Minus小编译程序(包括词法分析,语法分析等重要子程序),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。
要求:
(1)设计词法分析器
设计各单词的状态转换图,并为不同的单词设计种别码。
将词法分析器设计成供语法分析器调用的子程序。
功能包括:
a.具备预处理功能。
将不翻译的注释等符号先滤掉,只保留要翻译的符号串,即要求设计一个供词法分析调用的预处理子程序;
b.能够拼出语言中的各个单词;
c.返回(种别码,属性值)。
(2)语法分析
要求用学习过的自底向上或自顶向下的分析方法等,实现对表达式、各种说明语句、控制语句进行语法分析。
若语法正确,则用语法制导翻译法进行语义翻译;生成并打印出语法树;若语法错误,要求指出出错性质和出错位置(行号)。
2分析与设计
2.1程序结构
本节主要分析程序的代码结构和代码工程文件的划分。
(程序由两个类组成:
Scanner类和Parser类,分别为词法分析和语法分析类。
工程分为四个文件:
scanner.h、scanner.cpp、parser.h、parser.cpp,分别对应Scanner类和Parser类的声明和实现文件)。
本程序采用C++语言以面向对象的思想编写,程序分为两部分:
词法分析(Scanner)和语法分析(Parser),分别将两个处理阶段封装成Scanner类和Parser类,两个类各司其职,分别完成词法分析和语法分析的任务。
Scanner类主要的工作是过滤注释、词法分析获取Token。
Parser类的主要工作是根据Scanner类词法分析之后的Token进行语法分析,生成语法树,最后并输出语法树。
在处理过程中,Scanner类的对象作为Parser类的一个成员变量,配合Parser类进行语法分析。
工程文件总体上是按照两个类的格局分为四个文件,分别是两个类的声明文件和实现文件。
四个文件分别为scanner.h和scanner.cpp以及parser.h和parser.cpp,他们分别是Scanner类声明文件、Scanner类实现文件、Parser类声明文件、Parser类实现文件。
词法分析
scanner.h:
与词法分析相关的类(Scanner类)的声明
scanner.cpp:
词法分析阶段类(Scanner类)的实现
语法分析
parser.h:
与语法分析相关的类(Parser类)的声明
parser.cpp:
语法分析阶段类(Parser类)的实现
2.2程序流程
在程序中,Scanner类的对象(scanner)作为Parser类中的一个成员变量,配合Parser类进行语法分析。
它们的关系是这样的:
Parser类的一个成员变量scanner首先对源程序删除注释,然后进行词法分析获取所有Token,并将获取的Token存储在scanner对象的tokenList(vector类型)中。
然后Parser类的语法分析程序就根据tokenList中的Token进行语法分析,生成语法树,最后打印语法树。
同时,这也是程序的流程。
3词法分析
3.1代码结构分析
词法分析阶段的代码被封装成一个类——Scanner,scanner.h中主要是Scanner类的声明代码,scanner.cpp中主要是Scanner类的实现代码。
Scanner类对外提供的函数主要有:
getSourseStringFromFile(strings)(从文件中获取待分析的源代码)、deleteComments()(过滤注释)、scan()(词法分析主程序)。
词法分析的过程主要是:
●Scanner调用getSourseStringFromFile(strings),从文件中获取待分析的源代码
●Scanner调用deleteComments(),将注释过滤掉,如果注释出错,则不进行词法分析
●Scanner调用scan(),进行词法分析,将分析得到的所有Token保存在Scanner类的成员变量tokenList中,以备语法阶段调用,并将Token输出到文件Token.txt中
以上三个函数构成了词法分析的骨架,在Scanner类中还有其他成员变量和函数,主要作为这三个函数处理过程的中间步骤,为这三个函数服务。
Scanner类的代码结构和主要的成员变量和函数如下图所示:
其他函数和成员变量的作用和含义:
●voidbackToLastChar():
在词法分析过程中,回退一个字符
●DFAStatecharType(char):
返回字符的类型(按状态分),如whitespace返回START,0-9返回NUM
●chargetNextChar():
获取到下一个字符
●TokengetTokenAt(int):
根据下标从tokenList数组中获取词法分析后所保存的Token(供语法分析阶段调用)
●voidprintToken():
将词法分析好的Token输出到文件Token.txt中
●TokenTypereturnTokenType(strings):
根据字符串返回对应的31种Token类型,如字符串"int"将返回INT,"var"将返回ID
●intcharIndex:
配合getNextChar()和backToLastChar()使用(分别自增和自减1),用以指示当前待分析的char在源代码中的位置
●boolcommentFlag:
标注注释开始的标志,为true时表示正在注释体内,即源代码进入"/*"之后且"*/"之前的状态
●intlineCount:
对行号计数,表示当前词法分析在源代码的行位置(每次获取到的char为'/n'就自增1)
●boolscanSuccess:
词法分析是否成功的标志
●stringsourseString:
获取源代码的字符串
●stringstr:
在分析过程中保存Token对应的串
●vector
保存Token序列
3.2Token定义
3.2.1Token的定义和类型
Token定义:
//定义的Token结构体,包括类型、对应的串、所在代码的行号
structToken
{
TokenTypetokenType;
stringtokenString;
intlineNo;
};
Token类型(TokenType):
程序中,将Token的类型分为31种,分别对应于else、if、int、return、void、while、+、-、*、/、<、<=、>、>=、==、!
=、=、;、,、(、)、[、]、{、}、/*、*/、num、id、错误、文件结束,TokenType的定义和种别码分别如下所示:
//定义的Token的类型(31种),分别对应于else、if、int、return、void、while、+、-、*、/、<、<=、>、>=、==、!
=、=、;、,、(、)、[、]、{、}、/*、*/、num、id、错误、结束
typedefenum
{
ELSE=1,IF,INT,RETURN,VOID,WHILE,
PLUS,MINUS,TIMES,OVER,LT,LEQ,GT,GEQ,EQ,NEQ,ASSIGN,SEMI,COMMA,LPAREN,RPAREN,LMBRACKET,RMBRACKET,LBBRACKET,RBBRACKET,LCOMMENT,RCOMMENT,
NUM,ID,ERROR,ENDFILE
}TokenType;
3.2.2Token的种别码
TokenType的种别码如下表所示,共31种
单词符号
种别码
Value
单词符号
种别码
Value
else
ELSE
1
=
ASSIGN
17
if
IF
2
;
SEMI
18
int
INT
3
COMMA
19
return
RETURN
4
(
LPAREN
20
void
VOID
5
)
RPAREN
21
while
WHILE
6
[
LMBRACKET
22
+
PLUS
7
]
RMBRACKET
23
-
MINUS
8
{
LBBRACKET
24
*
TIMES
9
}
RBBRACKET
25
/
OVER
10
/*
LCOMMENT
26
<
LT
11
*/
RCOMMENT
27
<=
LEQ
12
num
NUM
28
>
GT
13
id
ID
29
>=
GEQ
14
错误
ERROR
30
==
EQ
15
结束
ENDFILE
31
!
=
NEQ
16
3.3DAF分析
由于词法分析程序分为两个步骤处理:
删除注释和词法分析获取Token。
所以对应有两个DFA,程序分别根据这两个DFA进行编写,现根据DFA分析两程序deleteComments()和scan()如下:
3.3.1删除注释DFA
删除注释的DFA描述:
删除注释的DFA如下所示,一共分为5个状态,在开始状态1时,如果输入的字符为/,则进入状态2,此时有可能进入注释状态,如果在状态2时,输入的字符为*,则进入注释状态,状态将转到3,如果在状态3时,输入的字符为*,则有可能结束注释状态,此时状态将转到状态4,如果在状态4时输入的字符为/,则注释状态结束,状态转移到结束状态。
对应的DFA的代码分析:
删除注释的功能通过Scanner类的成员函数deleteComments()实现,功能是将源代码中的注释过滤掉,将其余代码输出到sourceFile.txt文件中。
deleteComments()函数按照上面的DFA编写,在函数中,state变量表示状态,共分为5个状态:
●在状态1时,如果输入的字符为/,则进入状态2,否则仍处在状态1,且输出输入的字符
●在状态2时,(此时可能进入注释状态),如果输入的字符为*,则进入注释状态,状态将转到3,否则跳转到状态1,并输出/和输入的字符
●在状态3时,(此时可能结束注释状态),如果输入的字符为*,此时状态将转到状态4,否则继续在状态3
●在状态4时,如果输入的字符为/,则注释状态结束,状态转移到结束状态
相应的DFA代码:
代码如下所示:
voidScanner:
:
deleteComments()
{
ofstreamfout_Sourse("sourseFile.txt");
intstate=1;
charch;
while(state<6)
{
ch=getNextChar();
if('\0'==ch)//文件结束
break;
if(1==state)//DFA中的状态
{
if('/'==ch)
state=2;
else
{
state=1;
fout_Sourse< } } elseif(2==state)//DFA中的状态 { if('*'==ch) { state=3; commentFlag=false; } else {
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 词法 扫描器 语法 分析器 实现