语法分析程序报告

合集下载

LL(1)语法分析程序实验报告

LL(1)语法分析程序实验报告

LL1实验报告1.设计原理所谓LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。

实现LL(1)分析的程序又称为LL(1)分析程序或LL1(1)分析器。

我们知道一个文法要能进行LL(1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。

当文法满足条件后,再分别构造文法每个非终结符的FIRST和FOLLOW 集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。

LL(1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C++语言来编写,其逻辑结构图如下:LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。

对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =‘#’,则宣布分析成功,停止分析过程。

(2)若X = a ‘#’,则把X从STACK栈顶弹出,让a指向下一个输入符号。

(3)若X是一个非终结符,则查看预测分析表M。

若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK栈顶,然后,把产生式的右部符号串按反序一一弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。

若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。

事实上,LL(1)的分析是根据文法构造的,它反映了相应文法所定义的语言的固定特征,因此在LL(1)分析器中,实际上是以LL(1)分析表代替相应方法来进行分析的。

2.分析LL ( 1) 分析表是一个二维表,它的表列符号是当前符号,包括文法所有的终结和自定义。

的句子结束符号#,它的表行符号是可能在文法符号栈SYN中出现的所有符号,包括所有的非终结符,所有出现在产生式右侧且不在首位置的终结符,自定义的句子结束符号#表项。

语法法分析实验报告

语法法分析实验报告

一、实验目的1. 理解语法分析的基本概念和原理。

2. 掌握语法分析器的构建方法。

3. 培养实际操作能力,提高编程水平。

二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.83. 开发工具:PyCharm三、实验内容1. 语法分析概述2. 词法分析3. 语法分析4. 实验实现四、实验步骤1. 语法分析概述(1)了解语法分析的定义、作用和意义。

(2)掌握语法分析的基本原理和流程。

2. 词法分析(1)编写词法分析器代码,将源代码分解成单词序列。

(2)实现词法分析器的各个功能,如:识别标识符、关键字、运算符等。

3. 语法分析(1)设计语法分析器,将单词序列转换为抽象语法树(AST)。

(2)实现语法分析器的各个功能,如:识别表达式、语句、函数等。

4. 实验实现(1)创建Python项目,导入相关库。

(2)编写词法分析器代码,实现单词序列的分解。

(3)编写语法分析器代码,实现抽象语法树的构建。

(4)测试语法分析器,验证其正确性。

五、实验结果与分析1. 词法分析结果实验中,我们成功地将源代码分解成单词序列,包括标识符、关键字、运算符等。

词法分析器的输出结果如下:```identifier: akeyword: intoperator: +identifier: boperator: =integer: 5```2. 语法分析结果通过语法分析器,我们将单词序列转换成抽象语法树。

以下是一个示例的抽象语法树:```Program├── Declaration│ ├── Type│ │ ├── Identifier│ │ └── Integer│ └── Identifier│ └── a└── Statement├── Expression│ ├── Identifier│ └── a└── Operator└── =└── Expression├── Identifier└── b└── Integer└── 5```从实验结果可以看出,我们的语法分析器能够正确地将源代码转换为抽象语法树。

语法分析器报告

语法分析器报告
While S[j]>a do
Begin
Repeat
Q:=S[j]
If S[j-1]∈VTthenj:=j-1elsej:=j-2
UntilS[j]<Q
把S[j+1]……S[K]归约为某个N
记录归约产生式序号
K:=j+1
S[K]:=N
End of while
If S[j]<a OR S[j]=a then
j++;
}
strings[m+1]='#';
strings[m+2]='\0';
cout<<"算术表达式"<<id<<"为: "<<oldstrings<<endl;
cout<<"转换为输入串: "<<strings<<endl;
cout<<" 步骤号符号栈优先关系当前分析符剩余输入串动作";
prior_analysis();
cout<<" # < < < < < e3 < ="<<endl;
if((fp=fopen("预处理.txt","r"))==NULL)
{
cout<<"请先将实验文件夹中的预处理.txt文件复制到实验文件夹中!"<<endl;
system("pause");
exit(0);
}
charch=fgetc(fp);

PL0语言语法分析器实验报告

PL0语言语法分析器实验报告

PL0语言语法分析器实验报告一、引言编译器是一种用于把高级语言程序转换成机器可执行代码的软件工具。

编译器由多个组件构成,其中语法分析器是编译器中的重要组成部分,其主要功能是对输入的源代码进行解析,并生成一个语法树。

本实验旨在通过使用BNF(巴科斯范式)描述PL0语言的语法规则,并通过实现PL0语言的语法分析器,来深入理解语法分析的原理和过程。

二、PL0语言的语法规则1.程序结构:<程序>::=[<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句>2.常量说明部分:<常量说明部分> ::= const <常量定义> { , <常量定义> };<常量定义>::=<标识符>=<无符号整数>3.变量说明部分:<变量说明部分> ::= var <标识符> { , <标识符> };4.过程说明部分:<过程说明部分>::=<过程首部><分程序>;<过程首部> ::= procedure <标识符> ;5.语句:<语句> ::= <赋值语句> , <if语句> , <while语句> , <调用语句> , <复合语句> , <读语句> , <写语句> , <空><赋值语句>::=<标识符>:=<表达式><if语句> ::= if <条件> then <语句> else <语句><while语句> ::= while <条件> do <语句><调用语句> ::= call <标识符><复合语句> ::= begin <语句> { ; <语句> } end<读语句> ::= read ( <标识符> )<写语句> ::= write ( <表达式> )6.表达式:<表达式>::=[+,-]<项>{(+,-)<项>}<项>::=<因子>{(*,/)<因子>}<因子>::=<标识符>,<无符号整数>,(<表达式>)7.条件:<条件>::=<表达式><关系运算符><表达式><关系运算符>::==,<>,<,<=,>,>=三、PL0语言的语法分析器设计与实现1.设计思路本次实验中,我们将使用自顶向下的递归下降分析法,来对PL0语言进行语法分析。

编译原理实验二LL(1)语法分析实验报告

编译原理实验二LL(1)语法分析实验报告

专题3_LL(1)语法分析设计原理与实现李若森 13281132 计科1301一、理论传授语法分析的设计方法和实现原理;LL(1) 分析表的构造;LL(1)分析过程;LL(1)分析器的构造。

二、目标任务实验项目实现LL(1)分析中控制程序(表驱动程序);完成以下描述算术表达式的 LL(1)文法的LL(1)分析程序。

G[E]:E→TE’E’→ATE’|εT→FT’T’→MFT’|εF→(E)|iA→+|-M→*|/设计说明终结符号i为用户定义的简单变量,即标识符的定义。

加减乘除即运算符。

设计要求(1)输入串应是词法分析的输出二元式序列,即某算术表达式“专题 1”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;(2)LL(1)分析程序应能发现输入串出错;(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。

任务分析重点解决LL(1)表的构造和LL(1)分析器的实现。

三、实现过程实现LL(1)分析器a)将#号放在输入串S的尾部b)S中字符顺序入栈c)反复执行c),任何时候按栈顶Xm和输入ai依据分析表,执行下述三个动作之一。

构造LL(1)分析表构造LL(1)分析表需要得到文法G[E]的FIRST集和FOLLOW集。

构造FIRST(α)构造FOLLOW(A)构造LL(1)分析表算法根据上述算法可得G[E]的LL(1)分析表,如表3-1所示:表3-1 LL(1)分析表主要数据结构pair<int, string>:用pair<int, string>来存储单个二元组。

该对照表由专题1定义。

map<string, int>:存储离散化后的终结符和非终结符。

vector<string>[][]:存储LL(1)分析表函数定义init:void init();功能:初始化LL(1)分析表,关键字及识别码对照表,离散化(非)终结符传入参数:(无)传出参数:(无)返回值:(无)Parse:bool Parse( const vector<PIS> &vec, int &ncol );功能:进行该行的语法分析传入参数:vec:该行二元式序列传出参数:emsg:出错信息epos:出错标识符首字符所在位置返回值:是否成功解析。

语法分析实验报告

语法分析实验报告

语法分析实验报告一、实验目的:. 了解单词(内部编码)符号串中的短语句型结构形成规律。

. 理解和掌握语法分析过程中语法分析思想(,)的智能算法化方法。

二、实验内容:构造自己设计的小语言的语法分析器:. 小语言的语法描述(语法规则)的设计即文法的设计;. 把文法形式符号中所隐含的信息内容挖掘出来并用或的资料形式(分析表)表示出来;. 语法分析的数据输入形式和输出形式的确定;. 语法分析程序各个模块的设计与调试。

主要设备和材料:电脑、操作系统、语言系统三、实验分工:学号姓名实验分工实验代码设计及编写检查校对代码写电子版实验报告查找、分析、整理资料查找、分析、整理资料四、实验步骤:、语法规则①<程序> {<变量定义语句><赋值语句><条件语句> <循环语句> }②<变量定义语句>变量{,变量};③<赋值语句>变量:<表达式>;④<表达式>标识符{运算符标识符};⑤<标识符>变量常量⑥<运算符> * > <⑦<条件语句><语句>[<语句>]⑧<语句> (表达式) [] {赋值语句条件语句循环语句}[]⑨<语句> [] {赋值语句条件语句循环语句} []⑩<循环语句>(表达式) [] {赋值语句条件语句循环语句} []<输出语句>表达式注:若语句、语句、循环语句中出现,后面的必须出现,即与同对出现注:、后的"(",")"表示终结符,而不是定义成分优先的说明符号、分析表:( ) : 变量常量,;运算符变量定义>②>②>②>②赋值语句>③>③>③>③ >③条件语句>⑦>⑦>⑦>⑦>⑦>⑦>⑦循环语句>⑩>⑩>⑩>⑩>⑩>⑩>⑩输出语句>>>分析表(续):变量定义>②赋值语句条件语句>⑦>⑦>⑦>⑦循环语句>⑩>⑩>⑩输出语句> 3、调试和测试五、源代码(见附录):六、实验总结:本实验在词法分析的基础上,对提取出的标识符进行语法判断。

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

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

一、目的编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。

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

二、任务及要求基本要求: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分析法等。

语法分析器实验报告

语法分析器实验报告

词法分析器实验报告实验名称:语法分析器实验内容:利用LL(1)或LR(1)分析语句语法,判断其是否符合可识别语法。

学会根据状态变化、first、follow或归约转移思想构造状态分析表,利用堆栈对当前内容进行有效判断实验设计:1.实现功能可对一段包含加减乘除括号的赋值语句进行语法分析,其必须以$为终结符,语句间以;隔离,判断其是否符合语法规则,依次输出判断过程中所用到的产生式,并输出最终结论,若有错误可以报错并提示错误所在行数及原因2.实验步骤3.算法与数据结构a)LLtable:left记录产生式左端字符;right记录产生式右端字符;ln记录产生式右端字符长度Status:记录token分析情况Token:category,类型;value,具体内容b)根据LL(1)算法,手工构造分析表,并将内容用数组存储,便于查找c)先将当前语句的各token按序存储,当前处理语句最后一个token以#标记,作为输入流与产生式比较,堆栈中初始放入#,x,a为处理输入流中当前读头内容✓若top=a=‘#‘表示识别成功,退出分析程序✓若top=a!=‘#‘表示匹配,弹出栈顶符号,读头前进一个✓若top为i或n,但top!=a,出错,输出当前语句所在行,出错具体字符✓若top不为i或n,查预测分析表,若其中存放关于top产生式,则弹出top,将产生式右部自右向左压入栈内,输出该产生式,若其中没有产生式,出错,输出当前语句所在行,出错具体字符d)以;作为语句终结,每次遇到分号则处理之前语句并清空后预备下语句处理,当遇到$表示该段程序结束,停止继续处理4.分析表构造过程a)x->i=ee->e+t|e-t|tt->t*f|t/f|ff->(e)|i|nnote: i表示变量,n表示数字,!表示空串b)提取左公因子x->i=ee->ea|ta->+t|-tt->tb|fb->*f|/ff->(e)|i|nc)消除左递归x->i=ee->tcc->ac|!a->+t|-tt->fdd->bd|!b->*e|/ff->(e)|i|n5.类class parser{public:LLtable table[100][100]; //LL(1)表void scanner(); //扫描输入流中内容并分析parser(istream& in); //初始化,得到输入文件地址int getLine() const; //得到当前行数private:int match(); //分析语法stack <char> proStack; //分析堆栈void constructTable(); //建立LL(1)表int getRow(char ch); //取字符所在表中行int getCol(char ch); //取字符所在表中列istream* pstream; //输入流void insertToken(token& t); //插入当前tokenstatus getToken(token& t); //找到tokenint getChar(); //得到当前字符int peekChar(); //下一个字符void putBackChar(char ch); //将字符放回void skipChar(); //跳过当前字符void initialization(); //初始化堆栈等int line; //当前行数token tokens[1000]; //字符表int counter; //记录当前字符表使用范围}6.主要代码void parser::constructTable() //建立LL(1)表{for (int i=0;i<8;i++){for (int j=0;j<9;j++){table[i][j].left=' ';for (int k=0;k<3;k++)table[i][j].right[k]=' ';}}table[0][6].left='x';table[0][6].ln=3;table[0][6].right[0]='i';table[0][6].right[1]='=';table[0][6].right[2]='e';table[1][4].left='e';table[1][4].ln=2;table[1][4].right[0]='t';table[1][4].right[1]='c';table[1][6].left='e';table[1][6].ln=2;table[1][6].right[0]='t';table[1][6].right[1]='c';table[1][7].left='e';table[1][7].ln=2;table[1][7].right[0]='t';table[1][7].right[1]='c';table[2][0].left='c';table[2][0].ln=2;table[2][0].right[0]='a';table[2][0].right[1]='c';table[2][1].left='c';table[2][1].ln=2;table[2][1].right[0]='a';table[2][1].right[1]='c';table[2][5].left='c';table[2][5].ln=0;table[2][5].right[0]='!';table[2][8].left='c';table[2][8].ln=0;table[2][8].right[0]='!';table[3][0].left='a';table[3][0].ln=2;table[3][0].right[0]='+'; table[3][0].right[1]='t'; table[3][1].left='a';table[3][1].ln=2;table[3][1].right[0]='-'; table[3][1].right[1]='t'; table[4][4].left='t';table[4][4].ln=2;table[4][4].right[0]='f'; table[4][4].right[1]='d'; table[4][6].left='t';table[4][6].ln=2;table[4][6].right[0]='f'; table[4][6].right[1]='d'; table[4][7].left='t';table[4][7].ln=2;table[4][7].right[0]='f'; table[4][7].right[1]='d'; table[5][0].left='d';table[5][0].ln=0;table[5][0].right[0]='!'; table[5][1].left='d';table[5][1].ln=0;table[5][1].right[0]='!'; table[5][2].left='d';table[5][2].ln=2;table[5][2].right[0]='b'; table[5][2].right[1]='d'; table[5][3].left='d';table[5][3].ln=2;table[5][3].right[0]='b'; table[5][3].right[1]='d'; table[5][5].left='d';table[5][5].ln=0;table[5][5].right[0]='!'; table[5][8].left='d';table[5][8].ln=0;table[5][8].right[0]='!'; table[6][2].left='b';table[6][2].ln=2;table[6][2].right[0]='*'; table[6][2].right[1]='f'; table[6][3].left='b';table[6][3].ln=2;table[6][3].right[0]='/'; table[6][3].right[1]='f'; table[7][4].left='f';table[7][4].ln=3;table[7][4].right[0]='(';table[7][4].right[1]='e';table[7][4].right[2]=')';table[7][6].left='f';table[7][6].ln=1;table[7][6].right[0]='i';table[7][7].left='f';table[7][7].ln=1;table[7][7].right[0]='n';}int parser::match() //分析语法{ofstream ofs("out.txt",ios::app);char a;int i=0;for (int p=0;p<counter;p++){cout<<tokens[p].value;ofs<<tokens[p].value;}cout<<endl;ofs<<endl<<"ANALYSIS:"<<endl;while(1){if(tokens[i].category=='n' || tokens[i].category=='i')a=tokens[i].category;elsea=(tokens[i].value)[0];if(a==proStack.top()){if(a=='#'){cout<<"This is valid!"<<endl<<endl;ofs<<"This is valid!"<<endl<<endl;return 0;}else{proStack.pop();i++;}}else{if(proStack.top() =='n'|| proStack.top() =='i'){if(a!='#'){cout<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;}else{cout<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;}cout<<"This is invalid!"<<endl<<endl;ofs<<"This is invalid!"<<endl<<endl;return 0;}else{if((table[getRow(proStack.top())][getCol(a)]).left!=' '){char pst=proStack.top();int n=table[getRow(pst)][getCol(a)].ln;int k=0;ofs<<table[getRow(pst)][getCol(a)].left<<"->"<<table[getRow(pst)][getCol(a)].right[0]<<table[getRow(pst)][g etCol(a)].right[1]<<table[getRow(pst)][getCol(a)].right[2]<<endl;proStack.pop();while (n>0){//cout<<n<<" "<<table[getRow(pst)][getCol(a)].right[n-1]<<endl;proStack.push(table[getRow(pst)][getCol(a)].right[n-1]);n--;}}else{if(a!='#'){cout<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;}else{cout<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;}cout<<"This is invalid!"<<endl<<endl;ofs<<"This is invalid!"<<endl<<endl;return 0;}}}}}实验结果:●输入(in.txt)●输出1输出2(out.txt)实验总结:原本以为处理四则运算赋值将会很困难,但在使用LL(1)后发现,思路还是挺清晰简单的,但在实验过程中,由于LL(1)不能出现左递归和左公因子,不得不将其消除,原本简单的产生式一下变多了,而在产生式理解上也没有原来直观,不过其状态复杂度没有LR高,故仍选择该方法。

语法分析实验报告

语法分析实验报告

语法分析实验报告语法分析实验报告引言语法分析是自然语言处理中的一项重要任务,它旨在根据给定的语法规则和输入句子,确定句子的结构和语法成分,并进行语义解析。

本实验旨在探索语法分析的基本原理和方法,并通过实际操作来加深对其理解。

实验目标本实验的主要目标是实现一个简单的自底向上的语法分析器,即基于短语结构文法的分析器。

具体而言,我们将使用Python编程语言来实现一个基于CYK 算法的语法分析器,并对其进行评估和分析。

实验过程1. 语法规则的定义在开始实验之前,我们首先需要定义一个适当的语法规则集。

为了简化实验过程,我们选择了一个简单的文法,用于分析包含名词短语和动词短语的句子。

例如,我们定义了以下语法规则:S -> NP VPNP -> Det NVP -> V NP2. 实现CYK算法CYK算法是一种自底向上的语法分析算法,它基于动态规划的思想。

我们将使用Python编程语言来实现CYK算法,并根据定义的语法规则进行分析。

具体而言,我们将根据输入的句子和语法规则,构建一个二维的表格,用于存储句子中各个子串的语法成分。

通过填充表格并进行推导,我们可以确定句子的结构和语法成分。

3. 实验结果与分析我们使用几个示例句子来测试我们实现的语法分析器,并对其结果进行分析。

例如,对于句子"the cat eats fish",我们的语法分析器可以正确地识别出该句子的结构,并给出相应的语法成分。

具体而言,我们的分析器可以识别出句子的主语是"the cat",谓语是"eats",宾语是"fish"。

通过对多个句子的测试,我们可以发现我们实现的语法分析器在大多数情况下都能正确地分析句子的结构和语法成分。

然而,在一些复杂的句子中,我们的分析器可能会出现一些错误。

这可能是由于语法规则的不完备性或者算法的限制所致。

结论与展望通过本实验,我们深入了解了语法分析的基本原理和方法,并实现了一个简单的自底向上的语法分析器。

语法分析实验报告

语法分析实验报告

语法分析实验报告一: 实验内容:编写语法分析程序, 实现对算术表达式的语法分析, 要求所分析的算术表达式由如下的文法产生。

E->E+T|E-T|TT->T*F|T/F|FF->id|(E)|num二: 实验要求:在对表达式进行分析的同时, 输出所采用的产生式。

1.编写LL(1)语法分析程序, 要求:编程实现算法4.2, 为给定的文法自动构造预测分析表编程实现算法4.1, 构造LL(1)预测分析程序,2.编写语法分析程序, 实现自底向上的分析, 要求:构造识别所有活前缀的DFA构造LR分析表编程实现算法4.3, 构造LR分析程序1.三: 实验分析:2.方法二(编写LL(1)语法分析程序)1.步骤:(1)根据题目所给出的文法构造相应的无左递归文法, 并求出该文法各非终结符的FIRST、FOLLOW集合;(2)构造文法的LL(1)分析表;(3)由此构造LL分析程序。

2.实现方法:1.输入缓冲区为一个字符型数组, 读入输入的算术表达式并保存在此, 以’$’结束;2.为构造文法的LL(1)分析表, 构建一个相对应的字符串数组;3.在实际程序中P代表E', Q代表T', e代表ε,i代表id, n代表num;4.处理输入表达式中代表id和num的子串, 分别将它们转化为'i'和'n'进行分析;5.LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。

对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =‘$’, 则宣布分析成功, 停止分析过程。

(2)若X = a!=‘$’, 则把X从STACK栈顶弹出, 让a指向下一个输入符号。

①如果是终结符合, 则栈不加入新符号②如果是非终结符合, 则把表达式右边入栈(3)若M[A, a]中存放着“出错标志”, 则调用出错诊断程序ERROR。

语法分析器设计实验报告

语法分析器设计实验报告

学号《编译原理》实验2:语法分析器设计学生姓名专业、班级指导教师赵璐成绩计算机与信息工程学院2018 年11 月27 日一、实验目的1.理解语法分析程序的功能。

2.熟悉语法分析程序的设计原理和构造方法。

3.掌握递归下降语法分析程序的构造方法。

4.设计一个递归下降的语法分析器,作为实验一构造的词法分析器的下一步编译工具,能语法分析前一步词法分析器输出的单词符号序列。

二、实验要求1.根据书P206给出的简单语言的语法规则,编写C或C++语言源程序,实现针对该简单语言的递归下降的语法分析器;2.独立做实验,输入、调试所编程序;3.实验结束后,根据实验报告模板编写实验报告。

三、实验内容和步骤用Visual C++作为实验开发环境,创建一个Win32 Console Application工程,工程名为你的学号,添加三个文件:(1)存储结构定义:以ParserDef.h和LexerDef.h为文件名;(2)基本操作的算法:以ParserAlgo.h和LexerAlgo.h为文件名;(3)调用基本操作的主程序:以ParserMain.cpp为文件名。

编写程序:(1)文件LexerDef.h和LexerAlgo.h为实验一的内容。

(2)文件ParserDef.h定义语法分析所需的全局变量等。

(3)文件ParserAlgo.h实现对语法规则中各语法成分的分析子算法。

(4)文件ParserMain.cpp实现针对P206简单语言语法规则的递归下降语法分析器。

源程序代码:=============================ParserDef.h================================ int kk;#define _KEY_WORD_END "waiting for your expanding"char * rwtab[]={"begin","if","then","while","do","end",_KEY_WORD_END};char input[255];char token[255]="";int p_input;int p_token;char ch;============================ParserAlgo.h================================ char prog[80];int syn,p,m,n,sum=0;void scaner() {m=0;for(n=0; n<8; n++) token[n]=NULL;ch=prog[p++];while(ch==' ') ch=prog[p++];if((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')) {while((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')||(ch>='0' && ch<='9')) {token[m++]=ch;ch=prog[p++];}token[m++]='\0';syn=10;p=p-1; //回退一个字符for(n=0; n<6; n++) {if(strcmp(token,rwtab[n])==0) {syn=n+1;break;}}} else if(ch>='0' && ch<='9') {sum=0;while(ch>='0' && ch<='9') {sum=sum*10+ch-'0';ch=prog[p++];}p=p-1;syn=11;} else {switch(ch) {case '<':m=0;token[m++]=ch;ch=prog[p];if(ch=='>') {syn=21;token[m++]=ch;} else if(ch=='=') {syn=22;token[m++]=ch;} else {syn=20;p=p-1;}p=p+1;token[m]='\0';break;case '>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=24;token[m++]=ch;} else {syn=23;p=p-1;}break;case ':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=18;token[m++]=ch;} else {syn=17;p=p-1;}break;case '+':syn=13;token[0]=ch;break;case '-':syn=14;token[0]=ch;break;case '*':syn=15;token[0]=ch;break;case '/':syn=16;token[0]=ch;break;case ';':syn=26;token[0]=ch;break;case '(':syn=27;token[0]=ch;break;case ')':syn=28;token[0]=ch;break;case '=':syn=25;token[0]=ch;break;case '#':syn=0;token[0]=ch;break;default:syn=-1;}}}============================ParserMain.cpp============================== #include<stdio.h>#include<stdlib.h>#include<string.h>#include"LexerDef.h"#include"ParserDef.h"#include"LexerAlgo.h"#include"ParserAlgo.h"void lrparser();void yucu();void statement();void expression();void term();void factor();void lrparser() {if (syn==1) { //beginscaner();yucu();if (syn==6) { //endscaner();if (syn==0 && kk==0) printf("success \n");} else {if(kk!=1) printf("error,lose 'end' ! \n");kk=1;}} else {printf("error,lose 'begin' ! \n");kk=1;}return;}void yucu() {statement();while(syn==26) {scaner();statement();}return;}void statement() {if (syn==10) { //为标识符scaner();if (syn==18) { //为:=scaner();expression();} else {printf("error!");kk=1;}} else {printf("error!");kk=1;}return;}void expression() {term();while(syn==13 || syn==14) {scaner();term();}return;}void term() {factor();while(syn==15 || syn==16) {scaner();factor();}return;}void factor() {if(syn==10 || syn==11)scaner(); //为标识符或整常数时,读下一个单词符号else if(syn==27) {scaner();expression();if(syn==28)scaner();else {printf(" ')' 错误\n");kk=1;}} else {printf("表达式错误\n");kk=1;}return;}void main() {p=0;printf("********************语法分析程序***************\n");printf("请输入源程序:\n");do {scanf("%c",&ch);prog[p++]=ch;} while(ch!='#');p=0;scaner();lrparser();printf("语法分析结束!\n");}四、解答下列问题(1)简述该语法分析器的算法思想。

编译原理词法分析和语法分析报告+代码[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 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码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所示。

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

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

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

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

语法分析器实验报告

语法分析器实验报告

语法分析器的设计实验报告一、实验内容语法分析程序用LL(1)语法分析方法。

首先输入定义好的文法书写文件(所用的文法可以用LL(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT集的交集是不是都为空,如果是,则输入文法符合LL(1)文法,可以进行分析。

对于文法:G[E]:E->E+T|TT->T*F|FF->i|(E)分析句子i+i*i是否符合文法。

二、基本思想1、语法分析器实现语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。

这里采用自顶向下的LL(1)分析方法。

语法分析程序的流程图如图5-4所示。

语法分析程序流程图该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;(5)由句型判别算法判断输入符号串是为该文法的句型。

三、核心思想该分析程序有15部分组成:(1)首先定义各种需要用到的常量和变量;(2)判断一个字符是否在指定字符串中;(3)读入一个文法;(4)将单个符号或符号串并入另一符号串;(5)求所有能直接推出&的符号;(6)求某一符号能否推出‘& ’;(7)判断读入的文法是否正确;(8)求单个符号的FIRST;(9)求各产生式右部的FIRST;(10)求各产生式左部的FOLLOW;(11)判断读入文法是否为一个LL(1)文法;(12)构造分析表M;(13)句型判别算法;(14)一个用户调用函数;(15)主函数;下面是其中几部分程序段的算法思想:1、求能推出空的非终结符集Ⅰ、实例中求直接推出空的empty集的算法描述如下:void emp(char c){ 参数c为空符号char temp[10];定义临时数组int i;for(i=0;i<=count-1;i++)从文法的第一个产生式开始查找{if 产生式右部第一个符号是空符号并且右部长度为1,then将该条产生式左部符号保存在临时数组temp中将临时数组中的元素合并到记录可推出&符号的数组empty中。

词法分析、语法分析、语义分析实例解析及实验报告

词法分析、语法分析、语义分析实例解析及实验报告

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

二、实验要求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 和sum 3.2 扫描子程序的算法思想:首先设置3个变量:①token 用来存放构成单词符号的字符串;②sum 用来存放整型单词;③syn 用来存放单词符号的种别码。

语法分析实验报告

语法分析实验报告

一、实验目的1. 了解语法分析的基本概念和原理。

2. 掌握语法分析的方法和步骤。

3. 提高对自然语言处理领域中语法分析技术的理解和应用能力。

二、实验内容1. 语法分析的基本概念语法分析是指对自然语言进行结构分析,将句子分解成词、短语和句子成分的过程。

通过语法分析,可以了解句子的结构、语义和语用信息。

2. 语法分析方法语法分析方法主要有两种:句法分析和语义分析。

(1)句法分析:句法分析是指根据语法规则,对句子进行分解和组合的过程。

常见的句法分析方法有:词法分析、短语结构分析、句法分析。

(2)语义分析:语义分析是指对句子进行分析,以揭示句子所表达的意义。

常见的语义分析方法有:词汇语义分析、句法语义分析、语用语义分析。

3. 语法分析步骤(1)词法分析:将句子中的单词进行分类,提取词性、词义和词形变化等特征。

(2)短语结构分析:将词法分析得到的词组进行分类,提取短语结构、短语成分和短语关系等特征。

(3)句法分析:根据短语结构分析的结果,将句子分解成句子成分,分析句子成分之间的关系。

(4)语义分析:根据句法分析的结果,分析句子所表达的意义。

三、实验过程1. 实验环境:Python 3.8,NLTK(自然语言处理工具包)。

2. 实验步骤:(1)导入NLTK库。

(2)加载句子数据。

(3)进行词法分析,提取词性、词义和词形变化等特征。

(4)进行短语结构分析,提取短语结构、短语成分和短语关系等特征。

(5)进行句法分析,分解句子成分,分析句子成分之间的关系。

(6)进行语义分析,揭示句子所表达的意义。

四、实验结果与分析1. 词法分析结果实验句子:“我喜欢吃苹果。

”词性标注:我/代词,喜欢/动词,吃/动词,苹果/名词。

2. 短语结构分析结果实验句子:“我喜欢吃苹果。

”短语结构:主语短语(我),谓语短语(喜欢吃苹果)。

3. 句法分析结果实验句子:“我喜欢吃苹果。

”句子成分:主语(我),谓语(喜欢),宾语(吃苹果)。

4. 语义分析结果实验句子:“我喜欢吃苹果。

编译原理——语法分析程序设计实验报告

编译原理——语法分析程序设计实验报告

实验二语法分析程序设计[实验目的]:1.了解语法分析的主要任务。

2.熟悉编译程序的编制。

[实验内容]:根据某文法,构造一基本递归下降语法分析程序。

给出分析过程中所用的产生式序列。

[实验要求]:1.选择一个文法,进行实验,可选的文法包括以下三个:P190 4.8P190 4.9P190 4.102.设计语法分析程序的输出形式(输出应为语法树或推导),一个可以参考的例子,可见图1。

3.编写递归下降语法分析程序(参考P148-149 Topdown parsing byrecursive-descent),实现基本的递归下降分析器,能够分析任给的符号串是否为该文法所定义的合法句子。

实验报告中要说明分析使用的方法。

4.根据所作业题选项e所给出的input,生成并输出分析过程中所用的产生式序列(show the actions of parser):1 产生式12 产生式2……5.自已设计一个不合法的句子,作为输出进行分析,给出结果。

[实验过程]本次实验选择的文法为P190 4.8lexp->atom|listatom->number|identifierlist->(lexp-seq)lexp-seq->lexp lexp-seq1.写出实现的算法,并画流程图。

本次实验采用递归下降算法,算法流程图如下图1-1:图1-1 算法流程图2.根据你选择的文法,分析左递归或左因子是否会影响本算法的结果。

会影响本算法的结果。

递归下降分析法要求的文法是LL(1)文法,需要消除左递归和左因子的影响。

如果存在左因子,对相同的字符跳转到不同的函数,无法实现递归。

3.列举实验设计过程中出现的问题及解决的方法(至少3条,选择实验中最困扰的问题)。

1).会多次输出accept/error结果解决方案:所有的递归函数返回类型为int,若accept返回1,error返回0,在main主函数中统一判断输出语句。

TEST语言--语法分析-词法分析实验报告

TEST语言--语法分析-词法分析实验报告

编译原理实验报告实验名称:分析调试语义分析程序TEST抽象机模拟器完整程序保证能用!!!!!一、实验目的通过分析调试TEST语言的语义分析和中间代码生成程序,加深对语法制导翻译思想的理解,掌握将语法分析所识别的语法范畴变换为中间代码的语义翻译方法。

二、实验设计程序流程图extern int TESTScan(FILE *fin,FILE *fout);FILE *fin,*fout; //用于指定输入输出文件的指针int main(){char szFinName[300];char szFoutName[300];printf("请输入源程序文件名(包括路径):");scanf("%s",szFinName);printf("请输入词法分析输出文件名(包括路径):");scanf("%s",szFoutName);if( (fin = fopen(szFinName,"r")) == NULL){printf("\n打开词法分析输入文件出错!\n");return 0;}if( (fout = fopen(szFoutName,"w")) == NULL){printf("\n创建词法分析输出文件出错!\n");return 0;}int es = TESTScan(fin,fout);fclose(fin);fclose(fout);if(es > 0)printf("词法分析有错,编译停止!共有%d个错误!\n",es);else if(es == 0){printf("词法分析成功!\n");int es = 0;es = TESTparse(szFoutName); //调语法分析if(es== true) printf("语法分析成功!\n");else printf("语法分析错误!\n");}elseprintf("词法分析出现未知错误!\n");}Parse.cpp#include<stdio.h>#include<string.h>#include<ctype.h>#include<conio.h>#include<vector>// functionbool TESTparse();bool compound_Stat();bool program();bool statement();bool expression_stat();bool expression();bool bool_expr();bool additive_expr();bool term();bool factor();bool if_stat();bool while_stat();bool for_stat();bool write_stat();bool read_stat();bool declaration_stat();bool declaration_list();bool statement_list();bool compound_stat();char token[20],token1[40]; //token保存单词符号,token1保存单词值FILE *fp; //用于指向输入文件的指针int EsLine = 0;typedef struct{int es;int line;}EsInf;std::vector<EsInf> StackEs;//语法分析程序void ProcessError(int es){EsInf temp;temp.es = es;temp.line = EsLine;StackEs.push_back(temp);}bool Read *tok, char *tok1){if(feof(fp))return false;fscanf(fp,"%s\t%s\n",tok,tok1);printf("%s\t%s\n",tok,tok1);EsLine++;return true;}bool TESTparse(char *p){bool es = true;if((fp=fopen(p,"r"))==NULL){printf("\n打开%s错误!\n",p);return false;}elseprogram();if(!feof(fp))ProcessError(9);fclose(fp);printf("=====语法分析结果!=====\n");if(StackEs.size() == 0){printf("语法分析成功!\n");return true;}else{int i;for(i = 0; i < StackEs.size(); i++){printf("在第%d行",StackEs[i].line);switch(StackEs[i].es){case 1:printf("缺少{!\n");break;case 2:printf("缺少}!\n");break;case 3:printf("缺少标识符!\n");break;case 4:printf("缺少分号!\n");break;case 5:printf("缺少(!\n");break;case 6:printf("缺少)!\n");break;case 7:printf("缺少操作数!\n");break;case 8:printf("文件为空!\n");break;case 9:printf("文件尾有多余字符!\n");break;case 10:printf("\n打开%s错误!\n",p);break;}}return false;}}//《程序》::={<声明序列><语句序列>}//program::={<declaration_;list><statement_list>}bool program(){bool es = true;if( Read) == false ){ProcessError(8); // 文件结束return false;}if(strcmp(token,"{")) //判断是否为‘{’ProcessError(1);if( Read) == false ) // 文件中仅有{ProcessError(2);es = declaration_list();if(es == false)return false;es = statement_list();if(es == false)return false;if(strcmp(token,"}")) //判断是否为‘}’ProcessError(2);return true;}//<声明序列>::=<声明序列><声明语句>|<声明语句>//<declaration>::=//<declaration_list><declaration_stat>|ε//改成<declaration_list>::={<declaration_stat>}bool declaration_list(){bool es = true;while (strcmp(token,"int")==0){es = declaration_stat();if(es == false)return false;}return es;}//<声明语句>::=int<变量>;//<declaration_stat>::=int ID;bool declaration_stat(){bool es = true;if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}if(strcmp(token,"ID"))ProcessError(3); //不是标识符if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}if(strcmp(token,";"))ProcessError(4);if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}return(es);}//<语句序列>::=<语句序列><语句>|ε//<statement_list>::=<statement_list><statement>|ε//改成<statement_list>::={<statement>}bool statement_list(){bool es = true;if(feof(fp))return false;while(strcmp(token,"}")){es = statement();if(es == false)return(es);}return(es);}//<语句>::=<if语句>|<while语句>|<for语句>|<read语句>// |<write语句>|<复合语句>|<表达式语句>//<statement>::=<if_sttat>|<while_stat>|<for_stat>// |<compound_stat>|<expression_stat>bool statement(){bool es = true;if(strcmp(token,"if")==0 )es=if_stat(); //<if语句>else if(strcmp(token,"while")==0 )es=while_stat(); //<while语句>else if(strcmp(token,"for")==0 )es=for_stat(); //<for语句>else if(strcmp(token,"read")==0 )es=read_stat(); //<read语句>else if(strcmp(token,"write")==0 )es=write_stat(); //<write语句>else if(strcmp(token,"{")==0 )es=compound_stat(); //<复合语句>else if(strcmp(token,"ID")==0 || strcmp(token,"NUM")==0 || strcmp(token,"(")==0 ) es=expression_stat(); //<表达式语句>return(es);}//<if语句>::=if(<表达式>)<语句>[else<语句>]//<if_stat>::=if(<expressiion>)<statement>[else<statement>] bool if_stat(){bool es = true; //ifif( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}if(strcmp(token,"("))ProcessError(5); //少左括号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es = expression();if(es == false)return(es);if(strcmp(token,")"))ProcessError(6); //少右括号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=statement();if(es == false)return(es);if(strcmp(token,"else")==0) //else部分处理{if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=statement();if(es == false)return(es);}return(es);}//<while语句>::=while(<表达式>)<语句>//<while_stat>::=while<espr><statement>bool while_stat(){bool es = true;if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}if(strcmp(token,"("))ProcessError(5); //少左括号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es = expression();if(es == false)return(es);if(strcmp(token,")"))ProcessError(6); //少右括号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es = statement();if(es == false)return es;return(es);}//<for语句>::=for(<表达式>;<表达式>;<表达式>)<语句>//<for_stat>::=for(<expression>;<expression>;<expression>)<statement> bool for_stat(){bool es = true;if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}if(strcmp(token,"(")) ProcessError(5); //少左括号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=expression();if(es == false) return (es);if(strcmp(token,";")) ProcessError(4); //少分号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=expression();if(es == false) return (es);if(strcmp(token,";")) ProcessError(4); //少分号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=expression();if(es == false) return (es);if(strcmp(token,")")) ProcessError(6); //少右括号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=statement();if(es == false) return (es);return es;}//<write_语句>::=write<表达式>;//<write_stat>::=write<expression>bool write_stat(){bool es = true;if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=expression();if(es == false) return (es);if(strcmp(token,";")) ProcessError(4); //少分号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}return es;}//<read_语句>::=read<变量>//<read_stat>::=read Id;bool read_stat(){bool es = true;if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}if(strcmp(token,"ID")) ProcessError(3); //少标识符if(strcmp(token,";")) ProcessError(4); //少分号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}return es;}//<复合语句>::{<语句序列>}//<compound_stat>::={<statement_list>}bool compound_stat() //复合语句函数{bool es = true;if( Read) == false )ProcessError(2); // 缺少}return false; // 文件结束}es = statement_list();if(es == false)return es;// -------------- new----------if(strcmp(token1,"}") != 0)ProcessError(2);else{if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}}// --------------- new ----------return es;}//<表达式语句>::=<<表达式>;|;//<expression_stat>::=<expression>;|;bool expression_stat(){bool es = true;if(strcmp(token,";")==0){if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}return es;es=expression();if(es == false) return es;if(strcmp(token,";")==0){if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}return es;}else{ProcessError(4); //少分号}return es;}//<表达式>::=<标识符>=<布尔表达式>|<布尔表达式>//<expression>::=ID=<bool_expr>|<bool_expr>bool expression(){bool es = true;int ;char token2[20],token3[40];if(strcmp(token,"ID")==0){(fp); //记住当前文件位置if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}if(strcmp(token2,"=")==0) //'='{if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=bool_expr();if(es == false) return es;}else{fseek(fp,); //若非‘=’,则文件指针回到‘=’前的标识符EsLine--;es=bool_expr();if(es == false) return es;}}else{es=bool_expr();if(es == false) return es;}return es;}//<布尔表达式>::= <算术表达式>[(>|<|>=|<=|==|!=)<算数表达式>]//<bool_expr>::= <additive_expr> [(>|<|>=|<=|==|!=)<additive_expr>]bool bool_expr(){bool es = true;es=additive_expr();if(es == false) return es;if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"!=")==0||strcmp(token,"==")==0){if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=additive_expr();if(es == false) return es;}return es;}//<算数表达式>::=<项>{(+|-)<项>}//<additive_expr>::=<term>{(+|-)<term>}bool additive_expr(){bool es = true;es=term();if(es == false) return es;while(strcmp(token,"+")==0||strcmp(token,"-")==0) {if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=term();if(es== false) return es;}return es;}//<项>::=<因子>{(*|/)<因子>}//<term>::=<factor>{(*|/)<factor>}bool term(){bool es = true;es=factor();if(es == false) return es;while(strcmp(token,"*")==0||strcmp(token,"/")==0){if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=factor();if(es == false) return es;}return es;}//<因子>::=(<表达式>)|<标识符>|<无符号整数>//<factor>::=(<expression>)|ID|NUMbool factor(){bool es = true;if(strcmp(token,"(")==0){if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}es=expression();if(es==false) return es;if(strcmp(token,")")) ProcessError(6); //少右括号if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}}else{if(strcmp(token,"ID")==0||strcmp(token,"NUM")==0){if( Read) == false ){ProcessError(2); // 缺少}return false; // 文件结束}return es;}else{ProcessError(7); //缺少操作数}}return es;}Scan.cpp#include<ctype.h>#include<cstring>#include<stdio.h>// 保留字#define KEYWORDNUM 8char *pKeyword[KEYWORDNUM] = {"if", "else", "for", "while", "do", "int", "read", "write"};// 单分界符char szSingleWord[50] = "+-(){};,:";// 双分界符char szDoubleWord[10] = "<>!";// 其他符char *szDivide = "/";char *szStar = "*";char *szEqual = "=";#define STATUSNUM 16 //状态个数#define DATANUM 10 // 数据流个数// 数据流类型typedef unsigned int DATA;#define OTHER 0 // wrong input#define LETTER 1 // 字母#define DIGIT 2 // 数字#define SINGLEWORD 3 // 单分界符#define DOUBLEWORD 4 // 双分界符#define DIVIDE 5 // /#define EQUAL 6 // =#define STAR 7 // *#define SPACE 8 // 空白#define 9// 状态类型typedef unsigned int STA TUS;#define NOSTATUS 0 // wrong input#define START 1#define CASE_ID 2#define END_ID 3#define CASE_NUM 4#define END_NUM 5#define CASE_SINGLE 6#define END_SINGLE 7#define CASE_DOUBLE 8#define CASE_DOUBLE2 9#define END_DOUBLE 10#define CASE_DIVIDE 11#define CASE_NOTE 12#define END_NOTE 13#define CASE_ERROR 14#define END_ERROR 15// 状态转换表// :到达终结状态的数据不保存在输出串中int reflect[STATUSNUM][DA TANUM] ={ //OTHER LETTER DIGIT SINGLEWORDDOUBLEWORD DIVIDE EQUAL STAR SPACE/*NOSTATUS*/ {NOSTATUS, NOSTA TUS, NOSTATUS, NOSTA TUS, NOSTATUS, NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS},/*START*/ {CASE_ERROR,CASE_ID, CASE_NUM,CASE_SINGLE,CASE_DOUBLE,CASE_DIVIDE,CASE_DOUBLE,CASE_SINGLE,STA RT, START},/*CADE_ID*/ {END_ID, CASE_ID, CASE_ID, END_ID, END_ID, END_ID, END_ID, END_ID, END_ID, END_ID},/*END_ID*/ {NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTATUS, NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS},/*CASE_NUM*/ {END_NUM, END_NUM, CASE_NUM, END_NUM, END_NUM, END_NUM, END_NUM, END_NUM, END_NUM, END_NUM},/*END_NUM*/ {NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS,NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS}, /*CASE_SINGLE*/ {END_SINGLE,END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE,END_SINGLE, END_SINGLE},/*END_SINGLE*/ {NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTATUS, NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS},/*CASE_DOUBLE*/ {END_SINGLE,END_SINGLE, END_SINGLE,END_SINGLE, END_SINGLE, END_SINGLE,CASE_DOUBLE2,END_SINGLE,END_SINGLE, END_SINGLE},/*CASE_DOUBLE2*/{END_DOUBLE,END_DOUBLE, END_DOUBLE,END_DOUBLE, END_DOUBLE, END_DOUBLE, END_DOUBLE,END_DOUBLE, END_DOUBLE, END_DOUBLE},/*END_DOUBLE*/ {NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS},/*CASE_DIVIDE*/ {END_SINGLE,END_SINGLE, END_SINGLE,END_SINGLE, END_SINGLE, END_SINGLE, END_SINGLE,CASE_NOTE, E ND_SINGLE, END_SINGLE},/*CASE_NOTE*/ {END_NOTE, E ND_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE, END_NOTE},/*END_NOTE*/ {NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTATUS, NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS},/*CASE_ERROR*/ {END_ERROR, END_ERROR, END_ERROR,END_ERROR, END_ERROR, END_ERROR, END_ERROR,END_ERROR, END_ERROR, END_ERROR},/*END_ERROR*/ {NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTATUS, NOSTATUS, NOSTA TUS, NOSTA TUS, NOSTA TUS, NOSTA TUS}};// 若在pString中找到word 则返回true,否则,返回falsebool SearchChar(char word,const char *pString){int n = strlen(pString);for(int i = 0; i < n; i++){if( word == pString[i])return true;}return false;}// 得到word的数据流类型DA TA GetDataByword(char word){if(word == EOF)return ;if(isalpha(word))return LETTER;if(isdigit(word))return DIGIT;if(SearchChar(word,szSingleWord))return SINGLEWORD;if(SearchChar(word,szDoubleWord))return DOUBLEWORD;if(SearchChar(word,szDivide))return DIVIDE;if(SearchChar(word,szEqual))return EQUAL;if(SearchChar(word,szStar))return STAR;if(isspace(word))return SPACE;return OTHER;}// 得到从status状态输入word后到达的状态STA TUS GetNextStatus(STATUS status, DA TA word){return reflect[status][word];}// 返回值表示错误个数。

语法分析器实验报告

语法分析器实验报告

杭州电子科技大学班级: 12052312 专业: 计算机科学与技术实验报告【实验名称】实验二语法分析一. 实验目的编写一个语法分析程序, 实现对词法分析程序所提供的单词序列的语法检查和结构分析。

二. 实验内容利用编程语言实现语法分析程序, 并对简单语言进行语法分析。

2.1 待分析的简单语言的语法用扩充的BNF表示如下:⑴<程序>: : =begin<语句串>end⑵<语句串>: : =<语句>{;<语句>}⑶<语句>: : =<赋值语句>⑷<赋值语句>: : =ID: =<表达式>⑸<表达式>: : =<项>{+<项> | -<项>}⑹<项>: : =<因子>{*<因子> | /<因子>⑺<因子>: : =ID | NUM | (<表达式>)2.2 实验要求说明输入单词串, 以“#”结束, 如果是文法正确的句子, 则输出成功信息, 打印“success”, 否则输出“error”。

例如:输入begin a:=9; x:=2*3; b:=a+x end #输出success!输入x:=a+b*c end #输出error测试以上输入的分析, 并完成实验报告。

2.3 语法分析程序的算法思想(1)主程序示意图如图2-1所示。

图2-1 语法分析主程序示意图(2)递归下降分析程序示意图如图2-2所示。

(3)语句串分析过程示意图如图2-3所示。

图2-3 语句串分析示意图图2-2 递归下降分析程序示意图(4)statement 语句分析程序流程如图2-4.2-5.2-6.2-7所示。

图2-4 statement 语句分析函数示意图 图2-5 expression 表达式分析函数示意图图2-7 factor 分析过程示意图三.个人心得一、 通过该实验, 主要有以下几方面收获: 二、 对实验原理有更深的理解。

LL(1)语法分析程序

LL(1)语法分析程序

《编译原理》上机实验报告题目:LL(1)语法分析程序1.设计要求(1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止;(2)输入已知文法,由程序自动生成它的LL(1)分析表;(3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。

2.分析该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;(5)由总控算法判断输入符号串是否为该文法的句型。

3.流程图4.源程序LL1语法分析程序#include<stdio.h>#include<string.h>int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){//int i;size_t i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;size_t(j)<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果'|'后的首符号和左部相同*/ for(j=n+1;size_t(j)<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果'|'后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;size_t(j)<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;size_t(j)<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/char grammer(char *t,char *n,char *left,char right[50][50]) {char vn[50],vt[50];char s;char p[50][50];printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的' ^ '一并并入目串;type=2,源串中的' ^ '不并入目串*/int i,j;for(i=0;size_t(i)<=strlen(s)-1;i++)if(type==2&&s[i]=='^');else{for(j=0;;j++){if(size_t(j)<strlen(d)&&s[i]==d[j])break;if(size_t(j)==strlen(d)){d[j]=s[i];d[j+1]='\0';break;}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由' ^ '推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出' ^ '********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)return(1);else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/ printf("\nerror1!");return(0);}for(j=0;size_t(j)<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为' ^ ',报错*/ printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;size_t(k)<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&size_t(k)<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&size_t(k)==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/{{if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(size_t(k)==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;size_t(n)<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;size_t(n)<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;size_t(j)<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;size_t(j)<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;size_t(j)<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;size_t(j)<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;size_t(i)<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;size_t(j)<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/ for(j=0;size_t(j)<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(size_t(k)==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("\nS:%s str:",S);for(p=j;size_t(p)<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();}}}5.执行结果(1)输入一个文法(2)输入一个符号串(3)再次输入一个符号串,然后退出程序。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
kk=1;
}
}
else { printf("Sorry,haven't got a 'begin'!\n");
kk=1;
}
return;
}
yucu()
{
statement(); /*调用函数statement();*/
while(syn==26)
{
scaner(); /*读下一个单词符号*/
if(syn!=6)
printf("\n----Please input the string end with '#':-------- \n");
do
{ scanf("%c",&ch);
prog[p++]=ch;
}while(ch!='#');
p=0;
scaner();
lrparser();
getch();
}
lrparser()

图2-7 factor分析过程示意图
三、语法分析程序的C语言程序源代码
#include "stdio.h"
#include "string.h"
char pro *rwtab[6]={"begin","if","then","while","do","end"};
xx理工大学
《编译原理》
题目语法分析程序
姓名:
学号:
班级:
一、实验目的
编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二、实验要求
利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
2.1待分析的简单语言的语法
用扩充的BNF表示如下:
⑴<程序>::=begin<语句串>end
}
return;
}
factor()
{ if((syn==10)||(syn==11)) scaner();
else if(syn==27)
{ scaner(); /*读下一个单词符号*/
expression(); /*调用函数statement();*/
if(syn==28)
scaner(); /*读下一个单词符号*/
{ scaner(); /*读下一个单词符号*/
term(); /*调用函数term();*/
}
return;
}
term()
{ factor();
while((syn==15)||(syn==16))
{ scaner(); /*读下一个单词符号*/
factor(); /*调用函数factor(); */
else { printf("Sorry,the error on '('\n");
kk=1;
}
}
else { printf("Sorry,the expression error!\n");
kk=1;
}
return;
}
scaner()
{ sum=0;
for(m=0;m<8;m++)token[m++]=NULL;
m=0;
ch=prog[p++];
while(ch==' ')ch=prog[p++];
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))
{ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
{
if(syn==1)
{
scaner(); /*读下一个单词符号*/
yucu(); /*调用yucu()函数;*/
if (syn==6)
{ scaner();
if ((syn==0)&&(kk==0))
printf("SUCCESS!\n");
}
else { if(kk!=1) printf("Sorry,the string haven't got an 'end'!\n");
int syn,p,m,n,sum;
int kk;
factor();
expression();
yucu();
term();
statement();
lrparser();
scaner();
main()
{
p=kk=0;
printf("\nGrade:05 Class:03 Name:Qiyubing Number:200507096 \n");
例如:
输入begin a:=9; x:=2*3; b:=a+x end #
输出success
输入x:=a+b*c end #
输出error
2.3语法分析程序的酸法思想
⑴主程序示意图如图2-1所示。
图2-1语法分析主程序示意图
⑵递归下降分析程序示意图如图2-2所示。
⑶语句串分析过程示意图如图2-3所示。








图2-2递归下降分析程序示意图图2-3语句串分析示意图
⑷statement语句分析程序流程如图2-4、2-5、2-6、2-7所示。


否是
图2-4 statement语句分析函数示意图图2-5 expression表达式分析函数示意图

否否





图2-6 term分析函数示意图

⑵<语句串>::=<语句>{;<语句>}
⑶<语句>::=<赋值语句>
⑷<赋值语句>::=ID:=<表达式>
⑸<表达式>::=<项>{+<项> | -<项>}
⑹<项>::=<因子>{*<因子> | /<因子>
⑺<因子>::=ID | NUM |(<表达式>)
2.2实验要求说明
输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。
{token[m++]=ch;
ch=prog[p++];
}
p--;
syn=10;
token[m++]='\0';
statement(); /*调用函数statement();*/
}
return;
}
statement()
{ if(syn==10)
{
scaner(); /*读下一个单词符号*/
if(syn==18)
{ scaner(); /*读下一个单词符号*/
expression(); /*调用函数statement();*/
}
else { printf("Sorry,the sing ':=' is wrong!\n");
kk=1;
}
}
else { printf("Sorry,wrong sentence!\n");
kk=1;
}
return;
}
expression()
{ term();
while((syn==13)||(syn==14))
相关文档
最新文档