编译原理实验二
编译原理-实验二-FLEX词法分析器

编译原理-实验⼆-FLEX词法分析器FLEX词法分析器⼀、Lex和Yacc介绍Lex 是⼀种⽣成扫描器的⼯具。
扫描器是⼀种识别⽂本中的词汇模式的程序。
⼀种匹配的常规表达式可能会包含相关的动作。
这⼀动作可能还包括返回⼀个标记。
当 Lex 接收到⽂件或⽂本形式的输⼊时,它试图将⽂本与常规表达式进⾏匹配。
它⼀次读⼊⼀个输⼊字符,直到找到⼀个匹配的模式。
如果能够找到⼀个匹配的模式,Lex 就执⾏相关的动作(可能包括返回⼀个标记)。
另⼀⽅⾯,如果没有可以匹配的常规表达式,将会停⽌进⼀步的处理,Lex 将显⽰⼀个错误消息。
Yacc代表 Yet Another Compiler Compiler 。
Yacc 的 GNU 版叫做 Bison。
它是⼀种⼯具,将任何⼀种编程语⾔的所有语法翻译成针对此种语⾔的 Yacc 语法解析器。
(下载下载flex和bison。
⽹址分别是/packages/flex.htm和/packages/bison.htm。
)⼆、配置环境(win7)①下载flex和bison并安装到D:\GnuWin32(尽量是根⽬录)②由于我们使⽤的flex和bison都是GNU的⼯具,所以为了⽅便,采⽤的C/C++编译器也采⽤GNU的编译器GCC,当然我们需要的也是Windows版本的GCC了。
所以提前准备好VC 6.0③检验是否可以进⾏lex⽂件编译1.新建⽂本⽂件,更改名称为lex.l,敲⼊下⾯代码%{int yywrap(void);%}%%%%int yywrap(void){return 1;}2.新建⽂本⽂件,更改名称为yacc.y,敲⼊下⾯代码%{void yyerror(const char *s);%}%%program:;%%void yyerror(const char *s){}int main(){yyparse();}我们暂且不讨论上⾯代码的意思。
打开控制台,进⼊到刚才所建⽴⽂件(lex.l,yacc.y)所在的⽂件夹。
编译原理课程实验报告

五、实验体会
指导教师评语:
日期:
编译原理课程实验报告实验2语法分析院系姓名任课教师实验地点实验课表现学号出勤表现得分操作结果得分指导教师实验时间实验报告得分实验总分一实验目的要求需分析本次实验的基本目的并综述你是如何实现这些目的的二实验内容要求对如下工作进行展开描述1给出如下语言成分的文法描述函数定义或过程定义变量说明赋值表达式循环分支2语法分析程序的总体结构及物理实现3语法分析表及其数据结构和查找算法4语法分析表的生成算法5错误处理错误的位置及类型等三实验结果要求将实验获得的结果进行描述基本内容包括1针对一测试程序输出其语法分析结果2输出针对此测试程序对应的语法错误报告注其中的测试样例需先用已编写的词法分析程序进行处理
变量说明
赋值
表达式
循环
分支
(2)语法分析程序的总体结构及物理实现
(3)语法分析表及其数据结构和查找算法
(4)语法分析表的生成算法
(5)错误处理
错误的位置及类型等
三、实验结果
要求:将实验获得的结果进行描述,基本内容包括:
(1)针对一测试程序输出其语法分析结果;
(2)输出针对此测试程序对应的语法错误报告;
编译原理课程实验报告
实验2:语法分析
姓名
院系
学号
任课教师
指导教师
实验地点
实验时间
实验课表现
出勤、表现得分
实验报告
得分
实验总分
操作结果得分
一、实验目的
要求:需分析本次实验的基本目的,并综述你是如何实现这些目的的?
二、实验内容
要求:对如下工作进行展开描述
编译原理实验二LL文法分析

实验2 LL(1)分析法一、实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。
使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。
有利于提高学生的专业素质,为培养适应社会多方面需要的能力。
二、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
2、如果遇到错误的表达式,应输出错误提示信息。
3、对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i三、实验内容根据某一文法编制调试LL ( 1 )分析程序,以便对任意输入的符号串进行分析。
构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。
分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。
四、实验步骤1、根据流程图编写出各个模块的源程序代码上机调试。
2、编制好源程序后,设计若干用例对系统进行全面的上机测试,并通过所设计的LL(1)分析程序;直至能够得到完全满意的结果。
3、书写实验报告;实验报告正文的内容:写出LL(1)分析法的思想及写出符合LL(1)分析法的文法。
程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;函数之间的调用关系图。
详细的算法描述(程序执行流程图)。
给出软件的测试方法和测试结果。
实验总结(设计的特点、不足、收获与体会)。
五、实验截图六、核心代码#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX 20using namespace std;char A[MAX];char B[MAX];char v1[MAX] = { 'i','+','-','*','/','(',')','#'}; char v2[MAX] = {'E','G','T','S','F'};int j = 0, b = 0, top = 0;int l; //l是字符串长度class type{public:char origin;char array[7];int length;};type e, t, g,g0, g1, s, s0,s1, f, f1;type C[10][10];void print(){int a;for ( a = 0; a <= top + 1; a++)cout<<A[a];cout << "\t\t";}void print1(){int j;for (j = 0; j<b; j++)cout << " ";for (j = b; j <= l; j++)cout << B[j];cout << "\t\t\t";}int main(){int m, n, k = 0;int flag = 0,finish = 0;char ch, x;type cha;e.origin = 'E';strcpy(e.array, "TG");e.length = 2;t.origin = 'T';strcpy(t.array, "FS");t.length = 2;g.origin = 'G';strcpy(g.array, "+TG");g.length = 3;g0.origin = 'G';strcpy(g0.array, "-TG");g0.length = 3;g1.origin = 'G';g1.array[0] = '^';g1.length = 1;s.origin = 'S';strcpy(s.array, "*FS");s.length = 3;s0.origin = 'S';strcpy(s0.array, "/FS");s0.length = 3;s1.origin = 'S';s1.array[0] = '^';s1.length = 1;f.origin = 'F';strcpy(f.array, "(E)");f.length = 3;f1.origin = 'F';f1.array[0] = 'i';f1.length = 1;for (m = 0; m <= 4;m++)for (n = 0; n <= 7; n++)C[m][n].origin = 'N';/*C[0][0] = e; C[0][3] = e; C[1][2] = g0;C[1][1] = g; C[1][4] = g1; C[1][5] = g1;C[2][0] = t; C[2][3] = t;C[3][1] = s1; C[3][2] = s;C[3][4] = C[3][5] = s1;C[4][0] = f1; C[4][3] = f;*/C[0][0] = e; C[0][5] = e;C[1][1] = g; C[1][2] = g0;C[1][6] = g1; C[1][7] = g1;C[2][0] = t; C[2][5] = t;C[3][1] = s1; C[3][2] = s1;C[3][3] = s;C[3][4] = s0; C[3][6] = s1; C[3][7] = s1;C[4][0] = f1; C[4][5] = f;cout << "input,please~:";do{cin >> ch;if ((ch!='i') &&(ch!='+') &&(ch!='-') &&(ch!='*') &&(ch!='/') &&(ch!='(') &&(ch!=')') &&(ch!='#')){cout << "Error!\n";exit(1);}B[j] = ch;j++;} while (ch != '#');l = j; //l是字符串长度/* for(j=0;j<l;j++)cout<<B[j]<<endl;*/ch = B[0]; //当前分析字符A[top] = '#';A[++top] = 'E';/*'#','E'进栈*/cout << "步骤\t\t分析栈\t\t剩余字符\t\t所用字符\n"; do{x = A[top--];cout << k++;cout << "\t\t";for (j = 0; j<=7 ; j++)if (x == v1[j]){flag = 1;break;}if (flag==1){if (x == '#'){finish = 1;cout << "acc!\n";getchar();getchar();exit(1);}if (x == ch){print();print1();cout <<ch << "匹配\n";ch = B[++b];flag = 0;}else{cout<<"x:"<<x<<endl;cout<<"ch:"<<ch<<endl;print();print1();cout <<ch<< "出错\n" ;exit(1);}}else //非终结符{for (j = 0; j <= 4; j++)if (x == v2[j]){m = j;//行号break;}for (j = 0; j <= 7; j++)if (ch == v1[j]){n = j; //列号break;}cha = C[m][n];if (cha.origin != 'N'){print();print1();cout << cha.origin << "->";for (j = 0; j<cha.length; j++)cout << cha.array[j];cout << "\n";for (j = (cha.length - 1); j >= 0; j--)A[++top] = cha.array[j];if (A[top] == '^')/*为空则不进栈*/top--;}else{print();print1();cout<<"x:"<<x<<endl;cout<<"ch:"<<ch<<endl;cout<<"sign1"<<endl;cout << "Error!" << x;exit(1);}}} while (finish == 0);}。
编译原理_实验报告实验二__语法分析(算符优先) 2

华北水利水电学院编译原理实验报告一、实验题目:语法分析(算符优先分析程序)(1)选择最有代表性的语法分析方法算符优先法;(2)选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
二、实验内容(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(4) 分析的句子为:(i+i)*i和i+i)*i三、程序源代#include<stdlib.h>#include<stdio.h>#include<string.h>#include<iostream.h>#define SIZE 128char priority[6][6]; //算符优先关系表数组char input[SIZE]; //存放输入的要进行分析的句子char remain[SIZE]; //存放剩余串char AnalyseStack[SIZE]; //分析栈void analyse();int testchar(char x); //判断字符X在算符优先关系表中的位置void remainString(); //移进时处理剩余字符串,即去掉剩余字符串第一个字符int k;void init()//构造算符优先关系表,并将其存入数组中{priority[0][2]='<';priority[0][3]='<';priority[0][4]='>';priority[0][5]='>';priority[1][0]='>';priority[1][1]='>';priority[1][2]='<';priority[1][3]='<';priority[1][4]='>';priority[1][5]='>';priority[2][0]='>';priority[2][1]='>';priority[2][2]='$';//无优先关系的用$表示priority[2][3]='$';priority[2][4]='>';priority[2][5]='>';priority[3][0]='<';priority[3][1]='<';priority[3][2]='<';priority[3][3]='<';priority[3][4]='=';priority[3][5]='$';priority[4][0]='>';priority[4][1]='>';priority[4][2]='$';priority[4][3]='$';priority[4][4]='>';priority[4][5]='>';priority[5][0]='<';priority[5][3]='<';priority[5][4]='$';priority[5][5]='=';}void analyse()//对所输入的句子进行算符优先分析过程的函数{FILE *fp;fp=fopen("li","a");int i,j,f,z,z1,n,n1,z2,n2;int count=0;//操作的步骤数char a; //用于存放正在分析的字符char p,Q,p1,p2;f=strlen(input); //测出数组的长度for(i=0;i<=f;i++){a=input[i];if(i==0)remainString();if(AnalyseStack[k]=='+'||AnalyseStack[k]=='*'||AnalyseStack[k]=='i'||Analy seStack[k]=='('||AnalyseStack[k]==')'||AnalyseStack[k]=='#')j=k;elsej=k-1;z=testchar(AnalyseStack[j]);//从优先关系表中查出s[j]和a的优先关系if(a=='+'||a=='*'||a=='i'||a=='('||a==')'||a=='#')n=testchar(a);else //如果句子含有不是终结符集合里的其它字符,不合法{printf("错误!该句子不是该文法的合法句子!\n");break;}if(p=='$'){printf("错误!该句子不是该文法的合法句子!\n");return;}if(p=='>'){ for( ; ; ){Q=AnalyseStack[j];if(AnalyseStack[j-1]=='+'||AnalyseStack[j-1]=='*'||AnalyseStack[j-1]=='i'||AnalyseStack[j-1]=='('||AnalyseStack[j-1]==')'||AnalyseStack[j-1]=='#')j=j-1;elsej=j-2;z1=testchar(AnalyseStack[j]);n1=testchar(Q);p1=priority[z1][n1];if(p1=='<') //把AnalyseStack[j+1]~AnalyseStack[k]归约为N{count++;printf("(%d) %s\t%10c\t%5c%17s\t 归约\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"归约");k=j+1;i--;AnalyseStack[k]='N';int r,r1;r=strlen(AnalyseStack);for(r1=k+1;r1<r;r1++)AnalyseStack[r1]='\0';break;}else}}else{if(p=='<') //表示移进{count++;printf("(%d) %s\t%10c\t%5c%17s\t 移进\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"移进");k=k+1;AnalyseStack[k]=a;remainString();}else{if(p=='='){z2=testchar(AnalyseStack[j]);n2=testchar('#');p2=priority[z2][n2];if(p2=='='){count++;printf("(%d) %s\t%10c\t%5c%17s\t 接受\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"接受");printf("该句子是该文法的合法句子。
编译原理实验二:压缩文法的等价变换

实验二:压缩文法的等价变换一:要求输入:任意的上下文无关文法输出:等价的压缩了的文法要求:除了可查看压缩了的文法,还可查看删除了哪些规则二:实验目的了解文法的简化三:实验原理删除文法中的有害规则和多余规则有害规则:若文法中有如U::=U的规则,则这就是有害规则,它会引起二义性,而无任何用处。
多余规则:(1)某条规则U::=u的左部非终结符U(U不是识别符号),不在任何其他规则右部出现,即所有的推导始终不会用到此规则。
【不可到达】(2)在推导句子的过程中,一旦使用了该规则,将推不出任何终结符号串。
即该规则中含有推不出任何终结符号串的非终结符。
【不可终止】四:数据结构与算法struct Chomsky{string left;string right;};void apart(Chomsky *p,int i) //分开产生式左右部void VNVT(Chomsky *p)//求VN和VTint zero(Chomsky *p)//0型文法int one(Chomsky *p)//1型文法int two(Chomsky *p)//2型文法void shanchu(Chomsky *p)//删除多余规则与有害规则五:出错分析1:变量重复定义导致了一些小错误2:程序太长{}缺少也导致了错误3:后面删除规则的程序出错了,没有调试成功。
六:实验结果与分析不是上下文无关文法的:2型文法的压缩:七:源代码#include<iostream>#include<string>using namespace std;#define max 50int NONE=1;int RELEFT=1;string strings,noend,end;//非终结符与终结符存储int n;//产生式总数int flag;struct Chomsky{string left;string right;};void apart(Chomsky *p,int i) //分开产生式左右部{int j;for(j=0;j<strings.length();j++)if(strings[j]=='-'){p[i].left=strings.substr(0,j);p[i].right=strings.substr(j+1,strings.length()-j);}}void VNVT(Chomsky *p)//求VN和VT{int i,j;for(i=0;i<n;i++){for(j=0;j<(int)p[i].left.length();j++){if((p[i].left[j]>='A'&&p[i].left[j]<='Z'))//非终结符判断{if(noend.find(p[i].left[j])>100)noend+=p[i].left[j];}else{if(end.find(p[i].left[j])>100)end+=p[i].left[j];}}{if(!(p[i].right[j]>='A'&&p[i].right[j]<='Z'))//终结符判断{if(end.find(p[i].right[j])>100)end+=p[i].right[j];}else{if(noend.find(p[i].right[j])>100)noend+=p[i].right[j];}}}}int zero(Chomsky *p)//0型文法{int flag(0),count(0);int i,j;for(i=0;i<n;i++){{if(p[i].left[j]>='A'&&p[i].left[j]<='Z') //有否非终结符flag++;}if(flag>0){flag=0;count++;}elsebreak; //左部没有非终结符,结束}if(count==n)return 1; //属于0型文法else{cout<<endl<<"所输产生式不属于任何文法。
编译原理实验2.

第二章语法分析器构造我们采用一种最为常用的语法分析器─LR分析器。
LR分析器的构造主要是指上下文无关文法的自下而上分析程序的自动构造。
从实践角度出发,我们采用手工方法来设计LR 分析器。
LR系指“自左向右扫描和自下而上进行归约”。
大多数用上下文无关文法描述的程序语言都可用LR分析器予以识别。
LR分析法在自左至右扫描输入串时就能发现其中的任何错误,并能准确地指出出错地点。
一个LR分析器包括两部分,一个总控(驱动)程序和一张分析表。
注意,所有LR分析器的总控程序都是一样的,只是分析表各有不同。
因此,产生器的主要任务就是产生分析表。
2.1 LR分析器基本知识我们知道,规范归约(最左归约,即最右推导的逆过程)的关键问题是寻找句柄。
LR 方法的基本思想是:在规范归约过程中,一方面记住已移进和归约出的整个符号串,即记住“历史”;另一方面根据所用的产生式推测未来的可能碰到的输入符号,即对未来进行“展望”。
当一串貌似句柄的符号串呈现于分析栈的顶端时,我们希望能够根据所记载的“历史”和“展望”以及“现实”的输入符号等三方面的材料,来确定栈顶的符号是否构成相对某一产生式的句柄。
一个LR分析器实质上是一个带先进后出存贮器(栈)的确定有限状态自动机。
我们将把“历史”和“展望”材料综合地抽象成某些“状态”。
分析栈(先进后出存贮器)用来存放状态。
栈里的每个状态概括了从分析开始直到某一归约阶段的全部“历史”和“展望”资料。
任何时候,栈顶的状态都代表了整个的历史和已推测出的展望。
LR分析器的每一步工作都是由栈顶状态和现行输入符号所唯一决定的。
为了有助于明确归约手续,我们把已归约出的文法符号串也同时放在栈里。
于是,栈的结构可看成图2-1所示的结构。
TOP图2-1 分析栈示意栈的每一项内容包括状态s和文法符号X两部分。
(s O,#)为分析开始前预先放入栈里的初始状态和句子括号。
栈顶状态为s m,符号串X1X2…X m是至今已移进归约出的文法符号串。
编译原理实验二:消除文法的左递归.doc

编译原理实验报告实验名称消除文法的左递归实验时间2013年11月12日院系计算机科学与电子技术系班级11计算机软件学号JV114001 JV114095 JP114065 姓名唐茹韩强强徐思维1.试验目的:输入:任意的上下文无关文法。
输出:消除了左递归的等价文法。
2.实验原理:1.直接左递归的消除消除产生式中的直接左递归是比较容易的。
例如假设非终结符P 的规则为:P →P α / β其中,β是不以P 开头的符号串。
那么,我们可以把P 的规则改写为如下的非直接左递归形式: P →βP ’P ’→αP ’ / ε这两条规则和原来的规则是等价的,即两种形式从P 推出的符号串是相同的。
设有简单表达式文法G[E]: E →E+T/ T T →T*F/ F F →(E )/ I经消除直接左递归后得到如下文法: E →TE ’E ’ →+TE ’/ ε T →FT ’T ’ →*FT ’/ εF →(E )/ I考虑更一般的情况,假定关于非终结符P 的规则为P →P α1 / P α2 /…/ P αn / β1 / β2 /…/βm其中,αi (I =1,2,…,n )都不为ε,而每个βj (j =1,2,…,m )都不以P 开头,将上述规则改写为如下形式即可消除P 的直接左递归:P →β1 P ’ / β2 P ’ /…/βm P ’P ’ →α1P ’ / α2 P ’ /…/ αn P ’ /ε 2.间接左递归的消除直接左递归见诸于表面,利用以上的方法可以很容易将其消除,即把直接左递归改写成直接右递归。
然而文法表面上不存在左递归并不意味着该文法就不存在左递归了。
有些文法虽然表面上不存在左递归,但却隐藏着左递归。
例如,设有文法G[S]:S →Qc/ c Q →Rb/ b R →Sa/ a虽不具有左递归,但S 、Q 、R 都是左递归的,因为经过若干次推导有 S ⇒Qc ⇒Rbc ⇒SabcQ ⇒Rb ⇒Sab ⇒Qcab R ⇒Sa ⇒Qca ⇒Rbca就显现出其左递归性了,这就是间接左递归文法。
编译原理实验二word版本

编译原理二-------词法分析器一.问题描述词法分析程序的功能:输入源程序,输出单词符号,如图所示:单词符号处理过程:在扫描源程序字符串时,一旦识别出关键字、分隔符、标识符、无符号常数中之一,即以单词形式(各类单词均采用相同的结构,即二元式编码形式)输出。
每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直至整个源程序全部扫描完毕,并形成相应的单词串形式的源程序。
二.需求分析1.对给定的程序通过词法分析器能够识别一个个单词符号,并以二元式(单词类型,单词符号)显示;2.可以将要分析的程序保存到文件中进行读取;3.删除无用的空白字符、回车符、及其它非实质性符号。
三.程序设计本程序规定:(1)关键字"begin","end","if","then","else","while","write","read", "do", "call","const","char","until","procedure","repeat"(2)运算符:"+","-","*","/","="(3)界符:"{","}","[","]",";",",",".","(",")",":"(4)其他标记如字符串,表示以字母开头的标识符。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验二语法分析一、实验目的:设计MiniC的上下文无关文法,利用JavaCC生成调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
二、语法分析器:按照MiniC语言的语法规则检查词法分析输出的记号流是否符合这些规则,并根据这些规则所体现出的语言中的各种语法结构的层次性。
把规则写入到JavaCC的.jjt文件中,可以生成树状的层次结构。
三、JavaCC:在JavaCC的文法规范文件中,不仅可以描述语言的语法规范,而且可以描述词法规范,本次实习中,利用JavaCC以MiniC语言构造一个不含语义分析的编译器前端,包括词法分析、语法分析,并要考虑语法分析中的错误恢复问题。
通过使用JavaCC, 可以体会LL(k)文法的编写特点,掌握编写JavaCC文法规范文件的方法。
内容:利用JavaCC生成一个MiniC的语法分析器;要求:1.用流的形式读入要分析的C语言程序,或者通过命令行输入源程序。
2.具有错误检查的能力,如果有能力可以输出错误所在的行号,并简单提示3.如果输入的源程序符合MiniC的语法规范,输出该程序的层次结构的语法树本次实习仅完成以下语法范畴的语法分析:1. 写出一个源程序中仅包含if…else, else语句的语法分析。
要求能分析其自身嵌套. 其他语句可简化处理2. 写出一个源程序中仅包含for语句的语法分析。
要求能分析其自身嵌套,其他语句可简化处理3. 写出一个源程序中仅包含while语句的语法分析。
要求能分析其自身嵌套。
其他语句可简化处理4. 写出一个源程序中包含上面的12或者13或者23或者123语句的语法分析。
要求能分析除其自身嵌套外,还包括相互嵌套。
其他语句可简化处理具体实施步骤如下:1.把MiniC转换为文法如下<程序〉→ main()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉;〈语句串〉|〈语句〉;〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|=|!>2.在eclipse环境下完成JavaCC的插件安装后,写一个JavaCC文法规范文件(扩展名为jj)3.完成的功能包括词法分析,语法分析(输出语法树),能够读文件,也能够把输出的结果保存文件中,可以把树的层次结果输出到文件中。
测试文件test.cvoid main(){while(3>4){if(4<=5){X=4}else{X=5}}}运行结果Reading from standard input...Enter c programe only main() with only while();" :eg. voidmian(){while(3<5)};" :Call: startCall: ProcedureConsumed token: <"void" at line 1 column 1>Consumed token: <"main" at line 1 column 6>Consumed token: <"(" at line 1 column 10>Consumed token: <")" at line 1 column 11>Consumed token: <"{" at line 2 column 1>Call: WhileStatementConsumed token: <"while" at line 3 column 9>Consumed token: <"(" at line 3 column 14>Call: ConditionCall: expressionCall: termCall: unaryConsumed token: <<CONSTANT>: "3" at line 3 column 15>Return: unaryReturn: termReturn: expressionConsumed token: <">" at line 3 column 16>Call: expressionCall: termCall: unaryConsumed token: <<CONSTANT>: "4" at line 3 column 17> Return: unaryReturn: termReturn: expressionReturn: ConditionConsumed token: <")" at line 3 column 18>Consumed token: <"{" at line 3 column 19>Call: ifStatementConsumed token: <"if" at line 5 column 11>Consumed token: <"(" at line 5 column 13>Call: ConditionCall: expressionCall: termCall: unaryConsumed token: <<CONSTANT>: "4" at line 5 column 14> Return: unaryReturn: termReturn: expressionConsumed token: <"<=" at line 5 column 15>Call: expressionCall: termCall: unaryConsumed token: <<CONSTANT>: "5" at line 5 column 17> Return: unaryReturn: termReturn: expressionReturn: ConditionConsumed token: <")" at line 5 column 18>Consumed token: <"{" at line 6 column 1>Call: assignConsumed token: <<IDENTIFIER>: "X" at line 6 column 2>Consumed token: <"=" at line 6 column 3>Consumed token: <<CONSTANT>: "4" at line 6 column 4>Return: assignConsumed token: <"}" at line 6 column 5>Consumed token: <"else" at line 7 column 1>Consumed token: <"{" at line 7 column 5>Call: assignConsumed token: <<IDENTIFIER>: "X" at line 7 column 6>Consumed token: <"=" at line 7 column 7>Consumed token: <<CONSTANT>: "5" at line 7 column 8>Return: assignConsumed token: <"}" at line 7 column 9>Return: ifStatementConsumed token: <"}" at line 8 column 9>Return: WhileStatementConsumed token: <"}" at line 9 column 1>Return: ProcedureConsumed token: <<EOF> at line 9 column 3>Return: startOK.实验代码/** JavaCC file*/options {JDK_VERSION = "1.5";DEBUG_PARSER = true;//}PARSER_BEGIN(whileParse)import java.io.FileInputStream;import java.io.FileNotFoundException;public class whileParse {public static void main(String args[]) throws ParseException { // whileParse parser = new whileParse(System.in);FileInputStream fileStream;try {fileStream = new FileInputStream("test.c");whileParse parser = new whileParse(fileStream);System.out.println("Reading from standard input...");System.out.print("Enter c programe only main() with only while();\" :");System.out.print("eg. void mian(){while(3<5)};\" :");try {switch (parser.start()) {case 0:System.out.println("OK.");break;case 1:System.out.println("Goodbye.");break;default:break;}} catch (Exception e) {System.out.println("NOK.");System.out.println(e.getMessage()); parser.ReInit(System.in);} catch (Error e) {System.out.println("Oops.");System.out.println(e.getMessage()); }} catch (FileNotFoundException e1) { // TODO Auto-generated catch blocke1.printStackTrace();}}}PARSER_END(whileParse)SKIP :{" "| "\r"| "\t"| "\n"}TOKEN : /* OPERATORS */{< PLUS:"+" >| < MINUS:"-" >| < MULTIPLY:"*" >| < DIVIDE:"/" >}TOKEN :{< CONSTANT: ( <DIGIT> )+ >| < #DIGIT: ["0" - "9"] >}TOKEN:{<MAIN:"main">| <VOID:"void">| <WHILE:"while">| <ASSIGN:"=">| <IF:"if">| <ELSE:"else">}TOKEN : /* 标识符 */<IDENTIFIER:<LETTER> (<LETTER>|<DIGIT>)* >| <LETTER:["_","a"-"z","A"-"Z"]>}TOKEN:{<GREAT:">">| <LOWER:"<">| <GREATE:">=">| <LOWERW:"<=">}TOKEN:{<LC:"(">| <RC:")">| <LM:"[">| <RM:"]">| <LB:"{">| <RB:"}">}int start() : {}{Procedure() <EOF> { return 0; }| ";" { return 1; }}/*处理主程序*/void Procedure():{}{<VOID><MAIN><LC><RC><LB>WhileStatement()<RB>}void WhileStatement():{}{<WHILE><LC>Condition()<RC><LB> ifStatement() <RB> }void ifStatement():{}{<IF><LC>Condition()<RC><LB>assign()<RB><ELSE><LB>assign()<RB>}void assign():{}{<IDENTIFIER><ASSIGN><CONSTANT>}void expression() : {}term() (( <PLUS> | <MINUS> ) term())*}void term() : {}{unary() (( <MULTIPLY> | <DIVIDE> ) unary())* }void unary() : {}{<CONSTANT>| <LC> expression()<RC>}void Condition():{}{expression()(<LOWER> expression()| <GREAT> expression()| <GREATE> expression()| <LOWERW> expression())}。