毕业设计编译原理设计报告c语言词法与语法分析器的实现
- 格式:doc
- 大小:234.50 KB
- 文档页数:35
编译原理课程设计报告课题名称:编译原理课程设计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。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
(此文档为word格式,下载后您可任意编辑修改!) 《编译原理课程设计》课程报告题目 C语言词法分析器和C-语言语法分析器学生姓名学生学号指导教师提交报告时间 2019 年 6 月 8 日C语言词法分析器1 实验目的及意义1.熟悉C语言词法2.掌握构造DFA的过程3.掌握利用DFA实现C语言的词法分析器4.理解编译器词法分析的工作原理2 词法特点及正则表达式2.1词法特点2.1.1 保留字AUTO, BREAK , CASE , CHAR , CONST , CONTINUE , DEFAULT , DO , DOUBLE , ELSE,ENUM , EXTERN , FLOAT , FOR , GOTO,IF , INT , LONG , REGISTER , RETURN,SHORT , SIGNED , SIZEOF , STATIC , STRUCT , SWITCH , TYPEDEF , UNION , UNSIGNED , VOID,VOLATILE , WHILE,2.1.2 符号+ - * ++ -- += -= *= < <= > >= == != = ; , ( ) [ ] { } * * :2.2 正则表达式whitespace = (newline|blank|tab|comment)+digit=0|..|9nat=digit+signedNat=(+|-)?natNUM=signedNat(“.”nat)?letter = a|..|z|A|..|ZID = letter(letter|digit|“_”)+CHAR = 'other+' STRING = “other+”3 Token定义3.1 token类型3.2 tokenType类型代码4 DFA设计4.1 注释的DFA设计注释的DFA如下所示,一共分为5个状态,在开始状态1时,如果输入的字符为, 则进入状态2,此时有可能进入注释状态,如果在状态2时,输入的字符为*,则进入注释状态,状态将转到3,如果在状态3时,输入的字符为*,则有可能结束注释状态,此时状态将转到状态4,如果在状态4时输入的字符为,则注释状态结束,状态转移到结束状态。
编写原理课程设计报告题目:编译原理课程设计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-编译器词法分析与语法分析的实现提交文档学生姓名:黄臻旸提交文档学生学号: 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小写大写字母是有区别的。
词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求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用来存放单词符号的种别码。
编译原理课程设计报告院系专业年级学号姓名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级软件四班学生学号:2014112218学生:何华均任课教师:丁光耀信息科学与技术学院2017.6课程设计1-C语言词法分析器1.题目C语言词法分析2.容选一个能正常运行的c语言程序,以该程序出现的字符作为单词符号集,不用处理c语言的所有单词符号。
将解析到的单词符号对应的二元组输出到文件中保存可以将扫描缓冲区与输入缓冲区合成一个缓冲区,一次性输入源程序后就可以进行预处理了3.设计目的掌握词法分析算法,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解4.设计环境(电脑语言环境)语言环境:C语言CPU:i7HQ6700存:8G5.概要设计(单词符号表,状态转换图)5.1 词法分析器的结构词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
词法分析程序可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词.为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序:1) ch 存放最新读进的源程序字符2) strToken 存放构成单词符号的字符串3) Buffer 字符缓冲区4)struct keyType 存放保留字的符号和种别5.2 待分析的简单词法(1)保留字break、case、char、const、int、do、while…(2)运算符和界符= 、+、-、* 、/、%、,、;、(、)、?、#5.3 各种单词符号对应的种别码const 6 unsigned 30 continue 7 void 31 default 8 volatile 32 do 9 while 33 double 10 = 34 else 11 + 35 enum 12 - 36 extern 13 * 37 float 14 / 38 for 15 % 39 goto 16 , 40 if 17 ; 41 int 18 ( 42 long 19 ) 43register 20 ? 44 return 21 clear 45 short 22 # 4647 signed 23 lettet(letter|digit)*dight dight* 48 5.3 状态转换图6.详细设计(数据结构,子程序)算法思想:首先设置3个变量:①strToken用来存放构成单词符号的字符串;②ch 用来字符;③struct keyType用来存放单词符号的种别码。
编译原理课程设计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:/作业/编译原理/运行结果九、 实验体会通过本次次法分析设计实验,我加深了对词法分析过程的理解。
编译原理课程设计报告课题名称:编译原理课程设计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)程序流程图程序主流程图:词法分析: 语法分析:读取程序对输入的字符进行匹配判断对应输出各行代码的词法分析结果读取程序进行递归下降分析匹配或建立树输出程序对应的语法树Start是否为num是否为dightNum是否为id是否为alphaID是否为>,<.,!,=是否为=单符号双符号是否为+,-,*等专用符号专用符号是否为/是否为*是否为*是否为/错误结果over是 否否是否否是是否是否否是是是是否否否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_P ARSE 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 COMPILA TION: %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 = V oid;match(token);switch (token){case ID:t-> = copyString(tokenString);t->kind.stmt = V arDK;match(ID);switch (token){case LZKH:t->kind.stmt = V arDK;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(RP AREN);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 = V oid;}else if(token == RP AREN)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 != RP AREN){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(RP AREN);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(RP AREN);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 == L T || 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 == LP AREN ){TreeNode * p = newStmtNode(CallK);p-> = t->;t=p;match(token);p->child[0] = args();match(RP AREN);}break;case LPAREN :match(LPAREN);t = expression();match(RP AREN);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!=RP AREN){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 = ST ART;/* 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 = LP AREN;break;case ')':currentToken = RP AREN;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; }break;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 = L T;}break;case INME:state = DONE;if(c== '=')currentToken = ME; else{ /* backup in the input */ungetNextChar();currentToken = MT;}break;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 getT oken */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 L T: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=V oid;}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);/*该函数是字符串拷贝函数,用来将一个字符串复制到一个字符数组中。