编译原理 语法分析实验
编译原理实验报告(词法分析器语法分析器)
函数 int f(char c) 和 int g(char c) , 判断运算符之间的优先关系 , 根据不同情况作各种不同操作 。 流程
图如下 :
word 完美格式
专业资料
输入算数表达式,以 #结束 初始化 loptr[1]= ’#’ 用 get()取一个待分析字符 s
Optr[1] 和 s 是否同时为 #
。
2 、而且对词法分析和语法分析在实践中的应用有了深入的掌握
。
3 、 更加熟悉了构造词法分析程序和语法分析程序的手工方式的相关原理
, 能够实现对词
法分析程序所提供的单词符号序列进行相应的语法检查和结构分析
,达到了学以致用的目的 。
word 完美格式
word 完美格式
专业资料
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)
-
9
*
10
<=
11
<
11
==
11
=
12
;
13
word 完美格式
助记符 while
if else switch case
编译原理语法分析试验报告
编译原理语法分析试验报告语法分析是编译原理中的重要内容之一,主要用于对源程序进行语法检查,判断其是否符合给定的语法规则。
本次试验通过使用ANTLR工具,对C语言的子集进行了语法分析的实现。
一、实验目的:1.了解语法分析的基本概念和方法;2.使用ANTLR工具生成语法分析器;3.掌握ANTLR工具的基本使用方法;4.实现对C语言子集的语法分析。
二、实验内容:本次试验主要内容是使用ANTLR工具生成C语言子集的语法分析器,并对给定的C语言子集进行语法分析。
三、实验步骤:1.学习ANTLR工具的基本概念和使用方法;2.根据C语言子集的语法规则,编写ANTLR的语法文件(.g文件);3.使用ANTLR工具生成语法分析器;4.编写测试代码,对给定的C语言子集进行语法分析。
四、实验结果:经过以上的步骤,得到了一个完整的C语言子集的语法分析器,并且通过测试代码对给定的C语言子集进行了语法分析。
五、实验总结:通过本次实验,我对语法分析有了更深入的了解,掌握了使用ANTLR工具生成语法分析器的基本方法,同时也巩固了对C语言的基本语法规则的理解。
在实验过程中,遇到了一些问题,例如在编写ANTLR的语法文件时,对一些特殊语法规则的处理上有些困惑,但通过查阅资料和与同学的探讨,最终解决了这些问题。
本次试验对于我的学习有很大的帮助,我了解到了编译原理中的重要内容之一,也更深入地理解了语法分析的基本原理和方法。
通过实验,我发现使用ANTLR工具能够更方便地生成语法分析器,大大提高了开发效率。
总之,本次试验让我对编译原理中的语法分析有了更深入的了解,并且提高了我的编程能力和分析问题的能力。
在今后的学习和工作中,我将继续深入研究编译原理相关的知识,并应用到实际项目中。
编译原理词法分析,语法分析实验报告
char left[50];
/* 左部 */
char right[50][50];
/* 右部 */
char first[50][50],follow[50][50];
/* 各产生式右部的 FIRST 和左部的 FOLLOW 集合 */
char first1[50][50];
/* 所有单个符号的 FIRST 集合 */
int i,j,k,result=1,mark=0;
char temp[20];
temp[0]=c;
temp[1]='\0';
merge(empt,temp,1);
if(in(c,empty)==1)
return(1);
for(i=0;;i++)
{
if(i==count)
return(0);
if(left[i]==c)
}
/*******************************************
将单个符号或符号串并入另一符号串 ********************************************/
void merge(char *d,char *s,int type)
{
/*d 是目标符号串, s 是源串, type=1,源串中的‘ ^ ’一并并入目串;
int count=0;
/* 分解的产生式的个数 */
int number;
/* 所有终结符和非终结符的总数 */
char start;
/* 开始符号 */
char termin[50];
/* 终结符号 */
char non_ter[50];
编译原理实验报告-语法分析
编译原理课程实验报告实验2:语法分析
(2)输出针对此测试程序对应的语法错误报告;
四、实验中遇到的问题总结
(一)实验过程中遇到的问题如何解决的?
问题1:关于action表中需要存储空‘#’以代表在某个状态读入空后所应该进行的动作,如何在action表中安排空这一列?
答:以0代表空,所以action表的列数为终结符数量加1,其中第0列表示某状态读入空时应该执行的动作。
问题2:关于数据结构,显然,文法中的终结符和非终结符都应该有一个唯一的标号来标识这是哪个文法符号,如何进行存储(文件和内存中)?用什么约束使得处理得到简化?答:我是通过一个short型的整型数标识文法符号的;文法输入文件的约束是,以终极符的数量加一为第一个非终结符的标识值,之后依次加一,必须连续且不重复。
对于终结符,从1开始为第1个终结符的标识值(0代表空),以后依次加一,必须连续且不重复;如此设计可以方便后续的action表和goto表的构建和查询操作。
问题3:构建项目集规范族或计算first集和follow集的过程中常常需要用到集合操作,如何编写相关代码?
答:可以直接使用现有的库或者自己实现一个set数据结构。
编译原理-词法语法分析实验报告
编译原理词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的C语言程序源代码:#include <stdio.h>#include <string.h>char prog[80],token[8],ch;int syn,p,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};scaner();void scanner_example (FILE *fp);main(){FILE *fp;fp=fopen("D:\\1.txt","r");//打开文件scanner_example (fp);scaner();}void scanner_example (FILE *fp){do{ch=fgetc (fp);prog[p++]=ch;}while (ch!='#');p=0;do{scaner();switch(syn){case 11:printf("( %-10d%5d )\n",sum,syn);break;case -1:printf("you have input a wrong string\n");default: printf("( %-10s%5d )\n",token,syn);break;}}while(syn!=0);}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;ch=prog[p++];m=0;while((ch==' ')||(ch=='\n'))ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch;ch=prog[p++];}p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){ syn=n+1;break;}}else if((ch>='0')&&(ch<='9')){ while((ch>='0')&&(ch<='9')){ sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=22;token[m++]=ch;}else{ syn=20;p--;}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=24;token[m++]=ch;}else{ syn=23;p--;}break;case '+': token[m++]=ch;ch=prog[p++];if(ch=='+'){ syn=17;token[m++]=ch;}else{ syn=13;p--;}break;case '-':token[m++]=ch;ch=prog[p++];if(ch=='-'){ syn=29;token[m++]=ch;}else{ syn=14;p--;}break;case '!':ch=prog[p++];if(ch=='='){ syn=21;token[m++]=ch;}else{ syn=31;p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=25;token[m++]=ch;}else{ syn=18;p--;}break;case '*': syn=15;token[m++]=ch;break;case '/': syn=16;token[m++]=ch;break;case '(': syn=27;token[m++]=ch;break;case ')': syn=28;token[m++]=ch;break;case '{': syn=5;token[m++]=ch;break;case '}': syn=6;token[m++]=ch;break;case ';': syn=26;token[m++]=ch;break;case '\"': syn=30;token[m++]=ch;break;case '#': syn=0;token[m++]=ch;break;case ':':syn=17;token[m++]=ch;break;default: syn=-1;break;}token[m++]='\0';}四、结果分析:输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图所示:五、总结:词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
编译原理语法分析实验报告
实验 2:语法分析
1.实验题目和要求
题目:语法分析程序的设计与实现。
实验内容:编写语法分析程序,实现对算术表达式的语法分析。
要求所分析算术表达式由如下的文法产生。
E E T|E T|T
T T*F|T/F|F F id
| (E) | num
实验要求:在对输入表达式进行分析的过程中,输出所采用的产生式。
方法 1 :编写递归调用程序实现自顶向下的分析。
方法 2 :编写 LL(1) 语法分析程序,要求如下。
(1)编程实现算法 4.2 ,为给定文法自动构造预测分析表。
(2)编程实现算法 4.1 ,构造 LL(1) 预测分析程序。
方法 3 :编写语法分析程序实现自底向上的分析,要求如下。
(1)构造识别所有活前缀的 DFA 。
(2)构造 LR 分析表。
(3)编程实现算法 4.3 ,构造 LR 分析程序。
方法 4 :利用 YACC 自动生成语法分析程序,调用LEX 自动生成的词法分析程序。
实现(采用方法1)1.1. 步骤:
1)对文法消除左递归
E TE '
E 'TE' | TE' |
T FT '
T '*FT'|/FT' |
F id | (E) | num
2)画出状态转换图
化简得:
3)源程序
在程序中I 表示 id
N 表示 num
1.2. 例子:
a)例子 1
输入 :I+(N*N)
输出:
b)例子 2
输入: I-NN
输出:。
编译原理语法分析实验报告
编译原理语法分析实验报告编译原理实验报告一、实验目的本实验的主要目的是熟悉编译原理中的语法分析算法及相关知识,并通过实际编码实现一个简单的语法分析器。
二、实验内容1.完成一个简单的编程语言的语法定义,并用BNF范式表示;2.基于给定的语法定义,实现自顶向下的递归下降语法分析器;3.实验所用语法应包含终结符、非终结符、产生式及预测分析表等基本要素;4.实现语法分析器的过程中,需要考虑文法的二义性和优先级等问题。
三、实验步骤1.设计一个简单的编程语言的语法,用BNF范式进行表达。
例如,可以定义表达式文法为:<exp> ::= <term> { + <term> , - <term> }<term> ::= <factor> { * <factor> , / <factor> }<factor> ::= <digit> , (<exp>) , <variable><digit> ::= 0,1,2,3,4,5,6,7,8,9<variable> ::= a,b,c,...,z2. 根据所设计的语法,构建语法分析器。
首先定义需要用到的终结符、非终结符和产生式。
例如,终结符可以是+、-、*、/、(、)等,非终结符可以是<exp>、<term>、<factor>等,产生式可以是<exp> ::= <term> + <term> , <term> - <term>等。
3.实现递归下降语法分析器。
根据语法的产生式,编写相应的递归函数进行递归下降分析。
递归函数的输入参数通常是一个输入字符串和当前输入位置,输出结果通常是一个语法树或语法分析错误信息。
4.在语法分析的过程中,需要处理语法的二义性和优先级问题。
编译原理词法分析,语法分析实验报告
编译原理实验报告一.LL(1)文法分析1.设计要求(1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止;(2)输入已知文法,由程序自动生成它的LL(1)分析表;(3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。
2.分析该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;(5)由总控算法判断输入符号串是否为该文法的句型。
3.流程图开始读入文法有效?是是LL(1)文法?是判断句型报错结束4.源程序/*******************************************语法分析程序作者:xxx学号:xxx********************************************/#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘|’后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果‘|’后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/ char grammer(char *t,char *n,char *left,char right[50][50]) {char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的‘^ ’一并并入目串;type=2,源串中的‘^ ’不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由‘^ ’推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出‘^ ’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/ printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为‘^ ’,报错*/ printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/ void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/ temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("\nS:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();}}}5.执行结果(1)输入一个文法(2)输入一个符号串(3)再次输入一个符号串,然后退出程序二.词法分析一、问题描述识别简单语言的单词符号识别简单语言的基本字、标识符、无符号整数、运算符和界符。
编译原理词法分析和语法分析
{ syn=21;
token[m++]=ch;
}
else
{ syn=31;
p--;
}
break;
case '=':token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{ syn=25;
token[m++]=ch;
}
else
{ syn=18;
p--;
}
break;
break;
case -1:printf("you have input a wrong string\n");
getch();
exit(0);
default: printf("( %-10s%5d )\n",token,syn);
break;
}
}while(syn!=0);
getch();
}
scaner()
printf("success!\n");
}
else { if(kk!=1) printf("the string haven't got a 'end'!\n");
kk=1;
}
}
else { printf("haven't got a 'begin'!\n");
kk=1;
}
return;
}
yucu()
if(syn==18)
{ scaner();/*读下一个单词符号*/
编译原理语法分析实验报告
//输出转化后
的文法规则串
{
printf("%s\n",text[i]);
}
for(i=0;i<x;i++) /*求每个终结符的推导结果(去掉"->"后的转化文
法,用于最后的规约)*/
{ string[i][0]=text[i][0];
for(j=3,l=1;text[i][j]!='\0';j++,l++)
表1-2 G[S]的算符优先关系矩阵表
#
i
+
*
(
)
#
i
+
*
(
)
二.程序设计
1.总体设计
求FIRSTVT模块 求LASTVT模块 识别终结符模块
读入文法规则 创建文法关系表模块
求下标模块
2.子程序设计
识别终结符模块
读取语法分析串 输入串分析模块 图2-1 总体设计图
求FIRSTVT模块 求LASTVT模块
编译原理实验三-自下而上语法分析及语义分析.docx
上海电力学院编译原理课程实验报告实验名称:实验三自下而上语法分析及语义分析院系:计算机科学与技术学院专业年级:学生姓名:学号:指导老师:实验日期:实验三自上而下的语法分析一、实验目的:通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:● LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义简单的表达式文法如下:(1)E->E+T(2)E->E-T(3)E->T(4)T->T*F(5)T->T/F(6)T->F(7)F->(E)(8)F->i状态ACTION(动作)GOTO(转换)i + - * / ( ) # E T F0 S5 S4 1 2 31 S6 S12 acc2 R3 R3 S7 S13 R3 R33 R6 R6 R6 R6 R6 R64 S5 S4 8 2 35 R8 R8 R8 R8 R8 R86 S5 S4 9 37 S5 S4 108 S6 R12 S119 R1 R1 S7 S13 R1 R110 R4 R4 R4 R4 R4 R411 R7 R7 R7 R7 R7 R712 S5 S4 14 313 S5 S4 1514 R2 R2 S7 S13 R2 R215 R5 R5 R5 R5 R5 R5五、处理程序例和处理结果例示例1:20133191*(20133191+3191)+ 3191#六、源代码【cifa.h】//cifa.h#include<string>using namespace std;//单词结构定义struct WordType{int code;string pro;};//函数声明WordType get_w();void getch();void getBC();bool isLetter();bool isDigit();void retract();int Reserve(string str);string concat(string str);【Table.action.h】//table_action.hclass Table_action{int row_num,line_num;int lineName[8];string tableData[16][8];public:Table_action(){row_num=16;line_num=8;lineName[0]=30;lineName[1]=7;lineName[2]=13;lineName[3]=8;lineName[4]=14;lineName[5]=1;lineName[6]=2;lineName[7]=15;lineName[8]=0;for(int m=0;m<row_num;m++)for(int n=0;n<line_num;n++)tableData[m][n]="";tableData[0][0]="S5";tableData[0][5]="S4";tableData[1][1]="S6";tableData[1][2]="S12";tableData[1][7]="acc";tableData[2][1]="R3";tableData[2][2]="R3";tableData[2][3]="S7";tableData[2][4]="S13";tableData[2][6]="R3";tableData[2][7]="R3";tableData[3][1]="R6";tableData[3][3]="R6"; tableData[3][4]="R6"; tableData[3][6]="R6"; tableData[3][7]="R6"; tableData[4][0]="S5"; tableData[4][5]="S4"; tableData[5][1]="R8"; tableData[5][2]="R8"; tableData[5][3]="R8"; tableData[5][4]="R8"; tableData[5][6]="R8"; tableData[5][7]="R8"; tableData[6][0]="S5"; tableData[6][5]="S4"; tableData[7][0]="S5"; tableData[7][5]="S4"; tableData[8][1]="S6"; tableData[8][2]="S12"; tableData[8][6]="S11"; tableData[9][1]="R1"; tableData[9][2]="R1"; tableData[9][3]="S7"; tableData[9][4]="S13"; tableData[9][6]="R1"; tableData[9][7]="R1"; tableData[10][1]="R4"; tableData[10][2]="R4"; tableData[10][3]="R4"; tableData[10][4]="R4"; tableData[10][6]="R4"; tableData[10][7]="R4"; tableData[11][1]="R7"; tableData[11][2]="R7"; tableData[11][3]="R7"; tableData[11][4]="R7"; tableData[11][6]="R7"; tableData[11][7]="R7"; tableData[12][0]="S5"; tableData[12][5]="S4"; tableData[13][0]="S5"; tableData[13][5]="S4"; tableData[14][1]="R2"; tableData[14][2]="R2";tableData[14][4]="S13";tableData[14][6]="R2";tableData[14][7]="R2";tableData[15][1]="R5";tableData[15][2]="R5";tableData[15][3]="R5";tableData[15][4]="R5";tableData[15][5]="R5";tableData[15][6]="R5";tableData[15][7]="R5";}string getCell(int rowN,int lineN){int row=rowN;int line=getLineNumber(lineN);if(row>=0&&row<row_num&&line>=0&&line<=line_num) return tableData[row][line];elsereturn"";}int getLineNumber(int lineN){for(int i=0;i<line_num;i++)if(lineName[i]==lineN)return i;return -1;}};【Table_go.h】//table_go.hclass Table_go{int row_num,line_num;//行数、列数string lineName[3];int tableData[16][3];public:Table_go(){row_num=16;line_num=3;lineName[0]="E";lineName[1]="T";lineName[2]="F";for(int m=0;m<row_num;m++)for(int n=0;n<line_num;n++)tableData[m][n]=0;tableData[0][0]=1;tableData[0][1]=2;tableData[0][2]=3;tableData[4][0]=8;tableData[4][1]=2;tableData[4][2]=3;tableData[6][1]=9;tableData[6][2]=3;tableData[7][2]=10;tableData[12][1]=14;tableData[12][2]=3;tableData[13][2]=15;}int getCell(int rowN,string lineNa){int row=rowN;int line=getLineNumber(lineNa);if(row>=0&&row<row_num&&line<=line_num) return tableData[row][line];elsereturn -1;}int getLineNumber(string lineNa){for(int i=0;i<line_num;i++)if(lineName[i]==lineNa)return i;return -1;}};【Stack_num.h】class Stack_num{int i; //栈顶标记int *data; //栈结构public:Stack_num() //构造函数{data=new int[100];i=-1;}int push(int m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{i--;return data[i+1];}int getTop() //返回栈顶{return data[i];}~Stack_num() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【Stack_str.h】class Stack_str{int i; //栈顶标记string *data; //栈结构public:Stack_str() //构造函数{data=new string[50];i=-1;}int push(string m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{data[i]="";i--;return i;}string getTop() //返回栈顶{return data[i];}~Stack_str() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【cifa.cpp】//cifa.cpp#include<iostream>#include<string>#include"cifa.h"using namespace std;//关键字表和对应的编码string codestring[10]={"main","int","if","then","else","return","void","cout","endl"}; int codebook[10]={26,21,22,23,24,25,27,28,29};//全局变量char ch;int flag=0;/*//主函数int main(){WordType word;cout<<"请输入源程序序列:";word=get_w();while(word.pro!="#")//#为自己设置的结束标志{cout<<"("<<word.code<<","<<"“"<<word.pro<<"”"<<")"<<endl;word=get_w();};return 0;}*/WordType get_w(){string str="";int code;WordType wordtmp;getch();//读一个字符getBC();//去掉空白符if(isLetter()){ //以字母开头while(isLetter()||isDigit()){str=concat(str);getch();}retract();code=Reserve(str);if(code==-1){wordtmp.code=0;wordtmp.pro=str;}//不是关键字else{wordtmp.code=code;wordtmp.pro=str;}//是关键字}else if(isDigit()){ //以数字开头while(isDigit()){str=concat(str);getch();}retract();wordtmp.code=30;wordtmp.pro=str;}else if(ch=='(') {wordtmp.code=1;wordtmp.pro="(";}else if(ch==')') {wordtmp.code=2;wordtmp.pro=")";}else if(ch=='{') {wordtmp.code=3;wordtmp.pro="{";}else if(ch=='}') {wordtmp.code=4;wordtmp.pro="}";}else if(ch==';') {wordtmp.code=5;wordtmp.pro=";";}else if(ch=='=') {wordtmp.code=6;wordtmp.pro="=";}else if(ch=='+') {wordtmp.code=7;wordtmp.pro="+";}else if(ch=='*') {wordtmp.code=8;wordtmp.pro="*";}else if(ch=='>') {wordtmp.code=9;wordtmp.pro=">";}else if(ch=='<') {wordtmp.code=10;wordtmp.pro="<";}else if(ch==',') {wordtmp.code=11;wordtmp.pro=",";}else if(ch=='\'') {wordtmp.code=12;wordtmp.pro="\'";}else if(ch=='-') {wordtmp.code=13;wordtmp.pro="-";}else if(ch=='/') {wordtmp.code=14;wordtmp.pro="/";}else if(ch=='#') {wordtmp.code=15;wordtmp.pro="#";}else if(ch=='|') {wordtmp.code=16;wordtmp.pro="|";}else {wordtmp.code=100;wordtmp.pro=ch;} return wordtmp;}void getch(){if(flag==0) //没有回退的字符ch=getchar();else //有回退字符,用回退字符,并设置标志flag=0;}void getBC(){while(ch==' '||ch=='\t'||ch=='\n')ch=getchar();}bool isLetter(){if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return true;elsereturn false;}bool isDigit(){if(ch>='0'&&ch<='9')return true;elsereturn false;}string concat(string str){return str+ch;}void retract(){flag=1;}int Reserve(string str){int i;for(i=0;i<=8;i++){if(codestring[i]==str) //是某个关键字,返回对应的编码return codebook[i];}if(i==9) //不是关键字return -1;}【LR.cpp】#include<iostream>#include<string>#include<cstdlib>#include"cifa.h"#include"stack_num.h"#include"stack_str.h"#include"table_action.h"#include"table_go.h"using namespace std;void process(){int stepNum=1;int topStat;Stack_num statusSTK; //状态栈Stack_str symbolSTK; //符号栈Stack_num valueSTK; //值栈WordType word;Table_action actionTAB; //行为表Table_go goTAB; //转向表cout<<"请输入源程序,以#结束:";word=get_w();//总控程序初始化操作symbolSTK.push("#");statusSTK.push(0);valueSTK.push(0);cout<<"步骤\t状态栈\t符号栈\t值栈\t当前词\t动作\t转向"<<endl;//分析while(1){topStat=statusSTK.getTop(); //当前状态栈顶string act=actionTAB.getCell(topStat,word.code);//根据状态栈顶和当前单词查到的动作//输出cout<<stepNum++<<"\t";statusSTK.outStack(); cout<<"\t";symbolSTK.outStack(); cout<<"\t";valueSTK.outStack(); cout<<"\t";cout<<word.pro<<"\t";//行为为“acc”,且当前处理的单词为#,且状态栈里就两个状态//说明正常分析结束if(act=="acc"&&word.pro=="#"&&statusSTK.topNumber()==1){cout<<act<<endl;cout<<"分析成功!"<<endl;cout<<"结果为:"<<valueSTK.getTop()<<endl;return;}//读到act表里标记为错误的单元格else if(act==""){cout<<endl<<"不是文法的句子!"<<endl;cout<<"错误的位置为单词"<<word.pro<<"附近。
编译原理语法分析实验报告
编译原理语法分析实验报告《编译原理》实验报告⼀,实验内容设计、编制并调式⼀个语法分析程序,加深对语法分析原理的理解。
⼆,实验⽬的及要求利⽤C++(或C)编制确定的⾃顶向下预测分析语法分析程序,并对简单语⾔进⾏语法分析。
2.1、待分析的简单语⾔的语法若⽂法G[ E]为:(1) E –> TE’(2) E’ –> +TE’(3) E’ –> ε(4) T –> FT’(5) T’ –> *FT’(6) T’ –> ε(7) F –> (E)(8) F –> i2.2、实验要求及说明具体要求如下:1、⽤可视化界⾯分步骤实现,显⽰输出每⼀步的处理结果。
2、⾸先按照判别步骤判断给定⽂法是否LL(1)⽂法。
3、给出⽂法的预测分析表。
4、编写预测分析程序,输出句⼦的分析过程。
5、输⼊源⽂件串,以“#”结束,如果是⽂法正确的句⼦,则输出成功信息,打印“SUCCESS”,否则输出“ERROR”。
例如:输⼊⽂件:i+i*(i+i) #输出success过程:略;输⼊⽂件:i+ii#输出error三,实验环境Dvc++#include#define MAX 50using namespace std;struct T_NT{int code;char str[MAX];};T_NTT[12]={{0,"i"},{1,"+"},{2,"*"},{3,"("},{4,")"},{5,"#"},{6,"!"},{256,"E"},{257,"E'" },{258,"T"},{259,"T'"},{260,"F"}};T_NTR[8]={{0,"->TR"},{1,"->+TR"},{2,"->e"},{3,"->FW"},{4,"->*FW"},{5,"->e"},{6, "->(E)"},{7,"->i"}};stack stak;int Yy_pushab[7][4]={{257,258,6},{257,258,1,6},{6},{259,260,6},{259,260,2,6},{0,6},{4,256,3,6}};int Yy_d[5][6]={{0,-1,-1,0,-1,-1},{-1,1,-1,-1,2,2},{3,-1,-1,3,-1,-1},{-1,2,4,-1,2,2},{5,-1,-1,6,-1,-1}int main(){char c,t[MAX];int s[MAX];cout<<"请输出要输⼊的字符串:";while(c!='#'){cin>>c;t[l]=c;switch(c){case'i':s[l]=0; break;case'+':s[l]=1; break;case'*':s[l]=2; break;case'(':s[l]=3; break;case')':s[l]=4; break;case'#':s[l]=5; break;case'!':s[l]=6; break;}l++;}cout<<"\n LL1⽂法预测分析表如下:\n"<cout<<" ";for(i=0;i<6;i++)//printf("%10c",T[i].str);cout<<" "<cout<for(i=0;i<5;i++){cout<<" -----------------------------------------------------------------"< //printf("%10c",T[i+7].str);cout<<" "<for(j=0;j<6;j++){//printf("%10c");{case 0:cout<case 1:cout<case 2:cout<case 3:cout<case 4:cout<case 5:cout<case 6:cout<case 7:cout<case-1:cout<<" ";break;}}cout<}cout<cout<<"\n 对输⼊句型的分析如下:\n"<cout<<" 步骤栈顶元素剩余输⼊串推到所⽤产⽣式或匹配"<cout<<"-------------------------------------------------------------------------------\n"; stak.push(5);stak.push(256);while(!stak.empty()){cout<<" "<p=stak.top(); //cout<<"p"<for(i=0;i<12;i++) // 输出栈顶元素{if(T[i].code==p){cout<<" "<break;}}cout<<" ";} //输出剩余字符串if(p>=0&&p<6) // 栈顶是终结符{if(p!=s[h]){cout<<" 语法错误!";break;}else if(p==5){cout<<" 接受"<cout<<"-------------------------------------------------------------------------------\n"; cout<<"\n该句型是该⽂法的句⼦\n";stak.pop();}else{cout<<" 与"<w++;h++;stak.pop();}}else{m=p-256;n=s[h];what=Yy_d[m][n]; //预测分析表if(what==-1){cout<<" 没有可⽤的产⽣式"<cout<<"-------------------------------------------------------------------------------\n"; cout<<"\n该句型不是该⽂法的句⼦\n";{cout<<" "<//cout<stak.pop();k=0;while(Yy_pushab[what][k]!=6) //产⽣式{stak.push(Yy_pushab[what][k]);k++;}}}b++;cout<}system("pause");return 0;}五。
编译原理实验 (词法语法分析报告 附源代码
编译原理实验报告******************************************************************************* ******************************************************************************* PL0语言功能简单、结构清晰、可读性强,而又具备了一般高级程序设计语言的必须部分,因而PL0语言的编译程序能充分体现一个高级语言编译程序实现的基本方法和技术。
PL/0语言文法的EBNF表示如下:<程序>::=<分程序>.<分程序> ::=[<常量说明>][<变量说明>][<过程说明>]<语句><常量说明> ::=CONST<常量定义>{,<常量定义>};<常量定义> ::=<标识符>=<无符号整数><无符号整数> ::= <数字>{<数字>}<变量说明> ::=VAR <标识符>{, <标识符>};<标识符> ::=<字母>{<字母>|<数字>}<过程说明> ::=<过程首部><分程序>{; <过程说明> };<过程首部> ::=PROCEDURE <标识符>;<语句> ::=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>|<复合语句>|<读语句><写语句>|<空><赋值语句> ::=<标识符>:=<表达式><复合语句> ::=BEGIN <语句> {;<语句> }END<条件语句> ::= <表达式> <关系运算符> <表达式> |ODD<表达式><表达式> ::= [+|-]<项>{<加法运算符> <项>}<项> ::= <因子>{<乘法运算符> <因子>}<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’<加法运算符> ::= +|-<乘法运算符> ::= *|/<关系运算符> ::= =|#|<|<=|>|>=<条件语句> ::= IF <条件> THEN <语句><过程调用语句> ::= CALL 标识符<当循环语句> ::= WHILE <条件> DO <语句><读语句> ::= READ‘(’<标识符>{,<标识符>}‘)’<写语句> ::= WRITE‘(’<表达式>{,<表达式>}‘)’<字母> ::= a|b|…|X|Y|Z<数字> ::= 0|1|…|8|9【预处理】对于一个pl0文法首先应该进行一定的预处理,提取左公因式,消除左递归(直接或间接),接着就可以根据所得的文法进行编写代码。
编译原理实验——语法分析器报告
组员学号姓名实验名称对各算术表达式进行语法分析实验室实验目的或要求实验目的:1、掌握语法分析器生成工具的使用和了解编译器的设计;2、了解自上而下语法分析器的构造过程;3、能够构造LR分析表,编写由该分析表驱动的语法分析器程序;4、借助语法制导翻译,可在语法分析的同时,完成对语义的翻译;5、借助语法分析,设计一个表达式的判断分析器,即从键盘上输入算术表达式,分析器将显示该表达式的正确与否。
实验原理(算法流程)实验算法流程图如下所示:开始输入表达式表达式保存到数ch第一个元素为)+-*/YCh[i]=’(’i++YNCh[i]=NULLNCh[i]是0~9i++YCh[i]是0~9Ch[i]=+ -*/)N多了+ -*/)Y其他错误NYCh[i]=* /Ni++YCh[i]=+ -*/NY多了+ -*/Ch[i]=+ -NNCh[i]=)Y少了)N错误首部多了) +-*/结束程序界面(效果图)实验结果界面:只选择几个典型的例子进行分析,可进行任意表达式输入。
1)未进行语法分析时的界面;2)输入正确的表达式(1+2)*(6-3)+1进行语法分析时的界面结果;3)输入错误的表达式1*2+(2+3并进行语法分析时的界面结果;程序界面(效果图)4)输入错误的表达式1+(+5+6)并进行语法分析时的界面结果;程序界面(效果图)程序代码 #include "stdafx.h"#include "grammer.h"#include "mfc_语法分析器.h"#include "mfc_语法分析器Dlg.h"int flag;int i,j;int length;CString string;int grammer(CString str){i=0;flag=0;char ch[MAX];length=str.GetLength();strcpy(ch,str);if(length!=0){F(ch);if(flag==0){MessageBox(NULL,"输入表达式符合文法","正确",MB_OK|MB_ICONINFORMATION);}//str=ch;//return flag;}else{MessageBox(NULL,"表达式为空","提示",MB_OK|MB_ICONW ARNING);//MessageBox(NULL,"表达式为空","提示",MB_OK|MB_ICONERROR);return -1;}return flag;}void F(char ch[]){if(ch[0]=='+'){程序代码flag=0;MessageBox(NULL,"输入表达式不符合文法0","错误",MB_OK|MB_ICONERROR); MessageBox(NULL,"开始处多了+","提示",MB_OK|MB_ICONINFORMA TION);flag=1;}elseif(ch[0]=='-'){flag=0;MessageBox(NULL,"输入表达式不符合文法0","错误",MB_OK|MB_ICONERROR);MessageBox(NULL,"开始处多了-","提示",MB_OK|MB_ICONINFORMA TION);flag=1;}elseif(ch[0]=='*'){flag=0;MessageBox(NULL,"输入表达式不符合文法0","错误",MB_OK|MB_ICONERROR);MessageBox(NULL,"开始处多了*","提示",MB_OK|MB_ICONINFORMA TION);flag=1;}elseif(ch[0]=='/'){flag=0;MessageBox(NULL,"输入表达式不符合文法0","错误",MB_OK|MB_ICONERROR);MessageBox(NULL,"开始处多了/","提示",MB_OK|MB_ICONINFORMA TION);flag=1;}elseif(ch[0]==')'){flag=0;MessageBox(NULL,"输入表达式不符合文法0","错误",MB_OK|MB_ICONERROR);MessageBox(NULL,"开始处多了)","提示",MB_OK|MB_ICONINFORMA TION);flag=1;}/*上述为对第一个字符的特殊处理*/elseif(ch[i]!=NULL){if(ch[i]=='('){i++;F(ch);程序代码if(ch[i]!=')'){if(flag==0){MessageBox(NULL,"输入表达式不符合文法1","错误",MB_OK|MB_ICONERROR);MessageBox(NULL,"少了')'","提示",MB_OK|MB_ICONINFORMATION);}flag=1;}else{i++;if(ch[i]!=NULL)T(ch);}}elseif(ch[i]<='9'&&ch[i]>='0'){while(ch[i]<='9'&&ch[i]>='0')i++;if(ch[i]!=NULL)T(ch);}else{if(flag==0){if(ch[i]!=NULL&&ch[i]!=')'){MessageBox(NULL,"输入表达式不符合文法2.1","错误",MB_OK|MB_ICONERROR);if(ch[i]==' ') MessageBox(NULL,"含有空格","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='+') {MessageBox(NULL,"多了'+'号","提示",MB_OK|MB_ICONINFORMA TION);}else if(ch[i]=='-') MessageBox(NULL,"多了'-'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='*') MessageBox(NULL,"多了'*'号","提示",MB_OK|MB_ICONINFORMA TION);程序代码else if(ch[i]=='/') MessageBox(NULL,"多了'/'号","提示",MB_OK|MB_ICONINFORMA TION);}else if(ch[i]==NULL){MessageBox(NULL,"输入表达式不符合文法2.2","错误",MB_OK|MB_ICONERROR);if(ch[i-1]==' ') MessageBox(NULL,"含有空格","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='+') MessageBox(NULL,"多了最后的'+'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='-') MessageBox(NULL,"多了最后的'-'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='*') MessageBox(NULL,"多了最后的'*'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='/') MessageBox(NULL,"多了最后的'/'号","提示",MB_OK|MB_ICONINFORMA TION);}else if(ch[i]!=NULL&&ch[i]==')'){MessageBox(NULL,"输入表达式不符合文法2.3","错误",MB_OK|MB_ICONERROR);if(ch[i-1]==' ') MessageBox(NULL,"含有空格","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='(') MessageBox(NULL,"含有一对空括号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='+') MessageBox(NULL,"多了最后的'+'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='-') MessageBox(NULL,"多了最后的'-'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='*') MessageBox(NULL,"多了最后的'*'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='/') MessageBox(NULL,"多了最后的'/'号","提示",MB_OK|MB_ICONINFORMA TION);}}flag=1;}}}void T(char ch[]){if(ch[i]=='*'||ch[i]=='/')程序代码{i++;if(ch[i]!=NULL&&ch[i]!='+'&&ch[i]!='-'&&ch[i]!='*'&&ch[i]!='/')F(ch);else{if(flag==0){MessageBox(NULL,"输入表达式不符合文法3","错误",MB_OK|MB_ICONERROR);if(ch[i]==' ') MessageBox(NULL,"含有空格","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='+') MessageBox(NULL,"多了'+'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='-') MessageBox(NULL,"多了'-'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='*') MessageBox(NULL,"多了'*'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='/') MessageBox(NULL,"多了'/'号","提示",MB_OK|MB_ICONINFORMA TION);}flag=1;}}elseE(ch);}void E(char ch[]){if(ch[i]=='+'||ch[i]=='-'){i++;if(ch[i]!=NULL&&ch[i]!='+'&&ch[i]!='-'&&ch[i]!='*'&&ch[i]!='/')F(ch);else{if(flag==0){if(ch[i]!=NULL){MessageBox(NULL,"输入表达式不符合文法4.1","错误",MB_OK|MB_ICONERROR);if(ch[i]==' ') MessageBox(NULL,"含有空格","提示",MB_OK|MB_ICONINFORMA TION);程序代码else if(ch[i]=='+') MessageBox(NULL,"多了'+'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='-') MessageBox(NULL,"多了'-'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='*') MessageBox(NULL,"多了'*'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i]=='/') MessageBox(NULL,"多了'/'号","提示",MB_OK|MB_ICONINFORMA TION);}else if(ch[i]==NULL){MessageBox(NULL,"输入表达式不符合文法4.2","错误",MB_OK|MB_ICONERROR);if(ch[i-1]==' ') MessageBox(NULL,"含有空格","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='+') MessageBox(NULL,"多了最后的'+'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='-') MessageBox(NULL,"多了最后的'-'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='*') MessageBox(NULL,"多了最后的'*'号","提示",MB_OK|MB_ICONINFORMA TION);else if(ch[i-1]=='/') MessageBox(NULL,"多了最后的'/'号","提示",MB_OK|MB_ICONINFORMA TION);}}flag=1;}}else if(ch[i]!=')'){if(flag==0){MessageBox(NULL,"输入表达式不符合文法5","错误",MB_OK|MB_ICONERROR);if(ch[i]=='('&&ch[i+2]==')') MessageBox(NULL,"含有一对多余的括号","提示",MB_OK|MB_ICONINFORMA TION);else MessageBox(NULL,"其他类型的错误","提示",MB_OK|MB_ICONINFORMA TION);}flag=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)⽂法,⽤预测分析表法判断输⼊的符号串是否符合刚才输⼊的⽂法,并打印出分析过程。
编译原理语法分析实验报告
编译原理语法分析实验报告一、实验目的本实验主要目的是学习和掌握编译原理中的语法分析方法,通过实验了解和实践LR(1)分析器的实现过程,并对比不同的文法对语法分析的影响。
二、实验内容1.实现一个LR(1)的语法分析器2.使用不同的文法进行语法分析3.对比不同文法对语法分析的影响三、实验原理1.背景知识LR(1)分析器是一种自底向上(bottom-up)的语法分析方法。
它使用一个分析栈(stack)和一个输入缓冲区(input buffer)来处理输入文本,并通过移进(shift)和规约(reduce)操作进行语法分析。
2.实验步骤1)构建文法的LR(1)分析表2)读取输入文本3)初始化分析栈和输入缓冲区4)根据分析表进行移进或规约操作,直至分析过程结束四、实验过程与结果1.实验环境本实验使用Python语言进行实现,使用了语法分析库ply来辅助实验。
2.实验步骤1)构建文法的LR(1)分析表通过给定的文法,根据LR(1)分析表的构造算法,构建出分析表。
2)实现LR(1)分析器使用Python语言实现LR(1)分析器,包括读取输入文本、初始化分析栈和输入缓冲区、根据分析表进行移进或规约操作等功能。
3)使用不同的文法进行语法分析选择不同的文法对编写的LR(1)分析器进行测试,观察语法分析的结果。
3.实验结果通过不同的测试案例,实验结果表明编写的LR(1)分析器能够正确地进行语法分析,能够识别出输入文本是否符合给定文法。
五、实验分析与总结1.实验分析本实验通过实现LR(1)分析器,对不同文法进行语法分析,通过实验结果可以观察到不同文法对语法分析的影响。
2.实验总结本实验主要学习和掌握了编译原理中的语法分析方法,了解了LR(1)分析器的实现过程,并通过实验提高了对语法分析的理解。
六、实验心得通过本次实验,我深入学习了编译原理中的语法分析方法,了解了LR(1)分析器的实现过程。
在实验过程中,我遇到了一些问题,但通过查阅资料和请教老师,最终解决了问题,并完成了实验。
编译原理语法分析实验报告
编译原理语法分析实验报告编译原理实验报告二、语法分析(一) 实验题目编写程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析。
(二) 实验内容和要求1. 要求程序至少能分析的语言的内容有:1) 变量说明语句2) 赋值语句3) 条件转移语句4) 表达式(算术表达式和逻辑表达式)5) 循环语句6) 过程调用语句2. 此外要处理:包括依据文法对句子进行分析;出错处理;输出结果的构造。
3. 输入输出的格式:输入:单词文件(词法分析的结果)输出:语法成分列表或语法树(都用文件表示),错误文件(对于不合文法的句子)。
4. 实现方法:可以采用递归下降分析法,LL(1)分析法,算符优先法或LR分析法的任何一种,也可以针对不同的句子采用不同的分析方法。
(三) 实验分析与设计过程1. 待分析的C语言子集的语法:该语法为一个缩减了的C语言文法,估计是整个C语言所有文法的60%(各种关键字的定义都和词法分析中的一样),具体的文法如下:语法:100: program -> declaration_list101: declaration_list -> declaration_list declaration | declaration 102: declaration -> var_declaration|fun_declaration103: var_declaration -> type_specifier ID;|type_specifier ID[NUM]; 104: type_specifier -> int|void|float|char|long|double|105: fun_declaration -> type_specifier ID (params)|compound_stmt 106: params -> params_list|void107: param_list ->param_list,param|param108: param -> type-spectifier ID|type_specifier ID[]109: compound_stmt -> {local_declarations statement_list}110: local_declarations -> local_declarations var_declaration|empty 111: statement_list -> statement_list statement|empty11编译原理实验报告112: statement -> epresion_stmt|compound_stmt|selection_stmt|iteration_stmt|return_stmt113: expression_stmt -> expression;|;114: selection_stmt -> if{expression)statement|if(expression)statement else statement115: iteration_stmt -> while{expression)statement116: return_stmt -> return;|return expression;117: expression -> var = expression|simple-expression118: var -> ID |ID[expression]119: simple_expression ->additive_expression relop additive_expression|additive_expression 120: relop -> <=|<|>|>=|= =|!=121: additive_expression -> additive_expression addop term | term 122: addop -> + | -123: term -> term mulop factor | factor124: mulop -> *|/125: factor -> (expression)|var|call|NUM126: call -> ID(args)127: args -> arg_list|empty128: arg_list -> arg_list,expression|expression该文法满足了实验的要求,而且多了很多的内容,相当于一个小型的文法说明:把文法标号从100到128是为了程序中便于找到原来的文法。
编译原理课程实验报告(词法分析器及语法分析器)
编译原理实验报告班级:软件0501班学号:**********姓名:***词法分析器与语法分析器I. 问题描述设计、编制并调试一个词法分析子程序,完成识别语言单词的任务;设计、编制、调试一个语法分析程序,并用它对词法分析程序所提供的单词序列进行语法检查和结构分析。
ii. 设计简要描述界面需求:为了更加形象的模拟过程,此实验使用图形界面。
要求从图形界面上输入输入串,点击词法分析,可以将词法分析后识别的单词符号显示,点击语法分析,可以将语法分析的堆栈过程显示,并且显示结果(是否是符合文法的句子),清空则可以将所有置空。
功能分析:1、由用户输入输入串;2、用户点击“词法分析”,可以将词法分析后识别的单词符号显示。
3、用户点击语法分析,可以将语法分析的堆栈过程显示,并且显示结果(是否是符合文法的句子)4、用户点击清空,则将界面所有组件置为空思路描述:一、设计构想:本实验决定编写一个简易C语言的词法分析器和语法分析器。
使其能够识别while,if等关键字,可以判断赋值语句、条件语句、循环语句。
二、文法分析1、需要识别的关键字及其识别码有:关键字识别码关键字识别码关键字识别码main 0 - 11 ;22int 1 * 12 > 23char 2 / 13 < 24if 3 ( 14 >= 25else 4 ) 15 <= 26for 5 [ 16 == 27while 6 ] 17 != 28ID 7 { 18 ERROR -1NUM 8 } 19= 9 , 20+ 10 : 212、文法〈程序〉→ mai n()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉;〈语句串〉|〈语句〉;〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|=|!>转化为符号表示:S→ main() K|空K→ { C }C→Y;C |空Y→F | T | XF→ ID = BT→ if J KX→ while J KJ→( B G B )B→ B Z B |( B )| ID | NUMZ→ + | - | * | /G→< | <= | > | >= | == | !>表示含义:S:程序 K:语句块 C:语句串 Y:语句 F :赋值语句T:条件语句 X:循环语句 J:条件 B:表达式 I:项 Z :运算符G:关系符3、LL(1)分析表(1),求出first集及follow集:FIRST(S)={mian}FIRST(K)={{}FIRST(C)= FIRST(Y)= {ID,if,while,空};FIRST(Y)= FIRST(F)+ FIRST(T)+ FIRST(X)={ID,if,while};FIRST(F)={ID};FIRST(T)={if};FIRST(X)={while};FIRST(J)= FIRST(B)={};FIRST(B)={(,ID,NUM };FIRST(Z)={+,-,*,/}FIRST(G)={<,<= ,>,>=,==,!= };FOLLO W(S)={#};FOLLO W(K)={;};FOLLO W(C)={}};FOLLO W(Y)={;}FOLLO W(F)={;};FOLLO W(T)={;};FOLLO W(X)={;};FOLLO W(J)={{,;};FOLLO W(B)={+,-,*,/,),<,<= ,>,>=,==,!=,;};FOLLO W(B’)={+,-,*,/,),<,<= ,>,>=,==,!=,;};FOLLO W(Z)={(,ID,NUM };FOLLO W(G)={(,ID,NUM };(2)消除左递归,拆分文法关系并编号0、S→ 空1、S→ main() K2、K→ { C }3、C→Y;C4、C→空5、Y→ F6、Y→ T7、Y→ X8、F→ ID = B9、T→ if J K10、X→ while J K11、J→( B G B )12、 B→( B )B'13、B→ ID B'14、B→ NUM B'15、B'→ BZB B'16、B'→空17、Z→ +18、Z→ -19、Z→ *20、Z→ /21、 G→ <22、 G→ <=23、 G→ >24、 G→ >=25、 G→ ==26、 G→ !=(3)构造LL (1)分析表(注:在表中用上一步的编号表示所需要的产生式)iii. 详细设计描述 项目构架:各函数功能介绍:main 空 () { } ; = if while ID num + - * / < <= > >= == != # S 10 K 2 C 4 4 3 3 3 Y 6 7 5 F 8 T 9 X10 J11 B1213 14B '16 15 16 16 15 15 16 16 16 16 16 16 16 16 16 16 Z 17 18 19 20G21 22 232425261、word.wordList包(存储了关键字):word:此类是定义了存储关键字的结构:包括String型的关键字,和int型的识别符。
编译原理实验报告-语法分析
编译原理课程实验报告实验2:语法分析要求:采用至少一种句法分析技术(LL(1)、SLR(1)、LR(1)或LALR(1))对类高级语言中的基本语句进行句法分析。
阐述句法分析系统所要完成的功能。
本语法分析器是在词法分析器的基础上实现对类高级语言中的基本语句进行句法分析,基本功能如下:(1)能识别以下几类语句:声明语句(包括变量声明、数组声明、记录声明和过程声明)表达式及赋值语句(包括数组元素的引用和赋值)分支语句:if_then_else循环语句:do_while过程调用语句(2)本语法分析器采用自顶向下的分析技术,能根据导入的文法,自动计算first集和follow集,能够生成每个产生式的select集,并自动生成预测分析表。
(3)本语法分析器具备语法错误处理能力,可以进行错误检测,如果检测到在出错时,采用恐慌模式,能够给出错误提示信息,格式:错误项错误原因行号a)忽略输入中的一些符号,直到输入中出现选定的同步词法单元集合中的某个词法单元,同步集合的选取是非终结符的follow集;b)如果终结符在栈顶而不能匹配,弹出此终结符。
c)输入栈中缺少某些应有的符号,比如只有右括号没有左括号等,会给出相应的提示。
(4)系统的输入形式多样:可以通过文件导入文法和测试用例,可以通过用户界面显示并编辑测试用例。
测试用例涵盖了第(1)条中列出的各种类型的语句,并设置了一些语法错误。
(5)系统的输出分为两部分:一部分是打印输出语法分析器的FIRST集、FOLLOW集、select集和LL(1)分析表。
另一部分是打印输出语法分析结果。
要求:给出如下语言成分的文法描述。
声明语句(包括变量声明、数组声明、记录声明和过程声明)表达式及赋值语句(包括数组元素的引用和赋值)分支语句:if_then_else循环语句:do_while过程调用语句本语法分析器主要针对C语言进行文法设计,下面给出各语言成分的文法描述。
程序入口:Program->PP->D P //支持连续声明P ->S PP->ε1)声明语句:D proc id ; D S|T id; //支持过程声明和变量声明T →X C | record D //支持结构体声明X →short|int | long|float|double|char|string //支持多种基本类型的声明C →[num]C | ε//支持数组的声明2)表达式及赋值语句:S id = E ;| L = E ;E E + E | E * E | E | (E) | id | digit | LL id[E] | L[E] //支持数组元素的引用和赋值3)控制流语句:S if B then S1 else S2 | while B do S1B →B || B //或语句| B && B //且语句| ! B //非语句三、系统设计得分要求:分为系统概要设计和系统详细设计。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理程序设计实验报告——表达式语法分析器的设计实现班级:计算机1306班姓名:李佳泽学号:20133951实验目标:实现表达式语法分析器的设计实现,使用递归下降子程序、LL1分析法、LR分析法,判断一个表达式是否符合某个语法。
实验内容:流程图:数据结构:struct Node{char content[30]; int type;Node * next;};建立链表用于标识符IT ,常数Ct ,字符存ct ,字符串st ,TOKEN 源程序代码:1.递归调用子程序#include<iostream>#include<string.h>#include<fstream>#include<stdlib.h>#include <stack>using namespace std;#define NOTKEY 50#define iT 00#define cT 01#define sT 02#define CT 03char * kt[5]={"int","main","void","if","char"};char * pt[18]={">=" , "<=" ,"==","=",">","<","+","-","*","/","{","}",",",";","(",")","[","]" };int Ty =3;int dd=0;char vn[]={'E','e','T','t','F'};char vt[]={'i','W','w','(',')','#'};char * right[]={"Te","WTe","","Ft","wFt","","i","(E)"};int seekkt(char * TOKEN){for(int i=0; i<5; i++){if(strcmp(TOKEN,kt[i]) == 0){return i+4;}}return NOTKEY;}int seekpt(char * TOKEN){for(int i=0; i<18; i++){if(strcmp(TOKEN,pt[i]) == 0){return i+10;}}return -1;}int main(){int TOHN();int intN ();int scan();int Right();int print();TOHN();intN ();scan();if(dd==0){cout<<endl;cout<<"分析结果:"<<endl;cout<<endl;Right();}print();return 0;}stack <char> s;struct Node{char content[30];int type;Node * next;};Node * itHead;Node * CtHead;Node * ctHead;Node * stHead;Node * TOHead;Node * pp;void E();void T();void F();void TOHN(){TOHead = new Node();strcpy(TOHead->content,"");TOHead->type = 0;TOHead->next = NULL;}void setTON(char * content,int type){Node * p = TOHead ;Node * temp = new Node();while(p->next!=NULL) {p = p->next;}strcpy(temp->content,content);temp->type = type;temp->next = NULL;p->next = temp;}//初始化所有表头结点void intN(){itHead = new Node();strcpy(itHead->content,"");itHead->type = iT;itHead->next = NULL;stHead = new Node();strcpy(stHead->content,"");stHead->type = sT;stHead->next = NULL;CtHead = new Node();strcpy(CtHead->content,"");CtHead->type = CT;CtHead->next = NULL;ctHead = new Node();strcpy(ctHead->content,"");ctHead->type = cT;ctHead->next = NULL;}//创建新节点void setN(char * content,int type,Node * head){Node * p = head ;Node * temp = new Node();int flag = 0;while(p->next!=NULL){if(strcmp(content,p->next->content) == 0){flag = 1;}p = p->next;}if(flag == 0){strcpy(temp->content,content);temp->type = type;temp->next = NULL;p->next = temp;}}void print(){Node * p = TOHead;p = p->next;while(p!=NULL){p = p->next;}}void scan(){//char filename[50];char ch;char a[30];char * TOKEN;int i;FILE * fp;/*printf("输入语法分析的C语言程序(形如D:\\\\test.txt):\n");scanf("%s",filename);fp = fopen(filename,"r");*/fp=fopen("test.txt","r");ch = fgetc(fp);while(ch!='#'){i = 0;//以字母或者下划线开头,处理关键字或者标识符if((ch>='A' && ch<='Z') || (ch>='a' && ch<='z') || ch == '_'){while((ch>='A' && ch<='Z')||(ch>='a' && ch<='z')||(ch>='0' && ch<='9') || ch == '_'){a[i++] = ch;ch = fgetc(fp);}TOKEN = new char[i+1];memcpy(TOKEN,a,i);TOKEN[i] = '\0';int seekTemp = seekkt(TOKEN);if(seekTemp!=NOTKEY){setTON(TOKEN,seekTemp);}else{setN(TOKEN,iT,itHead);setTON(TOKEN,iT);}fseek(fp,-1L,SEEK_CUR);}//以数字开头,处理数字else if(ch >='0' && ch<='9'){int flag = 0;int flag2 = 0;while(ch >='0' && ch<='9'){a[i++] = ch;ch =fgetc(fp);}//处理floatif(ch == '.'){flag = 1;a[i++] = ch;ch = fgetc(fp);if(ch>='0' && ch<='9'){while(ch>='0' && ch<='9'){a[i++] = ch;ch = fgetc(fp);}}//处理Doubleif(ch == 'E' || ch == 'e'){a[i++] = ch;ch = fgetc(fp);if(ch == '+' || ch == '-'){a[i++] = ch;ch = fgetc(fp);}if(ch >='0' && ch<='9'){a[i++] = ch;ch = fgetc(fp);}}}TOKEN= new char[i+1];memcpy(TOKEN,a,i);TOKEN[i] = '\0';if(flag == 0){setN(TOKEN,CT,CtHead);setTON(TOKEN,CT);}else{setN(TOKEN,CT,CtHead);setTON(TOKEN,CT);}fseek(fp,-1L,SEEK_CUR);}//处理常量字符串else if(ch == '"'){a[i++] = ch;ch = fgetc(fp);while(ch!='"'){a[i++] = ch;ch = fgetc(fp);}a[i++] = ch;ch = fgetc(fp);TOKEN = new char[i+1];memcpy(TOKEN,a,i);TOKEN[i] = '\0';setN(TOKEN,sT,stHead);setTON(TOKEN,sT);fseek(fp,-1L,SEEK_CUR);}//处理常量字符else if(ch == '\''){a[i++] = ch;ch = fgetc(fp);while(ch!='\''){a[i++] = ch;ch = fgetc(fp);}a[i++] = ch;ch = fgetc(fp);TOKEN = new char[i+1];memcpy(TOKEN,a,i);TOKEN[i] = '\0';setN(TOKEN,cT,ctHead);setTON(TOKEN,cT);fseek(fp,-1L,SEEK_CUR);}//结束符else if((ch>='!'&&ch<='/')||(ch>=':'&&ch<='@')||(ch>='['&&ch<='`')||(ch>='('&&ch<='~')){int seektemp;if(ch=='<'||ch=='>'||ch=='='){a[i++] = ch;ch = fgetc(fp);}else {a[i++] = ch;ch = fgetc(fp);}TOKEN = new char[i+1];memcpy(TOKEN,a,i);TOKEN[i] = '\0';seektemp=seekpt(TOKEN);if(seektemp==-1)//结束符不存在{cout<<"结束符错误请检查"<<endl;dd=1;}else{setTON(TOKEN,seektemp);}fseek(fp,-1L,SEEK_CUR);}ch = fgetc(fp);}setTON("#",333);fclose(fp);}void Right(){pp=TOHead;pp=pp->next;E();if(strcmp(pp->content,"#") == 0&&Ty==3){cout<<"RIGHT"<<endl;}else{if(strcmp(pp->content,"#") != 0 &&Ty==3){cout<<"WRONG"<<endl<<endl;cout<<"理由:括号不匹配"<<endl;cout<<endl;}else if (Ty==1){cout<<"WRONG"<<endl<<endl;cout<<"理由:非法字符"<<endl;cout<<endl;}else if(Ty ==2){cout<<"WRONG"<<endl<<endl;cout<<"理由:缺少“)”"<<endl;cout<<endl;}}}void E(){if (Ty != 3) return;T();while (strcmp(pp->content,"+") == 0||strcmp(pp->content,"-") == 0){pp=pp->next;T();}return ;}void T(){if (Ty != 3) return;F();while (strcmp(pp->content,"*") == 0||strcmp(pp->content,"/") == 0){pp=pp->next;F();}return ;}void F(){if (Ty != 3) return;if (pp->type == CT||pp->type == iT){pp=pp->next;return;}elseif(strcmp(pp->content,"(") == 0){pp=pp->next;E();if (strcmp(pp->content,")") == 0){pp=pp->next;return;}else{Ty = 2;return;}}else{Ty = 1;return;}}2.LL1分析法#include<iostream>#include<string.h>#include<fstream>#include<stdlib.h>#include <stack>using namespace std;#define NOTKEY 50#define iT 00#define cT 01#define sT 02#define CT 03char * kt[5]={"int","main","void","if","char"};char * pt[18]={">=" , "<=" ,"==","=",">","<","+","-","*","/","{","}",",",";","(",")","[","]" }; int dd=0;int sss=0;int seekkt(char * TOKEN){for(int i=0; i<5; i++){if(strcmp(TOKEN,kt[i]) == 0){return i+4;}}return NOTKEY;}int seekpt(char * TOKEN){for(int i=0; i<18; i++){if(strcmp(TOKEN,pt[i]) == 0){return i+10;}}return -1;}int main(){int TOHN();int intN ();int scan();int print();int wrong();TOHN();intN ();scan();print();if(dd==0){cout<<"分析结果:"<<endl<<endl; wrong();cout<<endl;}return 0;}stack <char*> s;struct Node{char content[30];int type;Node * next;};Node * itHead;Node * CtHead;Node * ctHead;Node * stHead;Node * TOHead;Node * pp;void TOHN(){TOHead = new Node();strcpy(TOHead->content,"");TOHead->type = 0;TOHead->next = NULL;}void setTON(char * content,int type){Node * p = TOHead ;Node * temp = new Node();while(p->next!=NULL) {p = p->next;}strcpy(temp->content,content);temp->type = type;temp->next = NULL;p->next = temp;}//初始化所有表头结点void intN(){itHead = new Node();strcpy(itHead->content,"");itHead->type = iT;itHead->next = NULL;stHead = new Node();strcpy(stHead->content,"");stHead->type = sT;stHead->next = NULL;CtHead = new Node();strcpy(CtHead->content,"");CtHead->type = CT;CtHead->next = NULL;ctHead = new Node();strcpy(ctHead->content,"");ctHead->type = cT;ctHead->next = NULL;}//创建新节点void setN(char * content,int type,Node * head){Node * p = head ;Node * temp = new Node();int flag = 0;while(p->next!=NULL){if(strcmp(content,p->next->content) == 0){flag = 1;}p = p->next;}if(flag == 0){strcpy(temp->content,content);temp->type = type;temp->next = NULL;p->next = temp;}}//打印链表void print(){Node * p = TOHead;p = p->next;while(p!=NULL){p = p->next;}}//扫描程序void scan(){//char filename[50];char ch;char array[30];char * TOKEN;int i;FILE * fp;/*printf("输入语法分析的C语言程序(形如test.txt):\n");scanf("%s",filename);fp = fopen(filename,"r");*/fp=fopen("test.txt","r");ch = fgetc(fp);while(ch!='#'){i = 0;if((ch>='A' && ch<='Z') || (ch>='a' && ch<='z') || ch == '_'){while((ch>='A' && ch<='Z')||(ch>='a' && ch<='z')||(ch>='0' && ch<='9') || ch == '_'){array[i++] = ch;ch = fgetc(fp);}TOKEN = new char[i+1];memcpy(TOKEN,array,i);TOKEN[i] = '\0';int seekTemp = seekkt(TOKEN);if(seekTemp!=NOTKEY){setTON(TOKEN,seekTemp);}else{setN(TOKEN,iT,itHead);setTON(TOKEN,iT);}fseek(fp,-1L,SEEK_CUR);}//以数字开头,处理数字else if(ch >='0' && ch<='9'){int flag = 0;int flag1 = 0;while(ch >='0' && ch<='9'){array[i++] = ch;ch =fgetc(fp);}//处理floatif(ch == '.'){flag1 = 1;array[i++] = ch;ch = fgetc(fp);if(ch>='0' && ch<='9'){while(ch>='0' && ch<='9'){array[i++] = ch;ch = fgetc(fp);}}//处理Doubleif(ch == 'E' || ch == 'e'){array[i++] = ch;ch = fgetc(fp);if(ch == '+' || ch == '-'){array[i++] = ch;ch = fgetc(fp);}if(ch >='0' && ch<='9'){array[i++] = ch;ch = fgetc(fp);}}}TOKEN= new char[i+1];memcpy(TOKEN,array,i);TOKEN[i] = '\0';if(flag == 0){setN(TOKEN,CT,CtHead);setTON(TOKEN,CT);}else{setN(TOKEN,CT,CtHead);setTON(TOKEN,CT);}fseek(fp,-1L,SEEK_CUR);}//处理常量字符串else if(ch == '"'){array[i++] = ch;ch = fgetc(fp);while(ch!='"'){array[i++] = ch;ch = fgetc(fp);}array[i++] = ch;ch = fgetc(fp);TOKEN = new char[i+1];memcpy(TOKEN,array,i);TOKEN[i] = '\0';setN(TOKEN,sT,stHead);setTON(TOKEN,sT);fseek(fp,-1L,SEEK_CUR); }//处理常量字符else if(ch == '\''){array[i++] = ch;ch = fgetc(fp);while(ch!='\''){array[i++] = ch;ch = fgetc(fp);}array[i++] = ch;ch = fgetc(fp);TOKEN = new char[i+1];memcpy(TOKEN,array,i);TOKEN[i] = '\0';setN(TOKEN,cT,ctHead);setTON(TOKEN,cT);fseek(fp,-1L,SEEK_CUR);}//结束符else if((ch>='!'&&ch<='/')||(ch>=':'&&ch<='@')||(ch>='['&&ch<='`')||(ch>='('&&ch<='~')){int seektemp;if(ch=='<'||ch=='>'||ch=='='){array[i++] = ch;ch = fgetc(fp);}else {array[i++] = ch;ch = fgetc(fp);}TOKEN = new char[i+1];memcpy(TOKEN,array,i);TOKEN[i] = '\0';seektemp=seekpt(TOKEN);if(seektemp==-1)//结束符不存在{cout<<"结束符错误请检查"<<endl;dd=1;}else{setTON(TOKEN,seektemp);}fseek(fp,-1L,SEEK_CUR);}ch = fgetc(fp);}setTON("#",333);fclose(fp);}/*内容类码( 24Aa 0+ 16) 25* 1888.2 3/ 19- 17# 123*/void ssss(){if(s.top()=="E"){if((pp->type==iT)||(pp->type==CT)){s.pop();s.push("E1");s.push("T");sss=1;return;}if(pp->type==24){s.pop();s.push("E1");s.push("T");sss=1;return;}if(s.top()=="E1"){if((pp->type==16)||(pp->type==17)){s.pop();s.push("E1");s.push("T");s.push("w0");sss=1;return;}if(pp->type==25){s.pop();sss=1;return;}if(pp->type==333){s.pop();sss=1;return;}}if(s.top()=="T"){if((pp->type==iT)||(pp->type==CT)){s.pop();s.push("T1");s.push("F");sss=1;return;if(pp->type==24){s.pop();s.push("T1");s.push("F");sss=1;return;}//处理float}if(s.top()=="T1"){if((pp->type==16)||(pp->type==17)){s.pop();;sss=1;return;}if((pp->type==18)||(pp->type==19)){s.pop();s.push("T1");s.push("F");s.push("w1");sss=1;return;}if(pp->type==25){s.pop();//处理floatsss=1;return;}if(pp->type==333){s.pop();sss=1;return;}}if(s.top()=="F"){if((pp->type==iT)||(pp->type==CT)){s.pop();s.push("I");sss=1;return;}if(pp->type==24){s.pop();s.push(")");s.push("E");s.push("(");sss=1;return;}}}void two(){string content(&pp->content[0],&pp->content[strlen(pp->content)]);if(pp->type==16||pp->type==17)content="w0";if(pp->type==18||pp->type==19)content="w1";if(pp->type==iT||pp->type==CT)content="I";if(strcmp(s.top(),content.c_str())==0){s.pop();pp=pp->next;sss=1;return;}}void wrong(){s.push("#");s.push("E");pp=TOHead;pp=pp->next;while(!s.empty()){sss=0;ssss();two();if (sss==0){cout<<"WRONG";break;}}if (sss!=0){cout<<"RIGHT";}}程序运行结果:(截屏)递归调用子程序输入:Aa+Bb)*(88.2/3)#输出:输入:(Aa+Bb)*(88.2/3)#输出:LL1分析法输入:Aa+Bb)*(88.2/3)#输出:输入:(Aa+Bb)*(88.2/3)#输出:。