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

合集下载

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

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

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

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

正确——该程序符合语法要求
错误——指出错误位置
三、实验说明
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、程序运行说明及测试数据。

编译原理语法分析器实验报告

编译原理语法分析器实验报告

编译原理语法分析器实验报告班级:学号:姓名:实验名称语法分析器一、实验目的1、根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。

2、本次实验的目的主要是加深对自上而下分析法的理解。

二、实验内容[问题描述]递归下降分析法:0.定义部分:定义常量、变量、数据结构。

1.初始化:从文件将输入符号串输入到字符缓冲区中。

2.利用递归下降分析法分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。

LL(1)分析法:模块结构:1、定义部分:定义常量、变量、数据结构。

2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等);3、运行程序:让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则;4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简单的错误提示。

[基本要求]1. 对数据输入读取2. 格式化输出分析结果2.简单的程序实现词法分析public static void main(String args[]) {LL l = new LL();l.setP();String input = "";boolean flag = true;while (flag) {try {InputStreamReader isr = newInputStreamReader(System.in);BufferedReader br = new BufferedReader(isr);System.out.println();System.out.print("请输入字符串(输入exit退出):");input = br.readLine();} catch (Exception e) {e.printStackTrace();}if(input.equals("exit")){flag = false;}else{l.setInputString(input);l.setCount(1, 1, 0, 0);l.setFenxi();System.out.println();System.out.println("分析过程");System.out.println("----------------------------------------------------------------------");System.out.println(" 步骤| 分析栈| 剩余输入串| 所用产生式");System.out.println("----------------------------------------------------------------------");boolean b = l.judge();System.out.println("----------------------------------------------------------------------");if(b){System.out.println("您输入的字符串"+input+"是该文法的一个句子");}else{System.out.println("您输入的字符串"+input+"有词法错误!");}}}}//实现各函数并且加注释三、编程并上机调试运行运行结果如下图:四、实验小结通过这次实验,我对语法分析有了更深刻的了解,对它的形成有了更清楚得认识。

编译原理实验二语法分析器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)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推导。

编译原理语法分析器实验报告

编译原理语法分析器实验报告

西安邮电大学编译原理实验报告学院名称:计算机学院****:***实验名称:语法分析器的设计与实现班级:计科1405班学号:04141152时间:2017年5月12日一.实验目的1.熟悉语法分析的过程2.理解相关文法分析的步骤3.熟悉First集和Follow集的生成二.实验要求对于给定的文法,试编写调试一个语法分析程序:要求和提示:1)可选择一种你感兴趣的语法分析方法(LL(1)、算符优先、递归下降、SLR(1)等)作为编制语法分析程序的依据。

2)对于所选定的分析方法,如有需要,应选择一种合适的数据结构,以构造所给文法的机内表示。

3)能进行分析过程模拟。

如输入一个句子,能输出与句子对应的语法树,能对语法树生成过程进行模拟;能够输出分析过程每一步符号栈的变化情况。

设计一个由给定文法生成First集和Follow集并进行简化的算法动态模拟三.实验内容1.文法:E->TE’E’->+TE’|εT->FT’T’->*FT’|εF->(E)|i:2.程序描述(LL(1)文法)本程序是基于已构建好的某一个语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。

基本实现思想:接收用户输入的字符串(字符串以“#”表示结束)后,对用做分析栈的一维数组和存放分析表的二维数组进行初始化。

然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,若是则语法分析结束,输入的字符串为文法的一个句子,否则出错若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。

若不为“#”且不与当前输入符号一样,则出错。

3.判断是否LL(1)文法要判断是否为LL(1)文法,需要输入的文法G有如下要求:具有相同左部的规则的SELECT集两两不相交,即:SELECT(A→?)∩SELECT(A→?)= ?如果输入的文法都符合以上的要求,则该文法可以用LL(1)方法分析。

编译原理_语法分析器

编译原理_语法分析器

编译原理实验报告语法分析器一.实验目的及内容实验目的:编制一个语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析。

实验内容:在上机(一)词法分析的基础上,采用递归子程序法或其他适合的语法分析方法,实现其语法分析程序。

要求编译后能检查出语法错误。

已知待分析的C语言子集的语法,用EBNF表示如下:<程序>→main()<语句块><语句块> →‘{’<语句串>‘}’<语句串> → <语句> {; <语句> };<语句> → <赋值语句> |<条件语句>|<循环语句><赋值语句>→ID=<表达式><条件语句>→if‘(‘条件’)’<语句块><循环语句>→while’(‘<条件>’)‘<语句块><条件> → <表达式><关系运算符> <表达式><表达式> →<项>{+<项>|-<项>}<项> → <因子> {* <因子> |/ <因子>}<因子> →ID|NUM| ‘(’<表达式>‘)’<关系运算符> →<|<=|>|>=|==|!=二、实验原理及基本技术路线图(方框原理图或程序流程图)三、所用仪器、材料(设备名称、型号、规格等或使用软件)1台PC以及VISUAL C++6.0软件四、实验方法、步骤(或:程序代码或操作过程)#include <iostream>#include <string>using namespace std;char prog[80],token[8];char ch;int syn,p,m,n,sum,k=0;char *key[6]={"main","int","char","if","else","while"};void scaner();void lrparser();void yucu();void statement();void expression();void term();void factor();void main(){p=0;cout<<"语法分析"<<endl;cout<<"请输入字符串,以“@”结尾:"<<endl;do {ch = getchar(); prog[p++]=ch;}while(ch!='@');p=0;scaner();lrparser();}void scaner(){sum=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';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,key[n])==0){syn=n+1; break;}}else if(ch>='0'&&ch<='9'){while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=20;}elseswitch(ch){case '<': m=0;token[m++]=ch;ch=prog[p++];if(ch=='<') {syn=33; token[m++]=ch;}else if(ch=='=') {syn=35; token[m++]=ch;}break;case '>': m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=34; token[m++]=ch;}else {syn=32; p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=36;token[m++]=ch;}else{ syn=21;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=22; token[0]=ch; break;case '-': syn=23; token[0]=ch; break;case '*': syn=24; token[0]=ch; break;case '/': syn=25; token[0]=ch; break;case ';': syn=31; token[0]=ch; break;case '(': syn=26; token[0]=ch; break;case ')': syn=27; token[0]=ch; break;case '@': syn=0; token[0]=ch; break;default : syn=-1;}}void lrparser(){if(syn==1){scaner();yucu();if(syn=6){scaner();if(syn==0 && (k==0))cout<<"\nsuccess\n"<<endl;}else{if(k!=1)cout<<"\nwhile error\n"<<endl;k=1;}}else{cout<<"\nmain error\n"<<endl;k=1;}return;}void yucu(){statement();while(syn==31){scaner();statement();}return;}void statement(){if(syn==10){scaner();if(syn==18){scaner();expression();}else{cout<<"\nscentence error\n"<<endl;k=1;}}return;}void expression(){term();while(syn==22||syn==23){scaner();term();}return;}void term(){factor();while(syn==24||syn==25){scaner();factor();}return;}void factor(){if(syn==10||syn==20)scaner();else if(syn==26){scaner();expression();if(syn==27)scaner();else{cout<<"( error"<<endl;k=1;}}else{cout<<"expression error"<<endl;k=1;}return;}五、实验过程原始记录( 测试数据、图表、计算等)六、实验结果、分析和结论(误差分析与数据处理、成果总结等。

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

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

编译原理程序设计实验报告——实验题目班级:计算机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)文法的语法分析器,深入了解语法分析的原理和实现方法。

二、实验目标本实验的目标是设计一个能够接受一个输入的程序代码并进行语法分析的程序。

具体而言,需要实现以下功能:1. 构建一个文法规则集合,用于描述程序代码的语法规范;2. 设计并实现一个LL(1)分析表,用于存储语法分析所需的预测分析表;3. 实现语法分析器,能够根据输入的程序代码,逐步地进行语法分析,并输出相应的结果。

三、实验环境本实验使用的是Java语言进行实现,操作系统环境为Windows 10。

使用的集成开发环境为Eclipse。

四、实验步骤1. 设计文法规则集合在语法分析器设计中,首先需要设计一个文法规则集合,用于描述需要分析的程序代码的语法规范。

文法规则集合的设计要符合LL(1)文法的要求,即每个非终结符的产生式至多有一个与输入符号串首符号相关的产生式。

2. 构建LL(1)分析表根据文法规则集合,构建一个LL(1)分析表,用于存储语法分析所需的预测分析表。

LL(1)分析表是一个二维表,其中行表示非终结符,列表示终结符。

表中的每个元素表示相应的产生式编号,用于指示语法分析器在分析过程中应该使用哪个产生式。

构建LL(1)分析表的方法包括:- 遍历文法规则集合,计算每个非终结符的FIRST集合和FOLLOW集合;- 根据计算得到的FIRST集合和FOLLOW集合,填充LL(1)分析表。

3. 实现语法分析器根据LL(1)分析表,实现一个语法分析器。

语法分析器的输入是一个程序代码,输出是语法分析器的分析结果。

实现语法分析器的主要过程包括:- 初始化分析栈,将文法规则的开始符号入栈;- 从输入的程序代码中读取下一个终结符;- 如果分析栈的栈顶是非终结符,根据LL(1)分析表中对应的产生式编号,将产生式右部的符号依次入栈;- 如果分析栈的栈顶是终结符,并且与输入的终结符相同,则将该终结符出栈,并继续读取下一个终结符;- 重复上述过程,直到分析栈为空或者无法继续推导。

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

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

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

词法分析器负责将源代码转化为一个个标记(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`列表中。

编译原理Lab2

编译原理Lab2

编译原理实验报告实验名称:语法分析器设计与实现实验日期: 2016.1.13学生姓名:学生学号:一、实验目的加深对语法分析器的工作过程的理解;加强对语法分析方法的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法分析。

通过本实验,应达到以下目标:1.掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。

2.掌握语法分析的实现方法。

3.上机调试编出的语法分析程序。

二、实验内容编写语法分析程序,利用实验一词法分析的结果,逐个读入经过词法分析生成的Token 序列。

根据定义好的句型,构造LR(1)分析表,根据该表对输入串进行规约,并输出规约序列。

语法分析是编译过程中的一个阶段,在词法分析后进行。

也可以和词法分析结合在一起进行,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。

输入:Token序列输出:规约序列三、实验方案1.程序的功能:从destination.txt文件读入Token序列,在syntax.txt文件中写入规约序列,格式为X->Y。

2.实现方案:采用LR(1)文法实现:a)定义上下文无关文法(CFG)b)根据CFG构造分层有限自动机c) 根据分层有限自动机构造LR(1)分析表c) 使用LR(1)分析表设计程序四、实验假设定义上下文无关文法如下:S’->SS->if S else SS->if SS->S;SS->EE->(E)E->E+TE->E-TE->TT->T*FT->T/FT->FF->idF->num五、相关的有限自动机根据上下文无关文法构造分层有限自动机(略)六、构造LR(1)分析表根据有限自动机构造LR(1)分析表如下:对于表中的冲突项:r2/S30冲突: 因为if的优先级高于;,所以应该将if S.;S左边的if S归约为S,故应保留r2。

语法分析器设计实验报告

语法分析器设计实验报告

学号《编译原理》实验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)⽂法,⽤预测分析表法判断输⼊的符号串是否符合刚才输⼊的⽂法,并打印出分析过程。

编译原理实验报告-语法分析

编译原理实验报告-语法分析

编译原理课程实验报告实验2:语法分析
三、系统设计得分
要求:分为系统概要设计和系统详细设计。

(1)系统概要设计:给出必要的系统宏观层面设计图,如系统框架图、数据流图、功能模块结构图等以及相应的文字说明。

1)系统的数据流图:
说明
说明:本语法分析器是基于上一个实验词法分析器的基础上,通过在界面写或者是导入源程序,词法分析器将源程序识别的词法单元传递给语法分析器,语法分析器验证这个词法单元组成的串是否可以由源语言的文法生成,能够输出语法分析的结果,文法的first集、follow 集和预测分析表,当然也可以以易于理解的方式报告语法错误。

2)系统框架图
本系统框架主要是三部分,一部分是词法分析,负责识别源程序的词法单元识别,并将其存
因为预测分析表实在是过于庞大,因此本处分段截取预测分析表,下面的表是接在上面表的右侧。

(3)针对一测试程序输出其句法分析结果;
测试程序:
语法分析结果:
语法分析树:
(4)输出针对此测试程序对应的语法错误报告;
带错误的测试程序:
语法错误报告:
(5)对实验结果进行分析。

总结:
本语法分析器具有强大的语法分析功能
●允许变量的连续声明,比如int a,b,c;
●允许声明的同时赋值,比如string c = “你好”;
●允许对数组的声明和引用,同时进行赋值,比如char[4] a = {‘a’,’b’,’c’,’d’};a[0] = ‘m’;
●支持多种类型的声明和赋值,比如int,short,long,flaot,double,char,string,boolean
的声明和赋值;
●允许声明和使用一个过程函数,比如:。

编译原理实验2语法分析器构造

编译原理实验2语法分析器构造
不为#N
将symbols中所有优先 级比当前字符低的弹 出栈存入ch直到有一
个不低于的
判断ch与word[i]是否相 等

规约为N,将N压入 symbols
从inputStr读入字符
判断当前字符优先级是

否不低于栈顶字符

将当前字符压入 symbols
当前字符是否为#

结束
报错
3. 主要技术问题的处理方法 (1) 判断优先级时,原本设置了三个函数,代码过于冗余,提取相同部分 后将他们整合为了一个函数,大大减少了代码量 (2) 最初基本功能全部写在了主函数内,虽然变量的传值十分简单,但是 逻辑也极其混乱,优化结构后将大部分功能封装在一个个的函数内部,结 构变得十分清晰,逻辑也更为优质。 (3) 在比较优先级的时候做的还不够完美,需要传入一个数组下标和一个 字符才可以比较,进一步的优化可以将其改为直接传入两个字符来进行优 先级的比较,代码也更加人性化。
default: return -1;
} } /* 判断终结符 */ int isVT(char ch) {
if(ch=='N') return 0;
return 1; }
/* 读入终结符 */ char readVT(int k) {
if(isVT(inputStr[k])) { return inputStr[k];
2018~2019 年春季学期
序号:
《编译原理》课程 实验报告
实验二 语法分析器构造
专业班级: 学生姓名: 学生学号:
一、目的和要求
借助于词法分析程序提供的分析结果,编写一个算符优先语法分析程序,程 序能进行语法结构分析和错误检查,并产生相应的归约信息。同时给出出错信息 和错误类型,从而加深对语法分析的理解。

语法分析器的设计

语法分析器的设计
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.了解语法分析的主要任务。

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

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

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

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

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

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

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

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

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

会影响本算法的结果。

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

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

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

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

语法分析器实验报告

语法分析器实验报告

杭州电子科技大学班级: 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 分析过程示意图三.个人心得一、 通过该实验, 主要有以下几方面收获: 二、 对实验原理有更深的理解。

(完整)编译原理实验报告(词法分析器 语法分析器)

(完整)编译原理实验报告(词法分析器 语法分析器)

编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字。

标示符。

无符号整数.运算符.和界符。

三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号.2、程序流程图(1)主程序(2)扫描子程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符.字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。

2 实验词法分析器源程序:#include 〈stdio.h〉#include <math.h>#include <string。

h>int i,j,k;char c,s,a[20],token[20]={’0’};int letter(char s){if((s〉=97)&&(s〈=122)) return(1);else return(0);}int digit(char s){if((s〉=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else”)==0) return(3);else if(strcmp(token,"switch”)==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf(”please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':case ’p':case ’q’:case 'r’:case 's’:case 't’:case ’u’:case ’v’:case ’w’:case ’x':case ’y':case ’z’:while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。

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

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

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

二、实验内容◆根据某一文法编制调试 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的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=∅(2)、预测分析表构造LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推导。

它的行对应文法的非终极符,列对应终极符,表中的值有两种:一是产生式的右部的字符串,一是null。

若用M表示LL(1)分析表,则M可表示如下:M: VN×VT→P∪{Error}M(A, t) = A→α,当t∈select(A→α) ,否则M(A, t) = Error其中P表示所有产生式的集合。

(3)、语法分析程序构造LL(1)分析中X为符号栈栈顶元素,a为输入流当前字符,E为给定测试数据的开始符号,#为句子括号即输入串的括号。

分析表用一个二位数组M表示,数组元素M[A,a]中的下标A表示非终结符,a为终结符或句子括号‘#’,二维数组中存放的是一条关于A 的产生式,表明当非终结符A向下推导时,面临输入符a时,所采用的候选产生式,当元素内容无产生式时,则表明用A 的左部向下推导时出现了不该出现的符号,因此元素内容转向出错处理的信息。

LL(1)分析过程主要包括以下四个动作:替换:当X∈VN时选相应产生式的右部β去替换X。

此时X出栈,β逆序入栈。

匹配:当X∈VT时它与a进行匹配,其结果可能成功,也可能失败,如果成功则符号栈中将X退栈并将输入流指针向前移动一位,否则报错。

接受:当格局为(#,空#)时报告分析成功。

报错:出错后,停止分析。

并给出相应的错误提示信息。

2.程序流程图:3、实验程序(1)分析栈类:public class stack {private char s[];private int top;public stack() {s = new char[200];s[0] = '#';top = 0;}char getTop() {return s[top];}void push(String str) {for (int i = str.length() - 1; i >= 0; i--) {s[++top] = str.charAt(i);}}void clear() {top = 0;}char pop() {if (top != 0) {top--;}return s[top];}public String toString() {String tmp = "";for (int i = 0; i <= top; i++) {tmp += s[i];}return tmp;}}(2)语法分析器类:public class anlysis {//分析表private String tab[][] = { { "$", "+", "-", "*", "/", "(", ")", "i", "#" },{ "E", "$", "$", "$", "$", "TG", "$", "TG", "$" },{ "G", "+TG", "-TG", "$", "$", "$", "ε", "$", "ε" },{ "T", "$", "$", "$", "$", "FS", "$", "FS", "$" },{ "S", "ε", "ε", "*FS", "/FS", "$", "ε", "$", "ε" },{ "F", "$", "$", "$", "$", "(E)", "$", "i", "$" } };private String input; //input中存放输入的表达式private StringBuffer tempBuffer; //存放要输出的字符串private int ptr, row, col, step; //指针,预测表中的行,列,当前步骤private boolean symbol;private stack stack;public anlysis(){stack =new stack();tempBuffer = new StringBuffer();symbol=true;input="";row=1;ptr=0;step=1;}//////////////////////////////////methods./////////////////////////// //////public int column(char c) { //判断预测表中的列switch (c) {case'+':return 1;case'-':return 2;case'*':return 3;case'/':return 4;case'(':return 5;case')':return 6;case'i':return 7;case'#':return 8;default:return -1;}}public int line(char c) { //判定预测表中的行switch (c) {case'E':return 1;case'G':return 2;case'T':return 3;case'S':return 4;case'F':return 5;default:return -1;}}public void pri(String str) {tempBuffer.append(String.format("%-8d%-20s%-20s%-20s\r\n", step, stack.toString(), input.substring(ptr), str));step++;}public void analyse() {stack.push(tab[row][0]); //预测表中的第一个元素‘E’pri("初始化");String tmp;char ctmp; //栈顶元素while (!(input.charAt(ptr) == '#' && stack.getTop() == '#')) { ctmp = stack.getTop();if (input.charAt(ptr) == ctmp) { //与栈顶元素比较stack.pop();ptr++;pri("" + ctmp + "匹配");continue;}col = column(input.charAt(ptr));if (col == -1) {symbol = false;pri("未定义的字符");ptr++;continue;}row = line(ctmp);if (row == -1) {symbol = false;pri("出错");stack.pop();if (input.charAt(ptr) != '#') {ptr++;}continue;}tmp = tab[row][col];if (tmp.charAt(0) == '$') {symbol = false;pri("出错");stack.pop();if (input.charAt(ptr) != '#') {ptr++;}} else if (tmp.charAt(0) == 'ε') {stack.pop();pri("" + ctmp + "->" + 'ε');} else {stack.pop();stack.push(tmp);pri("" + ctmp + "->" + tmp);}}}public String work(String ts) {input = ts;input = input.trim()+ '#';symbol = true;stack.clear();tempBuffer.append("\r\n步骤分析栈剩余输入栈所用产生式\r\n");analyse();if (symbol) {tempBuffer.append("\r是正确的符号串\r");return tempBuffer.toString();} else {tempBuffer.append("\r不是正确的符号串\r");return tempBuffer.toString();}}////////////////////////////////////gets andsets////////////////////////////////public StringBuffer getTempBuffer() {return tempBuffer;}public void setTempBuffer(StringBuffer tempBuffer) { this.tempBuffer = tempBuffer;}public stack getStack() {return stack;}public void setStack(stack stack) {this.stack = stack;}public String[][] getTab() {return tab;}public void setTab(String[][] tab) {this.tab = tab;}public String getInput() {return input;}public void setInput(String ns) {this.input = ns;}public int getPtr() {return ptr;}public void setPtr(int ptr) {this.ptr = ptr;}public int getRow() {return row;}public void setRow(int row) {this.row = row;}public int getCol() {return col;}public void setCol(int col) {this.col = col;}public int getStep() {return step;}public void setStep(int step) {this.step = step;}public boolean isBoo() {return symbol;}public void setBoo(boolean boo) {this.symbol = boo;}}(3)WINDOW窗体类:import java.awt.BorderLayout;import java.awt.GridLayout;import java.awt.Panel;import javax.swing.JFrame;import javax.swing.JScrollPane;public class gui extends javax.swing.JFrame {/** Creates new form gui */private javax.swing.JButton jButton1;private javax.swing.JLabel jLabel1;private javax.swing.JLabel jLabel2;private javax.swing.JTextArea jTextArea1;private javax.swing.JTextField jTextField1;private Panel p1=new Panel();private Panel p2=new Panel();public gui() {initComponents();}private void initComponents() {jLabel1 = new javax.swing.JLabel();jTextField1 = new javax.swing.JTextField();jLabel2 = new javax.swing.JLabel();jTextArea1 = new javax.swing.JTextArea(20,30);jButton1 = new javax.swing.JButton();setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOS E);jLabel1.setText("本程序只能对由'+','-','*','/','(',')','i'构成的以'#'结尾的字符串进行分析。

相关文档
最新文档