编译原理课程设计报告C语言词法与语法分析器的实现

合集下载

(完整版)编译原理词法分析和语法分析报告+代码(C语言版)[1]

(完整版)编译原理词法分析和语法分析报告+代码(C语言版)[1]

词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求2.1待分析的简单的词法( 1)关键字:begin if then while do end所有的关键字都是小写。

( 2)运算符和界符:=+-*/<<=<>>>==;()#( 3)其他单词是标识符(ID )和整型常数( SUM ),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*( 4)空格有空白、制表符和换行符组成。

空格一般用来分隔ID 、SUM 、运算符、界符和关键字,词法分析阶段通常被忽略。

2.2各种单词符号对应的种别码:表 2.1各种单词符号对应的种别码单词符号种别码单词符号种别码bgin1:17If2: =18Then3<20wile4<>21do5<=22end6>23lettet( letter|digit ) *10>=24 dight dight*11=25 +13;26—14(27*15)28/16#02.3词法分析程序的功能:输入:所给文法的源程序字符串。

输出:二元组( syn,token 或 sum)构成的序列。

其中: syn 为单词种别码;token 为存放的单词自身字符串;sum 为整型常数。

例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end # 的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1主程序示意图:主程序示意图如图3-1 所示。

其中初始包括以下两个方面:⑴ 关键字表的初值。

编译原理词法分析和语法分析报告+代码(C语言版)[1]

编译原理词法分析和语法分析报告+代码(C语言版)[1]

西南交通大学编译原理课程设计报告系(院):信息科学与技术学院专业:软件工程班级:软件二班姓名:吴任杰学号:******** ****:***2012年12 月14 日词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。

(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。

空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

2.2 各种单词符号对应的种别码:2.3 词法分析程序的功能:输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图:主程序示意图如图3-1所示。

其中初始包括以下两个方面: ⑴ 关键字表的初值。

关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。

如能查到匹配的单词,则该单词为关键字,否则为一般标识符。

编译原理课程设计报告C语言词法与语法分析器的实现

编译原理课程设计报告C语言词法与语法分析器的实现

编译原理课程设计报告课题名称:编译原理课程设计C-语言词法与语法分析器的实现C-词法与语法分析器的实现1.课程设计目标(1)题目实用性C-语言拥有一个完整语言的基本属性,通过编写C-语言的词法分析和语法分析,对于理解编译原理的相关理论和知识有很大的作用。

通过编写C-语言词法和语法分析程序,能够对编译原理的相关知识:正则表达式、有限自动机、语法分析等有一个比较清晰的了解和掌握。

(2)C-语言的词法说明①语言的关键字:else if int return void while所有的关键字都是保留字,并且必须是小写。

②专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */③其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter*NUM = digit digit*letter = a|..|z|A|..|Zdigit = 0|..|9注:ID表示标识符,NUM表示数字,letter表示一个字母,digit表示一个数字。

小写和大写字母是有区别的。

④空格由空白、换行符和制表符组成。

空格通常被忽略。

⑤注释用通常的c语言符号/ * . . . * /围起来。

注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。

注释不能嵌套。

(3)程序设计目标能够对一个程序正确的进行词法及语法分析。

2.分析与设计(1)设计思想a. 词法分析词法分析的实现主要利用有穷自动机理论。

有穷自动机可用作描述在输入串中识别模式的过程,因此也能用作构造扫描程序。

通过有穷自动机理论能够容易的设计出词法分析器。

b. 语法分析语法分析采用递归下降分析。

递归下降法是语法分析中最易懂的一种方法。

它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。

因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。

二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。

三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。

在本次实验中,我们使用有限自动机的理论来设计词法分析器。

首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。

然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。

在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。

(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。

在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。

首先,我们根据给定的语法规则,编写了相应的递归函数。

每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。

在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。

(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。

在本次实验中,我们使用了四元式作为中间代码的表示形式。

在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。

同时,根据语法树的结构,生成相应的四元式中间代码。

(四)代码优化代码优化的目的是提高生成代码的质量和效率。

在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。

通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。

编译原理词法分析和语法分析报告+代码(C语言版)_2

编译原理词法分析和语法分析报告+代码(C语言版)_2

词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。

(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。

空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

2.2 各种单词符号对应的种别码:输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图:主程序示意图如图3-1所示。

其中初始包括以下两个方面:⑴关键字表的初值。

关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。

如能查到匹配的单词,则该单词为关键字,否则为一般标识符。

关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。

编译原理词法分析和语法分析报告+代码(C语言版)

编译原理词法分析和语法分析报告+代码(C语言版)

信息工程学院实验报告(2010 ~2011 学年度第一学期)姓名:***学号:**********班级:083词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。

(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。

空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

2.2 各种单词符号对应的种别码:输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图:主程序示意图如图3-1所示。

其中初始包括以下两个方面:⑴关键字表的初值。

关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。

如能查到匹配的单词,则该单词为关键字,否则为一般标识符。

关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。

编译原理词法分析和语法分析报告 代码(C语言版)[1]

编译原理词法分析和语法分析报告 代码(C语言版)[1]

char ch='\0';
/*从字符缓冲区读取当前字符*/
int count=0;
/*词法分析结果缓冲区计数器*/
static char spelling[10]={""}; /*存放识别的字*/
static char line[81]={""}; /*一行字符缓冲区,最多 80 个字符*/
char *pline;
scaner(); main() {p=0;
printf("\n please input a string(end with '#'):/n"); do{
scanf("%c",&ch); prog[p++]=ch; }while(ch!='#'); p=0; do{ scaner(); switch(syn)
EO
19
B or(即布尔表达式中的 B∨ )
Plus
34
“+”
Times
36
Becomes
38
Op_and
39
Op_or
40
Op_not
41
Rop
42
Lparent
48
Rparent
49
Ident
56
Intconst
57
#define sy_if
0
#define sy_then 1
#define sy_else 2
case '*': syn=15; token[m++]=ch; break;
case '/': syn=16; token[m++]=ch; break;

编译原理词法分析器语法分析器实验报告

编译原理词法分析器语法分析器实验报告

编译技术班级网络0802 学号3080610052姓名叶晨舟指导老师朱玉全2011年 7 月 4 日一、目的编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。

从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。

二、任务及要求基本要求:1.词法分析器产生下述小语言的单词序列这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:单词符号种别编码助记符内码值DIMIFDO STOP END标识符常数(整)=+***,()1234567891011121314$DIM$IF$DO$STOP$END$ID$INT$ASSIGN$PLUS$STAR$POWER$COMMA$LPAR$RPAR------内部字符串标准二进形式------对于这个小语言,有几点重要的限制:首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。

所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。

例如,下面的写法是绝对禁止的:IF(5)=x其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。

也就是说,对于关键字不专设对应的转换图。

但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。

当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。

再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。

例如,一个条件语句应写为IF i>0 i= 1;而绝对不要写成IFi>0 i=1;因为对于后者,我们的分析器将无条件地将IFI看成一个标识符。

这个小语言的单词符号的状态转换图,如下图:2.语法分析器能识别由加+ 减- 乘* 除/ 乘方^ 括号()操作数所组成的算术表达式,其文法如下:E→E+T|E-T|TT→T*F|T/F|FF→P^F|Pp→(E)|i使用的算法可以是:预测分析法;递归下降分析法;算符优先分析法;LR分析法等。

编译原理课程设计报告C语言词法与语法分析器的实现

编译原理课程设计报告C语言词法与语法分析器的实现

编写原理课程设计报告题目:编译原理课程设计C语言词法和语法分析器的实现C-词法和语法分析器的实现1.课程设计目标(1)题目的实用性C语言具有完整语言的基本属性,写C语言的词法分析和语法分析对理解编译原理的相关理论和知识会起到很大的作用。

通过编写C语言词法和语法分析程序,可以对编译原理的相关知识:正则表达式、有限自动机、语法分析等有一个清晰的认识和掌握。

(2)C语言的词法描述①语言的关键词:else if int返回void while的所有关键字都是保留字,必须小写。

②特殊符号:+ - * / < <= > >= == != = ;, ( ) [ ] { } /* */③其他标记是ID和NUM,它们由以下正则表达式定义:ID =字母字母*NUM =数字数字*字母= a|..|z|A|..|Zdigit = 0|..|9注:ID表示标识符,NUM表示数字,letter表示字母,digit表示数字。

小写字母和大写字母是有区别的。

④它由空格、换行符和制表符组成。

空格通常会被忽略。

⑤用常用的C语言符号/*将注释括起来...*/.注释可以放在任何空白位置(也就是注释不能放在标记上),可以多行。

注释不能嵌套。

(3)规划目标能够正确分析程序的词法和语法。

2.分析和设计(1)设计理念a.词汇分析词法分析的实现主要使用有限自动机理论。

有限自动机可以用来描述识别输入字符串中模式的过程,因此也可以用来构造扫描程序。

词法分析器可以很容易地用有限自动机理论来设计。

b.语法分析语法分析采用递归下降分析法。

递归下降法是语法分析中最容易理解的方法。

其主要原理是根据每个非终结符的产生式结构为其构造相应的解析子程序,其中终结符生成匹配命令,非终结符生成过程调用命令。

这种方法被称为递归子例程下降法或递归下降法,因为语法递归的相应子例程也是递归的。

子程序的结构与产生式的结构几乎相同。

(2)程序流程图主程序流程图:词法分析:语法分析:词汇分析子流程图:语法分析子流程图:3.程序代码实现整个词法与语法程序设计在同一个项目中,包含八个文件,分别是main.cpp、parse.cpp、scan.cpp、util.cpp、scan.h、util.h、globals.h和parse.h,其中scan.cpp和scan.h是词法分析程序。

编译原理课程设计C编译器词法分析与语法分析的实现

编译原理课程设计C编译器词法分析与语法分析的实现

编译原理课程设计报告课落款称: C-编译器词法分析与语法分析的实现提交文档学生姓名:黄臻旸提交文档学生学号: 1043041227 同组成员名单:无指导教师姓名:金军指导教师评阅成绩:指导教师评阅意见:..提交报告时刻:2021年 6 月 5 日编译原理课程设计报告 (1)一、课程设计目标 (3)二、分析与设计 (3)2.一、说明所用的方式: (3)2.二、系统总图: (3)2.2.一、scanner部份: (3)2.2.二、parse部份: (5)2.2.3、代码设计说明 (7)3、程序代码实现 (10)3.一、获取输入部份(在main.c中): (10)3.二、词法分析部份(在scan.c中): (10)3.3、语法分析部份(在parse.c中): (15)3.4、输出与结点的成立(在util.c中) (29)3.五、TokenType、treeNode与结点类型的声明(在globals.h中) (35)4、测试结果 (36)五、总结 (40)5.一、收成 (43)5.二、不足 (43)一、课程设计目标本次实验,本C- 编译器要紧设计而且实现了C- 编译器的词法分析功能与语法分析功能。

二、分析与设计2.一、说明所用的方式:各部份的实现方式(scanner:手工实现、Lex;parser:递归下降、LL(1)、LR(0)、SLR(1)、2.二、系统总图:2.2.一、scanner部份:2.2.1.一、实验原理:扫描程序的任务是从源代码中读取字符并形成由编译器的以后部份(一般是分析程序)处置的逻辑单元。

由扫描程序生成的逻辑单元称作记号(token),将字符组合成记号与在一个英语句子中将字母将字母组成单词并确信单次的含义很相像。

在此程序中,我将记号分成了以下类型:typedef enum {ENDFILE,ERROR,IF,ELSE,INT,RETURN,VOID,WHILE,ID,NUM,ASSIGN,PLUS,MINUS,TIMES,OVER,L T,LET,BT,BET,EQ,NEQ,// = + - * / < <= > >= == !=LPAREN_1,RP AREN_1,SEMI,COM,LPAREN_2,RP AREN_2,LPAREN_3,RP AREN_3,LIN,RIN// { } ; , [ ] ( ) /*} TokenType;其中,关键字有:else、if、int、return、void、while;专用符号有:+、-、*、/、<、<=、>、>=、==、~=、=、;、,、(、)、[、]、{、}、/*、*/其他标记是ID、NUM,通过以下正那么表达式概念:ID = letter letter*NUM = digit digit*letter = a|..|z|A|..|Zdigit = 0|..|9小写大写字母是有区别的。

编译原理词法分析器语法分析器实验报告

编译原理词法分析器语法分析器实验报告
opt2:
printf("请输入各终结符(#号表示结束)Vt[i]:\n");
for(i=0;i<100;i++)
{
scanf("%c",&Vt[i]);
if(Vt[i]=='#')
{
r=i;
break;
}
}
printf("请输入非终结符个数:\n");
scanf("%d",&n);
getchar();
p=s->next;
while(p!=NULL)
{
st[i++]=p->data;
p=p->next;
}
for(j=i-1;j>=0;j--)
printf("%c",st[j]);
for(j=0;j<16-i;j++) //打印对齐格式
printf("%c",' ');
}
char gettop(stackk *s) //返回栈顶元素值
{
stackk *p;
p=(stackk *)malloc(sizeof(stackk));
p->data=x;
p->next=s->next;
s->next=p;
}
void display(stackk *s) //打印现实显示栈内元素
{
stackk *p;
int i=0,j;
char st[100];
#include<string.h>
#include<malloc.h>

编译原理课程设计-词法分析器和语法分析器

编译原理课程设计-词法分析器和语法分析器

编译原理课程设计报告院系专业年级学号姓名2013年12月 8日课程设计一:手工设计C语言的词法分析器一、设计内容手工设计c语言的词法分析器,结合状态转换图的原理完成对c语言源程序的基本单词的分析及提取,并设计相应的数据结构保存提取出来的单词。

以及对c语言中的保留字的处理策略,实现一个完整的C语言的词法分析器的编写。

二、设计目的通过本实验的设计更具体的理解词法分析器的工作机制。

同时更理解C语言的结构体系。

从而更深刻的透析编译原理过程。

三、设计平台1、硬件环境(1)Intel(R) Core(TM) i3-2310M CPU @2.10GHz 2.10GHz(2)内存4G2、软件环境(1)Window8 Professor(2)Visual C++6.0开发软件3、开发语言:C语言。

四、需求分析:词法分析程序又称词法分析器或词法扫描器。

可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词,这里,作为子程序词法分析器的结构:状态转换图的程序实现为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序:1) ch 存放最新读进的源程序字符2) strToken存放构成单词符号的字符串3)Buffer 字符缓冲区4)struct keyType存放保留字的符号和种别五、概要设计保留字表的设计结构:基本功能状态转换:六、详细设计1.GETCHAR 读一个字符到 ch中2.GETBC 读一个非空白字符到ch中3.CONCAT 把CHAR 中字符连接到strToken 之后4.LETTER 判断CHAR 中字符是否为字母5.DIGIT 判断ch中字符是否为数字6.RESERVE 用strToken中的字符串查找保留字表,并返回保留字种别码,若返回零,则非保留字7.RETRACT 把CHAR 中字符回送到缓冲区源程序:#include "stdio.h"#include "stdlib.h"#include "conio.h"#include "string.h"#define N 47 //保留字个数char ch='\0'; //存放最新读进的源程序字符char strToken[20]="\0"; //存放构成单词符号的字符串char buffer[257]="\0"; //字符缓冲区/*------------保留字结构-------------*/struct keyType{char keyname[256];int value;}Key[N]={{"$ID",0},{"$INT",1},{"auto",2},{"break",3},{"case",4},{"char",5},{"const",6},{"continue",7},{"default",8},{"do",9},{"double",10},{"else",11},{"enum",12},{"extern",13},{"float",14},{"for",15},{"goto",16},{"if",17},{"int",18},{"long",19},{"register",20},{"return",21},{"short",22},{"signed",23},{"sizeof",24},{"static",25},{"struct",26},{"switch",27},{"typedef",28},{"union",29},{"unsigned",30},{"void",31},{"volatile",32},{"while",33},{"=",34},{"+",35},{"-",36},{"*",37},{"/",38},{"%",39},{",",40},{";",41},{"(",42},{")",43},{"?",44},{"clear",45},{"#",46}};/*-------------子过程-------------*/void GetChar() //读一个字符到ch中{ int i;if(strlen(buffer)>0){ch=buffer[0];for(i=0;i<256;i++)buffer[i]=buffer[i+1];}elsech='\0';}void GetBC() //读一个非空白字符到ch中{ int i;while(strlen(buffer)){i=0;ch=buffer[i];for(;i<256;i++)buffer[i]=buffer[i+1];if(ch!=' '&&ch!='\n'&&ch!='\0') break;}}void ConCat() //把ch连接到strToken之后{ char temp[2];temp[0]=ch;temp[1]='\0';strcat(strToken,temp);}bool Letter() //判断ch是否为字母{ if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z')return true;elsereturn false;}bool Digit() //判断ch是否为数字{ if(ch>='0'&&ch<='9')return true;elsereturn false;}int Reserve() //用strToken中的字符查找保留字表,并返回保留字种别码,若返回0,则非保留字{ int i;for(i=0;i<N;i++)if(strcmp(strToken,Key[i].keyname)==0)return Key[i].value;return 0;}void Retract() //把ch中的字符回送到缓冲区{ int i;if(ch!='\0') {buffer[256]='\0';for(i=255;i>0;i--)buffer[i]=buffer[i-1];buffer[0]=ch;}ch='\0';}/*----------词法分析器------------*/keyType ReturnWord(){ strcpy(strToken,"\0");int c;keyType tempkey;GetBC();if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z') {。

编译原理课程设计报告-词法语法分析器

编译原理课程设计报告-词法语法分析器

编译原理课程设计Course Design of Compiling(课程代码3273526)半期题目:词法和语法分析器实验学期:大三第二学期学生班级:2014级软件四班学生学号:18学生姓名:何华均任课教师:丁光耀信息科学与技术学院课程设计1-C语言词法分析器1.题目C语言词法分析2.内容选一个能正常运行的c语言程序,以该程序出现的字符作为单词符号集,不用处理c语言的所有单词符号。

将解析到的单词符号对应的二元组输出到文件中保存可以将扫描缓冲区与输入缓冲区合成一个缓冲区,一次性输入源程序后就可以进行预处理了3.设计目的掌握词法分析算法,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解4.设计环境(电脑语言环境)语言环境:C语言CPU:i7HQ6700内存:8G5.概要设计(单词符号表,状态转换图)词法分析器的结构词法分析程序的功能:输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

词法分析程序可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词.为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序:1) ch 存放最新读进的源程序字符2) strToken 存放构成单词符号的字符串3) Buffer 字符缓冲区4)struct keyType 存放保留字的符号和种别(1)保留字break、case、char、const、int、do、while…(2)运算符和界符= 、+、-、* 、/、%、,、;、(、)、、#各种单词符号对应的种别码状态转换图6.详细设计(数据结构,子程序)算法思想:首先设置3个变量:①strToken用来存放构成单词符号的字符串;②ch用来字符;③struct keyType用来存放单词符号的种别码。

扫描子程序主要部分流程如下图所示。

子程序结构:子程序名功能GETCHAR()读一个字符到ch 中GETBC()读一个非空白字符到ch 中CONCAT()把CHAR 中字符连接到strToken 之后LETTER()判断CHAR 中字符是否为字母7.程序清单eyname) == 0)return Key[i].value;return 0;}void Retract()alue;}else if (ch >= '0'&&ch <= '9') {ConCat();GetChar();while (Digit()) {ConCat();GetChar();}Retract();strcpy, strToken);= 1;}else {ConCat();strcpy, strToken);= Reserve();}return tempkey;}/*主函数*/int main() {行结果E:/作业/编译原理/运行结果九、 实验体会通过本次次法分析设计实验,我加深了对词法分析过程的理解。

编译原理实验词法分析器与语法分析器实现

编译原理实验词法分析器与语法分析器实现

编译原理实验词法分析器与语法分析器实现词法分析器与语法分析器是编译器的两个重要组成部分,它们在编译过程中扮演着至关重要的角色。

词法分析器负责将源代码转化为一个个标记(token)序列,而语法分析器则根据词法分析器生成的标记序列构建语法树,验证源代码的语法正确性。

本实验旨在实现一个简单的词法分析器和语法分析器。

实验一:词法分析器实现在实现词法分析器之前,需要定义所需词法项的规则。

以C语言为例,常见的词法项包括关键字(如int、if、for等)、标识符、运算符(如+、-、*、/等)、常量(如整数、浮点数等)和分隔符(如括号、逗号等)。

接下来,我们来实现一个简单的C语言词法分析器。

1. 定义词法项的规则在C语言中,关键字和标识符由字母、数字和下划线组成,且首字符不能为数字。

运算符包括各种数学运算符和逻辑运算符。

常量包括整数和浮点数。

分隔符包括括号、逗号等。

2. 实现词法分析器的代码下面是一个简单的C语言词法分析器的实现代码:```pythondef lexer(source_code):keywords = ['int', 'if', 'for'] # 关键字列表operators = ['+', '-', '*', '/'] # 运算符列表separators = ['(', ')', '{', '}', ',', ';'] # 分隔符列表tokens = [] # 标记序列列表current_token = '' # 当前标记for char in source_code:if char.isspace(): # 如果是空格,则忽略continueelif char.isalpha(): # 如果是字母,则可能是关键字或标识符的一部分current_token += charelif char.isdigit(): # 如果是数字,则可能是常量的一部分current_token += charelif char in operators or char in separators: # 如果是运算符或分隔符,则当前标记结束if current_token:tokens.append(current_token)current_token = ''tokens.append(char)else: # 如果是其他字符,则当前标记结束if current_token:tokens.append(current_token)current_token = ''return tokens```以上代码通过遍历源代码的字符,根据定义的规则生成一个个标记,存储在`tokens`列表中。

编译原理词法分析和语法分析报告+代码(C语言版)

编译原理词法分析和语法分析报告+代码(C语言版)

词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。

(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。

空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

2.2 各种单词符号对应的种别码:输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图:主程序示意图如图3-1所示。

其中初始包括以下两个方面:⑴关键字表的初值。

关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。

如能查到匹配的单词,则该单词为关键字,否则为一般标识符。

关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。

C-Minus词法分析和语法分析设计编译器编译原理课程设计

C-Minus词法分析和语法分析设计编译器编译原理课程设计

编译原理课程设计报告课题名称:C- Minus词法分析和语法分析设计1.课程设计目标实验建立C-编译器。

只含有扫描程序(scanner)和语法分析(parser)部分。

2.分析与设计C-编译器设计的整体框架,本实验实现扫描处理和语法分析程序(图中粗黑部分)。

2.1 、扫描程序scanner部分2.1.1系统设计思想设计思想:根据DFA图用switch-case结构实现状态转换。

惯用词法:①语言的关键字:else if int return void while②专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */③其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter*NUM = digit digit*letter = a|..|z|A|..|Zdigit = 0|..|9大写和小写字母是有区别的④空格由空白、换行符和制表符组成。

空格通常被忽略,除了它必须分开ID、NUM关键字。

⑤注释用通常的C语言符号/ * . . . * /围起来。

注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。

注释不能嵌套scanner的DFA说明:当输入的字符使DFA到达接受状态的时候,则可以确定一个单词了。

初始状态设置为START,当需要得到下一个token时,取得次token的第一个字符,并且按照DFA与对此字符的类型分析,转换状态。

重复此步骤,直到DONE为止,输出token类型。

当字符为“/”时,状态转换为SLAH再判断下一个字符,如果为“*”则继续转到INCOMMENT,最后以“*”时转到ENDCOMMENT状态,表明是注释,如果其他的则是字符停滞于当前字符,并且输出“/”。

2.1.2程序流程图2.1.3 各文件或函数的设计说明扫描程序用到:scanner.h,scanner.cppscanner.h:声明词法状态,词法分析//DFA中的状态typedef enum{START = 1, INNUM, INID, INDBSYM, DONE} DFAState;//定义的Token的类型(31种),分别对应于else、if、int、return、void、while、+、-、*、/、<、<=、>、>=、==、!=、=、;、,、(、)、[、]、{、}、/*、*/、num、id、错误、结束typedef enum{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;//定义的Token结构体,包括类型、对应的串、所在代码的行号struct Token{TokenType tokenType;string tokenString;int lineNo;};//每种TokenType对应的串,如tokenTypeString[ELSE]=="ELSE"const string tokenTypeString[32] = {"OTHER", "ELSE", "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"};class Scanner:定义scanner.cpp中函数scanner.cpp文件函数说明void Scanner :: scan():设置输出结果界面以及设置各种输出状态。

编译原理教程实验报告

编译原理教程实验报告

一、实验目的本次实验旨在使学生通过编译原理的学习,了解编译程序的设计原理及实现技术,掌握编译程序的各个阶段,并能将所学知识应用于实际编程中。

二、实验内容1. 词法分析2. 语法分析3. 语义分析4. 中间代码生成5. 代码优化6. 目标代码生成三、实验步骤1. 词法分析(1)设计词法分析器,识别输入源代码中的各种词法单元;(2)使用C语言实现词法分析器,并进行测试。

2. 语法分析(1)根据文法规则设计语法分析器,识别输入源代码的语法结构;(2)使用C语言实现语法分析器,并进行测试。

3. 语义分析(1)设计语义分析器,检查语法分析后的语法树,确保语义正确;(2)使用C语言实现语义分析器,并进行测试。

4. 中间代码生成(1)设计中间代码生成器,将语义分析后的语法树转换为中间代码;(2)使用C语言实现中间代码生成器,并进行测试。

5. 代码优化(1)设计代码优化器,对中间代码进行优化,提高程序性能;(2)使用C语言实现代码优化器,并进行测试。

6. 目标代码生成(1)设计目标代码生成器,将优化后的中间代码转换为特定目标机的汇编语言;(2)使用C语言实现目标代码生成器,并进行测试。

四、实验结果与分析1. 词法分析实验结果:成功识别输入源代码中的各种词法单元,包括标识符、关键字、运算符、常量等。

2. 语法分析实验结果:成功识别输入源代码的语法结构,包括表达式、语句、程序等。

3. 语义分析实验结果:成功检查语法分析后的语法树,确保语义正确。

4. 中间代码生成实验结果:成功将语义分析后的语法树转换为中间代码,为后续优化和目标代码生成提供基础。

5. 代码优化实验结果:成功对中间代码进行优化,提高程序性能。

6. 目标代码生成实验结果:成功将优化后的中间代码转换为特定目标机的汇编语言,为程序在目标机上运行做准备。

五、实验心得1. 编译原理是一门理论与实践相结合的课程,通过本次实验,我对编译程序的设计原理及实现技术有了更深入的了解。

编译原理课程实验报告(词法分析器及语法分析器)

编译原理课程实验报告(词法分析器及语法分析器)

编译原理实验报告班级:软件0501班学号:**********姓名:***词法分析器与语法分析器I. 问题描述设计、编制并调试一个词法分析子程序,完成识别语言单词的任务;设计、编制、调试一个语法分析程序,并用它对词法分析程序所提供的单词序列进行语法检查和结构分析。

ii. 设计简要描述界面需求:为了更加形象的模拟过程,此实验使用图形界面。

要求从图形界面上输入输入串,点击词法分析,可以将词法分析后识别的单词符号显示,点击语法分析,可以将语法分析的堆栈过程显示,并且显示结果(是否是符合文法的句子),清空则可以将所有置空。

功能分析:1、由用户输入输入串;2、用户点击“词法分析”,可以将词法分析后识别的单词符号显示。

3、用户点击语法分析,可以将语法分析的堆栈过程显示,并且显示结果(是否是符合文法的句子)4、用户点击清空,则将界面所有组件置为空思路描述:一、设计构想:本实验决定编写一个简易C语言的词法分析器和语法分析器。

使其能够识别while,if等关键字,可以判断赋值语句、条件语句、循环语句。

二、文法分析1、需要识别的关键字及其识别码有:关键字识别码关键字识别码关键字识别码main 0 - 11 ;22int 1 * 12 > 23char 2 / 13 < 24if 3 ( 14 >= 25else 4 ) 15 <= 26for 5 [ 16 == 27while 6 ] 17 != 28ID 7 { 18 ERROR -1NUM 8 } 19= 9 , 20+ 10 : 212、文法〈程序〉→ mai n()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉;〈语句串〉|〈语句〉;〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|=|!>转化为符号表示:S→ main() K|空K→ { C }C→Y;C |空Y→F | T | XF→ ID = BT→ if J KX→ while J KJ→( B G B )B→ B Z B |( B )| ID | NUMZ→ + | - | * | /G→< | <= | > | >= | == | !>表示含义:S:程序 K:语句块 C:语句串 Y:语句 F :赋值语句T:条件语句 X:循环语句 J:条件 B:表达式 I:项 Z :运算符G:关系符3、LL(1)分析表(1),求出first集及follow集:FIRST(S)={mian}FIRST(K)={{}FIRST(C)= FIRST(Y)= {ID,if,while,空};FIRST(Y)= FIRST(F)+ FIRST(T)+ FIRST(X)={ID,if,while};FIRST(F)={ID};FIRST(T)={if};FIRST(X)={while};FIRST(J)= FIRST(B)={};FIRST(B)={(,ID,NUM };FIRST(Z)={+,-,*,/}FIRST(G)={<,<= ,>,>=,==,!= };FOLLO W(S)={#};FOLLO W(K)={;};FOLLO W(C)={}};FOLLO W(Y)={;}FOLLO W(F)={;};FOLLO W(T)={;};FOLLO W(X)={;};FOLLO W(J)={{,;};FOLLO W(B)={+,-,*,/,),<,<= ,>,>=,==,!=,;};FOLLO W(B’)={+,-,*,/,),<,<= ,>,>=,==,!=,;};FOLLO W(Z)={(,ID,NUM };FOLLO W(G)={(,ID,NUM };(2)消除左递归,拆分文法关系并编号0、S→ 空1、S→ main() K2、K→ { C }3、C→Y;C4、C→空5、Y→ F6、Y→ T7、Y→ X8、F→ ID = B9、T→ if J K10、X→ while J K11、J→( B G B )12、 B→( B )B'13、B→ ID B'14、B→ NUM B'15、B'→ BZB B'16、B'→空17、Z→ +18、Z→ -19、Z→ *20、Z→ /21、 G→ <22、 G→ <=23、 G→ >24、 G→ >=25、 G→ ==26、 G→ !=(3)构造LL (1)分析表(注:在表中用上一步的编号表示所需要的产生式)iii. 详细设计描述 项目构架:各函数功能介绍:main 空 () { } ; = if while ID num + - * / < <= > >= == != # S 10 K 2 C 4 4 3 3 3 Y 6 7 5 F 8 T 9 X10 J11 B1213 14B '16 15 16 16 15 15 16 16 16 16 16 16 16 16 16 16 Z 17 18 19 20G21 22 232425261、word.wordList包(存储了关键字):word:此类是定义了存储关键字的结构:包括String型的关键字,和int型的识别符。

(完整)编译原理实验报告(词法分析器 语法分析器)

(完整)编译原理实验报告(词法分析器 语法分析器)

编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字。

标示符。

无符号整数.运算符.和界符。

三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号.2、程序流程图(1)主程序(2)扫描子程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符.字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。

2 实验词法分析器源程序:#include 〈stdio.h〉#include <math.h>#include <string。

h>int i,j,k;char c,s,a[20],token[20]={’0’};int letter(char s){if((s〉=97)&&(s〈=122)) return(1);else return(0);}int digit(char s){if((s〉=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else”)==0) return(3);else if(strcmp(token,"switch”)==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf(”please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':case ’p':case ’q’:case 'r’:case 's’:case 't’:case ’u’:case ’v’:case ’w’:case ’x':case ’y':case ’z’:while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

编译原理课程设计报告课题名称:编译原理课程设计C-语言词法与语法分析器的实现C-词法与语法分析器的实现1.课程设计目标(1)题目实用性C-语言拥有一个完整语言的基本属性,通过编写C-语言的词法分析和语法分析,对于理解编译原理的相关理论和知识有很大的作用。

通过编写C-语言词法和语法分析程序,能够对编译原理的相关知识:正则表达式、有限自动机、语法分析等有一个比较清晰的了解和掌握。

(2)C-语言的词法说明①语言的关键字:else if int return void while所有的关键字都是保留字,并且必须是小写。

②专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */③其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter*NUM = digit digit*letter = a|..|z|A|..|Zdigit = 0|..|9注:ID表示标识符,NUM表示数字,letter表示一个字母,digit表示一个数字。

小写和大写字母是有区别的。

④空格由空白、换行符和制表符组成。

空格通常被忽略。

⑤注释用通常的c语言符号/ * . . . * /围起来。

注释可以放在任何空白出现的位置(即注释不能放在标记)上,且可以超过一行。

注释不能嵌套。

(3)程序设计目标能够对一个程序正确的进行词法及语法分析。

2.分析与设计(1)设计思想a.词法分析词法分析的实现主要利用有穷自动机理论。

有穷自动机可用作描述在输入串中识别模式的过程,因此也能用作构造扫描程序。

通过有穷自动机理论能够容易的设计出词法分析器。

b.语法分析语法分析采用递归下降分析。

递归下降法是语法分析中最易懂的一种方法。

它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。

因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。

其中子程序的结构与产生式结构几乎是一致的。

(2)程序流程图程序主流程图:词法分析: 语法分析:3.程序代码实现整个词法以及语法的程序设计在一个工程里面,一共包含了8个文件,分别为main.cpp、parse.cpp、scan.cpp、util.cpp、scan.h、util.h、 globals.h、parse.h,其中scan.cpp和scan.h为词法分析程序。

以下仅列出各个文件中的核心代码:Main.cpp#include "globals.h"#define NO_PARSE FALSE#include "util.h"#if NO_PARSE#include "scan.h"#else#include "parse.h"#endifint lineno=0;FILE * source;FILE * listing;FILE * code;int EchoSource = TRUE;int TraceScan=TRUE;int TraceParse=TRUE;int Error = FALSE;int main(int argc,char * argv[]){TreeNode * syntaxTree;char pgm[120];scanf("%s",pgm);source=fopen(pgm,"r");if(source==NULL){fprintf(stderr,"File %s not found\n",pgm);exit(1);}listing = stdout;fprintf(listing,"\nC COMPILATION: %s\n",pgm); #if NO_PARSEwhile(getToken()!=ENDFILE);#elsesyntaxTree = parse();if(TraceParse){fprintf(listing,"\nSyntaxtree:\n");printTree(syntaxTree);}#endiffclose(source);return 0;}Parse.cpp#include "globals.h"#include "util.h"#include "scan.h"#include "parse.h"static TokenType token; /* holds current token *//* function prototypes for recursive calls */static TreeNode * declaration_list(void);static TreeNode * declaration(void);static TreeNode * params(void);static TreeNode * param_list(void);static TreeNode * param(void);static TreeNode * compound_stmt(void);static TreeNode * local_declarations(void);static TreeNode * statement_list(void);static TreeNode * statement(void);static TreeNode * expression_stmt(void);static TreeNode * if_stmt(void);static TreeNode * while_stmt(void);static TreeNode * return_stmt(void);static TreeNode * expression(void);static TreeNode * var(void);static TreeNode * simple_exp(void);static TreeNode * additive_expression(void);static TreeNode * term(void);static TreeNode * factor(void);static TreeNode * args(void);static TreeNode * arg_list(void);static void syntaxError(char * message){ fprintf(listing,"\n>>> ");fprintf(listing,"Syntax error at line %d: %s",lineno,message); Error = TRUE;}/*判断读取的字符*/static void match(TokenType expected){if(token==expected){token=getToken( );}else{syntaxError("unexpected token -> ");printToken(token,tokenString);fprintf(listing," ");}}/*进行语法分析,构建语法树*/TreeNode * declaration_list(void){TreeNode * t= declaration();TreeNode * p= t;while ((token==INT) || (token==VOID) ){TreeNode *q = declaration();if (q!=NULL) {if (t==NULL) t = p = q;else /* now p cannot be NULL either */{p->sibling = q;p = q;}}}return t;}TreeNode * declaration(void){ TreeNode * t = NULL;switch (token){case VOID :case INT :t = newStmtNode(DecK);if(token == INT)t->type =Integer;elset->type = Void;match(token);switch (token){case ID:t-> = copyString(tokenString);t->kind.stmt = VarDK;match(ID);switch (token){case LZKH:t->kind.stmt = VarDK;t->type = IntArray;match(LZKH);match(NUM);match(RZKH);match(SEMI);break;case LPAREN:t->kind.stmt = FunDK;match(LPAREN);t->child[0] = params();match(RPAREN);t->child[1] = compound_stmt();break;default: match(SEMI);break;}break;default:syntaxError("unexpected token -> ");printToken(token,tokenString);token = getToken();break;}break;default : syntaxError("unexpected token -> ");printToken(token,tokenString);token = getToken();break;} /* end case */return t;}TreeNode * params(void){TreeNode * t = NULL;if(token == VOID){match(token);t = newStmtNode(ParamList);t->child[0] = newStmtNode(ParamK);t->child[0]->type = Void;}else if(token == RPAREN)t=NULL;else{t = param_list();}return t;}TreeNode * param_list(void){TreeNode * t = newStmtNode(ParamList);int i = 1;t->child[0] = param();while(token != RPAREN){match(DOT);t->child[i] = param();i++;}return t;}TreeNode * param(void){TreeNode * t = NULL;match(INT);t= newStmtNode(ParamK);t->type=Integer;t->=copyString(tokenString);match(ID);if(token == LZKH){t->type=IntArray;match(LZKH);match(RZKH);}return t;}TreeNode * compound_stmt(void){TreeNode * t = newStmtNode(ComK);match(LDKH);t->child[0] = local_declarations();t->child[1] = statement_list();match(RDKH);return t;}TreeNode * local_declarations(void){TreeNode * t = newStmtNode(LocalDecK);int i=0;while(token == INT || token == VOID){t->child[i] = declaration();i++;}return t;}TreeNode * statement_list(void){TreeNode * t = newStmtNode(StmtList);int i=0;while(token != RDKH){t->child[i] =statement();i++;}return t;}TreeNode * statement(void){TreeNode * t ;switch (token) {case IF : t = if_stmt(); break;case WHILE : t = while_stmt(); break;case ID :case SEMI:t = expression_stmt(); break;case RETURN : t = return_stmt(); break;case LDKH : t=compound_stmt();break;default : syntaxError("unexpected token -> ");printToken(token,tokenString);token = getToken();break;} /* end case */return t;}TreeNode * expression_stmt(void){TreeNode * t = newStmtNode(ExpstmtK);if(token == SEMI)match(SEMI);else{t = expression();match(SEMI);}return t;}TreeNode * if_stmt(void){TreeNode * t = newStmtNode(IfK);if(t!=NULL){match(IF);match(LPAREN);t->child[0] = expression();match(RPAREN);t->child[1] = statement();if (token==ELSE){match(ELSE);if (t!=NULL) t->child[2] = newStmtNode(ElseK);t->child[2]->child[0] = statement();} }return t;}TreeNode * while_stmt(void){TreeNode * t = newStmtNode(WhileK);match(WHILE);match(LPAREN);if (t!=NULL) t->child[0] = expression();match(RPAREN);if (t!=NULL) t->child[1] = statement();return t;}TreeNode * return_stmt(void){TreeNode * t = newStmtNode(RetK);if(token == RETURN)match(RETURN);if(token == SEMI)match(SEMI);else{t->child[0] = expression();match(SEMI);}return t;}TreeNode * expression(void){TreeNode * t = simple_exp();return t;}TreeNode* var(void){TreeNode* t = newExpNode(IdK);if ((t!=NULL) && (token==ID))t-> = copyString(tokenString);match(ID);if(token == LZKH){match(token);t->type = ArrayUnit;t->child[0] = expression();match(RZKH);}return t;}TreeNode * simple_exp(void){TreeNode * t = additive_expression();if(t!=NULL){if (token == LT || token == LE|| token == MT || token == ME||token ==EQ||token ==NEQ){TreeNode * p = newExpNode(OpK);if(p!=NULL){p->attr.op = token;p->child[0] = t;match(token);p->child[1] = additive_expression();t=p;}}}return t;}TreeNode* additive_expression(void){TreeNode * t = term();while(token == PLUS || token == MINUS){TreeNode * p = newExpNode(OpK);p->attr.op = token;p->child[0] = t;match(token);p->child[1] = term();t = p;}return t;}TreeNode * term(void){TreeNode * t = factor();while ((token==TIMES)||(token==OVER)){TreeNode * p = newExpNode(OpK);if (p!=NULL) {p->child[0] = t;p->attr.op = token;match(token);p->child[1] = factor();t = p;}}return t;}TreeNode * factor(void){TreeNode * t = NULL;switch (token){case NUM :t = newExpNode(ConstK);if ((t!=NULL) && (token==NUM))t->attr.val = atoi(tokenString);match(NUM);break;case ID :t = var();if (token == ASSIGN){TreeNode* p = newStmtNode(AssignK);p-> = t->;match(token);p->child[0] = expression();t = p;}if (token == LPAREN ){TreeNode * p = newStmtNode(CallK);p-> = t->;t=p;match(token);p->child[0] = args();match(RPAREN);}break;case LPAREN :match(LPAREN);t = expression();match(RPAREN);break;default:syntaxError("unexpected token -> ");printToken(token,tokenString);token = getToken();break;}return t;}TreeNode * args(void){TreeNode * t = newStmtNode(ArgList);if(token != RPAREN){t->child[0] = arg_list();return t;}elsereturn NULL;}TreeNode * arg_list(void){TreeNode * t = newStmtNode(ArgK);int i = 1;if(token != RPAREN)t->child[0] = expression();while(token!=RPAREN){match(DOT);t->child[i] = expression();i++;}return t;}TreeNode * parse(void){ TreeNode * t;token = getToken();t =declaration_list();if (token!=ENDFILE)syntaxError("Code ends before file\n");return t;}scan.cpp#include "globals.h"#include "util.h"#include "scan.h"/*对扫描的字符进行匹配判断*/TokenType getToken(void){ /* index for storing into tokenString */int tokenStringIndex = 0;/* holds current token to be returned */TokenType currentToken;/* current state - always begins at START */ StateType state = START;/* flag to indicate save to tokenString */ int save;while (state != DONE){ int c = getNextChar();save = TRUE;switch (state){ case START:if (isdigit(c))state = INNUM;else if (isalpha(c))state = INID;else if (c == '=')state = INEQUAL;else if (c == '<')state = INLE;else if (c == '>')state = INME;else if ((c == ' ') || (c == '\t') || (c == '\n')) save = FALSE;else if (c== '!')state = INNEQ;else if (c == '/'){if(getNextChar()!='*'){ungetNextChar();state = DONE;currentToken = OVER;break;}else{save = FALSE;state = INCOMMENT;}}else{ state = DONE;switch (c){ case EOF:save = FALSE;currentToken = ENDFILE;break;case '+':currentToken = PLUS;break;case '-':currentToken = MINUS; break;case '*':currentToken = TIMES; break;case '(':currentToken = LPAREN; break;case ')':currentToken = RPAREN; break;case ';':currentToken = SEMI; break;case '[':currentToken=LZKH;break;case ']':currentToken=RZKH;break;case '{':currentToken=LDKH;break;case '}':currentToken=RDKH;break;case ',':currentToken=DOT;break;default:currentToken = ERROR; break;}}break;case INCOMMENT:save = FALSE;if (c == EOF){state = DONE;currentToken = ERROR;}else if(c=='*'){if(getNextChar()=='/'){state = START;}else{ungetNextChar();}}break;case INNEQ:state=DONE;if(c=='=')currentToken=NEQ;else{ungetNextChar();save=FALSE;currentToken=ERROR;}break;case INEQUAL:state = DONE;if (c == '=')currentToken = EQ;else{ /* backup in the input */ ungetNextChar();currentToken = ASSIGN;}case INNUM:if (!isdigit(c)){ /* backup in the input */ ungetNextChar();save = FALSE;state = DONE;currentToken = NUM;}break;case INID:if (!isalpha(c)){ /* backup in the input */ ungetNextChar();save = FALSE;state = DONE;currentToken = ID;}break;case INLE:state = DONE;if(c== '=')currentToken = LE;else{ /* backup in the input */ ungetNextChar();currentToken = LT;}break;case INME:state = DONE;if(c== '=')currentToken = ME;else{ /* backup in the input */ ungetNextChar();currentToken = MT;}case DONE:default: /* should never happen */fprintf(listing,"Scanner Bug: state= %d\n",state); state = DONE;currentToken = ERROR;break;}if ((save) && (tokenStringIndex <= MAXTOKENLEN))tokenString[tokenStringIndex++] = (char) c;if (state == DONE){ tokenString[tokenStringIndex] = '\0';if (currentToken == ID)currentToken = reservedLookup(tokenString);}}if (TraceScan) {fprintf(listing,"\t%d: ",lineno);printToken(currentToken,tokenString);}return currentToken;} /* end getToken */Util.cpp#include "globals.h"#include "util.h"void printToken(TokenType token, const char* tokenString) {/*根据对应的判断输出判断结果*/switch(token){case ELSE:case IF:case INT:case RETURN:case VOID:case WHILE:fprintf(listing, "reserved word: %s\n", tokenString);break;case LT:fprintf(listing,"<\n");break;case EQ:fprintf(listing,"==\n");break;case LPAREN:fprintf(listing,"(\n");break;case RPAREN:fprintf(listing,")\n");break;case SEMI:fprintf(listing,";\n");break;case PLUS:fprintf(listing,"+\n");break;case MINUS:fprintf(listing,"-\n");break;case TIMES:fprintf(listing,"*\n");break;case OVER:fprintf(listing,"/\n");break;case ENDFILE:fprintf(listing,"EOF\n");break;case MT:fprintf(listing,">\n");break;case NEQ:fprintf(listing,"!=\n");break;case ASSIGN:fprintf(listing,"=\n");break;case DOT:fprintf(listing,",\n");break;case LZKH:fprintf(listing,"[\n");break;case RZKH:fprintf(listing,"]\n");break;case LDKH:fprintf(listing,"{\n");break;case RDKH:fprintf(listing,"}\n");break;case LZS:fprintf(listing,"/*\n");break;case RZS:fprintf(listing,"*/\n");break;case ME:fprintf(listing,">=\n");break;case LE:fprintf(listing,"<=\n");break;case NUM:fprintf(listing,"NUM,val= %s\n",tokenString);break;case ID:fprintf(listing,"ID, name= %s\n",tokenString);break;case ERROR:fprintf(listing,"ERROR: %s\n",tokenString);break;default:fprintf(listing,"Unknown token: %d\n",token);}}/*this function is used to establish the new stmt node*/TreeNode * newStmtNode(StmtKind kind){TreeNode * t = (TreeNode *)malloc(sizeof(TreeNode));int i;if(t==NULL){fprintf(listing, "Out of memory error at line %d\n",lineno);}else{for(i=0;i<MAXCHILDREN;i++){t->child[i]=NULL;}t->sibling=NULL;t->nodekind=StmtK;t->kind.stmt=kind;t->lineno=lineno;}return t;}/* Function newExpNode creates a new expressionnode for syntax tree construction*/TreeNode * newExpNode(ExpKind kind){TreeNode * t = (TreeNode *)malloc(sizeof(TreeNode));int i;if(t==NULL){fprintf(listing, "Out of memory error at line %d\n",lineno);}else{for(i=0;i<MAXCHILDREN;i++){t->child[i]=NULL;}t->sibling=NULL;t->nodekind=ExpK;t->kind.exp=kind;t->lineno=lineno;t->type=Void;}return t;}char * copyString(char * s){int n;char * t;if(s==NULL){return NULL;}n=strlen(s)+1;t=(char *)malloc(n);/*其作用是在存的动态存储区中分配一个长度为n的连续空间.保存tokenstring*/ if(t==NULL){fprintf(listing, "Out of memory error at line %d\n",lineno);}else{strcpy(t,s);/*该函数是字符串拷贝函数,用来将一个字符串复制到一个字符数组中。

相关文档
最新文档