编译原理语法分析报告
- 格式:doc
- 大小:23.71 KB
- 文档页数:17
编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
实验3 语义分析实验报告一、实验目的二、通过上机实习, 加深对语法制导翻译原理的理解, 掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
三、实验要求四、采用递归下降语法制导翻译法, 对算术表达式、赋值语句进行语义分析并生成四元式序列。
五、算法思想1.设置语义过程。
(1)emit(char *result,char *ag1,char *op,char *ag2)该函数的功能是生成一个三地址语句送到四元式表中。
四元式表的结构如下:struct{ char result[8];char ag1[8];char op[8];char ag2[8];}quad[20];(2) char *newtemp()该函数回送一个新的临时变量名, 临时变量名产生的顺序为T1, T2, …char *newtemp(void){ char *p;char m[8];p=(char *)malloc(8);k++;itoa(k,m,10);strcpy(p+1,m);p[0]=’t’;return(p);}六、 2.函数lrparser 在原来语法分析的基础上插入相应的语义动作: 将输入串翻译成四元式序列。
在实验中我们只对表达式、赋值语句进行翻译。
源程序代码:#include<stdio.h>#include<string.h>#include<iostream.h>#include<stdlib.h>struct{char result[12];char ag1[12];char op[12];char ag2[12];}quad;char prog[80],token[12];char ch;int syn,p,m=0,n,sum=0,kk; //p是缓冲区prog的指针, m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"};void scaner();char *factor(void);char *term(void);char *expression(void);int yucu();void emit(char *result,char *ag1,char *op,char *ag2);char *newtemp();int statement();int k=0;void emit(char *result,char *ag1,char *op,char *ag2){strcpy(quad.result,result);strcpy(quad.ag1,ag1);strcpy(quad.op,op);strcpy(quad.ag2,ag2);cout<<quad.result<<"="<<quad.ag1<<quad.op<<quad.ag2<<endl;}char *newtemp(){char *p;char m[12];p=(char *)malloc(12);k++;itoa(k,m,10);strcpy(p+1,m);p[0]='t';return (p);}void scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;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--;syn=11;if(sum>32767)syn=-1;}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=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}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=25;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=0;token[0]=ch;break; default: syn=-1;break;}}int lrparser(){//cout<<"调用lrparser"<<endl;int schain=0;kk=0;if(syn==1){scaner();schain=yucu();if(syn==6){scaner();if(syn==0 && (kk==0))cout<<"success!"<<endl;}else{if(kk!=1)cout<<"缺end!"<<endl;kk=1;}}else{cout<<"缺begin!"<<endl;kk=1;}return(schain);}int yucu(){// cout<<"调用yucu"<<endl;int schain=0;schain=statement();while(syn==26){scaner();schain=statement();}return(schain);}int statement(){//cout<<"调用statement"<<endl;char *eplace,*tt;eplace=(char *)malloc(12);tt=(char *)malloc(12);int schain=0;switch(syn){case 10:strcpy(tt,token);scaner();if(syn==18){scaner();strcpy(eplace,expression());emit(tt,eplace,"","");schain=0;}else{cout<<"缺少赋值符!"<<endl;kk=1;}return(schain);break;}return(schain);}char *expression(void){char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt =(char *)malloc(12);strcpy(eplace,term ()); //调用term分析产生表达式计算的第一项eplacewhile((syn==15)||(syn==16)){if(syn==15)strcpy(tt,"+");else strcpy(tt,"-");scaner();strcpy(ep2,term()); //调用term分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *term(void){// cout<<"调用term"<<endl;char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt=(char *)malloc(12);strcpy(eplace,factor());while((syn==13)||(syn==14)){if(syn==13)strcpy(tt,"*");else strcpy(tt,"/");scaner();strcpy(ep2,factor()); //调用factor分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *factor(void){char *fplace;fplace=(char *)malloc(12);strcpy(fplace,"");if(syn==10){strcpy(fplace,token); //将标识符token的值赋给fplacescaner();}else if(syn==11){itoa(sum,fplace,10);scaner();}else if(syn==27){scaner();fplace=expression(); //调用expression分析返回表达式的值if(syn==28)scaner();else{cout<<"缺)错误!"<<endl;kk=1;}}else{cout<<"缺(错误!"<<endl;kk=1;}return(fplace);}void main(){p=0;cout<<"**********语义分析程序**********"<<endl;cout<<"Please input string:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();}七、结果验证1、给定源程序begin a:=2+3*4; x:=(a+b)/c end#输出结果2、源程序begin a:=9; x:=2*3-1; b:=(a+x)/2 end#输出结果八、收获(体会)与建议通过此次实验, 让我了解到如何设计、编制并调试语义分析程序, 加深了对语法制导翻译原理的理解, 掌握了将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
国开电大编译原理实验4:语法分析实
验报告
1. 实验目的
本实验的目的是研究和掌握语法分析的原理和实现方法。
2. 实验内容
本次实验主要包括以下内容:
- 设计并实现自顶向下的LL(1)语法分析器;
- 通过语法分析器对给定的输入串进行分析,并输出相应的分析过程;
- 编写测试用例,验证语法分析器的正确性。
3. 实验步骤
3.1 设计LL(1)文法
首先,根据实验要求和给定的语法规则,设计LL(1)文法。
3.2 构建预测分析表
根据所设计的LL(1)文法,构建预测分析表。
3.3 实现LL(1)语法分析器
根据预测分析表,实现自顶向下的LL(1)语法分析器。
3.4 对输入串进行分析
编写程序,通过LL(1)语法分析器对给定的输入串进行分析,并输出相应的分析过程和结果。
3.5 验证语法分析器的正确性
设计多组测试用例,包括正确的语法串和错误的语法串,验证语法分析器的正确性和容错性。
4. 实验结果
经过实验,我们成功设计并实现了自顶向下的LL(1)语法分析器,并对给定的输入串进行了分析。
实验结果表明该语法分析器具有较好的准确性和容错性。
5. 实验总结
通过本次实验,我们对语法分析的原理和实现方法有了更深入的了解。
同时,我们也学会了如何设计并实现自顶向下的LL(1)语
法分析器,并验证了其正确性和容错性。
这对于进一步研究编译原理和深入理解编程语言的语法结构具有重要意义。
6. 参考资料
- 《编译原理与技术》
- 课程实验文档及代码。
编译原理实验实验二语法分析器实验二:语法分析实验一、实验目的根据给出的文法编制LR(1)分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对LR(1)分析法的理解。
二、实验预习提示1、LR(1)分析法的功能LR(1)分析法的功能是利用LR(1)分析表,对输入符号串自下而上的分析过程。
2、LR(1)分析表的构造及分析过程。
三、实验内容对已给语言文法,构造LR(1)分析表,编制语法分析程序,要求将错误信息输出到语法错误文件中,并输出分析句子的过程(显示栈的内容);实验报告必须包括设计的思路,以及测试报告(输入测试例子,输出结果)。
语法分析器一、功能描述:语法分析器,顾名思义是用来分析语法的。
程序对给定源代码先进行词法分析,再根据给定文法,判断正确性。
此次所写程序是以词法分析器为基础编写的,由于代码量的关系,我们只考虑以下输入为合法:数字自定义变量+ * ()$作为句尾结束符。
其它符号都判定为非法。
二、程序结构描述:词法分析器:class wordtree;类,内容为字典树的创建,插入和搜索。
char gettype(char ch):类型处理代入字串首字母ch,分析字串类型后完整读入字串,输出分析结果。
因读取过程会多读入一个字母,所以函数返回该字母进行下一次分析。
bool isnumber(char str[]):判断是否数字代入完整“数字串”str,判断是否合法数字,若为真返回1,否则返回0。
bool isoperator(char str[]):判断是否关键字代入完整“关键字串”str,搜索字典树判断是否存在,若为存在返回1,否则返回0。
语法分析器:int action(int a,char b):代入当前状态和待插入字符,查找转移状态或归约。
node2 go(int a):代入当前状态,返回归约结果和长度。
void printstack():打印栈。
int push(char b):将符号b插入栈中,并进行归约。
专题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:出错标识符首字符所在位置返回值:是否成功解析。
一、实验目的1. 理解编译原理的基本概念和原理。
2. 掌握编译器的各个阶段及其实现方法。
3. 能够运用编译原理的知识解决实际问题。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 20194. 实验内容:词法分析、语法分析、语义分析、中间代码生成、代码优化、目标代码生成三、实验内容1. 词法分析(1)实验目的:实现一个简单的词法分析器,将源代码中的字符序列转换为词法符号序列。
(2)实验步骤:1)定义词法符号类型,包括标识符、关键字、运算符、常量等。
2)设计词法分析器算法,对源代码进行遍历,将字符序列转换为词法符号序列。
3)实现词法分析器程序,输出词法符号序列。
(3)实验结果:输入源代码:int a = 10;输出词法符号序列:{<int, int>, <a, a>, <=, =>, <10, 10>, <;, ;>}2. 语法分析(1)实验目的:实现一个简单的语法分析器,将词法符号序列转换为抽象语法树(AST)。
(2)实验步骤:1)定义语法规则,包括产生式、非终结符、终结符等。
2)设计语法分析算法,根据语法规则对词法符号序列进行解析,生成AST。
3)实现语法分析器程序,输出AST。
(3)实验结果:输入词法符号序列:{<int, int>, <a, a>, <=, =>, <10, 10>, <;, ;>}输出AST:```AST:- ExpressionStatement- Expression- BinaryExpression- Identifier: a- Operator: =- Constant: 10```3. 语义分析(1)实验目的:实现语义分析器,对AST进行语义检查,确保程序的正确性。
(2)实验步骤:1)定义语义规则,包括类型检查、作用域检查等。
编译原理语法分析器实验报告西安邮电大学编译原理实验报告学院名称:计算机学院****:***实验名称:语法分析器的设计与实现班级:计科1405班学号:04141152时间:2017年5月12日把SELECT (i)存放到temp中结果返回1;1.构建好的预测分析表2.语法分析流程图一.实验结果正确运行结果:错误运行结果:二.设计技巧和心得体会这次实验编写了一个语法分析方法的程序,但是在LL(1)分析器的编写中我只达到了最低要求,就是自己手动输入的select集,first集,follow集然后通过程序将预测分析表构造出来,然后自己编写总控程序根据分析表进行分析。
通过本次试验,我能够设计一个简单的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
还能选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序。
三.源代码package com.LL1;import java.util.ArrayDeque;import java.util.Deque;/*** LL1文法分析器,已经构建好预测分析表,采用Deque实现* Created by HongWeiPC on 2017/5/12.*/public class LL1_Deque {//预测分析表private String[][] analysisTable = new String[][]{{"TE'", "", "", "TE'", "", ""},{"", "+TE'", "", "", "ε", "ε"},{"FT'", "", "", "FT'", "", ""},{"", "ε", "*FT'", "", "ε", "ε"},{"i", "", "", "(E)", "", ""}};//终结符private String[] VT = new String[]{"i", "+", "*", "(", ")", "#"};//非终结符private String[] VN = new String[]{"E", "E'", "T", "T'", "F"};//输入串strTokenprivate StringBuilder strToken = new StringBuilder("i*i+i");//分析栈stackprivate Deque<String> stack = new ArrayDeque<>();//shuru1保存从输入串中读取的一个输入符号,当前符号private String shuru1 = null;//X中保存stack栈顶符号private String X = null;//flag标志预测分析是否成功private boolean flag = true;//记录输入串中当前字符的位置private int cur = 0;//记录步数private int count = 0;public static void main(String[] args) {LL1_Deque ll1 = new LL1_Deque();ll1.init();ll1.totalControlProgram();ll1.printf();}//初始化private void init() {strToken.append("#");stack.push("#");System.out.printf("%-8s %-18s %-17s %s\n", "步骤", "符号栈", "输入串", "所用产生式");stack.push("E");curCharacter();System.out.printf("%-10d %-20s %-20s\n", count, stack.toString(), strToken.substring(cur, strToken.length()));}//读取当前栈顶符号private void stackPeek() {X = stack.peekFirst();}//返回输入串中当前位置的字母private String curCharacter() {shuru1 = String.valueOf(strToken.charAt(cur));return shuru1;}//判断X是否是终结符private boolean XisVT() {for (int i = 0; i < (VT.length - 1); i++) {if (VT[i].equals(X)) {return true;}}return false;}//查找X在非终结符中分析表中的横坐标private String VNTI() {int Ni = 0, Tj = 0;for (int i = 0; i < VN.length; i++) {if (VN[i].equals(X)) {Ni = i;}}for (int j = 0; j < VT.length; j++) {if (VT[j].equals(shuru1)) {Tj = j;}}return analysisTable[Ni][Tj];}//判断M[A,a]={X->X1X2...Xk}//把X1X2...Xk推进栈//X1X2...Xk=ε,不推什么进栈private boolean productionType() {return VNTI() != "";}//推进stack栈private void pushStack() {stack.pop();String M = VNTI();String ch;//处理TE' FT' *FT'特殊情况switch (M) {case "TE'":stack.push("E'");stack.push("T");break;case "FT'":stack.push("T'");stack.push("F");break;case "*FT'":stack.push("T'");stack.push("F");stack.push("*");break;case "+TE'":stack.push("E'");stack.push("T");stack.push("+");break;default:for (int i = (M.length() - 1); i >= 0; i--) {ch = String.valueOf(M.charAt(i));stack.push(ch);}break;}System.out.printf("%-10d %-20s %-20s %s->%s\n", (++count), stack.toString(), strToken.substring(cur, strToken.length()), X, M);}//总控程序private void totalControlProgram() {while (flag) {stackPeek(); //读取当前栈顶符号令X=栈顶符号if (XisVT()) {if (X.equals(shuru1)) {cur++;shuru1 = curCharacter();stack.pop();System.out.printf("%-10d %-20s %-20s \n", (++count), stack.toString(), strToken.substring(cur, strToken.length()));} else {ERROR();}} else if (X.equals("#")) {if (X.equals(shuru1)) {flag = false;} else {ERROR();}} else if (productionType()) {if (VNTI().equals("")) {ERROR();} else if (VNTI().equals("ε")) {stack.pop();System.out.printf("%-10d %-20s %-20s %s->%s\n", (++count), stack.toString(), strToken.substring(cur, strToken.length()), X, VNTI());} else {pushStack();}} else {ERROR();}}}//出现错误private void ERROR() {System.out.println("输入串出现错误,无法进行分析");System.exit(0);}//打印存储分析表private void printf() {if (!flag) {System.out.println("****分析成功啦!****");} else {System.out.println("****分析失败了****");}}}。
词法分析一、实验目的二、设计、编制并调试一个词法分析程序, 加深对词法分析原理的理解。
三、实验要求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 用来存放单词符号的种别码。
上海电力学院编译原理课程实验报告实验名称:实验三自下而上语法分析及语义分析院系:计算机科学与技术学院专业年级:学生姓名:学号:指导老师:实验日期:实验三自上而下的语法分析一、实验目的:通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:●LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
●编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义简单的表达式文法如下:(1)E->E+T(2)E->E-T(3)E->T(4)T->T*F(5)T->T/F(6)T->F(7)F->(E)(8)F->i五、处理程序例和处理结果例示例1:20133191*(20133191+3191)+ 3191#六、源代码【cifa.h】//cifa.h#include<string> using namespace std;//单词结构定义struct WordType{int code;string pro;};//函数声明WordType get_w();void getch();void getBC();bool isLetter();bool isDigit();void retract();int Reserve(string str); string concat(string str); 【Table.action.h】//table_action.hclass Table_action{int row_num,line_num;int lineName[8];string tableData[16][8]; public:Table_action(){row_num=16;line_num=8;lineName[0]=30;lineName[1]=7;lineName[2]=13;lineName[3]=8;lineName[4]=14;lineName[5]=1;lineName[6]=2;lineName[7]=15;lineName[8]=0;for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++) tableData[m][n]="";tableData[0][0]="S5";tableData[0][5]="S4";tableData[1][1]="S6";tableData[1][2]="S12";tableData[1][7]="acc";tableData[2][1]="R3";tableData[2][2]="R3";tableData[2][3]="S7";tableData[2][6]="R3"; tableData[2][7]="R3"; tableData[3][1]="R6"; tableData[3][2]="R6"; tableData[3][3]="R6"; tableData[3][4]="R6"; tableData[3][6]="R6"; tableData[3][7]="R6"; tableData[4][0]="S5"; tableData[4][5]="S4"; tableData[5][1]="R8"; tableData[5][2]="R8"; tableData[5][3]="R8"; tableData[5][4]="R8"; tableData[5][6]="R8"; tableData[5][7]="R8"; tableData[6][0]="S5"; tableData[6][5]="S4"; tableData[7][0]="S5"; tableData[7][5]="S4"; tableData[8][1]="S6";tableData[8][6]="S11"; tableData[9][1]="R1"; tableData[9][2]="R1"; tableData[9][3]="S7"; tableData[9][4]="S13"; tableData[9][6]="R1"; tableData[9][7]="R1"; tableData[10][1]="R4"; tableData[10][2]="R4"; tableData[10][3]="R4"; tableData[10][4]="R4"; tableData[10][6]="R4"; tableData[10][7]="R4"; tableData[11][1]="R7"; tableData[11][2]="R7"; tableData[11][3]="R7"; tableData[11][4]="R7"; tableData[11][6]="R7"; tableData[11][7]="R7"; tableData[12][0]="S5"; tableData[12][5]="S4";tableData[13][5]="S4";tableData[14][1]="R2";tableData[14][2]="R2";tableData[14][3]="S7";tableData[14][4]="S13";tableData[14][6]="R2";tableData[14][7]="R2";tableData[15][1]="R5";tableData[15][2]="R5";tableData[15][3]="R5";tableData[15][4]="R5";tableData[15][5]="R5";tableData[15][6]="R5";tableData[15][7]="R5";}string getCell(int rowN,int lineN){int row=rowN;int line=getLineNumber(lineN);if(row>=0&&row<row_num&&line>=0&&line<=line_num) return tableData[row][line];elsereturn"";}int getLineNumber(int lineN){for(int i=0;i<line_num;i++)if(lineName[i]==lineN)return i;return -1;}};【Table_go.h】//table_go.hclass Table_go{int row_num,line_num;//行数、列数string lineName[3];int tableData[16][3];public:Table_go(){row_num=16;line_num=3;lineName[0]="E";lineName[1]="T";lineName[2]="F";for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++)tableData[m][n]=0;tableData[0][0]=1;tableData[0][1]=2;tableData[0][2]=3;tableData[4][0]=8;tableData[4][1]=2;tableData[4][2]=3;tableData[6][1]=9;tableData[6][2]=3;tableData[7][2]=10;tableData[12][1]=14;tableData[12][2]=3;tableData[13][2]=15;}int getCell(int rowN,string lineNa){int row=rowN;int line=getLineNumber(lineNa);if(row>=0&&row<row_num&&line<=line_num) return tableData[row][line];elsereturn -1;}int getLineNumber(string lineNa){for(int i=0;i<line_num;i++)if(lineName[i]==lineNa)return i;return -1;}};【Stack_num.h】class Stack_num{int i; //栈顶标记int *data; //栈结构public:Stack_num() //构造函数{data=new int[100];i=-1;}int push(int m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{i--;return data[i+1];}int getTop() //返回栈顶{return data[i];}~Stack_num() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【Stack_str.h】class Stack_str{int i; //栈顶标记string *data; //栈结构public:Stack_str() //构造函数{data=new string[50];i=-1;}int push(string m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{data[i]="";i--;return i;}string getTop() //返回栈顶{return data[i];}~Stack_str() //析构函数{delete []data;int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【cifa.cpp】//cifa.cpp#include<iostream>#include<string>#include"cifa.h"using namespace std;//关键字表和对应的编码stringcodestring[10]={"main","int","if","then","else","return","void","cout","endlint codebook[10]={26,21,22,23,24,25,27,28,29};//全局变量char ch;int flag=0;/*//主函数int main(){WordType word;cout<<"请输入源程序序列:";word=get_w();while(word.pro!="#")//#为自己设置的结束标志{cout<<"("<<word.code<<","<<"“"<<word.pro<<"”"<<")"<<endl;word=get_w();};return 0;}*/WordType get_w(){string str="";int code;WordType wordtmp;getch();//读一个字符getBC();//去掉空白符if(isLetter()){ //以字母开头while(isLetter()||isDigit()){str=concat(str);getch();}retract();code=Reserve(str);if(code==-1){wordtmp.code=0;wordtmp.pro=str;}//不是关键字else{wordtmp.code=code;wordtmp.pro=str;}//是关键字}else if(isDigit()){ //以数字开头while(isDigit()){str=concat(str);getch();}retract();wordtmp.code=30;wordtmp.pro=str;}else if(ch=='(') {wordtmp.code=1;wordtmp.pro="(";} else if(ch==')') {wordtmp.code=2;wordtmp.pro=")";} else if(ch=='{') {wordtmp.code=3;wordtmp.pro="{";} else if(ch=='}') {wordtmp.code=4;wordtmp.pro="}";} else if(ch==';') {wordtmp.code=5;wordtmp.pro=";";} else if(ch=='=') {wordtmp.code=6;wordtmp.pro="=";} else if(ch=='+') {wordtmp.code=7;wordtmp.pro="+";} else if(ch=='*') {wordtmp.code=8;wordtmp.pro="*";} else if(ch=='>') {wordtmp.code=9;wordtmp.pro=">";} else if(ch=='<') {wordtmp.code=10;wordtmp.pro="<";} else if(ch==',') {wordtmp.code=11;wordtmp.pro=",";} else if(ch=='\'') {wordtmp.code=12;wordtmp.pro="\'";} else if(ch=='-') {wordtmp.code=13;wordtmp.pro="-";} else if(ch=='/') {wordtmp.code=14;wordtmp.pro="/";} else if(ch=='#') {wordtmp.code=15;wordtmp.pro="#";} else if(ch=='|') {wordtmp.code=16;wordtmp.pro="|";}else {wordtmp.code=100;wordtmp.pro=ch;}return wordtmp;}void getch(){if(flag==0) //没有回退的字符ch=getchar();else //有回退字符,用回退字符,并设置标志flag=0;}void getBC(){while(ch==' '||ch=='\t'||ch=='\n')ch=getchar();}bool isLetter(){if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return true;elsereturn false;}bool isDigit(){if(ch>='0'&&ch<='9')return true;elsereturn false;}string concat(string str){return str+ch;}void retract(){flag=1;}int Reserve(string str){int i;for(i=0;i<=8;i++){if(codestring[i]==str) //是某个关键字,返回对应的编码return codebook[i];}if(i==9) //不是关键字return -1;}【LR.cpp】#include<iostream>#include<string>#include<cstdlib>#include"cifa.h"#include"stack_num.h"#include"stack_str.h"#include"table_action.h"#include"table_go.h"using namespace std;void process(){int stepNum=1;int topStat;Stack_num statusSTK; //状态栈Stack_str symbolSTK; //符号栈Stack_num valueSTK; //值栈WordType word;Table_action actionTAB; //行为表Table_go goTAB; //转向表cout<<"请输入源程序,以#结束:";word=get_w();//总控程序初始化操作symbolSTK.push("#");statusSTK.push(0);valueSTK.push(0);cout<<"步骤\t状态栈\t符号栈\t值栈\t当前词\t动作\t转向"<<endl;//分析while(1){topStat=statusSTK.getTop(); //当前状态栈顶string act=actionTAB.getCell(topStat,word.code);//根据状态栈顶和当前单词查到的动作//输出cout<<stepNum++<<"\t";statusSTK.outStack(); cout<<"\t";symbolSTK.outStack(); cout<<"\t";valueSTK.outStack(); cout<<"\t";cout<<word.pro<<"\t";//行为为“acc”,且当前处理的单词为#,且状态栈里就两个状态//说明正常分析结束if(act=="acc"&&word.pro=="#"&&statusSTK.topNumber()==1){cout<<act<<endl;cout<<"分析成功!"<<endl;cout<<"结果为:"<<valueSTK.getTop()<<endl;return;}//读到act表里标记为错误的单元格else if(act==""){cout<<endl<<"不是文法的句子!"<<endl;cout<<"错误的位置为单词"<<word.pro<<"附近。
上机练习二:语法分析一、根据上机练习一给出的PL/0语言扩充的巴克斯式语法描述,利用递归下降的语法分析方法,编写PL/0语言的语法分析程序。
要求:1.对给出的PL/0语言进行分析,证明其可以进行自上而下的语法分析;2.对block、proc、statement、condition、expression、term、factor进行分析,画出语法分析图,在此基础上描述这些子程序的设计思想;3.具有一定的语法错误处理能力;二、源代码#include<iostream>#include<string>#include <fstream>#include<iomanip>#include<stdlib.h>using namespace std;struct yufa{string SYM; //单词的类别string strToken; //用户所定义的标识符的值int l; //记录换行符的个数,即记录源文件的行数}yufa0, yufa1, yufa2[1000];//yufa1用于保存各个单词,yufa1用于词法分析过程;yufa0主要用于语法分析;char ch;int mm= 0; //结构体数组下标int line = 0;//出错位置//char ch = ' ';string key[15] = { "begin", "end", "if", "then", "else", "while", "write", "read","do", "call", "const", "var", "procedure", "program", "odd" };//预设保留字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 error3(){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 << "行procedure错误" << 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()//程序的递归子程序实现{line++;if (yufa0.SYM == "program")// program{mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "biaoshifu") // <id>,即标识符{mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == ";")//;{mm++; yufa0.SYM = yufa2[mm].SYM;block();}else error1();//缺少;}else error2();//缺少标识符或者标识符错误}else error0();cout << "\n\n--------------------------语法分析结束------------------------\n\n" << endl;}void block()//程序体的递归子程序实现,<block> →[<condecl>][<vardecl>][<proc>]<body> {if (yufa0.SYM == "const")condecl();if (yufa0.SYM == "var")vardecl();if (yufa0.SYM == "procedure")proc();body();}void condecl()//常量说明的递归子程序实现,<condecl> →const <const>{,<const>};{line++;if (yufa0.SYM == "const") // const{mm++; yufa0.SYM = yufa2[mm].SYM;_const();//<const>while (yufa0.SYM == ",")//,逗号{mm++; yufa0.SYM = yufa2[mm].SYM;_const();}//<const>if (yufa0.SYM == ";")//;{mm++; yufa0.SYM = yufa2[mm].SYM;}else error1();//缺少;}else error3();//缺少常量定义const}void _const()//常量,<const> →<id>:=<integer>{if (yufa0.SYM == "biaoshifu") // <id>{mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "fuzhi"){mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "didit"){mm++; yufa0.SYM = yufa2[mm].SYM;}else error4();//常量未赋值}else error5();//缺少赋值号,或者赋值号错误}else error2(); //缺少标识符}void vardecl()//变量说明的递归子程序实现,<vardecl> →var <id>{,<id>}; {line++;if (yufa0.SYM == "var"){mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "biaoshifu") //<id>{mm++; yufa0.SYM = yufa2[mm].SYM;while (yufa0.SYM == ",")//,{mm++; yufa0.SYM = yufa2[mm].SYM;//下一单词if (yufa0.SYM == "biaoshifu") //<id>{mm++; yufa0.SYM = yufa2[mm].SYM;}else error2();//缺少标识符即缺少变量}if (yufa0.SYM == ";"){mm++; yufa0.SYM = yufa2[mm].SYM;}//下一单词else error2();}}else error6();//变量未声明}void proc()//<proc> →procedure <id>(<id>{,<id>});<block>{;<proc>}{line++;if (yufa0.SYM == "procedure") //procedure{mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "biaoshifu") // <id>{mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "(") //({mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "biaoshifu")// <id>{mm++; yufa0.SYM = yufa2[mm].SYM;while (yufa0.SYM == ",")// ,{mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "biaoshifu"){mm++; yufa0.SYM = yufa2[mm].SYM;}else error2();}}if (yufa0.SYM == ")")// ){mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == ";") //;{mm++; yufa0.SYM = yufa2[mm].SYM;//下一单词---------->>block();while (yufa0.SYM == ";"){mm++; yufa0.SYM = yufa2[mm].SYM;proc();}}else error1();// 缺少;}else error7();//括号不匹配(右括号少)}else error8();//左括号缺少}else error9();//缺少参数}else error10();//procedure错误}void body()//<body> →begin <statement>{;<statement>}end{if (yufa0.SYM == "begin"){line++;mm++; yufa0.SYM = yufa2[mm].SYM;statement();// while ((yufa0.SYM == "biaoshi") || (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 = yufa2[mm].SYM;statement();}if (yufa0.SYM == "end"){line ++;mm++; yufa0.SYM = yufa2[mm].SYM;}else error11();//缺少end与begin匹配}else error12();//缺少begin}//<statement> →<id> := <exp> <statement> //语句// |if <lexp> then <statement>[else <statement>]// |while <lexp> do <statement>// |call <id>[(<exp>{,<exp>})]// |<body>// |read (<id>{,<id>})// |write (<exp>{,<exp>})void statement(){if (yufa0.SYM == "biaoshifu") //<statement> →<id> := <exp>{line++;mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "fuzhi"){mm++; yufa0.SYM = yufa2[mm].SYM;exp();}else error5();//赋值号错误}else if (yufa0.SYM == "if") //if <lexp> then <statement>[else <statement>] {line++;mm++; yufa0.SYM = yufa2[mm].SYM;lexp();if (yufa0.SYM == "then"){mm++; yufa0.SYM = yufa2[mm].SYM;statement();if (yufa0.SYM == "else"){mm++; yufa0.SYM = yufa2[mm].SYM;statement();}}else error12();//缺少then}else if (yufa0.SYM == "while")//while <lexp> do <statement>{line++;mm++; yufa0.SYM = yufa2[mm].SYM;lexp();if (yufa0.SYM == "do"){mm++; yufa0.SYM = yufa2[mm].SYM;statement();}else error13();//缺少do不匹配(while 与do 不匹配)}else if (yufa0.SYM == "call")//call <id>[(<exp>{,<exp>})]{line++;mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "biaoshifu") //{mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "(") //{mm++; yufa0.SYM = yufa2[mm].SYM;while(yufa0.SYM == ","){mm++;yufa0.SYM = yufa2[mm].SYM;exp();}if (yufa0.SYM == ")"){mm++; yufa0.SYM = yufa2[mm].SYM;}else error7();//缺少右括号}// 此处不会报错,[(<exp>{,<exp>})]因为表示可有可无的}else error14();//调用过程缺少标识符}else if (yufa0.SYM == "read")//read (<id>{,<id>}){line++;mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "("){mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "biaoshifu"){mm++; yufa0.SYM = yufa2[mm].SYM;while (yufa0.SYM == ","){mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "biaoshifu"){mm++; yufa0.SYM = yufa2[mm].SYM;}else error2();//缺少标示符}if (yufa0.SYM == ")"){mm++; yufa0.SYM = yufa2[mm].SYM;}else error7();//缺少右括号}else error9();//read缺少参数}else error8();//缺少左括号}else if (yufa0.SYM == "write")//write (<exp>{,<exp>}) {line++;mm++; yufa0.SYM = yufa2[mm].SYM;if (yufa0.SYM == "("){mm++; yufa0.SYM = yufa2[mm].SYM;exp();while (yufa0.SYM == ","){mm++; yufa0.SYM = yufa2[mm].SYM;exp();}if (yufa0.SYM == ")"){mm++; yufa0.SYM = yufa2[mm].SYM;}else error7();//缺少右括号}else error8();//缺少左括号}else body();//<body>}//<lexp> →<exp> <lop> <exp>|odd <exp>//<exp> →[+|-]<term>{<aop><term>}//<term> →<factor>{<mop><factor>}//<factor>→<id>|<integer>|(<exp>)//<lop> →=|<>|<|<=|>|>=//<aop> →+|-//<mop> →*|///<id> →l{l|d} (注:l表示字母)//<integer> →d{d}void lexp()//<lexp> →<exp> <lop> <exp>|odd <exp> {if (yufa0.SYM == "odd"){mm++;yufa0.SYM = yufa2[mm].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 = yufa2[mm].SYM;exp();}elseerror15();//条件语句出错,缺少界符}//odd是否存在?}void exp()//<exp> →[+|-]<term>{<aop><term>}{while((yufa0.SYM == "+") || (yufa0.SYM == "-")){mm++;yufa0.SYM = yufa2[mm].SYM;term();//<term>}term();while ((yufa0.SYM == "+") || (yufa0.SYM == "-"))//<aop> →+|-{mm++;yufa0.SYM = yufa2[mm].SYM;term();}}void term()//<term> →<factor>{<mop><factor>}{factor();while ((yufa0.SYM == "*") || (yufa0.SYM == "/"))//<mop> →*|/{mm++;yufa0.SYM = yufa2[mm].SYM;factor();//factor()}}void factor()//<factor>→<id>|<integer>|(<exp>){if (yufa0.SYM == "biaoshi"){mm++;yufa0.SYM = yufa2[mm].SYM;}else if (yufa0.SYM == "digit"){mm++;yufa0.SYM = yufa2[mm].SYM;}else if (yufa0.SYM == "("){mm++;yufa0.SYM = yufa2[mm].SYM;exp();if (yufa0.SYM == ")"){mm++;yufa0.SYM = yufa2[mm].SYM;}else error7(); //缺少右括号}else error8();//缺少左括号}string Concat(char ch,string strToken){strToken += ch;return strToken;}int IsLetter(char c ) //判断字母{if (((c <= 'z')&&(c >= 'a')) || ((c <= 'Z')&&(c >= '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; i<15; i++){if (key[i].compare(StrToken) == 0)return 1;}return 0;}void getsym(fstream &file){string StrToken = "";// if (ch == ' ' || ch == '\t' || ch == '\n') //滤掉空白字符// ch = file.get();if (IsLetter(ch)){while (IsLetter(ch) || IsDigit(ch)){StrToken = Concat(ch,StrToken);ch = file.get();}if (IsKey(StrToken)){int i;for (i = 0; i<15; i++){if (key[i].compare(StrToken) == 0)yufa1.SYM = key[i];}yufa1.strToken = StrToken;}else{yufa1.SYM = "biaoshifu";yufa1.strToken = StrToken;}if (IsDigit(ch)){StrToken = "";while(IsDigit(ch)){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 = 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 = ")";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 = ":=";}cout << ":" << "词法错误(:后面没有=)" << endl;ch = file.get();break;}case'>':{ch = file.get();if (ch == '='){yufa1.SYM = "ge";yufa1.strToken = ">=";}else{yufa1.SYM = "g";yufa1.strToken = ">";}ch = file.get();break;}case'<':{ch = file.get();if (ch == '='){yufa1.SYM = "le";yufa1.strToken = "<=";}else if (ch == '>'){yufa1.SYM = "ne";yufa1.strToken = "<>";}else{yufa1.SYM = "l";yufa1.strToken = "<";}ch = file.get();break;}}}int main(){int nn = 0;string StrToken = "";fstream file;char ch;int ll;char filename[30];cout << "请输入源文件名:";cin.getline(filename, 30);file.open(filename, ios::in);if (!file){cout << "文件打开失败!\n\n";exit(0);}yufa2[nn].l = 0;cout << "\n--------------------------词法分析------------------------" << endl; // ch = file.get();while (!file.eof()){// if (ch == ' ' || ch == '\t' || ch == '\n') //滤掉空白字符// ch = file.get();// ch = file.get();if (ch == ' ' || ch == '\t')ch=file.get();while (ch == '\n'){ll ++;ch = file.get();}getsym(file);nn++;yufa2[nn].SYM = yufa1.SYM;yufa2[nn].strToken = yufa1.strToken;yufa2[nn].l = ll;// cout.setf(ios::left);cout << "(" << setw(2) << nn << ") ";cout << setw(13) << yufa2[nn].SYM << setw(9) << yufa2[nn].strToken << "\n";cout << setw(13) << yufa1.SYM << setw(9) << yufa1.strToken << "\n";}// nn++;// yufa2[nn].SYM = "the_end";//完成// yufa2[nn].strToken = "the_end";file.close();// cout << "\n\n\n--------------------------语法分析------------------------" << endl;yufa0.SYM = yufa2[mm].SYM;// yufa0.SYM = yufa1.SYM;prog();return 0;}。