1、上机练习二:语法分析一、根据上机练习一给出的PL/0语言扩充的巴克斯范式语法描述,利用递归下降的语法分析方法,编写PL/0语言的语法分析程序。要求:1. 对给出的PL/0语言进行分析,证明其可以进行自上而下的语法分析;2. 对block、proc、statement、condition、expression、term、factor进行分析,画出语法分析图,在此基础上描述这些子程序的设计思想;3. 具有一定的语法错误处理能力;二、源代码#include#include#include #include#includeusing namespace std;struct yufastring SY
2、M; /单词的类别string strToken; /用户所定义的标识符的值int l; /记录换行符的个数,即记录源文件的行数yufa0, yufa1, yufa21000;/yufa1用于保存各个单词,yufa1用于词法分析过程;yufa0主要用于语法分析;char ch;int mm= 0; /结构体数组下标int line = 0;/出错位置/char ch = ;string key15 = begin, end, if, then, else, while, write, read,do, call, const, var, procedure, program, odd ;/预设
3、保留字void prog();void block();void condecl();void _const();void vardecl();void proc();void body();void statement();void lexp();void exp();void term();void factor();void error0()cout program标示符出错 endl;exit(0); /出错即退出 void error1()cout 第 line 行缺少分号 endl;void error2()cout 第 line 行标识符(变量名)出错 endl;void err
4、or3()cout 第 line 常量未声明(缺少const) endl;void error4()cout 第 line 常量未赋值 endl;void error5()cout 第 line 赋值号出错或者缺少赋值号 endl;void error6()cout 第 line 变量未声明(缺少var) endl; void error7()cout 第 line 行缺少右括号 endl;void error8()cout 第 line 行缺少左括号 endl;void error9()cout 第 line 行缺少参数 endl;void error10()cout 第 line 行pro
5、cedure错误 endl;void error11()cout 第 line 行缺少end(begin与end不匹配) endl;void error12()cout 第 line 行缺少then(if与then不匹配) endl;void error13()cout 第 line 行缺少do(while与do不匹配) endl;void error14()cout 第 line 行调用过程缺少标识符 endl;void error15()cout 第 line 行缺少分号 endl;void error16()cout 第 line 行条件语句出错(缺少界符) endl;void prog
6、)/程序的递归子程序实现line+;if (yufa0.SYM = program)/ programmm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = biaoshifu) / ,即标识符 mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = ;)/;mm+; yufa0.SYM = yufa2mm.SYM;block();else error1();/缺少; else error2();/缺少标识符或者标识符错误 else error0();cout nn-语法分析结束-nn endl;void block()/程
7、序体的递归子程序实现, if (yufa0.SYM = const)condecl();if (yufa0.SYM = var)vardecl();if (yufa0.SYM = procedure)proc();body();void condecl()/常量说明的递归子程序实现, const ,;line+;if (yufa0.SYM = const) / constmm+; yufa0.SYM = yufa2mm.SYM;_const();/while (yufa0.SYM = ,)/,逗号mm+; yufa0.SYM = yufa2mm.SYM;_const();/if (yufa0.
8、SYM = ;)/;mm+; yufa0.SYM = yufa2mm.SYM;else error1();/缺少; else error3();/缺少常量定义const void _const()/常量, :=if (yufa0.SYM = biaoshifu) / mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = fuzhi)mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = didit)mm+; yufa0.SYM = yufa2mm.SYM;else error4();/常量未赋值 else error5();
9、/缺少赋值号,或者赋值号错误 else error2(); /缺少标识符 void vardecl()/变量说明的递归子程序实现, var ,;line+;if (yufa0.SYM = var) mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = biaoshifu) /mm+; yufa0.SYM = yufa2mm.SYM;while (yufa0.SYM = ,)/,mm+; yufa0.SYM = yufa2mm.SYM;/下一单词if (yufa0.SYM = biaoshifu) /mm+; yufa0.SYM = yufa2mm.SYM;e
10、lse error2();/缺少标识符即缺少变量 if (yufa0.SYM = ;)mm+; yufa0.SYM = yufa2mm.SYM;/下一单词else error2();else error6();/变量未声明 void proc()/ procedure (,);line+;if (yufa0.SYM = procedure) /proceduremm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = biaoshifu) / mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = () /(mm+; yufa0
11、SYM = yufa2mm.SYM;if (yufa0.SYM = biaoshifu)/ mm+; yufa0.SYM = yufa2mm.SYM;while (yufa0.SYM = ,)/ ,mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = biaoshifu)mm+; yufa0.SYM = yufa2mm.SYM;else error2();if (yufa0.SYM = )/ )mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = ;)/;mm+; yufa0.SYM = yufa2mm.SYM;/下一单
12、词-block();while (yufa0.SYM = ;)mm+; yufa0.SYM = yufa2mm.SYM;proc();else error1();/ 缺少; else error7();/括号不匹配 (右括号少) else error8();/左括号缺少 else error9();/缺少参数 else error10();/procedure错误 void body()/ begin ;endif (yufa0.SYM = begin)line+;mm+; yufa0.SYM = yufa2mm.SYM;statement();/while (yufa0.SYM = biao
13、shi) | (yufa0.SYM = if) | (yufa0.SYM = while) |/ (yufa0.SYM = call) | (yufa0.SYM = read) | (yufa0.SYM = write) | (yufa0.SYM = begin)/error1();/语句未到最后一条,缺少;while(yufa0.SYM = ;)mm+; yufa0.SYM = yufa2mm.SYM;statement();if (yufa0.SYM = end)line +;mm+; yufa0.SYM = yufa2mm.SYM;else error11();/缺少end与begin匹
14、配 else error12();/缺少begin/ := /语句 / |if then else / |while do / |call (,)/ |/ |read (,)/ |write (,)void statement()if (yufa0.SYM = biaoshifu) / := line+;mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = fuzhi)mm+; yufa0.SYM = yufa2mm.SYM;exp();else error5();/赋值号错误 else if (yufa0.SYM = if) /if then else l
15、ine+;mm+; yufa0.SYM = yufa2mm.SYM;lexp();if (yufa0.SYM = then) mm+; yufa0.SYM = yufa2mm.SYM;statement();if (yufa0.SYM = else)mm+; yufa0.SYM = yufa2mm.SYM;statement();else error12();/缺少then else if (yufa0.SYM = while)/while do line+;mm+; yufa0.SYM = yufa2mm.SYM;lexp();if (yufa0.SYM = do) mm+; yufa0.S
16、YM = yufa2mm.SYM;statement();else error13();/缺少do不匹配(while 与do 不匹配) else if (yufa0.SYM = call)/call (,)line+;mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = biaoshifu) /mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = () /mm+; yufa0.SYM = yufa2mm.SYM;while(yufa0.SYM = ,)mm+;yufa0.SYM = yufa2mm.SYM;exp(); i
17、f (yufa0.SYM = )mm+; yufa0.SYM = yufa2mm.SYM; else error7();/缺少右括号/此处不会报错,(,)因为表示可有可无的else error14();/调用过程缺少标识符 else if (yufa0.SYM = read)/read (,)line+;mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = () mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = biaoshifu) mm+; yufa0.SYM = yufa2mm.SYM;while (yufa0.S
18、YM = ,)mm+; yufa0.SYM = yufa2mm.SYM;if (yufa0.SYM = biaoshifu) mm+; yufa0.SYM = yufa2mm.SYM;else error2();/缺少标示符if (yufa0.SYM = ) mm+; yufa0.SYM = yufa2mm.SYM;else error7();/缺少右括号else error9();/read缺少参数 else error8();/缺少左括号else if (yufa0.SYM = write)/write (,)line+;mm+; yufa0.SYM = yufa2mm.SYM; if (
19、yufa0.SYM = () mm+; yufa0.SYM = yufa2mm.SYM; exp();while (yufa0.SYM = ,) mm+; yufa0.SYM = yufa2mm.SYM; exp();if (yufa0.SYM = ) mm+; yufa0.SYM = yufa2mm.SYM; else error7();/缺少右括号else error8();/缺少左括号else body();/ |odd / +|-/ /|()/ =|=/ +|-/ *|/ ll|d (注:l表示字母)/ ddvoid lexp()/ |odd if (yufa0.SYM = odd)m
20、m+;yufa0.SYM = yufa2mm.SYM;exp();else exp();if (yufa0.SYM = ge) | (yufa0.SYM = g) | (yufa0.SYM = l) | (yufa0.SYM = ne) | (yufa0.SYM = l) | (yufa0.SYM = =)mm+;yufa0.SYM = yufa2mm.SYM;exp();elseerror15();/条件语句出错,缺少界符 /odd是否存在? void exp()/ +|-while(yufa0.SYM = +) | (yufa0.SYM = -)mm+;yufa0.SYM = yufa2m
21、m.SYM;term();/ term();while (yufa0.SYM = +) | (yufa0.SYM = -)/ +|- mm+;yufa0.SYM = yufa2mm.SYM;term(); void term()/ factor();while (yufa0.SYM = *) | (yufa0.SYM = /)/ *|/ mm+;yufa0.SYM = yufa2mm.SYM;factor();/factor()void factor()/|()if (yufa0.SYM = biaoshi)mm+;yufa0.SYM = yufa2mm.SYM;else if (yufa0.
22、SYM = digit)mm+;yufa0.SYM = yufa2mm.SYM;else if (yufa0.SYM = ()mm+;yufa0.SYM = yufa2mm.SYM;exp();if (yufa0.SYM = )mm+;yufa0.SYM = yufa2mm.SYM;else error7(); /缺少右括号else error8();/缺少左括号 string Concat(char ch,string strToken) strToken += ch; return strToken;int IsLetter(char c ) /判断字母 if (c = a) | (c =
23、 A) return 1;else return 0;int IsDigit(char c) /判断数字 if (c = 0)&(c = 9) return 1;else return 0;int IsKey(string StrToken) /判断保留字 int i;for (i = 0; i15; i+) if (pare(StrToken) = 0) return 1;return 0;void getsym(fstream &file)string StrToken = ;/if (ch = | ch = t | ch = n) /滤掉空白字符/ch = file.get();if (
24、IsLetter(ch)while (IsLetter(ch) | IsDigit(ch)StrToken = Concat(ch,StrToken);ch = file.get();if (IsKey(StrToken)int i;for (i = 0; i15; i+)if (pare(StrToken) = 0)yufa1.SYM = keyi;yufa1.strToken = StrToken;elseyufa1.SYM = biaoshifu;yufa1.strToken = StrToken; if (IsDigit(ch) StrToken = ; while(IsDigit(c
25、h) StrToken = Concat(ch,StrToken);ch = file.get(); if(IsLetter(ch) /数字后面跟字母,错误词法 while(IsLetter(ch)|IsDigit(ch)StrToken = Concat(ch,StrToken);ch = file.get();cout 词法错误!(数字后面跟字母) StrToken endl;elseyufa1.SYM = digit;yufa1.strToken = StrToken;else switch (ch)case+:yufa1.SYM = +;yufa1.strToken = +;ch =
26、file.get();break;case-:yufa1.SYM = -;yufa1.strToken = -;ch = file.get();break;case*:yufa1.SYM = *;yufa1.strToken = *;ch = file.get();break;case/:yufa1.SYM = /;yufa1.strToken = /;ch = file.get();break;case(:yufa1.SYM = (;yufa1.strToken = (;ch = file.get();break;case):yufa1.SYM = );yufa1.strToken = );
27、ch = file.get();break;case=:yufa1.SYM = =;yufa1.strToken = =;ch = file.get();break;case;:yufa1.SYM = ;yufa1.strToken = ;ch = file.get();break;case,:yufa1.SYM = ,;yufa1.strToken = ,;ch = file.get();break;case:ch = file.get();if (ch = =)yufa1.SYM = fuzhi;yufa1.strToken = :=;elsecout : 词法错误(:后面没有=) :ch
28、 = file.get();if (ch = =)yufa1.SYM = ge;yufa1.strToken = =;elseyufa1.SYM = g;yufa1.strToken = ;ch = file.get();break;case:ch = file.get();if (ch = =)yufa1.SYM = le;yufa1.strToken = )yufa1.SYM = ne;yufa1.strToken = ;elseyufa1.SYM = l;yufa1.strToken = ;ch = file.get();break;int main()int nn = 0;string
29、 StrToken = ;fstream file;char ch;int ll;char filename30;cout 请输入源文件名:;cin.getline(filename, 30);file.open(filename, ios:in);if (!file)cout 文件打开失败!nn;exit(0);yufa2nn.l = 0;cout n-词法分析- endl;/ch = file.get();while (!file.eof()/if (ch = | ch = t | ch = n) /滤掉空白字符/ch = file.get();/ch = file.get();if (c
30、h = | ch = t)ch=file.get();while (ch = n)ll +;ch = file.get();getsym(file);nn+;yufa2nn.SYM = yufa1.SYM;yufa2nn.strToken = yufa1.strToken;yufa2nn.l = ll;/cout.setf(ios:left);cout ( setw(2) nn ) ;cout setw(13) yufa2nn.SYM setw(9) yufa2nn.strToken n;cout setw(13) yufa1.SYM setw(9) yufa1.strToken n;/nn+;/yufa2nn.SYM = the_end;/完成/yufa2nn.strToken = the_end;file.close();/cout nnn-语法分析- endl;yufa0.SYM = yufa2mm.SYM;/yufa0.SYM = yufa1.SYM;prog();return 0;