编译原理实验 (词法语法分析报告 附源代码

合集下载

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。

二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。

三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。

在本次实验中,我们使用有限自动机的理论来设计词法分析器。

首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。

然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。

在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。

(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。

在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。

首先,我们根据给定的语法规则,编写了相应的递归函数。

每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。

在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。

(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。

在本次实验中,我们使用了四元式作为中间代码的表示形式。

在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。

同时,根据语法树的结构,生成相应的四元式中间代码。

(四)代码优化代码优化的目的是提高生成代码的质量和效率。

在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。

通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。

编译原理词法分析和语法分析报告 代码(C语言版)

编译原理词法分析和语法分析报告 代码(C语言版)
s_find=MarkPush(s_find,str[0],r_find->relationship);
admit=0;
for(in=0;in<cal-1;in++){str[in]=str[in+1];}
str[in]='\0';
cal--;
r_find=r_find->next;
}//:入栈~
if(r_find->line_States==s_find->num&&r_find->rank_Letter==str[0]&&r_find->name=='r'){//:规约
词法分析
三、词法分析程序的算法思想:
算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1主程序示意图:


扫描子程序主要部分流程图
是是

字母
数字其他
运算符、符号
界符等符号


词法分析程序的C语言程序源代码:
//词法分析函数: void scan()
//数据传递:形参fp接收指向文本文件头的文件指针;
//全局变量buffer与line对应保存源文件字符及其行号,char_num保存字符总数。
void scan()
{
char ch;
int flag,j=0,i=-1;
while(!feof(fp1))
{
ch=fgetc(fp1);
flag=judge(ch);
struct Sign *next;

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

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

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];

【编译原理】词法分析(CC++源代码+实验报告)

【编译原理】词法分析(CC++源代码+实验报告)

【编译原理】词法分析(CC++源代码+实验报告)⽂章⽬录1 实验⽬的和内容1.1实验⽬的(1)根据 PL/0 语⾔的⽂法规范,编写PL/0语⾔的词法分析程序;或者调研词法分析程序的⾃动⽣成⼯具LEX或FLEX,设计并实现⼀个能够输出单词序列的词法分析器。

(2)通过设计调试词法分析程序,实现从源程序中分离出各种类型的单词;加深对课堂教学的理解;提⾼词法分析⽅法的实践能⼒。

(3)掌握从源程序⽂件中读取有效字符的⽅法和产⽣源程序的内部表⽰⽂件的⽅法。

(4)掌握词法分析的实现⽅法。

(5)上机调试编出的词法分析程序。

1.2实验内容根据PL/0语⾔的⽂法规范,编写PL/0语⾔的词法分析程序。

要求:(1)把词法分析器设计成⼀个独⽴⼀遍的过程。

(2)词法分析器的输出形式采⽤⼆元式序列,即:(单词种类, 单词的值)2 设计思想2.1单词种类及其正规式(1)基本字单词的值单词类型正规式rbegin beginsym begincall callsym callconst constsym constdo dosym doend endsym endif ifsym ifodd oddsym oddprocedure proceduresym procedureread readsym readthen thensym thenvar varsym varwhile whilesym whilewrite writesym write(2)标识符单词的值单词类型正规式r标识符ident(字母)(字母|数字)*(3)常数单词的值单词类型正规式r常数number(数字)(数字)*(4)运算符单词的值单词类型正规式r+plus+-minus-*times*/slash/=eql=<>neq<><lss<<=leq<=>gtr>>=geq>=:=becomes:=(5)界符单词的值单词类型正规式r(lparen()rparen),comma,;semicolon;.period.2.2 根据正规式构造NFA下⾯我们根据上述的正规式来构造该⽂法的NFA,如下图所⽰,其中状态0为初态,凡带双圈的状态均为终态,状态24是识别不出单词符号的出错情形,其他状态的识别情况如下图中右边的注释所⽰。

编译原理实验词法分析语法分析

编译原理实验词法分析语法分析

本代码只供学习参考:词法分析源代码:#include<iostream>#include<fstream>#include<string>using namespace std;string key[8]={"do","end","for","if","printf","scanf","then","while"}; string optr[4]={"+","-","*","/"};string separator[6]={",",";","{","}","(",")"};char ch;//判断是否为保留字bool IsKey(string ss) {int i;for(i=0;i<8;i++)if(!strcmp(key[i].c_str(),ss.c_str()))return true;return false;}//字母判断函数bool IsLetter(char c) {if(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z')))return true;return false;}//数字判断函数bool IsDigit(char c) {if(c>='0'&&c<='9')return true;return false;}//运算符判断函数bool IsOptr(string ss) {int i;for(i=0;i<4;i++)if(!strcmp(optr[i].c_str(),ss.c_str()))return true ;return false;}//分界符判断函数bool IsSeparator(string ss) {int i;for(i=0;i<6;i++)if(!strcmp(separator[i].c_str(),ss.c_str()))return true;return false;}void analyse(ifstream &in) {string st="";char ch;int line=1,row=0;while((in.get(ch))) {st="";if((ch==' ')||(ch=='\t')){} //空格,tab健elseif(ch=='\n') {line++;row=0; } //换行行数加一处理elseif(IsLetter(ch)) //关键字、标识符的处理{row++;while(IsLetter(ch)||IsDigit(ch)){st+=ch;in.get(ch);}in.seekg(-1,ios::cur);//文件指针(光标)后退一个字节if(IsKey(st)) //判断是否为关键字查询关键字表;cout<<st<<"\t("<<st<<","<<1<<")"<<'\t'<<'\t'<<"关键字"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else //否则为标示符cout<<st<<"\t("<<st<<","<<2<<")"<<'\t'<<'\t'<<"标识符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}elseif(IsDigit(ch)) //无符号整数处理{row++;while(IsDigit(ch)){st+=ch;ch=in.get();}in.seekg(-1,ios::cur);cout<<st<<"\t("<<st<<","<<3<<")"<<'\t'<<'\t'<<"常数"<<'\t'<<"("<<line<<","<<row<<")"<<endl;// break;}else{st="";st+=ch;if(IsOptr(st)) //运算符处理{row++;cout<<st<<"\t("<<st<<","<<4<<")"<<'\t'<<'\t'<<"运算符"<<"("<<line<<","<<row<<")"<<endl;}elseif(IsSeparator(st))//分隔符处理{ row++;cout<<st<<"\t("<<st<<","<<5<<")"<<'\t'<<'\t'<<"分界符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}else{switch(ch){row++;case'=' : {row++;cout<<"="<<"\t("<<"="<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}case'>' :{row++;ch=in.get();if(ch=='=')cout<<">="<<'\t'<<"("<<">="<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else {cout<<">"<<"\t("<<">"<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;in.seekg(-1,ios::cur);}} break;case'<' :{row++;ch=in.get();if(ch=='=')cout<<"<="<<'\t'<<"("<<"="<<","<<"6"<<")"<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else if(ch=='>') cout<<"<>"<<'\t'<<"("<<"<>"<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else{cout<<"<"<<"\t("<<"<"<<","<<"6"<<")"<<"\t"<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;in.seekg(-1,ios::cur);}}break;default :{row++; cout<<ch<<'\t'<<"\t$无法识别字符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}}}}}}int main(){ifstream in;in.open("test.txt",ios::in);cout<<"关键字-》1 标识符-》2 常数-》3 运算符-》4 分隔符-》5"<<endl;if(in.is_open()){analyse(in);in.close();system("pause");}elsecout<<"文件操作出错"<<endl;}语法分析实验源代码LL#include<iostream>using namespace std;const int MaxLen=20; //初始化栈的长度const int Length=20;//初始化数组长度char Vn[5]={'E','G','T','S','F'};//非终结符数组char Vt[8]={'i','(',')','+','-','*','/','#'};//终结符数组char ch,X;//ch读当前字符,X获取栈顶元素char strToken[Length];//存储规约表达式struct LL//ll(1)分析表的构造字初始化{char*c;};LL E[8]={"TG","TG","error","error","error","error","error","error"};LL G[8]={"error","error","null","+TG","-TG","error","error","null"};LL T[8]={"FS","FS","error","error","error","error","error","error"};LL S[8]={"error","error","null","null","null","*FS","/FS","null"};LL F[8]={"i","(E)","error","error","error","error","error","error"};class stack//栈的构造及初始化{public:stack();//初始化bool empty() const;//是否为空bool full() const;//是否已满bool get_top(char &c)const;//取栈顶元素bool push(const char c);//入栈bool pop();//删除栈顶元素void out();//输出栈中元素~stack(){}//析构private:int count;//栈长度char data[MaxLen];//栈中元素};stack::stack(){count=0;}bool stack::empty() const{if(count==0)return true;return false;}bool stack::full() const{if(count==MaxLen)return true;return false;}bool stack::get_top(char &c)const{if(empty())return false;else{c=data[count-1];return true;}}bool stack::push(const char c){if(full())return false;data[count++]=c;return true;}bool stack::pop(){if(empty())return false;count--;return true;}void stack::out(){for(int i=0;i<count;i++)cout<<data[i];cout<<'\t';}int length(char *c){int l=0;for(int i=0;c[i]!='\0';i++)l++;return l;}void print(int i,char*c)//剩余输入串的输出{for(int j=i;j<Length;j++)cout<<c[j];cout<<'\t';}void run(){bool flag=true;//循环条件int step=0,point=0;//步骤、指针int len;//长度cout<<"输入规约的字符串:"<<endl;cin>>strToken;ch=strToken[point++];//读取第一个字符stack s;s.push('#');//栈中数据初始化s.push('E');s.get_top(X);//取栈顶元素cout<<"步骤\t"<<"分析栈\t"<<"剩余输入串\t\t"<<"所用产生式\t"<<"动作"<<endl;cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<'\t'<<"初始化"<<endl;while(flag){if((X==Vt[0])||(X==Vt[1])||(X==Vt[2])||(X==Vt[3])||(X==Vt[4])||(X==Vt[5])||(X==Vt[6])) //判断是否为终结符(不包括#){if(X==ch)//终结符,识别,进行下一字符规约{s.pop();s.get_top(X);ch=strToken[point++];cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<'\t'<<"GETNEXT(I)"<<endl;}else{flag=false;}}else if(X=='#')//规约结束{if(X==ch){cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<ch<<'\t'<<"结束"<<endl;s.pop();flag=false;}else{flag=false;}}else if(X==Vn[0]) //非终结符E{for(int i=0;i<8;i++)//查分析表if(ch==Vt[i]){if(strcmp(E[i].c,"error")==0)//出错{flag=false;}else{ //对形如X->X1X2的产生式进行入栈操作s.pop();len=length(E[i].c)-1;for(int j=len;j>=0;j--)s.push(E[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<E[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<E[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[1]) //同上,处理G{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(G[i].c,"null")==0){s.pop();cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<"ε"<<'\t'<<"POP"<<endl;s.get_top(X);}else if(strcmp(G[i].c,"error")==0){flag=false;}else{s.pop();len=length(G[i].c)-1;for(int j=len;j>=0;j--)s.push(G[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<G[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<G[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[2]) //同上处理T{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(T[i].c,"error")==0){flag=false;}else{s.pop();len=length(T[i].c)-1;for(int j=len;j>=0;j--)s.push(T[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<T[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<T[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[3])//同上处理S{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(S[i].c,"null")==0){s.pop();cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<"ε"<<'\t'<<"POP"<<endl;s.get_top(X);}else if(strcmp(S[i].c,"error")==0){flag=false;}else{s.pop();len=length(S[i].c)-1;for(int j=len;j>=0;j--)s.push(S[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<S[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<S[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[4]) //同上处理F{for(int i=0;i<7;i++)if(ch==Vt[i]){if(strcmp(F[i].c,"error")==0){flag=false;}else{s.pop();len=length(F[i].c)-1;for(int j=len;j>=0;j--)s.push(F[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<F[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<F[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else //出错处理{flag= false;}}}int main(){cout<<"实验二"<<endl;run();system("pause");return 0;}语法实验源代码LR#include<iostream>using namespace std;const int MaxLen=20; //初始化栈的长度const int Length=20;//初始化数组长度char ch,Y;//全局变量,ch用于读当前字符,Y用于获取栈顶元素char strToken[Length];//存储规约表达式bool flag=true;//循环条件int point=0,step=1;//步骤、指针class stack//栈的构造及初始化{public:stack();//初始化bool empty() const;//是否为空bool full() const;//是否已满bool get_top(char &c)const;//取栈顶元素bool push(const char c);//入栈bool pop();void out();//输出栈中元素void out1();~stack(){}//析构private:int count;//栈长度char data[MaxLen];//栈中元素};stack l,r;//l代表符号栈,r代表状态栈stack::stack(){count=0;}bool stack::empty() const{if(count==0)return true;return false;}bool stack::full() const{if(count==MaxLen)return true;return false;}bool stack::get_top(char &c)const{if(empty())return false;else{c=data[count-1];return true;}}bool stack::push(const char c){if(full())return false;data[count++]=c;return true;}bool stack::pop(){if(empty())return false;count--;return true;}void stack::out(){for(int i=0;i<count;i++)cout<<data[i];cout<<'\t';}void stack::out1(){for(int i=0;i<count;i++)cout<<int(data[i]);cout<<'\t';}void print(int i,char*c)//剩余输入串的输出{for(int j=i;j<Length;j++)cout<<c[j];cout<<'\t';}void Goto(int i,char c)//状态转换函数,对应于表中GOTO {if(i==0){if(c=='E'){r.push(1);cout<<",GOTO(0,E)=1入栈"<<endl;}else if(c=='T'){r.push(2);cout<<",GOTO(0,T)=2入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(0,F)=3入栈"<<endl;}elseflag=false;}else if(i==4){if(c=='E'){r.push(8);cout<<",GOTO(4,E)=8入栈"<<endl;}else if(c=='T'){r.push(2);cout<<",GOTO(4,T)=2入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(4,F)=3入栈"<<endl;}elseflag=false;}else if(i==6){if(c=='T'){r.push(9);cout<<",GOTO(6,T)=9入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(6,F)=3入栈"<<endl;}elseflag=false;}else if(i==7){if(c=='F'){r.push(10);cout<<",GOTO(7,F)=10入栈"<<endl;}elseflag=false;}elseflag=false;}void Action0()//状态0时{if(ch=='i')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[0,i]=S5,状态5入栈"<<endl;r.push(5);l.push(ch);ch=strToken[point++];}else if(ch=='(')//下一个操作符为( ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[0,(]=S4,状态4入栈"<<endl;r.push(4);l.push(ch);ch=strToken[point++];}elseflag=false;}void Action1()//状态1{if(ch=='+')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[1,+]=S6,状态6入栈"<<endl;r.push(6);l.push(ch);ch=strToken[point++];}else if(ch=='#')//分析成功{flag=false;cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"Acc:分析成功"<<endl;}elseflag=false;}void Action2() //状态2{if(ch=='*')//下一个操作符为* ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[2,*]=S7,状态7入栈"<<endl;r.push(7);l.push(ch);ch=strToken[point++];}else if((ch=='+')||(ch==')')||(ch=='#'))//下一个操作符为+,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('E');print(point-1,strToken);cout<<"r2: E→T归约";r.pop();r.get_top(Y);Goto(int(Y),'E');}elseflag=false;}void Action3()//状态3{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('T');print(point-1,strToken);cout<<"r4: T→F归约";r.pop();r.get_top(Y);Goto(int(Y),'T');}elseflag=false;}void Action4_6_7(int x)//状态4,6,7{if(ch=='i')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[";cout<<x<<",i]=S5,状态5入栈"<<endl;r.push(5);l.push(ch);ch=strToken[point++];}else if(ch=='(')//下一个操作符为(,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[";cout<<x<<",(]=S4,状态4入栈"<<endl;r.push(4);l.push(ch);ch=strToken[point++];}elseflag=false;}void Action5()//状态5{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('F');print(point-1,strToken);cout<<"r6: F→i归约";r.pop();r.get_top(Y);Goto(int(Y),'F');}elseflag=false;}void Action8()//状态8{if(ch=='+')//下一个操作符为+ ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[8,+]=S6,状态6入栈"<<endl;r.push(6);l.push(ch);ch=strToken[point++];}else if(ch==')')//下一个操作符为),移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[8,)]=S11,状态11入栈"<<endl;r.push(11);ch=strToken[point++];}elseflag=false;}void Action9()//状态9{if(ch=='*')//下一个操作符为* ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[9,*]=S7,状态7入栈"<<endl;r.push(7);l.push(ch);ch=strToken[point++];}else if((ch=='+')||(ch==')')||(ch=='#'))//下一个操作符为+,,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.pop();l.pop();l.push('E');print(point-1,strToken);cout<<"r1: E→E+T归约";r.pop();r.pop();r.pop();r.get_top(Y);Goto(int(Y),'E');}elseflag=false;}void Action10()//状态10{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';l.out();l.pop();l.pop();l.pop();l.push('T');print(point-1,strToken);cout<<"r3: T→T*F归约";r.pop();r.pop();r.pop();r.get_top(Y);Goto(int(Y),'T');}elseflag=false;}void Action11()//状态11{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.pop();l.pop();l.push('F');print(point-1,strToken);cout<<"r5: F→(E)归约";r.pop();r.pop();r.pop();r.get_top(Y);Goto(int(Y),'F');}elseflag=false;}void run()//规约{cout<<"请输入要规约的字符串:"<<endl;cin>>strToken;cout<<"步骤\t"<<"状态栈\t"<<"符号栈\t"<<"输入串\t\t"<<"动作说明"<<endl;ch=strToken[point++];//读取第一个字符l.push('#');r.push(0);r.get_top(Y);while(flag)//循环规约{if(int(Y)==0)Action0();else if(int(Y)==1)Action1();else if(int(Y)==2)Action2();else if(int(Y)==3)Action3();else if((int(Y)==4)||(int(Y)==6)||(int(Y)==7))Action4_6_7(int(Y));else if(int(Y)==5)Action5();else if(int(Y)==8)Action8();else if(int(Y)==9)Action9();else if(int(Y)==10)Action10();else if(int(Y)==11)Action11();elseflag=false;r.get_top(Y);}}int main(){cout<<"实验三"<<endl;run();system("pause");return 0;}。

编译原理语法分析实验报告(含有源代码)

编译原理语法分析实验报告(含有源代码)

《编译原理》实验报告
四、实验过程原始记录(数据、图表、计算等)
输入begin a:=9;x:=2*3;b:=a+x end #
输出success
输入x:=a+b*c end #
输出error
五、实验结果及分析,以及心得体会
通过学习了语法分析,再经过实验,让我对语法分析有了深刻的认识和了解。

递归下降分析法,是一种确定的自顶向下分析技术,它的实现思想是,对文法中分别代表一种语法成分的每个非终结符号编写一个子程序,已完成非终结符号所对应的语法成分的分析任务。

在分析过程中调用一系列过程或函数,对源程序进行语法语义分析直到整个程序处理结束。

编译原理实验报告——词法分析器(内含源代码)

编译原理实验报告——词法分析器(内含源代码)

编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。

该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。

二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。

同时增强编写和调试程序的能力。

三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。

四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。

int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。

void GetChar(char *ch); //将下一个输入字符读到ch中。

void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。

void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。

int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。

void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。

编译原理语法分析报告+代码

编译原理语法分析报告+代码

语法分析一、实验目的编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

二、实验要求利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

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 #输出error2.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分析过程示意图三、语法分析程序的C语言程序源代码:#include "stdio.h"#include "string.h"char prog[100],token[8],ch;char *rwtab[6]={"begin","if","then","while","do","end"};int syn,p,m,n,sum;int kk;factor();expression();yucu();term();statement();lrparser();scaner();main(){p=kk=0;printf("\nplease input a string (end with '#'): \n");do{ scanf("%c",&ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();getch();}lrparser(){if(syn==1){scaner(); /*读下一个单词符号*/yucu(); /*调用yucu()函数;*/if (syn==6){ scaner();if ((syn==0)&&(kk==0))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(){statement(); /*调用函数statement();*/while(syn==26){scaner(); /*读下一个单词符号*/if(syn!=6)statement(); /*调用函数statement();*/}return;}statement(){ if(syn==10){scaner(); /*读下一个单词符号*/if(syn==18){ scaner(); /*读下一个单词符号*/ expression(); /*调用函数statement();*/ }else { printf("the sing ':=' is wrong!\n");kk=1;}}else { printf("wrong sentence!\n");kk=1;}return;}expression(){ term();while((syn==13)||(syn==14)){ scaner(); /*读下一个单词符号*/ term(); /*调用函数term();*/}return;}term(){ factor();while((syn==15)||(syn==16)){ scaner(); /*读下一个单词符号*/ factor(); /*调用函数factor(); */ }return;}factor(){ if((syn==10)||(syn==11)) scaner();else if(syn==27){ scaner(); /*读下一个单词符号*/expression(); /*调用函数statement();*/ if(syn==28)scaner(); /*读下一个单词符号*/else { printf("the error on '('\n");kk=1;}}else { printf("the expression error!\n");kk=1;}return;}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;m=0;ch=prog[p++];while(ch==' ')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;token[m++]='\0';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 '<':m=0;ch=prog[p++];if(ch=='>'){ syn=21;}else if(ch=='='){ syn=22;}else{ syn=20;p--;}break;case '>':m=0;ch=prog[p++];if(ch=='='){ syn=24;}else{ syn=23;p--;}break;case ':':m=0;ch=prog[p++];if(ch=='='){ syn=18;}else{ syn=17;p--;}break;case '+': syn=13; break;case '-': syn=14; break;case '*': syn=15;break;case '/': syn=16;break;case '(': syn=27;break;case ')': syn=28;break;case '=': syn=25;break;case ';': syn=26;break;case '#': syn=0;break;default: syn=-1;break;}}四、结果分析:输入begin a:=9; x:=2*3; b:=a+x end # 后输出success!如图4-1所示:图4-1输入x:=a+b*c end # 后输出error 如图4-2所示:图4-2五、总结:通过本次试验,了解了语法分析的运行过程,主程序大致流程为:“置初值”→调用scaner 函数读下一个单词符号→调用IrParse→结束。

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

编译原理实验报告******************************************************************************* ******************************************************************************* 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文法首先应该进行一定的预处理,提取左公因式,消除左递归(直接或间接),接着就可以根据所得的文法进行编写代码。

【实验一】词法分析【实验目的】给出PL/0文法规,要求编写PL/0语言的词法分析程序。

【实验容】已给PL/0语言文法,输出单词(关键字、专用符号以及其它标记)。

【实验要求】1.确定编译中使用的表格、标识符与关键字的区分方法等。

2.把词法分析器设计成一个独立一遍的过程。

3.词法分析器的输出形式采用二元式序列,例如:(ident, a)(plus, + )(number, 15)(times, * )(ident, b )【输入输出】输入:PL/0源程序。

例: a+15*b输出:(ident, a)(plus, + )(number, 15)(times, * )(ident, b )【实验结果】实验结果与实验要求相同,没有异议,对输入字符采取一个一个读入,到达句柄时,则采取LL(1)文法进行规约。

实验结果如下:实验结果用文本来进行输入输出,所以在工程目录下还会有一个文本输入,输出文件。

分别为in.txt out.txt【实验体会】在编写这段代码的过程中,比较麻烦得还是之前的语法预处理阶段,将不满足ll(1)文法的语法转化为标准的ll(1)文法。

程序在处理词法分析的过程就是不断通过getsym()这个函数来条用getch(),不断形成一个一个的词汇,供下面语法分析时使用。

记录词汇类型的sym是一个枚举类型。

使用起来会方便许多,比较系统。

其中还用到了文本输入输出的技巧,把读出的词汇保存起来。

词法分析还是比较简单,在编写代码的时候没有太大的阻碍。

通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。

另外,也让我重新熟悉了C++语言的相关容,加深了对C++语言的用途的理解。

【实验二】语法分析【实验目的】给出PL/0文法规,要求编写PL/0语言的语法分析程序。

【实验容】已给PL/0语言文法,构造表达式部分的语法分析器。

【实验要求】1.将实验一“词法分析”的输出结果,作为表达式语法分析器的输入,进行语法解析,对于语确的表达式,报告“语确”;对于语法错误的表达式,报告“语法错误”,指出错误原因。

2.把语法分析器设计成一个独立一遍的过程。

3.语法分析器的编写方法采用递归子程序法。

【输入输出】输入:PL/0表达式,用实验一的输出形式作为输入。

例如: 对于PL/0表达式,a+15*b用下列形式作为输入:(ident, a)(plus, + )(number, 15)(times, * )(ident, b )输出:对于语确的表达式,报告“语确”;对于语法错误的表达式,报告“语法错误”,指出错误原因。

【实验结果】实验结果与实验要求相同,没有异议,对输入字符采取一个一个读入,对输入的一个语句进行判断,判断语法的正误,采用对算法的判断,若全为数字则进行最后的计算【实验体会】通过语法分析可以判断当前输入语句是否正确,实验通过对数学式的处理来进行对语句的判断是否正确,若正确则只要输入“语句正确”即可,若语句错误则需要根据错误的原因输出错误的理由,以方便编译员修改自己的代码。

实现方法是通过对文本文件的输入,当前数据与即将输入的字符串进行匹配,若不符合LL(1)文法则判定为错误,若符合则继续向下完成语法分析。

【源代码】#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <iostream>#include <stack>#include <string>#include <fstream>using namespace std;ifstream fin("in.txt");ofstream fout("out.txt");enum symbol{ //0 1 2 3 4 56 7nul, ident, number, plus, minus, times, slash, oddsym,eql, neq, lss, leq, gtr, geq,lparen, rparen,comma, semicolon, period, becomes, beginsym, endsym, ifsym, thensym,whilesym, writesym, readsym, dosym, callsym, constsym, varsym, procsym};#define symnum 32char symwork[symnum][10];//单符号#define norw 13 //key_word num#define al 10 //maxstr#define nmax 10//number longchar word[norw][al];//key wordchar ch;//bufferchar getch()enum symbol sym;char id[al+1];// identchar a[al+1];//tempchar ID[al+1];int cc=0,ll=0,num;//当前在行的位置cc,行字符的长度ll,num数字的值int nn=0;char line[81];int flg=0;// 正数;//char line[81];enum symbol ssym[256];enum symbol wsym[norw];//int cc,ll;//ch[cc]int err;void init(){int i;for(i=0;i<=255;i++)ssym[i]=nul;//0ssym['+']=plus;ssym['-']=minus;ssym['/']=slash;ssym['(']=lparen;ssym[')']=rparen;ssym['=']=eql;ssym[',']=comma;ssym['.']=period;ssym['#']=neq;//not equalssym[';']=semicolon;strcpy(&symwork[plus][0],"plus");strcpy(&symwork[minus][0],"minus");strcpy(&symwork[times][0],"times");strcpy(&symwork[slash][0],"slash");strcpy(&symwork[lparen][0],"lparen"); strcpy(&symwork[rparen][0],"rparen"); strcpy(&symwork[eql][0],"eql");strcpy(&symwork[comma][0],"comma");strcpy(&symwork[neq][0],"neq");strcpy(&symwork[period][0],"period"); strcpy(&symwork[semicolon][0],"semicolon");strcpy(&word[0][0],"begin");//关键字小写字母strcpy(&word[1][0],"call");strcpy(&word[2][0],"const");strcpy(&word[3][0],"do");strcpy(&word[4][0],"end");strcpy(&word[5][0],"if");strcpy(&word[6][0],"odd");strcpy(&word[7][0],"procedure");strcpy(&word[8][0],"read");strcpy(&word[9][0],"then");strcpy(&word[10][0],"var");strcpy(&word[11][0],"while");strcpy(&word[12][0],"write");wsym[0]=beginsym;wsym[1]=callsym;wsym[2]=constsym;wsym[3]=dosym;wsym[4]=endsym;wsym[5]=ifsym;wsym[6]=oddsym;wsym[7]=procsym;wsym[9]=thensym;wsym[10]=varsym;wsym[11]=whilesym;wsym[12]=writesym;}void WordAnalyse(){switch(sym){case nul://fout <<"( "<<"nul"<<" , "<<ID<<" )"<<endl;break;case ident:fout <<"( "<<"ident"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"ident"<<" , "<<ID<<" )"<<endl;break;case number:fout <<"( "<<"number"<<" , "<<num<<" )"<<endl;cout<<"( "<<"number"<<" , "<<num<<" )"<<endl;break;case plus:fout <<"( "<<"plus"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"plus"<<" , "<<ID<<" )"<<endl;break;case minus:fout <<"( "<<"minus"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"minus"<<" , "<<ID<<" )"<<endl;break;case times:fout <<"( "<<"times"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"times"<<" , "<<ID<<" )"<<endl;break;case slash:fout <<"( "<<"slash"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"slash"<<" , "<<ID<<" )"<<endl;break;case oddsym:fout <<"( "<<"oddsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"oddsym"<<" , "<<ID<<" )"<<endl;break;case lss:fout <<"( "<<"lss"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"lsst"<<" , "<<ID<<" )"<<endl;break;case eql:fout <<"( "<<"eql"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"eql"<<" , "<<ID<<" )"<<endl;break;case neq:fout <<"( "<<"neq"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"neq"<<" ,"<<ID<<" )"<<endl;break;case leq:fout <<"( "<<"leq"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"leq"<<" , "<<ID<<" )"<<endl;break;case gtr:fout <<"( "<<"gtr"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"gtr"<<" , "<<ID<<" )"<<endl;break;case geq:fout <<"( "<<"geq"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"geqt"<<" , "<<ID<<" )"<<endl;break;case lparen:fout <<"( "<<"lparent"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"lparent"<<" , "<<ID<<" )"<<endl;break;case rparen:fout <<"( "<<"rparent"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"rparent"<<" , "<<ID<<" )"<<endl;break;case comma:fout <<"( "<<"comma"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"comma"<<" , "<<ID<<" )"<<endl;break;case semicolon:fout <<"( "<<"semicolon"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"semicolon"<<" , "<<ID<<" )"<<endl;break;case period:fout <<"( "<<"period"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"period"<<" , "<<ID<<" )"<<endl;break;case becomes:fout <<"( "<<"becomes"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"becomes"<<" , "<<ID<<" )"<<endl;break;case beginsym:fout <<"( "<<"beginsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"beginsym"<<" , "<<ID<<" )"<<endl;break;case endsym:fout <<"( "<<"endsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"endsym"<<" , "<<ID<<" )"<<endl;break;case ifsym:fout <<"( "<<"ifsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"ifsym"<<" , "<<ID<<" )"<<endl;break;case thensym:fout <<"( "<<"thensym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"thensym"<<" , "<<ID<<" )"<<endl;break;case whilesym:fout <<"( "<<"whilesym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"whilesym"<<" , "<<ID<<" )"<<endl;break;case writesym:fout <<"( "<<"writesym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"writesym"<<" , "<<ID<<" )"<<endl;break;case readsym:fout <<"( "<<"readsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"readsym"<<" , "<<ID<<" )"<<endl;break;case dosym:fout <<"( "<<"dosym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"dosym"<<" , "<<ID<<" )"<<endl;break;case callsym:fout <<"( "<<"callsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"callsym"<<" , "<<ID<<" )"<<endl;break;case constsym:fout <<"( "<<"constsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"constsym"<<" , "<<ID<<" )"<<endl;strcpy(ID,"");break;case varsym:fout <<"( "<<"varsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"varsym"<<" , "<<ID<<" )"<<endl;break;case procsym:fout <<"( "<<"procsym"<<" , "<<ID<<" )"<<endl;cout<<"( "<<"procsym"<<" , "<<ID<<" )"<<endl;break;default :break;}}int getch(){if(cc==ll){if(fin.eof()){cout<<"program incpmplete!!!"<<endl;return -1;}ll=cc=0;fin.getline(line,81);ll=strlen(line);ch=' ';return 0;}if(cc==0) cout <<line<<endl;ch=line[cc];cout<<ch<<endl;cc++;nn=cc;return 0;}#define getchdo if(-1==getch()) return -1//词法分析部分实验1int getsym()//读符号大写字母不要出现{int i,j,k; //用于循环等辅助计数while(ch==' '||ch==9||ch==10) //////////////////////////////////////////{getchdo;}if(ch>='a'&&ch<='z'){k=0;while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9') //名字或保留字以a.z 开头{if(k<al){ID[k]=ch;k++;}getchdo;}ID[k]=0;i=0;j=norw;do /* 搜索当前符号是否为保留字 */{k=(i+j)/2;if(strcmp(ID,word[k])<=0)j=k-1;if(strcmp(ID,word[k])>=0)i=k+1;}while(i<=j);if(i-1>j)sym=wsym[k]; else sym=ident; /* 搜索失败,则是名字或数字 */}else{if(ch>='0'&&ch<='9'){k=0;num=0;sym=number;do{ID[k]=ch;num=num*10+ch-'0';k++;getchdo;}while(ch>='0'&&ch<='9');if(flg==1) {num=-num;flg=0;}ID[k]=0;k--;if(k>nmax){// error(30);;}}else{if(ch==':'){getchdo;if(ch=='='){sym=becomes;strcpy(ID,":=");getchdo;}else{sym=nul;strcpy(ID,"NULL");}}else{if(ch=='>'){getchdo;if(ch=='='){sym=geq;strcpy(ID,">=");getchdo;}else{sym=gtr;strcpy(ID,">");}}else{if(ch=='<'){getchdo;if(ch=='='){sym=leq;strcpy(ID,"<=");getchdo;}else{sym=lss;strcpy(ID,"<");}}else{sym=ssym[ch];strcpy(ID,&ch);//if(sym!=period){getchdo;}}}}}}return 1;}//语法分析部分实验2int lp=0;int rp=0;#define getsymdo if(-1==getsym()) return -1#define expressiondo() if(-1==expression()) return -1#define termdo() if(-1==term()) return -1#define factordo() if(-1==factor()) return -1int expression();//语法分析int factor(){if(sym!=ident &&sym!=number&&sym!=lparen){err++;if(err==1) printf("语法错误: \n");printf("error----Factor Needs Ident or Number or Lparen\n");}if ((sym == ident) || (sym == number) || (sym == lparen)) {if (sym == ident){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("变量后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == number){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("数字后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == lparen){WordAnalyse();lp++;if(getsym()==-1){lp--;err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");return -1;}expressiondo();if (sym == rparen){WordAnalyse();lp--;if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus){err++;if(err==1) printf("语法错误: \n");printf("括号后没有跟上+-*\\ \n");}}else{err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");}}}return 0;}int term(){factordo();if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=ident&& sym!=number&&sym!=lparen&&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == times) || (sym == slash)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("* \\ 后缺项\n");return -1;}factordo();}return 0;}int expression(){if ((sym == plus) || (sym == minus)){//cout<<strlen(ID)<<endl;if (sym==minus&&2==strlen(ID)+1)flg=1;else{flg=0;WordAnalyse();}getsymdo;termdo();}else{//WordAnalyse();termdo();}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=ident&& sym!=number&&sym!=lparen&&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == plus) || (sym == minus)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("+ - 后缺项\n");return -1;}termdo();}return 0;}int main(int argc, char* argv[]){init();err=0;ifstream fin("in.txt");ofstream fout("out.txt");ch=' ';lp=0;getsymdo;expression();if(err==0) cout<<"语确"<<endl;elsecout<<"语法错误,错误个数: "<<err<<endl; }。

相关文档
最新文档