实验二--语法分析-
编译原理实验报告
编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
编译原理实验报告
编译原理实验报告班级姓名:学号:自我评定:实验一词法分析程序实现一、实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。
二、实验内容根据教学要求并结合学生自己的兴趣和具体情况,从具有代表性的高级程序设计语言的各类典型单词中,选取一个适当大小的子集。
例如,可以完成无符号常数这一类典型单词的识别后,再完成一个尽可能兼顾到各种常数、关键字、标识符和各种运算符的扫描器的设计和实现。
输入:由符合或不符合所规定的单词类别结构的各类单词组成的源程序。
输出:把单词的字符形式的表示翻译成编译器的内部表示,即确定单词串的输出形式。
例如,所输出的每一单词均按形如(CLASS,VALUE)的二元式编码。
对于变量和常数,CLASS字段为相应的类别码;VALUE字段则是该标识符、常数的具体值或在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串;常数表登记项中则存放该常数的二进制形式)。
对于关键字和运算符,采用一词一类的编码形式;由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。
另外,为便于查看由词法分析程序所输出的单词串,要求在CLASS字段上放置单词类别的助记符。
三、实现方法与环境词法分析是编译程序的第一个处理阶段,可以通过两种途径来构造词法分析程序。
其一是根据对语言中各类单词的某种描述或定义(如BNF),用手工的方式(例如可用C语言)构造词法分析程序。
一般地,可以根据文法或状态转换图构造相应的状态矩阵,该状态矩阵同控制程序便组成了编译器的词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。
构造词法分析程序的另外一种途径是所谓的词法分析程序的自动生成,即首先用正规式对语言中的各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程序所应进行的语义处理工作,然后由一个所谓词法分析程序的构造程序对上述信息进行加工。
实验二--LL分析法实验报告
实验二LL(1)分析法一、实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。
使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。
有利于提高学生的专业素质,为培养适应社会多方面需要的能力。
二、实验内容及设计原理所谓LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。
实现LL(1)分析的程序又称为LL(1)分析程序或LL1(1)分析器。
我们知道一个文法要能进行LL(1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。
当文法满足条件后,再分别构造文法每个非终结符的FIRST和FOLLOW集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。
LL(1)的语法分析程序包含了三个部分,总控程序,预测分析表函数,先进先出的语法分析栈,本程序也是采用了同样的方法进行语法分析,该程序是采用了C++语言来编写,其逻辑结构图如下:LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。
对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =‘#’,则宣布分析成功,停止分析过程。
(2)若X = a ‘#’,则把X从STACK栈顶弹出,让a指向下一个输入符号。
(3)若X是一个非终结符,则查看预测分析表M。
若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK栈顶,然后,把产生式的右部符号串按反序一一弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。
若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。
三、程序结构描述1、定义的变量初始化预测分析表: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","(i)","error","error","error","error","error","error"}; const int MaxLen=10; 初始化栈的长度const int Length=10; 初始化数组长度char Vn[5]={'E','G','T','S','F'}; 非终结符数组char Vt[8]={'i','(',')','+','-','*','/','#'}; 终结符数组char ch,X; /全局变量,ch用于读当前字符,X用于获取栈顶元素char strToken[Length]; 存储规约表达式2、定义的函数class stack 栈的构造及初始化int length(char *c) 输出字符数组的长度void print(int i,char*c) 剩余输入串的输出void run() 分析程序3、LL(1)预测分析程序流程图四、程序源代码及运行结果#include<iostream>using namespace std;const int MaxLen=10; //初始化栈的长度const int Length=10;//初始化数组长度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","(i)","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<<" ";}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<<" ";}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<<"步骤"<<"分析栈"<<"剩余输入串"<<"所用产生式"<<"动作"<<endl;cout<<step++<<" ";s.out();print(point-1,strToken);cout<<" "<<"初始化"<<endl;while(flag){if((X==Vt[0])||(X==Vt[1])||(X==Vt[2])||(X==Vt[3])||(X==Vt[4])||(X==Vt[5])||(X==V t[6])) //判断是否为终结符(不包括#){if(X==ch)//终结符,识别,进行下一字符规约{s.pop();s.get_top(X);ch=strToken[point++];cout<<step++<<" ";s.out();print(point-1,strToken);cout<<" "<<"GETNEXT(I)"<<endl;}else{flag=false;cout<<"error!"<<endl;}}else if(X=='#')//规约结束{if(X==ch){cout<<step++<<" ";s.out();print(point-1,strToken);cout<<" "<<X<<"->"<<ch<<" "<<"结束"<<endl;s.pop();flag=false;}else{flag=false;cout<<"error!"<<endl;}}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;cout<<"error"<<endl;}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++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<E[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<E[i].c[z];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++<<" ";s.out();print(point-1,strToken);cout<<" "<<X<<"->"<<"ε"<<" "<<"POP"<<endl;s.get_top(X);}else if(strcmp(G[i].c,"error")==0){flag=false;cout<<"error"<<endl;}else{s.pop();len=length(G[i].c)-1;for(int j=len;j>=0;j--)s.push(G[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<G[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<G[i].c[z];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;cout<<"error"<<endl;}else{s.pop();len=length(T[i].c)-1;for(int j=len;j>=0;j--)s.push(T[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<T[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<T[i].c[z];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++<<" ";s.out();print(point-1,strToken);cout<<" "<<X<<"->"<<"ε"<<" "<<"POP"<<endl;s.get_top(X);}else if(strcmp(S[i].c,"error")==0){flag=false;cout<<"error"<<endl;}else{s.pop();len=length(S[i].c)-1;for(int j=len;j>=0;j--)s.push(S[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<S[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<S[i].c[z];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;cout<<"error"<<endl;}else{s.pop();len=length(F[i].c)-1;for(int j=len;j>=0;j--)s.push(F[i].c[j]);cout<<step++<<" ";s.out();print(point-1,strToken);cout<<X<<"->"<<F[i].c<<" "<<"POP,PUSH(";for(int z=len;z>=0;z--)cout<<F[i].c[z];cout<<")"<<endl;s.get_top(X);}}}else //出错处理{flag= false;cout<<"error"<<endl;}}}int main(){run();system("pause");return 0;}测试:输入i*i+i#结果:实验二--LL(1)分析法实验报告五、实验总结1. 本实例能利用正确的LL1文法分析表判断任意符号串是否属于该文法的句子;显示了具体分析过程;支持打开、新建、保存分析表;保存分析结果。
实验二--语法分析程序的设计-
姓名:学号:专业班级
一、实验目的
通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析中预测分析方法。
二、实验内容
设计一个文法的预测分析程序,判断特定表达式的正确性。
三、实验要求
1、给出文法如下:
G[E]
E->T|E+T;
import java.io.*;
public class test2 {
static String[] key_word = { "main", "if", "then", "while", "do", "int",
"else" };
static String[] cal_word = { "+", "-", "*", "/", "<", ">", "{", "}", "(",
static String[] firstT = { "i", "(" };
static String[] firstTB = { "*", "@" };
static String[] firstF = { "i", "(" };
static String[][] list = { { "", "i", "+", "*", "(", ")", "#" },
编译原理实验二LL(1)语法分析实验报告
专题3_LL(1)语法分析设计原理与实现李若森 13281132 计科1301一、理论传授语法分析的设计方法和实现原理;LL(1) 分析表的构造;LL(1)分析过程;LL(1)分析器的构造。
二、目标任务实验项目实现LL(1)分析中控制程序(表驱动程序);完成以下描述算术表达式的 LL(1)文法的LL(1)分析程序。
G[E]:E→TE’E’→ATE’|εT→FT’T’→MFT’|εF→(E)|iA→+|-M→*|/设计说明终结符号i为用户定义的简单变量,即标识符的定义。
加减乘除即运算符。
设计要求(1)输入串应是词法分析的输出二元式序列,即某算术表达式“专题 1”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;(2)LL(1)分析程序应能发现输入串出错;(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
任务分析重点解决LL(1)表的构造和LL(1)分析器的实现。
三、实现过程实现LL(1)分析器a)将#号放在输入串S的尾部b)S中字符顺序入栈c)反复执行c),任何时候按栈顶Xm和输入ai依据分析表,执行下述三个动作之一。
构造LL(1)分析表构造LL(1)分析表需要得到文法G[E]的FIRST集和FOLLOW集。
构造FIRST(α)构造FOLLOW(A)构造LL(1)分析表算法根据上述算法可得G[E]的LL(1)分析表,如表3-1所示:表3-1 LL(1)分析表主要数据结构pair<int, string>:用pair<int, string>来存储单个二元组。
该对照表由专题1定义。
map<string, int>:存储离散化后的终结符和非终结符。
vector<string>[][]:存储LL(1)分析表函数定义init:void init();功能:初始化LL(1)分析表,关键字及识别码对照表,离散化(非)终结符传入参数:(无)传出参数:(无)返回值:(无)Parse:bool Parse( const vector<PIS> &vec, int &ncol );功能:进行该行的语法分析传入参数:vec:该行二元式序列传出参数:emsg:出错信息epos:出错标识符首字符所在位置返回值:是否成功解析。
编译原理实验 词法分析&语法分析程序
编译原理实验词法分析程序实验一:词法分析程序1、实验目的从左至右逐个字符的对源程序进行扫描,产生一个个单词符号,把字符串形式的源程序改造成单词符号形式的中间程序。
2、实验内容表C语言子集的单词符号及内码值单词符号种别编码助记符内码值while 1 while --if 2 if --else 3 else --switch 4 switch --case 5 case --标识符 6 id id在符号表中的位置常数7 num num在常数表中的位置+ 8 + --- 9 - --* 10 * --<= 11 relop LE< 11 relop LT== 11 relop LQ= 12 = --; 13 ; --输入源程序如下if a==1 a=a+1;else a=a+2;输出对应的单词符号形式的中间程序3、实验过程实验上机程序如下:#include "stdio.h"#include "string.h"int i,j,k;char s ,a[20],token[20];int letter(){if((s>=97)&&(s<=122))return 1;else return 0;}int Digit(){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(){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 you source program,end('#'):\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=1;memset(token,0,sizeof(char)*10);j=0;get();while(s!='#'){if(s==' '||s==10||s==13)get();else{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(Digit()||letter()){token[j]=s;j=j+1;get();}retract();k=lookup();if(k==0)printf("(6,%s)\n",token); elseprintf("(%d,null)\n",k); break;case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':while(Digit()){token[j]=s;j=j+1;get();}retract();printf("(%d,%s)\n",7,token); break;case'+':printf("(+,null)\n"); break;case'-':printf("(-,null)\n"); break;case'*':printf("(*,null)\n"); break;case'<':get();if(s=='=')printf("(relop,LE)\n"); else{retract();printf("(relop,LT)\n");}break;case'=':get();if(s=='=')printf("(relop,EQ)\n"); else{retract();printf("(=,null)\n");}break;case';':printf("(;,null)\n"); break;default:printf("(%c,error)\n",s);break;}memset(token,0,sizeof(char)*10);j=0;get();}}}4、实验结果实验结果分析:if是关键字,对应种别编码为2,输出(2,null)a是标识符,对应种别编码为6,值为a,输出(6,a)==的助记符是relop,内码值为LE,输出(relop,LE)1是常数,对应种别编码为7,值为1,输出(7,1)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)1是常数,对应种别编码为7,值为1,输出(7,1);是语句结束符号,直接输出(;,null)else是关键字,对应种别编码为3,输出(3,null)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)2是常数,对应种别编码为7,值为2,输出(7,2);是语句结束符号,直接输出(;,null)#是输入结束标志编译原理实验语法分析程序实验二:语法分析程序1、实验目的:将单词组成各类语法单位,讨论给类语法的形成规则,判断源程序是否符合语法规则3、实验内容:给定文法:G[E]:E→E+E|E-E|E*E|E/E|(E)E→0|1|2|3|4|5|6|7|8|9首先把G[E]构造为算符优先文法,即:G’[E]:E→E+T|TT→T-F|FF→F*G|GG→G/H|HH→(E)|i得到优先关系表如下:+ - * / i ( ) # + ·><·<·<·<·<··>·> - ·>·><·<·<·<··>·> * ·>·>·><·<·<··>·> / ·>·>·>·><·<··>·>i ·>·>·>·>·>·>( <·<·<·<·<·<·=) ·>·>·>·>·>·> # <·<·<·<·<·<·=构造出优先函数+ - * / i ( ) #f 6 8 10 12 12 2 12 2g 5 7 9 11 13 13 2 2要求输入算术表达式:(1+2)*3+2*(1+2)-4/2输出其对应的语法分析结果4、实验过程:上机程序如下:#include "stdio.h"#include "string.h"char a[20],optr[10],s,op;int i,j,k,opnd[10],x1,x2,x3;int operand(char s){if((s>=48)&&(s<=57))return 1;else return 0;}int f(char s){switch(s){case'+':return 6;case'-':return 8;case'*':return 10;case'/':return 12;case'(':return 2;case')':return 12;case'#':return 2;default:printf("error");}}int g(char s){switch(s){case'+':return 5;case'-':return 7;case'*':return 9;case'/':return 11;case'(':return 13;case')':return 2;case'#':return 2;default:printf("error");}}void get(){s=a[i];i=i+1;}void main(){printf("请输入算数表达式,并以‘#’结束:\n");i=0;do{scanf("%c",&a[i]);i++;}while(a[i-1]!='#');i=0;j=0;k=0;optr[j]='#';get();while((optr[j]!='#')||(s!='#')){if(operand(s)){opnd[k]=s-48;k=k+1;get();}else if(f(optr[j])<g(s)){j=j+1;optr[j]=s;get();}else if(f(optr[j])==g(s)){if(optr[j]=='('&&s==')'){j=j-1;get();}else if(optr[j]=='('&&s=='#'){printf("error\n");break;}else if(optr[j]=='#'&&s==')'){printf("error\n");break;}}else if(f(optr[j])>g(s)){op=optr[j];j=j-1;x2=opnd[k-1];x1=opnd[k-2];k=k-2;switch(op){case'+':x3=x1+x2;break;case'-':x3=x1-x2;break;case'*':x3=x1*x2;break;case'/':x3=x1/x2;break;}opnd[k]=x3;k=k+1;printf("(%c,%d,%d,%d)\n",op,x1,x2,x3);}else{printf("error\n");break;}}if(j!=0||k!=1)printf("error\n");}5、实验结果:实验结果分析:(1+2)*3+2*(1+2)-4/2#因为‘)’优先级大于‘*’,先计算1+2=3,并输出(+,1,2,3)原式变为:3*3+2*(1+2)-4/2#因为‘*’优先级大于‘+’,先计算3*3=9,并输出(*,3,3,9)原式变为:9+2*(1+2)-4/2#因为‘)’优先级大于‘-’,先计算1+2=3,并输出(+,1,2,3)原式变为:9+2*3-4/2#因为‘*’优先级大于‘-’,先计算2*3=6,并输出(*,2,3,6)原式变为:9+6-4/2#因为‘/’优先级大于‘#’,先计算4/2=2,并输出(/,4,2,2)原式变为:9+6-2#因为‘-’优先级大于‘#’,先计算6-2=4,并输出(-,6,2,4)原式变为:9+4#因为‘+’优先级大于‘#’,计算9+4=13,并输出(+,9,4,13)原式变为13#优先级等于#,跳出while循环,运算结束!。
语法分析
实验二语法分析一、实验目的:通过本实验理解语法分析的作用,分析对象、分析的方式和处理的结果,是重点内容。
二、实验学时:6学时。
三、实验内容根据给出的简单语言的语法构成规则(见五),编制语法分析程序,要求能将词法分析输出的单词文件用给定的语法规则书写的源程序进行语法分析,输出相应的语法分析结果和错误信息。
关于错误信息:不要求错误种类,可以只给出出错位置。
四、实验方法使用LL(1)分析法,或LR分析法实现。
要先构造分析表再编写程序实现。
五、文法定义简单的表达式文法如下:E->E+T|E-T|TT->T*F|T/F|FF->(E)|i、六、处理程序例例1: 正确源程序例:i+(i+i)*i-i例2: 错误源程序例:i+(i+)-i附录、实验报告格式:编译原理实验报告一、实验内容和程序名称实验内容:根据给出的简单语言的语法构成规则(见五),编制语法分析程序,要求能将词法分析输出的单词文件用给定的语法规则书写的源程序进行语法分析,输出相应的语法分析结果和错误信息。
关于错误信息:不要求错误种类,可以只给出出错位置。
程序名称:grammarAnalysis.cpp 二、主要方法说明scanner()函数: 读入一个单词符号 judge()函数: 进行语法分析 三、你的程序的使用手册介绍如何使用你的程序和结果样式,要求的使用环境等。
1.图2-1 语法分析主程序示意图2. judge()函数结构分析示意图如下:(2)递归下降分析程序示意图如图2-2所示。
(3)语句串分析过程示意图如图2-3所示。
否图2-3 语句串分析示意图图2-2 递归下降分析程序示意图(4)ZF语句分析程序流程如图2-4、2-5、2-6、2-7所示。
图2-4 ZF语句分析函数示意图图2-5 JJ表达式分析函数示意图否 否是是否否是图 2-6 CC 分析函数示意图否 是图2-7 ZS 分析过程示意图3. 运行结果是否整常数?是否(?调用scanner调用JJ 函数是否)?调用调用scanner出错处理四、实验过程分析实验过程中发生的问题分析,解决过程及方法。
编译原理实验二: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)⽂法,⽤预测分析表法判断输⼊的符号串是否符合刚才输⼊的⽂法,并打印出分析过程。
07级_实验二_用算符优先分析法进行表达式分析
return ('*');
}
/**********************************/
int Operate(int a,int b,SYMBOL o)
{
switch (o)
{
case PLUS: return a+b;
case MINUS: return a-b;
case TIMES: return a*b;
若θ1和θ2之间无优先关系,则报错。
2、源程序提示
利用以前实验进行单词识别,并自组织工程文件,关于算符优先算法要用到的部份函数提示如下。
[1]一些自定义的变量和函数的声明
#define MAX 255
SYMBOLtitle[7]= {PLUS,MINUS,TIMES,SLASH,LPAREN,RPAREN,SHAP};//用来将相应的种别码与数组下标进行映射
θ2
θ1
+
-
*
/
(
)
#
+
>
>
<
<
<
>
>
-
>
>
<
<
<
>
>
*
>
>
>
>
<
>
>
/
>
>
>>
(
<
<
<
<
<
=
)
>
>
>
>
语法分析实验报告
语法分析实验报告一、实验目的语法分析是编译原理中的重要环节,本次实验的目的在于深入理解和掌握语法分析的基本原理和方法,通过实际操作和实践,提高对编程语言语法结构的分析能力,为进一步学习编译技术和开发相关工具打下坚实的基础。
二、实验环境本次实验使用的编程语言为 Python,使用的开发工具为 PyCharm。
三、实验原理语法分析的任务是在词法分析的基础上,根据给定的语法规则,将输入的单词符号序列分解成各类语法单位,并判断输入字符串是否符合语法规则。
常见的语法分析方法有自顶向下分析法和自底向上分析法。
自顶向下分析法包括递归下降分析法和预测分析法。
递归下降分析法是一种直观、简单的方法,但存在回溯问题,效率较低。
预测分析法通过构建预测分析表,避免了回溯,提高了分析效率,但对于复杂的语法规则,构建预测分析表可能会比较困难。
自底向上分析法主要包括算符优先分析法和 LR 分析法。
算符优先分析法适用于表达式的语法分析,但对于一般的上下文无关文法,其适用范围有限。
LR 分析法是一种功能强大、适用范围广泛的方法,但实现相对复杂。
四、实验内容(一)词法分析首先,对输入的源代码进行词法分析,将其分解为一个个单词符号。
单词符号包括关键字、标识符、常量、运算符、分隔符等。
(二)语法规则定义根据实验要求,定义了相应的语法规则。
例如,对于简单的算术表达式,可以定义如下规则:```Expression > Term | Expression '+' Term | Expression ''TermTerm > Factor | Term '' Factor | Term '/' FactorFactor >'(' Expression ')'| Identifier | Number```(三)语法分析算法实现选择了预测分析法来实现语法分析。
首先,根据语法规则构建预测分析表。
然后,从输入字符串的起始位置开始,按照预测分析表的指导进行分析。
词法分析、语法分析、语义分析实例解析及实验报告
词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求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 各种单词符号对应的种别码:输入:所给文法的源程序字符串。
输出:二元组(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)……标识符(需进一步判断是否为关键字)数字+=+-=-词法分析状态转换图(终结状态右上角*表示多读一个符号)三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面: ⑴ 关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin ”, “if ”, “then ”, “while ”, “do ”, “end ”,};图3-1(2)程序中需要用到的主要变量为syn,token 和sum 3.2 扫描子程序的算法思想:首先设置3个变量:①token 用来存放构成单词符号的字符串;②sum 用来存放整型单词;③syn 用来存放单词符号的种别码。
语法分析实验报告
一、实验目的1. 了解语法分析的基本概念和原理。
2. 掌握语法分析的方法和步骤。
3. 提高对自然语言处理领域中语法分析技术的理解和应用能力。
二、实验内容1. 语法分析的基本概念语法分析是指对自然语言进行结构分析,将句子分解成词、短语和句子成分的过程。
通过语法分析,可以了解句子的结构、语义和语用信息。
2. 语法分析方法语法分析方法主要有两种:句法分析和语义分析。
(1)句法分析:句法分析是指根据语法规则,对句子进行分解和组合的过程。
常见的句法分析方法有:词法分析、短语结构分析、句法分析。
(2)语义分析:语义分析是指对句子进行分析,以揭示句子所表达的意义。
常见的语义分析方法有:词汇语义分析、句法语义分析、语用语义分析。
3. 语法分析步骤(1)词法分析:将句子中的单词进行分类,提取词性、词义和词形变化等特征。
(2)短语结构分析:将词法分析得到的词组进行分类,提取短语结构、短语成分和短语关系等特征。
(3)句法分析:根据短语结构分析的结果,将句子分解成句子成分,分析句子成分之间的关系。
(4)语义分析:根据句法分析的结果,分析句子所表达的意义。
三、实验过程1. 实验环境:Python 3.8,NLTK(自然语言处理工具包)。
2. 实验步骤:(1)导入NLTK库。
(2)加载句子数据。
(3)进行词法分析,提取词性、词义和词形变化等特征。
(4)进行短语结构分析,提取短语结构、短语成分和短语关系等特征。
(5)进行句法分析,分解句子成分,分析句子成分之间的关系。
(6)进行语义分析,揭示句子所表达的意义。
四、实验结果与分析1. 词法分析结果实验句子:“我喜欢吃苹果。
”词性标注:我/代词,喜欢/动词,吃/动词,苹果/名词。
2. 短语结构分析结果实验句子:“我喜欢吃苹果。
”短语结构:主语短语(我),谓语短语(喜欢吃苹果)。
3. 句法分析结果实验句子:“我喜欢吃苹果。
”句子成分:主语(我),谓语(喜欢),宾语(吃苹果)。
4. 语义分析结果实验句子:“我喜欢吃苹果。
python程序设计的8个实验内容
一、概述Python是一种直观、易学、功能强大的计算机编程语言,广泛应用于Web开发、数据分析、人工智能等领域。
本文将介绍Python程序设计的8个实验内容,帮助读者深入了解和掌握Python编程技能。
二、实验一:基础语法1. 学习Python的基本语法,包括变量、数据类型、运算符等。
2. 编写一个简单的Python程序,实现对用户输入的数字进行排序并输出结果。
三、实验二:条件控制和循环1. 掌握Python的条件控制语句,如if-else和switch-case。
2. 熟练运用循环结构,包括for循环和while循环。
3. 编写一个Python程序,实现对用户输入的数字进行判断,输出是否为素数。
四、实验三:函数1. 学习Python函数的定义和调用。
2. 掌握参数传递和返回值的用法。
3. 编写一个Python程序,实现计算两个数的最大公约数和最小公倍数的函数,并进行调用测试。
五、实验四:列表和元组1. 了解Python中列表和元组的概念和用法。
2. 编写一个Python程序,实现对列表和元组的增删改查操作,并输出结果。
六、实验五:字典和集合1. 掌握Python中字典和集合的特点和用法。
2. 编写一个Python程序,实现对字典和集合的遍历和操作,并输出结果。
七、实验六:文件操作1. 学习Python文件的打开、读取和写入操作。
2. 编写一个Python程序,从文件中读取数据并进行处理,然后将结果写入新文件。
八、实验七:异常处理1. 理解Python中异常的概念和分类。
2. 编写一个Python程序,模拟发生异常并进行处理,保证程序正常运行。
九、实验八:面向对象编程1. 学习Python面向对象编程的相关知识,包括类、对象、继承等。
2. 编写一个简单的Python程序,实现一个基本的面向对象应用,并进行测试。
十、结语通过以上8个实验内容的学习,读者可以系统地了解和掌握Python程序设计的基础知识和技能,为进一步深入学习和应用Python打下坚实的基础。
编译原理——语法分析程序设计实验报告
实验二语法分析程序设计[实验目的]: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主函数中统一判断输出语句。
北方工业大学计算机专业编译原理实验报告——语法分析器详细代码报告
else if(m==0)
cout<<"="<<setw(8);
else
cout<<"<"<<setw(8);
cout<<a<<setw(10);
cout<<&strings[k]<<setw(10);
if(t)
{
cout<<"归约"<<setw(8);
No[n++]=step-1;
}
else
cout<<"移进"<<setw(8);
{
push(a);
print(0,0);
if(stack[top]!='#')
goto u;
}
else
{
error(j);
a='#';
}
}
}while(a!='#');
}
void main()
{
cout<<"*********算符优先语法分析程序*********"<<endl;
cout<<" E->E+T|E-T|T"<<endl;
}
else
printf("\n错误e3:非法右括号!");
}
void prior_analysis()
语法分析实验报告(实验二)
编译原理语法分析实验报告软工082班兰洁4一、实验容二、实验目的三、实验要求四、程序流程图●主函数;●scanner();●irparser()函数●yucu() /*语句串分析*/●statement()/*语句分析函数*/●expression()/*表达式分析函数*/●term()/*项分析函数*/●factor()/*因子分析函数*/五、程序代码六、测试用例七、输出结果八、实验心得一、实验容:编写为一上下文无关文法构造其递归下降语法分析程序,并对任给的一个输入串进行语法分析检查。
程序要求能对输入串进行递归下降语法分析,能判别程序是否符合已知的语法规则,如果不符合(编译出错),则输出错误信息。
二、实验目的:构造文法的语法分析程序,要求采用递归下降语法分析方法对输入的字符串进行语法分析,实现对词法分析程序所提供的单词序列的语法检查和结构分析,进一步掌握递归下降的语法分析方法。
三、实验要求:利用C语言编制递归下降分析程序,并对Training语言进行语法分析。
1.待分析的Training语言语法。
用扩充的表示如下:<程序>-->function<语句串>endfunc<语句串>--><语句>{;<语句>}<语句>→<赋值语句><赋值语句>→ID→<表达式><表达式>→<项>{+<项>|-<项>}<项>→<因子>{*<因子>|/<因子>}<因子>→ID|NUM|(<表达式>)备注:实验当中我对程序进行了扩展,增加了程序识别if条件判断语句,while循环语句的功能2.实验要求说明输入单词串以“#”结束,如果是文确的句子,则输出成功信息,打印“success”,否则输出“error”。
《编译原理》科学实验指导说明书
《编译原理》实验指导书实验一词法分析器的设计一、实验目的和要求加深对状态转换图的实现及词法分析器的理解。
熟悉词法分析器的主要算法及实现过程。
要求学生掌握词法分析器的设计过程,并实现词法分析。
二、实验基本内容给出一个简单语言的词法规则,画出状态转换图,并依据状态转换图编制出词法分析程序,能从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单Error”,然后跳过错误部分继续显示)词法规则如下:三、实验时间:上机三次。
第一次按照自己的思路设计一个程序。
第二、三次在理论课学习后修改程序,使得程序结构更加合理。
四、实验过程和指导:(一)准备:1.阅读课本有关章节(c/c++,数据结构),花一周时间明确语言的语法,写出基本算法以及采用的数据结构和要测试的程序例。
2.初步编制好程序。
3.准备好多组测试数据。
(二)上课上机:将源代码拷贝到机上调试,发现错误,再修改完善。
(三)程序要求:程序输入/输出示例:输入如下一段:main(){/*一个简单的c++程序*/int a,b; //定义变量a = 10;b = a + 20;}要求输出如右图。
要求:(1) 剔除注解符(2) 常数为无符号整数(可增加实型数,字符型数等)(四)练习该实验的目的和思路:程序开始变得复杂起来,可能是大家以前编过的程序中最复杂的,但相对于以后的程序来说还是简单的。
因此要认真把握这个过渡期的练习。
程序规模大概为200行及以上。
通过练习,掌握对字符进行灵活处理的方法。
(五)为了能设计好程序,注意以下事情:1.模块设计:将程序分成合理的多个模块(函数/类),每个模块(类)做具体的同一事情。
2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。
3.编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
4.程序设计语言不限,建议使用面向对象技术及可视化编程语言,如C++,VC,JA V A,VJ++等。
北邮编译原理实验 LR语法分析 实验报告
LR语法分析实验报告班级:2010211308 姓名:杨娜学号:10211369一.题目:LR语法分析程序的设计与实现二.设计目的:(1)了解语法分析器的生成工具和编译器的设计。
(2)了解自上而下语法分析器的构造过程。
(3). 理解和掌握LR语法分析方法的基本原理;根据给出的LR)文法,掌握LR分析表的构造及分析过程的实现。
(4)掌握预测分析程序如何使用分析表和栈联合控制实现LR分析。
三.实验内容:编写语法分析程序,实现对算术表达式的语法分析,要求所分析算数表达式由如下的文法产生:E->E+T|E-T|TT->T/F|T*F|FF->i|n|(E)四.实验要求:编写LR语法分析程序,要求如下:(1)构造识别所有活动的DFA(2)构造LR分析表(3)编程实现算法4.3,构造LR分析程序五.算法流程分析程序可分为如下几步:六.算法设计1.数据结构s :文法开始符号line :产生式的个数G[i][0] :产生式的标号Vt[] :终结符Vn[] :非终结符id :项目集编号Prjt *next :指示下一个项目集Prjt[]:存储项目的编号,prjt[0]项目编号的个数Pointafter[] :圆点后的字符,pointafter[0]为字符个数Prjset*actorgo[]:存储出度Pointbefore:圆点前面的字符Form:动态数组下标,同时作为符号的编号Vn[] :非终结符序列Vt[]:终结符序列2.LR分析器由三个部分组成(1)总控程序,也可以称为驱动程序。
对所有的LR分析器总控程序都是相同的。
(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
分析器的动作就是由栈顶状态和当前输入符号所决定。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验二--语法分析(算符优先)-(2)编译原理实验报告实验名称:语法分析器设计专业:计算机科学与技术姓名:田莉莉学号:201117906语法分析—算符优先分析程序一.实验要求⑴ 选择最有代表性的语法分析方法,如算符优先法、递归子程序法或LR 分析法⑵ 选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
⑶ 实习时间为6 学时。
二.实验内容及要求( 1)根据给定文法,先求出 FirstVt 和 LastVt 集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);( 2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:G(E ' ): E'T #E#E—E+T | TT—T*F |FF—(E)|i(4)分析的句子为 :(i+i)*i 和 i+i)*i三.程序设计思想及实现步骤程序的设计思想:按照编译原理教材提供的算法,本程序的设计主要实现三个主要的过程:(1) 求解 FristVT 集和 LastVT 集:利用 CString 数组存放 VT 集,利用数组下标对应非终结符关系;(2) 输出算符优先分析表:利用 MFC 中的 ClistCtrl 控件输出显示算符表, 比利用二维数组对应其在内存中的关系。
(3) 利用算符优先分析表进行归约:根据教材所给算法,并对其进行实现在 屏幕上输出归约过程。
实现步骤:1、为程序各变量设计存储形式,具体设计如下所示:CString m_strTElem[T_LEN]; CString m_strNTElem[NT_LEN];// 非终结符CMapStringToPtr m_mapProdu; // 存放产生式 CMapStringToPtr m_mapProduEX; // 存放 扩展产生式 CString m_strFristVT[NT_LEN]; CString m_strLastVT[NT_LEN];int m_nPriSheet[T_LEN+1][T_LEN+1];// 终结符 //fristVT 集 //lastVT 集大表示空白1 表示小于0 表示相等1 表示Find m_F[STACK_LEN]; //bool2、为程序设计各个过程,具体设计如下所示:void CreateFristVT(Find* F); 建 FristVT 集void CreateLastVT(Find* F); 建 LastVT 集void SearchPForFirtVT(Find& f); P->Qa ….的产生式void SearchQForFristVT(void); 生式void SearchPForLastVT(Find& f); P->...a 的产生式void SearchQForLastVT(void); 生式OnBnClickedBtnAnasysic();3、对各个过程进行实现;4、调试运行并检验实验结果,结果如图 2.1和 2.2所示:CStrack m_stack; // 堆栈大 于 数组// 为每一个非终// 为每一个非终 // 搜索形如 P // 搜索形如 P->..// 搜索形如 P-> // 搜索形如 P->..图2.1 分析成功图内GrarTiinarABailys £井忻旬子图2.2 分析失败图四.程序源码产生式初始化:// 产生式CString* str = new CString;*str = _T("|E+T|T|");m_mapProdu.SetAt(_T("E"),(void*)str); CString* str1 = new CString;*str1 = _T("|T*F|F|");m_mapProdu.SetAt(_T("T"),(void*)str1); CString* str2 = new CString ;*str2 = _T("|(E)|i|");m_mapProdu.SetAt(_T("F"),(void*)str2); CString* str3 = new CString;*str3 = _T("|E+T|F+F|F*F|E+F|T|F|");m_mapProduEX.SetAt(_T("E"),(void*)str3); CString* str4 = new CString;*str4 = _T("|T*F|F|");m_mapProduEX.SetAt(_T("T"),(void*)str4); CString* str5 = new CString ;*str5 = _T("|(E)|i|(F)|");m_mapProduEX.SetAt(_T("F"),(void*)str5); 程序主要代码:void CGrammarAnalysisDlg::InitFind(void){int i,j;int k = 0;while(k<STACK_LEN){for(i=0;i<NT_LEN;i++) for(j=0;j<T_LEN;j++) {m_F[k].m_strNTerm = m_strNTElem[i];m_F[k].m_strTerm = m_strTElem[j];m_F[k].m_bIsVT = FALSE;k++;}}}// 查找P->a... 和P->Qa...void CGrammarAnalysisDlg::SearchPForFirtVT(Find& f){CString* str;m_mapProdu.Lookup(f.m_strNTerm,(void*&)str); intnFrist = 0;int nLen = 0; while(nLen+1 < str->GetLength())// P->a... P 和P->Qa. {nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLen-nFrist-1);if(IsNT(strProduce,0) && IsT(strProduce,1)){if(strProduce.GetAt(1) == f.m_strTerm){ if(!f.m_bIsVT){f.m_bIsVT = TRUE; //CreateFristVT(f);m_stack.PushStack(f);}}} if(IsT(strProduce,0)){ if(strProduce.GetAt(0) == f.m_strTerm){ if(!f.m_bIsVT){f.m_bIsVT = TRUE;if(!m_F[i].m_bIsVT)m_stack.PushStack(m_F[for(int i=0;i<T_LEN;i++) if(strProduc.GetAt(nLocat) == m_strTElem[i])return 1;if(strProduc.GetAt(nLocat) == '#')return 1; return 0;void CGrammarAnalysisDlg::SearchQForFristVT(void)void CGrammarAnalysisDlg::SearchPForLastVT(Find& f) CString strNT; CString* str;while(m_stack.m_nTop != 0)m_mapProdu.Lookup(f.m_strNTerm,(void*&)str);int nFrist = 0;m_stack.PopStack(Q);POSITION pos = m_mapProdu.GetStartPosition(); while(nLen+1 < str->GetLength())// P->a... P{// //P->...aQ P->...a}// 判断产生式第 //CreateFristVT(f); m_stack.PushStack(f)位置的字符是否是非终结符BOOL CGrammarAnalysisDlg::IsNT(CString strProduc,int nLocat)for(int i=0;i<NT_LEN;i++) if(strProduc.GetAt(nLocat) == m_strNTElem[i])return 1;return 0;m_mapProdu.GetNextAssoc(pos,strNT,(void*&)str); int nFrist = 0; int nLen = 0;while(nLen+1 < str->GetLength())nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLen-n if(IsNT(strProduce,0))if(strProduce.GetAt(0) == Q.m_strNTerm)//Q.m_bIsVT = TRUE;for(int i=0;i<STACK_LEN;i++)if(m_F[i].m_strNTerm == strNT &&== Q.m_strTerm) //判断产生式第 nLocat 位置的字符是否是终结符 BOOL CGrammarAnalysisDlg::IsT(CString strProduc, int nLocat){m_F[i].m_bIsVT = TRUE; break;}//遍历所有的产生式 P->Q Find Q; CString* str;int nLen = 0;和 P->Qa...nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLen-nFrist-1); int nLocat = strProduce.GetLength();m_mapProdu.GetNextAssoc(pos,strNT,(void*&)str); int nFrist = 0; int nLen = 0;while(nLen+1 < str->GetLength()){if(strProduce.GetAt(nLocat-2) ==f.m_strTerm) {if(!f.m_bIsVT){f.m_bIsVT = TRUE; m_stack.PushStack(f);} }}}if(IsT(strProduce,nLocat-1))if(strProduce.GetAt(nLocat-1) == f.m_strTerm) {if(!f.m_bIsVT){f.m_bIsVT = TRUE; m_stack.PushStack(f);}}}nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLen-n int nLocat = strProduce.GetLength(); if(IsNT(strProduce,nLocat-1)){if(strProduce.GetAt(nLocat-1) == Q.m_strN{//Q.m_bIsVT = TRUE;for(int i=0;i<STACK_LEN;i++){if(m_F[i].m_strNTerm == strNT &&{if(!m_F[i].m_bIsVT){m_F[i].m_bIsVT = TRUE; m_stack.PushStack(m_F[ b reak;}}}}}Find Q; void CGrammarAnalysisDlg::OnBnClickedBtnAnsysic(){// TODO: 在此添加控件通知处理程序代码// 初始化列表控件 //m_lbResult.AddString(_T("kjl"));m_lst.SetExtendedStyle(LVS_EX_AUTOSIZECOLUMNS|LVS_EX_GRIDLPOSITION pos = m_mapProdu.GetStartPosition(); while(pos) C Rect rc; {m_lst.GetClientRect(rc);if(nLocat-2>0)if(IsNT(strProduce,nLocat-1) && IsT(strProduce,nLocat-2)) == Q.m_strTerm)}} }// //P-> Q }void CGrammarAnalysisDlg::SearchQForLastVT(void) }CString strNT; CString* str;while(m_stack.m_nTop != 0){m_stack.PopStack(Q);int nWidth = rc.Width()/(T_LEN+2);int i = 0;m_lst.InsertColumn(i,_T(""),LVCFMT_CENTER,nWidth); for(i=1;i<T_LEN+1;i++){nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLen-nFrist int nLocat = strProduce.GetLength(); for(int i=0;i<nLocat-1;i++)m_lst.InsertColumn(i,m_strTElem[i-1],LVCFMT_CENTER,nWidth); { }m_lst.InsertColumn(i,_T("#"),LVCFMT_CENTER,nWidth);for(i=0;i<T_LEN;i++){ m_lst.InsertItem(i,m_strTElem[i]);} m_lst.InsertItem(i,_T("#")); if(IsT(strProduce,i) && IsT(strProduce,i+1)){nItem = FindTLocat(strProduce.GetAt(i));nColumn = FindTLocat(strProduce.GetAt(i+1m_nPriSheet[nItem][nColumn] = 0;m_lst.SetItemText(nItem,nColumn+1,_T("=") }if(i<=nLocat-2 && IsT(strProduce,i) && IsT(s// IsNT(strProduce,i+1))//FirstVTInitFind();//Find f(_T("+"),_T("E"));for(int i=0;i<STACK_LEN;i++)SearchPForFirtVT(m_F[i]); SearchQForFristVT();CreateFristVT(m_F);//LastVTInitFind();//Find f(_T("+"),_T("E"));for(int i=0;i<STACK_LEN;i++)SearchPForLastVT(m_F[i]); SearchQForLastVT(); CreateLastVT(m_F);// 遍历产生式构造算符优先表CString* str;POSITION pos =m_mapProdu.GetStartPosition(); CString strNT;int nColumn;int nItem;while(pos){ m_mapProdu.GetNextAssoc(pos,strNT,(void*&)str);int nFrist = 0;int nLen = 0; while(nLen+1 <str->GetLength()){{nItem = FindTLocat(strProduce.GetAt(i));nColumn = FindTLocat(strProduce.GetAt(i+2m_nPriSheet[nItem][nColumn] = 0;m_lst.SetItemText(nItem,nColumn+1,_T("=") }if(IsT(strProduce,i) && IsNT(strProduce,i+1)){nItem = FindTLocat(strProduce.GetAt(i));int nNTLocat = FindNTLocat(strProduce.Getint nVTLen = m_strFristVT[nNTLocat].GetLefor(int j=0;j<nVTLen;j++){nColumn = FindTLocat(m_strFristVT[nNTm_nPriSheet[nItem][nColumn] = -1;m_lst.SetItemText(nItem,nColumn+1,_T }}if(IsNT(strProduce,i) && IsT(strProduce,i+1)){nColumn = FindTLocat(strProduce.GetAt(i+1int nNTLocat = FindNTLocat(strProduce.Getint nVTLen = m_strLastVT[nNTLocat].GetLenfor(int j=0;j<nVTLen;j++){nItem = FindTLocat(m_strLastVT[nNTLom_nPriSheet[nItem][nColumn] = 1;m_lst.SetItemText(nItem,nColumn+1,_T }m_lst.SetItemText(i,nColumn+1,_T(">")); break;}case 1:m_nPriSheet[i][nColumn] = 1;}// 处理‘ #',, 行 nItem = T_LEN; wchar_t ch = '(';for(int i=0;i<T_LEN+1;i++){switch(m_nPriSheet[FindTLocat(ch)][i]){case 0: break; case INFI: break; case -1:m_nPriSheet[nItem][i] = -1; m_lst.SetItemText(nItem,i+1,_T("<")); break; case 1:m_nPriSheet[nItem][i] = 1; m_lst.SetItemText(nItem,i+1,_T(">")); break;}}// 处理‘ #',,列 nColumn = T_LEN;}// 最后一角nItem = T_LEN; nColumn = T_LEN;m_nPriSheet[nItem][nColumn] = 0;m_lst.SetItemText(nItem,nColumn+1,_T("="));}void CGrammarAnalysisDlg::CreateFristVT(Find* F){for(int i=0;i<STACK_LEN;i++){if(F[i].m_bIsVT){for(int j=0;j<NT_LEN;j++){if(F[i].m_strNTerm == m_strNTElem[j]){m_strFristVT[j] += F[i].m_strTerm; break;}}}}}void CGrammarAnalysisDlg::CreateLastVT(Find* F)ch = ')'; {for(int i=0;i<T_LEN;i++){switch(m_nPriSheet[i][FindTLocat(ch)]){case 0:break; case INFI:break; case -1:m_nPriSheet[i][nColumn] = -1;m_lst.SetItemText(i,nColumn+1,_T("<"));break;for(int i=0;i<STACK_LEN;i++){if(F[i].m_bIsVT){for(int j=0;j<NT_LEN;j++){if(F[i].m_strNTerm == m_strNTElem[j]){m_strLastVT[j] += F[i].m_strTerm; break;}}}int CGrammarAnalysisDlg::FindTLocat(wchar_t strT){for(int i=0;i<T_LEN;i++){if(m_strTElem[i] == strT) return i;}if(strT = '#')return T_LEN;}int CGrammarAnalysisDlg::FindNTLocat(wchar_t strNT){for(int i=0;i<NT_LEN;i++){if(m_strNTElem[i] == strNT) return i;}if(IsT(m_stack.m_Ch[k],0))j = k;else j = k-1;int nItem =FindTLocat(m_stack.m_Ch[j].GetAt(0)); int nColumn = FindTLocat(m_strSen[i]);return 0;}void CGrammarAnalysisDlg::OnBnClickedBtnAnasysic() {// TODO: 在此添加控件通知处理程序代码// 清空列表控件int nCount = m_lbResult.GetCount();for(int i=0;i<nCount;i++)m_lbResult.DeleteString(0);//UpdateData();// 清空栈m_stack.m_nTop = 0;// 初值int j,k = 1;CString Q;m_stack.m_Ch[k] = (_T("#"));////int nLen = m_strSen.GetLength();m_strSen += _T("#");int i = -1;do while(m_nPriSheet[nItem][nColumn] == 1){int nItem1,nColumn1;do{Q = m_stack.m_Ch[j];if(IsT(m_stack.m_Ch[j-1],0))j = j-1;else j= j-2;nItem1 = FindTLocat(m_stack.m_Ch[j].GetAt(0))nColumn1 = FindTLocat(Q.GetAt(0));} while (m_nPriSheet[nItem1][nColumn1] != -1);CString strToProduce;for(int m = j+1;m<=k;m++){strToProduce += m_stack.m_Ch[m];}// 输出产生式POSITION pos = m_mapProduEX.GetStartPosition();CString strNT;CString* str;while(pos){m_mapProduEX.GetNextAssoc(pos,strNT,(void*&)sint nFrist = 0;int nLen = 0;while(nLen+1 < str->GetLength()){nFrist = nLen;nLen = str->Find('|',nFrist+1);CString strProduce = str->Mid(nFrist+1,nLif(strProduce == strToProduce) {i++;CString strResult;strResult += _T("->"); strResult += strToProduce;m_lbResult.AddString(strResult);k = j+1;m_stack.m_Ch[k] = strNT; break;}}}nItem = FindTLocat(m_stack.m_Ch[j].GetAt(0)); nColumn = FindTLocat(m_strSen[i]);}nItem = FindTLocat(m_stack.m_Ch[j].GetAt(0)); nColumn = FindTLocat(m_strSen[i]); }五.结果分析及试验心得:本次实验做起来有点复杂,我认为重点在对教材所给算法的理解及个变量存 储形式的设计。