实验二 语法分析器的设计与实现

合集下载

编译原理_实验二_语法分析_递归下降分析器设计_实验报告

编译原理_实验二_语法分析_递归下降分析器设计_实验报告

递归下降分析器设计一、实验/实习过程内容:利用JavaCC生成一个MiniC的语法分析器;要求:1. 用流的形式读入要分析的C语言程序,或者通过命令行输入源程序。

2. 具有错误检查的能力,如果有能力可以输出错误所在的行号,并简单提示3. 如果输入的源程序符合MiniC的语法规范,输出该程序的层次结构的语法树具体实施步骤如下:1.把MiniC转换为文法如下<程序〉→ main()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉〈语句串〉|〈语句〉〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|==|!=2.消除语句中的回溯与左递归3.在eclipse环境下完成JavaCC的插件安装后,写一个JavaCC文法规范文件(扩展名为jj)4.完成的功能包括词法分析,语法分析二、代码:options {JDK_VERSION = "1.5";}PARSER_BEGIN(eg1)public class eg1 {public static void main(String args[]) throws ParseException { eg1 parser = new eg1(System.in);parser.start();}}PARSER_END(eg1)SKIP :{" "| "\r"| "\t"| "\n"}TOKEN : /* OPERATORS */{< PLUS: "+" >| < MINUS: "-" >| < MULTIPLY: "*" >| < DIVIDE: "/" >}TOKEN :{<BIGGER:">"> |<SMALLER:"<"> |<NOTVOLUTION:"!="> |<SMALLEREQDD:"<="> |<BIGGEREE:">=" > |<DOUBLE:"==">TOKEN: //关键字{<MAIN:"main"> |<VOID:"void"> |<IF:"if"> |<INT:"int"> | <WHILE:"while"> |<CHAR:"char"> | <VOLUTION:"="> }TOKEN : //定义整型数{< INTEGER: ["0" - "9"]( <DIGIT> )+ >| < #DIGIT: ["0" - "9"] >}TOKEN : //数字{<NUMBER:(<DIGIT>)+ | (<DIGIT>)+"."| (<DIGIT>)+"."(<DIGIT>)+| "."(<DIGIT>)+>}TOKEN : //标记{<COMMA:","> | <SEMICOLON:";"> | <COLON:":"> | <LEFTPARENTHESES:"("> |<RIGHTPARENTHESES:")"> | <LEFTBRACE:"{"> | <RIGHTBRACE:"}"> }TOKEN : //标识符{<IDENTIFIER:<LETTER> |<LETTER>(<LETTER> | <DIGIT> )* >|<#LETTER:["a"-"z", "A"-"Z"]>}void start():{}{<MAIN> <LEFTPARENTHESES> <RIGHTPARENTHESES> block() }void block():{}{<LEFTBRACE> string() <RIGHTBRACE>}void string():{}{yuju() (string())?}void yuju():{}{fuzhiyuju() | tiaojianyuju() | xunhuanyuju()}void fuzhiyuju():{}{<IDENTIFIER> <VOLUTION> biaodashi() <SEMICOLON>}void tiaojianyuju():{}{<IF> tiaojian() block()}void xunhuanyuju():{}<WHILE> tiaojian() block()}void tiaojian():{}{<LEFTPARENTHESES> biaodashi() guanxifu() biaodashi()<RIGHTPARENTHESES>}void biaodashi():{}{( <LEFTPARENTHESES> biaodashi() <RIGHTPARENTHESES> biaodashi2()) |(<IDENTIFIER> biaodashi2() ) | ( <NUMBER> biaodashi2() )}void biaodashi2():{}{(yunsuanfu() biaodashi() biaodashi2() )?}void yunsuanfu():{}{< PLUS > | < MINUS > |< MULTIPLY> | < DIVIDE >}void guanxifu() :{}{<BIGGER> | <SMALLER> | <NOTVOLUTION><SMALLEREQDD> | <BIGGEREE> | <DOUBLE>}三、实验/实习总结本次实习,我使用javacc完成了包括词法分析,语法分析(输出语法树),能够读文件的功能,总的来说比较满意,通过本次实习掌握了javacc基本的使用。

实验二 语法分析器的设计与实现

实验二 语法分析器的设计与实现

实验二语法分析器的设计与实现
一、实验目的
构造一个小语言的语法分析程序。

二、实验要求
输入属性字文件,输出源程序是否符合语法要求的结果。

正确——该程序符合语法要求
错误——指出错误位置
三、实验说明
1、总体说明
构造并存储预测分析表,构造分析器,并能进行出错处理,实现LL(1)分析法。

设计好一个文法,消除文法的左递归性。

将消除了左递归性的文法,构造每个非终结符的FIRST和FOLLOW集合。

根据FIRST和FOLLOW集合构造LL(1)分析表。

然后,利用分析表,根据LL(1)语法分析构造一个分析器。

2、语法描述
文法:E→E+T | T
T→T*F | F
F→( E ) | i
经消去左递归后变成:E→TP
P→+TP | ε
T→FQ
Q→*FQ | ε
F→( E ) | i
3、设计原理
LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a行事的。

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

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

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

②FOLLOW集合的构造算法
四、实验成果提交
1、非终结符的FIRST集合
2、非终结符的FOLLOW集合
3、预测分析表
4、程序流程图
5、源代码
6、程序运行说明及测试数据。

编译原理实验二语法分析器LL(1)实现

编译原理实验二语法分析器LL(1)实现

编译原理程序设计实验报告——表达式语法分析器的设计班级:计算机1306班:涛学号:20133967 实验目标:用LL(1)分析法设计实现表达式语法分析器实验容:⑴概要设计:通过对实验一的此法分析器的程序稍加改造,使其能够输出正确的表达式的token序列。

然后利用LL(1)分析法实现语法分析。

⑵数据结构:int op=0; //当前判断进度char ch; //当前字符char nowword[10]=""; //当前单词char operate[4]={'+','-','*','/'}; //运算符char bound[2]={'(',')'}; //界符struct Token{int code;char ch[10];}; //Token定义struct Token tokenlist[50]; //Token数组struct Token tokentemp; //临时Token变量struct Stack //分析栈定义{char *base;char *top;int stacksize;};⑶分析表及流程图逆序压栈int IsLetter(char ch) //判断ch是否为字母int IsDigit(char ch) //判断ch是否为数字int Iskey(char *string) //判断是否为关键字int Isbound(char ch) //判断是否为界符int Isboundnum(char ch) //给出界符所在token值int init(STack *s) //栈初始化int pop(STack *s,char *ch) //弹栈操作int push(STack *s,char ch) //压栈操作void LL1(); //分析函数源程序代码:(加入注释)#include<stdio.h>#include<string.h>#include<ctype.h>#include<windows.h>#include <stdlib.h>int op=0; //当前判断进度char ch; //当前字符char nowword[10]=""; //当前单词char operate[4]={'+','-','*','/'}; //运算符char bound[2]={'(',')'}; //界符struct Token{int code;char ch[10];}; //Token定义struct Token tokenlist[50]; //Token数组struct Token tokentemp; //临时Token变量struct Stack //分析栈定义{char *base;char *top;int stacksize;};typedef struct Stack STack;int init(STack *s) //栈初始化{(*s).base=(char*)malloc(100*sizeof(char)); if(!(*s).base)exit(0);(*s).top=(*s).base;(*s).stacksize=100;printf("初始化栈\n");return 0;}int pop(STack *s,char *ch) //弹栈操作{if((*s).top==(*s).base){printf("弹栈失败\n");return 0;(*s).top--;*ch=*((*s).top);printf("%c",*ch);return 1;}int push(STack *s,char ch) //压栈操作{if((*s).top-(*s).base>=(*s).stacksize){(*s).base=(char*)realloc((*s).base,((*s).stacksize+10)*sizeof(char)); if(!(*s).base)exit(0);(*s).top=(*s).base+(*s).stacksize;(*s).stacksize+=10;}*(*s).top=ch;*(*s).top++;return 1;}void LL1();int IsLetter(char ch) //判断ch是否为字母{int i;for(i=0;i<=45;i++)if ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))return 1;return 0;}int IsDigit(char ch) //判断ch是否为数字{int i;for(i=0;i<=10;i++)if (ch>='0'&&ch<='9')return 1;return 0;}int Isbound(char ch) //判断是否为界符{int i;for(i=0;i<2;i++)if(ch==bound[i]){return i+1;}}return 0;}int Isoperate(char ch) //判断是否为运算符{int i;for(i=0;i<4;i++){if(ch==operate[i]){return i+3;}}return 0;}int main(){FILE *fp;int q=0,m=0;char sour[200]=" ";printf("请将源文件置于以下位置并按以下方式命名:F:\\2.txt\n");if((fp=fopen("F:\\2.txt","r"))==NULL){printf("文件未找到!\n");}else{while(!feof(fp)){if(isspace(ch=fgetc(fp)));else{sour[q]=ch;q++;}}}int p=0;printf("输入句子为:\n");for(p;p<=q;p++)printf("%c",sour[p]);}printf("\n");int state=0,nowlen=0;BOOLEAN OK=TRUE,ERR=FALSE;int i,flagpoint=0;for(i=0;i<q;i++){if(sour[i]=='#')tokenlist[m].code=='#';switch(state){case 0:ch=sour[i];if(Isbound(ch)){if(ERR){printf("无法识别\n");ERR=FALSE;OK=TRUE;}else if(!OK){printf("<10,%s>标识符\n",nowword); tokentemp.code=10;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;OK=TRUE;}state=4;}else if(IsDigit(ch)){if(OK){memset(nowword,0,strlen(nowword)); nowlen=0;nowword[nowlen]=ch;nowlen++;state=3;OK=FALSE;break;}else{nowword[nowlen]=ch;nowlen++;}}else if(IsLetter(ch)){if(OK){memset(nowword,0,strlen(nowword));nowlen=0;nowword[nowlen]=ch;nowlen++;OK=FALSE;}else{nowword[nowlen]=ch;nowlen++;}}else if(Isoperate(ch)){if(!OK){printf("<10,%s>标识符\n",nowword);tokentemp.code=10;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;OK=TRUE;}printf("<%d,%c>运算符\n",Isoperate(ch),ch); tokentemp.code=Isoperate(ch);tokentemp.ch[10]=ch;tokenlist[m]=tokentemp;m++;}break;case 3:if(IsLetter(ch)){printf("错误\n");nowword[nowlen]=ch;nowlen++;ERR=FALSE;state=0;break;}if(IsDigit(ch=sour[i])){nowword[nowlen]=ch;nowlen++;}else if(sour[i]=='.'&&flagpoint==0){flagpoint=1;nowword[nowlen]=ch;nowlen++;}else{printf("<20,%s>数字\n",nowword);i--;state=0;OK=TRUE;tokentemp.code=20;tokentemp.ch[10]=nowword[10];tokenlist[m]=tokentemp;m++;}break;case 4:i--;printf("<%d,%c>界符\n",Isbound(ch),ch); tokentemp.code=Isbound(ch);tokentemp.ch[10]=ch;tokenlist[m]=tokentemp;m++;state=0;OK=TRUE;break;}}printf("tokenlist值为%d\n",m);int t=0;tokenlist[m+1].code='r';m++;for(t;t<m;t++){printf("tokenlist%d值为%d\n",t,tokenlist[t].code);}LL1();printf("tokenlist值为%d\n",m);if(op+1==m)printf("OK!!!");elseprintf("WRONG!!!");return 0;}void LL1(){STack s;init(&s);push(&s,'#');push(&s,'E');char ch;int flag=1;do{pop(&s,&ch);printf("输出栈顶为%c\n",ch);printf("输出栈顶为%d\n",ch);printf("当前p值为%d\n",op);if((ch=='(')||(ch==')')||(ch=='+')||(ch=='-')||(ch=='*')||(ch=='/')||(ch==10)||(ch==20)) {if(tokenlist[op].code==1||tokenlist[op].code==20||tokenlist[op].code==10||tokenlist[op].cod e==2||tokenlist[op].code==3||tokenlist[op].code==4||tokenlist[op].code==5||tokenlist[op].co de==6)op++;else{printf("WRONG!!!");exit(0);}}else if(ch=='#'){if(tokenlist[op].code==0)flag=0;else{printf("WRONG!!!");exit(0);}}else if(ch=='E'){printf("进入E\n");if(tokenlist[op].code==10||tokenlist[op].code==20||tokenlist[op].code==1) {push(&s,'R');printf("将R压入栈\n");push(&s,'T');}}else if(ch=='R'){printf("进入R\n");if(tokenlist[op].code==3||tokenlist[op].code==4){push(&s,'R');push(&s,'T');printf("将T压入栈\n");push(&s,'+');}if(tokenlist[op].code==2||tokenlist[op].code==0){}}else if(ch=='T'){printf("进入T\n");if(tokenlist[op].code==10||tokenlist[op].code==20||tokenlist[op].code==1) {push(&s,'Y');push(&s,'F');}}else if(ch=='Y'){printf("进入Y\n");if(tokenlist[op].code==5||tokenlist[op].code==6){push(&s,'Y');push(&s,'F');push(&s,'*');}elseif(tokenlist[op].code==3||tokenlist[op].code==2||tokenlist[op].code==0||tokenlist[op].code= =4){}}else if(ch=='F'){printf("进入F\n");if(tokenlist[op].code==10||tokenlist[op].code==20){push(&s,10);}if(tokenlist[op].code==1){push(&s,')');push(&s,'E');push(&s,'(');}}else{printf("WRONG!!!!");exit(0);}}while(flag);}程序运行结果:(截屏)输入:((Aa+Bb)*(88.2/3))#注:如需运行请将文件放置F盘,并命名为:2.txt输出:思考问题回答:LL(1)分析法的主要问题就是要正确的将文法化为LL (1)文法。

编译原理实验二语法分析器LL实现

编译原理实验二语法分析器LL实现

编译原理实验二语法分析器L L(1)实现(总12页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--编译原理程序设计实验报告——表达式语法分析器的设计班级:计算机1306班姓名:张涛学号:实验目标:用LL(1)分析法设计实现表达式语法分析器实验内容:⑴概要设计:通过对实验一的此法分析器的程序稍加改造,使其能够输出正确的表达式的token序列。

然后利用LL(1)分析法实现语法分析。

⑵数据结构:int op=0;逆序压栈ase=(char*)malloc(100 *sizeof(char));if(!(*s).base)exit(0);(*s).top=(*s).base;(*s).stacksize=100;printf("初始化栈\n");return 0;}int pop(STack *s,char *ch) op==(*s).base){printf("弹栈失败\n");return 0;}(*s).top--;*ch=*((*s).top);printf("%c",*ch);return 1;}int push(STack *s,char ch) op-(*s).base>=(*s).stacksize){(*s).base=(char*)realloc((*s).base,((*s).stacksize+10)*sizeof(char)); if(!(*s).base)exit(0);(*s).top=(*s).base+(*s).stacksize;(*s).stacksize+=10;}*(*s).top=ch;*(*s).top++;return 1;}void LL1();int IsLetter(char ch) ode=='#';switch(state){case 0:ch=sour[i];if(Isbound(ch)){if(ERR){printf("无法识别\n");ERR=FALSE;OK=TRUE;}else if(!OK){printf("<10,%s>标识符\n",nowword);=10;[10]=nowword[10];tokenlist[m]=tokentemp;m++;OK=TRUE;}state=4;}else if(IsDigit(ch)){if(OK){memset(nowword,0,strlen(nowword));nowlen=0;nowword[nowlen]=ch;nowlen++;state=3;OK=FALSE;break;}else{nowword[nowlen]=ch;nowlen++;}}else if(IsLetter(ch)){if(OK){memset(nowword,0,strlen(nowword)); nowlen=0;nowword[nowlen]=ch;nowlen++;OK=FALSE;}else{nowword[nowlen]=ch;nowlen++;}}else if(Isoperate(ch)){if(!OK){printf("<10,%s>标识符\n",nowword);=10;[10]=nowword[10];tokenlist[m]=tokentemp;m++;OK=TRUE;}printf("<%d,%c>运算符\n",Isoperate(ch),ch); =Isoperate(ch);[10]=ch;tokenlist[m]=tokentemp;m++;}break;case 3:if(IsLetter(ch))printf("错误\n");nowword[nowlen]=ch;nowlen++;ERR=FALSE;state=0;break;}if(IsDigit(ch=sour[i])){nowword[nowlen]=ch;nowlen++;}else if(sour[i]=='.'&&flagpoint==0){flagpoint=1;nowword[nowlen]=ch;nowlen++;}else{printf("<20,%s>数字\n",nowword);i--;state=0;OK=TRUE;=20;[10]=nowword[10];tokenlist[m]=tokentemp;m++;}break;case 4:i--;printf("<%d,%c>界符\n",Isbound(ch),ch); =Isbound(ch);[10]=ch;tokenlist[m]=tokentemp;m++;state=0;OK=TRUE;break;}}printf("tokenlist值为%d\n",m);tokenlist[m+1].code='r';m++;for(t;t<m;t++){printf("tokenlist%d值为%d\n",t,tokenlist[t].code);}LL1();printf("tokenlist值为%d\n",m);if(op+1==m)printf("OK!!!");elseprintf("WRONG!!!");return 0;}void LL1(){STack s;init(&s);push(&s,'#');push(&s,'E');char ch;int flag=1;do{pop(&s,&ch);printf("输出栈顶为%c\n",ch);printf("输出栈顶为%d\n",ch);printf("当前p值为%d\n",op);if((ch=='(')||(ch==')')||(ch=='+')||(ch=='-')||(ch=='*')||(ch=='/')||(ch==10)||(ch==20)){if(tokenlist[op].code==1||tokenlist[op].code==20||tokenlist[op].code==10||tokenlist[op].code==2||to kenlist[op].code==3||tokenlist[op].code==4||tokenlist[op].code==5||tokenlist[op].code==6)op++;else{printf("WRONG!!!");exit(0);}}else if(ch=='#'){if(tokenlist[op].code==0)flag=0;else{printf("WRONG!!!@@@@@@@@@");exit(0);}}else if(ch=='E'){printf("进入E\n");if(tokenlist[op].code==10||tokenlist[op].code==20||tokenlist[op].code==1) {push(&s,'R');printf("将R压入栈\n");push(&s,'T');}}else if(ch=='R'){printf("进入R\n");if(tokenlist[op].code==3||tokenlist[op].code==4){push(&s,'R');push(&s,'T');printf("将T压入栈\n");push(&s,'+');}if(tokenlist[op].code==2||tokenlist[op].code==0){}}else if(ch=='T'){printf("进入T\n");if(tokenlist[op].code==10||tokenlist[op].code==20||tokenlist[op].code==1) {push(&s,'Y');push(&s,'F');}}else if(ch=='Y'){printf("进入Y\n");if(tokenlist[op].code==5||tokenlist[op].code==6){push(&s,'Y');push(&s,'F');push(&s,'*');}elseif(tokenlist[op].code==3||tokenlist[op].code==2||tokenlist[op].code==0||tokenlist[op].code==4) {}}else if(ch=='F'){printf("进入F\n");if(tokenlist[op].code==10||tokenlist[op].code==20){push(&s,10);}if(tokenlist[op].code==1){push(&s,')');push(&s,'E');push(&s,'(');}}else{printf("WRONG!!!!");exit(0);}}while(flag);}程序运行结果:(截屏)输入:((Aa+Bb)*3))#注:如需运行请将文件放置F盘,并命名为:输出:思考问题回答:LL(1)分析法的主要问题就是要正确的将文法化为LL (1)文法。

编译原理实验二-语法分析器的设计

编译原理实验二-语法分析器的设计

班级:学号: 实验集美大学计算机工程学院实验报告课程名称:编译原理指导教师:实验项目编号:实验二实验项目名称:语法分析器的设计 一、 实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区 别和联系。

使了解语法分析的功能,掌握语法分析程序设计的原理和构造方法, 训练掌握开发应用程序的基本方法。

二、 实验容♦根据某一文法编制调试LL ( 1 )分析程序,以便对任意输入的符号串 进行分析。

♦构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分 析程序。

♦分析法的功能是利用LL (1)控制程序根据显示栈栈顶容、向前看符号以 及LL (1)分析表,对输入符号串自上而下的分析过程。

三、 实验要求1、 编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

2、 如果遇到错误的表达式,应输出错误提示信息。

四、 实验设计方案1、设计思想(1)、LL (1)文法的定义LL(1)分析法属于确定的自顶向下分析方法。

LL(1)的含义是:第一个L 表明 自顶向下分析是从左向右扫描输入串,第2个L 表明分析过程中将使用最左推导, 1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推 导。

LL(1)文法的判别需要依次计算FIRST 集、FOLLOW 集和SELLECT 集,然后判 断是否为LL(1)文法,最后再进行句子分析。

需要预测分析器对所给句型进行识别。

即在LL(1)分析法中,每当在符号栈 的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现 终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析, 否则报错。

LL(1)分析方法要求文法满足如下条件:对于任一非终极符A 的两个 不同产生式都要满足下面条件:SELECT(A->a) ASELECT(A->p)=0(2)、预测分析表构造LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推导。

语法分析器的设计与实现

语法分析器的设计与实现
辅导教师成绩
实验日期
实验时间
1实验名称语法分析器的设计与实现
2、实验目的
掌握自上而下语法分析方法、自下而上语法分析方法
3、实验要求
(1)实验内容:四选一
1设计及实现能够识别表达式的预测分析程序。
文法如下:
G[E]:E->E+T|T
T->T*F|F
F->(E)|i
2设计及实现能够识别表达式的LR分析程序。
st.push(ch[i]);
}
}
int find(char c,char array[],int n) //查找函数,返回布尔值
{
int i;
int flag=0;
for(i=0;i<n;i++)
{
if(c==array[i])
flag=1;
}
return flag;
}
int location(char c,char array[]) //定位函数,指出字符所在位置,即将字母转换为数组下标值
{error();break;} //对应项为空,则出错
else
{
string str0=M[p][q];
cout<<" "<<X<<"-->"<<str0<<endl; //显示对应的产生式
st.pop();
if(str0!="$") //$代表“空”字符
for(i=str0.size()-1;i>=0;i--) st.push(str0[i]);//产生式右端逆序进栈
#include <stack>

语法分析器实验报告2

语法分析器实验报告2

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

二实验要求 要求语法分析器的输入是单词串(含词的字符串形式、在源文件中的起止位置、 词的类别),输出是源程序中各句子的单词起止编号、句子的语法树。

三实验内容 以下不同语法分析器中任选一个: 1.2. 3. 4. 递归下降分析器。

可分解为:文法输入及解析、消除左递归、提取左公 共因子、产生式匹配。

LL(1)分析器。

可分解为:文法输入及解析、分析表构造(含SELECT 集 求解)、主控程序、语法树展示。

算符优先文法分析器。

可分解为:文法输入及解析、分析表构造、主控 程序、语法树展示。

LR(1)分析器。

可分解为:文法输入及解析、分析表构造(含项目及项目 簇集求解)、主控程序、语法树展示。

四、实验步骤 给定的文法G[E] E->TE' E'->+TE' | £ T->FT' T'->*F T ' | £ F->(E) | i 采用递归下降分析法编写语法分析程序及 LL (1)语法分析法编写语法分析程序。

实验代码: #include<stdio.h> #in clude<stri ng.h> #in clude<malloc.h> #defi ne N 100 int seek Prod(i nt stackT op ,i nt inpu tstrT op); //char inpu tstr[10]="i*i+i#"; char inpu tstr[20]; char stack[10]=""; typ edef struct p roducti on{ char leftChar; char rightChars[4]; char allChars[8]; }P rod;Prod p roduct ion s[8]; void in it(); int stack Pu sh(i nt *top, Prod p rod); int matchi ng(i nt *top, char *inpu tstr);int mai n()int le n;//输入串的长度int stackTop=1;int inputstrTop=0;int i;char *z="#";int index=0;init();//产生式初始化stack[0]='#'; stack[stackTop]='E';printf(" 请输入字符串: ");gets(inputstr);len=strlen(inputstr);inputstr[len]='#';while( stackTop>=0 ){// printf("%d,%d\n",stackTop,inputstrTop);printf(” 第%2d 步:",++index);printf(" 当前栈: %-8s",stack);printf(" 输入字符串: %8s",inputstr);//根据栈定元素和字符串首字母if(matching(&stackTop,inputstr)){ printf("\n");}else{i=seekProd(stackTop,inputstrTop);stackPush(&stackTop,productions[i]);// 压栈printf(" 进行下一步所用的产生式: %s\n",productions[i].allChars);}}if(stackTop+1==0){printf(" 分析成功! \n");}return 0;}//搜索分析表int seekProd(int stackTop,int inputstrTop){// printf("stack[stackTop]=%c\n",stack[stackTop]);if(stack[stackTop]=='E'){if(inputstr[inputstrTop]=='i'){return 0;}else if(inputstr[inputstrTop]=='('){return 0;}else{return -1;}}else if(stack[stackTop]=='X'){ if(inputstr[inputstrTop]=='+') {return 1;}elseif(inputstr[inputstrTop]==')'){return 2;}elseif(inputstr[inputstrTop]=='#'){return 2;}else{return -1;}}else if(stack[stackTop]=='T'){ if(inputstr[inputstrTop]=='i') {return 3;}elseif(inputstr[inputstrTop]=='('){return 3;}else{return -1;}}else if(stack[stackTop]=='Y'){ if(inputstr[inputstrTop]=='+') {return 5;}elseif(inputstr[inputstrTop]=='*'){return 4;}elseif(inputstr[inputstrTop]==')'){return 5;}elseif(inputstr[inputstrTop]=='#'){return 5;}else{return -1;}}else if(stack[stackTop]=='F'){ if(inputstr[inputstrTop]=='i'){ return 7;}elseif(inputstr[inputstrTop]=='('){return 6;}else{return -1;}}else{ printf(" 错误! ");}return -1;}void init(){ productions[0].leftChar='E';strcpy(productions[0].rightChars,"TX");strcpy(productions[0].allChars,"E->TX"); productions[1].leftChar='X';strcpy(productions[1].rightChars,"+TX");strcpy(productions[1].allCh ars,"E->+TX");productions[2].leftChar='X';strcpy(productions[2].rightChars,"strcpy(productions[2].allChars,"X- >£ ");productions[3].leftChar='T';strcpy(productions[3].rightChars,"FY");strcpy(productions[3].allChars,"T->FY"); productions[4].leftChar='Y';strcpy(productions[4].rightChars,"*FY");strcpy(productions[4].allCha rs,"Y->*FY");productions[5].leftChar='Y';strcpy(productions[5].rightChars,"strcpy(productions[5].allChars,"Y- >£ "); productions[6].leftChar='F';strcpy(productions[6].rightChars,"(E)");strcpy(productions[6].allChars ,"F->(E)");productions[7].leftChar='F';strcpy(productions[7].rightChars,"i");strcpy(productions[7].allChars,"F->i");}int stackPush(int *top, Prod prod){int len;int i;char *c=" £ "; len=strlen(prod.rightChars); if(!strcmp(prod.rightChars,c)) { stack[(*top)]='\0';}else{ for(i=len-1;i>=0;i--){ stack[(*top)++] = prod.rightChars[i];}}--(*top);return 0;");£ ");}int matchi ng(i nt *top, char *inpu tstr) {int len; int i;if(stack[(*to p) ]==i npu tstr[0]) {stack[(*to p)--]='\0'; len=strle n(i npu tstr); for(i=0;i<le n-1;i++) {inpu tstr[i]=i npu tstr[i+1]; }inp utstr[i]='\O'; return 1; }else {return 0; } }实验截图:通过这次的实验,我深入了解了语法分析器和 LL(1)文法预测分析法设计和实现,增强了我的自学能力和独立思考能力,也让我对程序设计有了更大的兴趣,自己通过查找资料、 复习课本、编程调试,写实验报告等环节,进一步掌握了以前学到的知识,并且还对编译原理应用有了更深入的认识与掌握。

编译原理语法分析实验二表达式语法分析器的设计实现

编译原理语法分析实验二表达式语法分析器的设计实现

编译原理程序设计实验报告——实验题目班级:计算机1306姓名:学号:实验目标:表达式语法分析器的设计实现1) 递归下降子程序 2) LL (1)分析法实验内容: 1. 概要设计1) 按照流程图,调用子程序实现;2) 通过ll (1)分析表和对应压栈、弹栈操作实现。

2. 流程图1) 递归: Z ’(main):N Err开始Read (w ) E #? 结束E: E1:Y NY NT: T1:YNYNF :N N err Y YY N err入口 TE1 入口+? -? 出口Read(w) T出口入口 FT1 出口入口*?/?出口Read (w )T入口I ? (? Read (w )E )? Read (w )出口2) LL (1):BeginPUSH(#),PUSH(E)POP(x)x ∈VTx ∈VNx=wendW=#nyNEXT(w)yn err查LL (1)分析表空?nPUSH (i )errny逆序压栈开始构建LL(1)分析表调用函数token ()切分单词 调用*Analyse(char *token)进行分析 结束3.关键函数1)递归下降子程序void E(); //E->TX;int E1(); //X->+TX | evoid T(); //T->FYint T1(); //Y->*FY | eint F(); //F->(E) | i2)LL(1)分析法char *Find(char vn,char vt)//是否查到表char *Analyse(char *token)//分析过程int Token()//将token中数字表示成i,标识符表示成n源程序代码:(加入注释)1)递归下降子程序:#include<stdio.h>#include<iostream>#include <string.h>#include <stdlib.h>using namespace std;/********全局变量**********/char str[30];int index=0;void E();//E->TX;int E1();//X->+TX | evoid T();//T->FYint T1();//Y->*FY | eint F();//F->(E) | iFILE *fp;char cur;/*************主函数************/int main(){int len;int m;if((fp=fopen("source.txt","r"))==NULL){cout<<"can not open the source file!"<<endl;exit(1);}cur=fgetc(fp);while(cur!='#'){E();}cout<<endl;cout<<"success"<<endl;return 0;}/*************************************/void E(){T();E1();}/*************************************/int E1(){if(cur=='+'){cur=fgetc(fp);T();cout<<'+'<<" ";E1();}else if(cur=='-'){cur=fgetc(fp);T();cout<<'-'<<" ";E1();}return 0;}/************************************/void T(){F();T1();}/***********************************/int T1(){if(cur=='*'){cur=fgetc(fp);F();cout<<'*'<<" ";T1();}else if(cur=='/'){cur=fgetc(fp);F();cout<<'/'<<" ";T1();}return 0;}int F(){if((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'){for(int i=0;i<20;i++){str[i]='\0';index=0;}str[index++]=cur;cur=fgetc(fp);while((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'||(cur<='9'&&cur>='0')){str[index++]=cur;cur=fgetc(fp);}cout<<str;cout<<" ";return NULL;}else if (cur<='9'&&cur>='0'){for(int i=0;i<20;i++){str[i]='\0';index=0;}while(cur<='9'&&cur>='0'){str[index++]=cur;cur=fgetc(fp);}if(cur=='.'){str[index++]=cur;cur=fgetc(fp);while(cur<='9'&&cur>='0'){str[index++]=cur;cur=fgetc(fp);}cout<<str;cout<<" ";return NULL;}else if((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'){printf("error6\n");exit(1);}else{cout<<str;cout<<" ";return NULL;}}else if (cur=='('){cur=fgetc(fp);E();if(cur==')'){cur=fgetc(fp);return 0;}else{printf("error3\n");exit (1);}}else{printf("error4\n");exit(1);}return 0;}程序运行结果:(截屏)输入:Source.txt文本((Aa+Bb)*(88.2/3))#输出:2)LL(1)#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <stack>using namespace std;struct Node1{char vn;char vt;char s[12];}MAP[22];//存储分析预测表每个位置对应的终结符,非终结符,产生式int k;char token[30];int token_index=0;charG[12][12]={"E->TR","R->+TR","R->-TR","R->e","T->FW","W->*FW","W->/FW", "W->e","F->(E)","F->i","F->n"};//存储文法中的产生式,用R代表E',W代表T',e代表空//char VN[6]={'E','R','T','W','F'};//存储非终结符//char VT[9]={'i','n','+','-','*','/','(',')','#'};//存储终结符char Select[12][12]={"(,i,n","+","-","),#","(,i,n","*","/","+,-,),#","(","i","n"};//存储文法中每个产生式对应的select集合charRight[12][8]={"->TR","->+TR","->-TR","->e","->FW","->*FW","->/FW","->e","->( E)","->i","->n"};stack<char> stak,stak1,stak2;char *Find(char vn,char vt){int i;for(i=0;i<k;i++){if(MAP[i].vn==vn&& MAP[i].vt==vt)return MAP[i].s;}return "error";}char *Analyse(char *token){char p,action[10],output[10];int i=1,j,k=0,l_act,m;while(!stak.empty())//判断栈中是否为空,若不空就将栈顶元素与分析表匹配进行相应操作stak.pop();stak.push('#');//栈底标志stak.push('E');//起始符号先入栈printf(" 步骤栈顶元素输入串推导所用产生式或匹配\n");p=stak.top();while(p!='#')//查预测分析表将栈顶元素进行匹配,若栈顶元素与输入串匹配成功则向前匹配,否则生成式反序入栈{printf("%7d ",i++);p=stak.top();//从栈中弹出一个栈顶符号,由p记录并输出stak.pop();printf("%6c ",p);for(j=0,m=0;j<token_index;j++)//将未被匹配的剩余输入串输出output[m++]=token[j];output[m]='\0';printf("%10s",output);if(p==token[k]){ if(p=='#')//若最后一个结束符号匹配说明输入表达式被接受,否则继续匹配{printf(" 接受\n");return "SUCCESS";}printf(" “%c”匹配\n",p);k++;}else{ //将未被匹配的第一个字符与find函数的结果进行比较,在预测分析表中查找相应生成式strcpy(action,Find(p,token[k]));if(strcmp(action,"error")==0){printf(" 没有可用的产生式\n");return "ERROR";}printf(" %c%s\n",p,action);int l_act=strlen(action);if(action[l_act-1]=='e')continue;for(j=l_act-1;j>1;j--)stak.push(action[j]);}}return "ERROR";}int Token(){FILE *fp;char cur;int i,j;fp=fopen("source.txt","r");cur=fgetc(fp);while(cur!=EOF)//把用字母数字表示的输入串转换为token序列的表示方法{if((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'){cur=fgetc(fp);while((cur<='z'&&cur>='a')||(cur<='Z'&&cur>='A')||cur=='_'||(cur<='9'&&cur>='0')){cur=fgetc(fp);} token[token_index++]='i';continue;}else if (cur<='9'&&cur>='0'){while(cur<='9'&&cur>='0')cur=fgetc(fp);if(cur=='.'){cur=fgetc(fp);while(cur<='9'&&cur>='0')cur=fgetc(fp);}token[token_index++]='n';continue;}else{token[token_index++]=cur;cur=fgetc(fp);continue;} }token[token_index]='#';cout<<"把文件中字符串用i表示,数字用n表示,转化后:";for(int index=0;index<=token_index;index++)cout<<token[index];cout<<endl<<endl;return 0;}int main (){int i,j,l,m;for(i=0,k=0;i<11;i++)//通过select集合生成预测分析表{l=strlen(Select[i]);for(j=0;j<l;j+=2){MAP[k].vn=G[i][0];MAP[k].vt=Select[i][j];strcpy(MAP[k].s,Right[i]);k++;}}Token();cout<<"分析过程如下:"<<endl;cout<<Analyse(token)<<endl;return 0;}程序运行结果:(截屏)输入:Source.txt文本((Aa+Bb)*(88.2/3))输出:目录第一章项目总论 ········································错误!未定义书签。

实验二 语法分析器

实验二 语法分析器

实验二自上而下的语法分析器
一、实验目的
设计、编制并调试一个自下而上的语法分析程序(非递归),加深对LL(1)文法,预测分析表的理解并实现对简单文法句子的分析。

二、设计要求
编写预测法分析程序,对于给定的文法和词法分析器得到的句子能够给出分析过程结束。

测试数据:
简单算术运算文法G[E]:
E→TR
R → +TR|ε
T→FW
W→*FW |ε
F→(E) |i
(1)手工计算非终结符的FIRST和FOLLOW集合
判断是否是LL(1)文法
(2)手工计算该文法的预测分析表,存储在数组中
输出要求
(1)编写代码输出该文法的预测分析表
(2)输出符号串i+i*i的分析过程
三、实验结果
文法:
预测分析表:
符号串i+i*i的分析过程
四.实验总结
1.源代码
2.总结和体会。

编译原理实验词法分析器与语法分析器实现

编译原理实验词法分析器与语法分析器实现

编译原理实验词法分析器与语法分析器实现词法分析器与语法分析器是编译器的两个重要组成部分,它们在编译过程中扮演着至关重要的角色。

词法分析器负责将源代码转化为一个个标记(token)序列,而语法分析器则根据词法分析器生成的标记序列构建语法树,验证源代码的语法正确性。

本实验旨在实现一个简单的词法分析器和语法分析器。

实验一:词法分析器实现在实现词法分析器之前,需要定义所需词法项的规则。

以C语言为例,常见的词法项包括关键字(如int、if、for等)、标识符、运算符(如+、-、*、/等)、常量(如整数、浮点数等)和分隔符(如括号、逗号等)。

接下来,我们来实现一个简单的C语言词法分析器。

1. 定义词法项的规则在C语言中,关键字和标识符由字母、数字和下划线组成,且首字符不能为数字。

运算符包括各种数学运算符和逻辑运算符。

常量包括整数和浮点数。

分隔符包括括号、逗号等。

2. 实现词法分析器的代码下面是一个简单的C语言词法分析器的实现代码:```pythondef lexer(source_code):keywords = ['int', 'if', 'for'] # 关键字列表operators = ['+', '-', '*', '/'] # 运算符列表separators = ['(', ')', '{', '}', ',', ';'] # 分隔符列表tokens = [] # 标记序列列表current_token = '' # 当前标记for char in source_code:if char.isspace(): # 如果是空格,则忽略continueelif char.isalpha(): # 如果是字母,则可能是关键字或标识符的一部分current_token += charelif char.isdigit(): # 如果是数字,则可能是常量的一部分current_token += charelif char in operators or char in separators: # 如果是运算符或分隔符,则当前标记结束if current_token:tokens.append(current_token)current_token = ''tokens.append(char)else: # 如果是其他字符,则当前标记结束if current_token:tokens.append(current_token)current_token = ''return tokens```以上代码通过遍历源代码的字符,根据定义的规则生成一个个标记,存储在`tokens`列表中。

语法分析器设计实验报告

语法分析器设计实验报告

学号《编译原理》实验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)简述该语法分析器的算法思想。

编译原理实验二:LL(1)语法分析器

编译原理实验二:LL(1)语法分析器

编译原理实验⼆:LL(1)语法分析器⼀、实验要求 1. 提取左公因⼦或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下⾯我贴出实验的⼀些关键代码和算法思想。

⼆、基于预测分析表法的语法分析 2.1 代码结构 2.1.1 Grammar类 功能:主要⽤来处理输⼊的⽂法,包括将⽂法中的终结符和⾮终结符分别存储,检测直接左递归和左公因⼦,消除直接左递归,获得所有⾮终结符的First集,Follow集以及产⽣式的Select集。

#ifndef GRAMMAR_H#define GRAMMAR_H#include <string>#include <cstring>#include <iostream>#include <vector>#include <set>#include <iomanip>#include <algorithm>using namespace std;const int maxn = 110;//产⽣式结构体struct EXP{char left; //左部string right; //右部};class Grammar{public:Grammar(); //构造函数bool isNotTer(char x); //判断是否是终结符int getTer(char x); //获取终结符下标int getNonTer(char x); //获取⾮终结符下标void getFirst(char x); //获取某个⾮终结符的First集void getFollow(char x); //获取某个⾮终结符的Follow集void getSelect(char x); //获取产⽣式的Select集void input(); //输⼊⽂法void scanExp(); //扫描输⼊的产⽣式,检测是否有左递归和左公因⼦void remove(); //消除左递归void solve(); //处理⽂法,获得所有First集,Follow集以及Select集void display(); //打印First集,Follow集,Select集void debug(); //⽤于debug的函数~Grammar(); //析构函数protected:int cnt; //产⽣式数⽬EXP exp[maxn]; //产⽣式集合set<char> First[maxn]; //First集set<char> Follow[maxn]; //Follow集set<char> Select[maxn]; //select集vector<char> ter_copy; //去掉$的终结符vector<char> ter; //终结符vector<char> not_ter; //⾮终结符};#endif 2.1.2 AnalyzTable类 功能:得到预测分析表,判断输⼊的⽂法是否是LL(1)⽂法,⽤预测分析表法判断输⼊的符号串是否符合刚才输⼊的⽂法,并打印出分析过程。

语法分析器的设计

语法分析器的设计
token = getnexttoken(); const_st(token);/*调用分析常量说明的函数*/ } if (token = "var") { /*表明下面是说明语句*/ token = getnexttoken(); varst(token);/*调用分析变量说明的函数*/ } token = getnexttoken(); /*下面是可执行部分的开始*/ if ( token = "begin") { token = getnexttoken(); ST_SORT(token); /*处理各种可执行语句*/ } token = getnexttoken(); if (token = ".") {/*处理程序结束*/
token = getnexttoken(); bf(); /*递归调用,not 后面应跟随另一个布尔量*/ } else /*处理括号(*/ if ( token = "(" ) {
token = getnexttoken( );
编译原理实验指导书
bexp( ); /*括号中仍然是表达式*/ token = getnexttoken( ); if ( token = ")" ) /*括号中的表达式处理完毕,后跟右括号*/
编译原理实验指导书
《编译原理》综合性实验二:
语法分析器的设计
实验目的:掌握高级语言语法结构的定义,掌握语法分析的常用方法――递归下降的分析方 法。 实验要求:在 6 学时内完成全部内容,要求用 VC++窗口界面实现。 实验内容:分为 3 次实验内容完成。
2.1 语法分析程序的设计要求
语法分析程序要求能实现 Sample 语言中几种最常见的、基本的语法单位的分析:算术 表达式、逻辑表达式、赋值语句、IF 语句、for 语句、while 语句、repeat 语句等,各个语法 单位的定义见第 1 章,要求有完整的程序和说明。

语法分析器的设计与实现

语法分析器的设计与实现

语法分析器的设计与实现一、设计概述1.定义语法规则:根据所设计的编程语言,确定其语法规则。

可以使用文法或者EBNF(扩展巴科斯-诺尔范式)来定义语法规则。

2. 设计语法分析算法:选择适合的语法分析算法,常见的有自顶向下(Top-Down)和自底向上(Bottom-Up)两种。

自顶向下算法从语法规则的起始符号开始,逐步向下匹配源代码,构建语法树。

自底向上算法则通过逐步将输入的源代码规约为语法规则的右侧,最终得到语法树。

3.实现语法分析器:根据所选择的语法分析算法,实现相应的算法,根据文法定义和源代码进行语法分析。

二、自顶向下语法分析自顶向下语法分析是一种递归的、自上而下构造语法树的方法。

它以文法的起始符号为目标,通过不断向下匹配文法规则,构造出整个语法树。

自顶向下语法分析的步骤如下:1.设计非终结符的产生规则:根据文法的非终结符定义产生规则。

非终结符表示语法规则的左侧。

2.设计终结符的匹配规则:根据文法的终结符定义匹配规则。

终结符表示具体的代码元素,如标识符、关键字等。

3.设计递归下降分析算法:根据文法的产生规则,设计递归下降分析算法。

算法的入口是文法的起始符号,通过递归调用不同的产生规则,不断向下匹配源代码,构造语法树。

三、自底向上语法分析自底向上语法分析是一种逆推的、以产生规则的右侧为目标的方法。

它通过逐步将源代码的串规约为文法规则的右侧,最终得到语法树。

自底向上语法分析的步骤如下:1.设计终结符的匹配规则:根据文法的终结符定义匹配规则。

2.设计产生规则的规约动作:根据文法的产生规则,为每个规则设计规约动作。

规约动作通常是将产生规则的右侧转化为左侧的非终结符。

3.设计移进-规约分析算法:根据终结符的匹配规则和产生规则的规约动作,实现移进-规约分析算法。

算法通过逐步将输入的源代码进行移进和规约操作,直到得到语法树。

四、错误处理在语法分析的过程中,可能会出现各种错误,如语法错误、缺失分号、括号不匹配等。

语法分析器实验报告

语法分析器实验报告

语法分析器实验报告实验报告:语法分析器的设计与实现摘要:语法分析器是编译器的一个重要组成部分,主要负责将词法分析器输出的词法单元序列进行分析和解释,并生成语法分析树。

本实验旨在设计与实现一个基于上下文无关文法的语法分析器,并通过实现一个简单的编程语言的解释器来验证其功能。

1.引言在计算机科学中,编译器是将高级程序语言转化为机器语言的一种工具。

编译器通常由词法分析器、语法分析器、语义分析器、中间代码生成器、优化器和目标代码生成器等多个模块组成。

其中,语法分析器负责将词法分析器生成的词法单元序列进行进一步的分析与解释,生成语法分析树,为后续的语义分析和中间代码生成提供基础。

2.设计与实现2.1上下文无关文法上下文无关文法(CFG)是指一类形式化的语法规则,其中所有的产生式规则都具有相同的左部非终结符,且右部由终结符和非终结符组成。

语法分析器的设计与实现需要依据给定的上下文无关文法来进行,在本实验中,我们设计了一个简单的CFG,用于描述一个名为"SimpleLang"的编程语言。

2.2预测分析法预测分析法是一种常用的自顶向下的语法分析方法,它利用一个预测分析表来决定下一步的推导选择。

预测分析表的构造依赖于给定的上下文无关文法,以及文法的FIRST集和FOLLOW集。

在本实验中,我们使用了LL(1)的预测分析法来实现语法分析器。

2.3语法分析器实现在实现语法分析器的过程中,我们首先需要根据给定的CFG构造文法的FIRST集和FOLLOW集,以及预测分析表。

接下来,我们将词法分析器输出的词法单元序列作为输入,通过不断地匹配输入符号与预测分析表中的预测符号,进行语法分析和推导。

最终,根据CFG和推导过程,构建语法分析树。

3.实验结果与分析通过实验发现,自顶向下的预测分析法在对简单的编程语言进行语法分析时具有较高的效率和准确性。

语法分析器能够正确地识别输入程序中的语法错误,并生成相应的错误提示信息。

语法分析器实验报告

语法分析器实验报告

杭州电子科技大学班级: 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)、SLR(1)、LR(1)等,经过设计、编制、调试实现一个经典语法分析程序,对试验一所得扫描器提供单词序列进行语法检验和结构分析,实现并深入掌握常见语法分析方法。

二、基础试验内容和要求选择对多种常见高级程序设计语言全部较为通用语法结构——算术表示式一个简化子集——作为分析对象,依据以下描述其语法结构BNF定义G2[<算术表示式>],任选一个学过语法分析方法,针对运算对象为无符号常数和变量四则运算,设计并实现一个语法分析程序。

G2[<算术表示式>]:<算术表示式> → <项> | <算术表示式>+<项> | <算术表示式>-<项><项> → <因式> | <项>*<因式> | <项>/<因式><因式> → <运算对象> | (<算术表示式>)若将语法范围<算术表示式>、<项>、<因式>和<运算对象>分别用E、T、F和i代表,则G2可写成:G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E)输入:由试验一输出单词串,比如:UCON,PL,UCON,MU,ID ······输出:若输入源程序中符号串是给定文法句子,则输出“RIGHT”,而且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,而且显示分析至此所得中间结果,如分析栈、符号栈中信息等,和必需犯错说明信息。

要求:1、确定语法分析程序步骤图,同时考虑对应数据结构,编写一个语法分析源程序。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验二语法分析器的设计与实现
一、实验目的
构造一个小语言的语法分析程序。

二、实验要求
输入属性字文件,输出源程序是否符合语法要求的结果。

正确——该程序符合语法要求
错误——指出错误位置
三、实验说明
1、总体说明
构造并存储预测分析表,构造分析器,并能进行出错处理,实现LL(1)分析法。

设计好一个文法,消除文法的左递归性。

将消除了左递归性的文法,构造每个非终结符的FIRST和FOLLOW集合。

根据FIRST和FOLLOW集合构造LL(1)分析表。

然后,利用分析表,根据LL(1)语法分析构造一个分析器。

2、语法描述
文法:E→E+T | T
T→T*F | F
F→( E ) | i
经消去左递归后变成:E→TP
P→+TP | ε
T→FQ
Q→*FQ | ε
F→( E ) | i
3、设计原理
LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a行事的。

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

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

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

②FOLLOW集合的构造算法
四、实验成果提交
1、非终结符的FIRST集合
2、非终结符的FOLLOW集合
3、预测分析表
4、程序流程图
5、源代码
6、程序运行说明及测试数据。

相关文档
最新文档