实验二语法分析算符优先法

合集下载

算符优先语法分析设计原理与实现技术实验报告

算符优先语法分析设计原理与实现技术实验报告

算符优先语法分析设计原理与实现技术实验报告变更说明一、实验目的:本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。

二、实验内容:[实验项目]实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。

G[E]:E→E+T∣E-T∣TT→T*F∣T/F∣FF→(E)∣i[实验说明]终结符号i 为用户定义的简单变量,即标识符的定义。

[设计要求](1)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。

输出为输入串是否为该文法定义的算术表达式的判断结果;(2)算符优先分析过程应能发现输入串出错;(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。

三、实验环境:操作系统:Windows 7软件:VC++6.0四、程序功能描述:●提供了文件输入方式,且输入的内容为二元式序列;●能够对输入的字符串做出正确的算符优先分析判断,并给出判断结果,判断结果输出到文件,并显示在屏幕;●能发现输入串中的错误,包含非法字符,输入不匹配等;●能够处理一些可预见性的错误,如文件不存在,输入非法等。

五、数据结构设计:六、程序结构描述:●设计方法:本程序采用从文件读取的输入方式,输入的内容需为二元式序列,然后按照算符优先分析的方法对输入的字符串进行分析判断,分析完成后输出判断结果到文件,并在屏幕显示。

程序通过对输入串的检查能够发现输入串中的错误。

程序规定的单词符号及其种别码见下表:算符优先矩阵+ - * / ( ) i #+ > > < < < > < >- > > < < < > < >* > > > > < > < >/ > > > > < > < >( < < < < < = < >) > > > > > >i > > > > > ># < < < < < < < =●算符优先分析法简介基本思路是根据既定的规则构建算符优先矩阵,然后根据算符之间的优先关系寻找输入串中的最左素短语,若找到,则寻找与最左素短语匹配的产生式进行规约;否则进行移进操作,及输入的算符进分析栈。

实验二 编译原理语法分析(算符优先)

实验二  编译原理语法分析(算符优先)

实验二语法分析算符优先分析程序一.实验要求⑴选择最有代表性的语法分析方法算符优先法;⑵选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。

⑶实习时间为6学时。

二.实验内容及要求(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(4)分析的句子为:(i+i)*i和i+i)*i三.实验代码#include "stdafx.h"#include "stdio.h"#include "stdlib.h"#include "iostream.h"int k;char a;int j;char q;int r;int r1;char st[10][30];char data[20][20];char s[100];char lable[20];char input[100];char string[20][10];char first[10][10];char last[10][10];int fflag[10]={0};int lflag[10]={0};int deal();int zhongjie(char c);int xiabiao(char c);void out(int j,int k,char *s);void firstvt(char c);void lastvt(char c);void table();void main(){int i,j,k=0;printf("请输入文法规则数:");scanf("%d",&r);printf("请输入文法规则:\n");for(i=0;i<r;i++){scanf("%s",st[i]);first[i][0]=0;last[i][0]=0;}for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf("不是算符文法!\n");exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf("不是算符文法!\n");exit(-1);}}}}for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='|') lable[k++]=st[i][j];}}lable[k]='#';lable[k+1]='\0';table();//输出每个非终结符的FIRSTVT集printf("每个非终结符的FIRSTVT集为:\n"); for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<first[i][0];j++){printf("%c ",first[i][j+1]);}printf("\n");}//输出每个非终结符的LASTVT集printf("每个非终结符的LASTVT集为:\n"); for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<last[i][0];j++){printf("%c ",last[i][j+1]);}printf("\n");}printf("算符优先分析表如下:\n");for(i=0;lable[i]!='\0';i++)printf("\t%c",lable[i]);printf("\n");for(i=0;i<k+1;i++){printf("%c\t",lable[i]);for(j=0;j<k+1;j++){printf("%c\t",data[i][j]);}printf("\n");}printf("请输入文法输入符号串以#结束:");scanf("%s",input);deal();}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0;i<r;i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0;i<r;i++){text[x][y]=st[i][0];y++;for(j=1;st[i][j]!='\0';j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;//输出转化后的文法规则串printf("转化后的文法为:\n");for(i=0;i<x;i++) {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++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0;i<x;i++){for(j=1;text[i][j+1]!='\0';j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i][j+1])) {m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0;t<first[k][0];t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0;t<last[k][0];t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0;t<first[0][0];t++){n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0;t<last[0][0];t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}//求FIRSTVT集void firstvt(char c) { int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0;j<r;j++){if(st[j][0]==st[i][m+1])break;}for(k=0;k<first[j][0];k++){int t;for(t=0;t<n;t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}//求LASTVT集{void lastvt(char c)int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|'){if(zhongjie(st[i][m])){last[i][n]=st[i][m];n++;}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0;j<r;j++){if(st[j][0]==st[i][m])break;}for(k=0;k<last[j][0];k++){int t;for(t=0;t<n;t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}int deal(){int i,j;int x,y;int z;k=1;s[k]='#';for(i=0;input[i]!='\0';i++);z=i--;i=0;while((a=input[i])!='\0'){if(zhongjie(s[k]))j=k;elsej=k-1;x=xiabiao(s[j]);y=xiabiao(a);if(data[x][y]=='>'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("规约\n");do{q=s[j];if(zhongjie(s[j-1]))j=j-1;else j=j-2;x=xiabiao(s[j]);y=xiabiao(q);}while(data[x][y]!='<');int m,n,N;for(m=j+1;m<=k;m++){for(N=0;N<r1;N++)for(n=1;string[N][n]!='\0';n++){if(!zhongjie(s[m])&&!zhongjie(string[N][n])) {if(zhongjie(s[m+1])&&zhongjie(string[N][n+1])&&s[m+1]==string[N][n+1]){s[j+1]=string[N][0];break;}}elseif(zhongjie(s[m]))if(s[m]==string[N][n]){s[j+1]=string[N][0];break;}}}k=j+1;if(k==2&&a=='#'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("结束\n");printf("输入串符合文法的定义!\n");return 1; } }elseif(data[x][y]=='<'||data[x][y]=='='){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("移进\n");k++;s[k]=a;i++;}else{printf("\nflase");return 0;}}printf("\nflase");return 0;}void out(int j,int k,char *s){int n=0;int i;for(i=j;i<=k;i++){printf("%c",s[i]);n++;}for(;n<15;n++){printf(" ");}}//判断字符c是否是终极符int zhongjie(char c){int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}//求字符c在算符优先关系表中的下标{int xiabiao(char c)int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}四、实验结果输入串为#(i+i)/i#存放于Read.txt文件中五、实验总结经过此次试验对算符优先分析的原理有了深入的理解,熟悉了算符分析的过程,掌握了算符优先分析的有关处理,能够使用一种高级语言构造算符优先的语法分析器。

编译原理实验二LL(1)语法分析实验报告

编译原理实验二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)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)实验要求独立完成,不允许有抄袭现象。

(4)实验完成后,要求提交源程序和上交实验报告(包括源程序清单)。

(附:实验报告格式)三、实验内容(1)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(2)分析的句子为:(i+i)*i和i+i)*i(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, * , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }FirstVT(E’)={ #} LastVT(E’)={ #}3,根据FirstVT和LastVT集构造算符优先表(2)程序参考源码#include <iostream>#include <string>using namespace std;#define max 100char b[max]; //存放终结符char precedence[max][max];//存放优先关系struct opg{int step;string stack;char privior;char presentsignal;string leftstr;string explain;}temp;//存放一步int search(char ch){int i=0;while(ch!=b[i])i++;return i;}void anolyze(){//struct opg temp;temp.step=0;char s[max],c,a;string sentence;int m=0,q=0,flag=0,i=0; //flag标记着当前读到那个字符cout<<"输入要分析的句子:";cin>>sentence;int k=0;//s[k]='#';s[k]=sentence[flag++];s[k+1]='\0';int j=k;a=sentence[flag++]; //读入一个给a;temp.leftstr=sentence;while(temp.leftstr[i]!=a){ //while循环获得第一次的剩余字符串temp.leftstr[i]=' ';i++;}temp.leftstr[i]=' ';//把已经读过的字符赋空则就找到了剩余的串cout<<"步骤 "<<" 栈 "<<" 优先关系 "<<"当前符号"<<" 剩余字符串 "<<"移进或归约"<<endl;while(!(s[j]=='#'&&a=='#')){//栈顶和当前字符都是#if(!isupper(s[k]))j=k;//s[k]是终结符else j=k-1;m=search(s[j]);//获取要比较终结符所在行号q=search(a);//获取要比较终结符所在列号temp.step=temp.step+1;temp.stack=s;temp.privior=precedence[m][q];temp.presentsignal=a;cout<<temp.step<<'\t'<<temp.stack<<'\t'<<temp.privior<<'\t'<<temp.presentsignal <<temp.leftstr<<'\t';if(precedence[m][q]=='<'||precedence[m][q]=='=')//优先关系为<或={temp.explain="移进";cout<<temp.explain<<endl;k=k+1;s[k]=a;s[k+1]='\0';//赋上字符串的终结标准,相当于一个栈a=sentence[flag++];//读入一个给a;temp.leftstr[++i]=' ';//每读入一个句子中一个字符把此位置赋空,作为剩余串}else if(precedence[m][q]=='>')//优先关系为>{temp.explain="归约";cout<<temp.explain<<endl;//cout<<s[j]<<s[k]<<a;do{c=s[j];if (!isupper(s[j-1]))//s[j-1]是终结符(即不是大写字母)j=j-1;elsej=j-2;m=search(s[j]);q=search(c);}while(precedence[m][q]=='=');k=j+1;s[k]='N';s[k+1]='\0';}//出错else {cout<<"不是该文法可以识别的句子";break;}//出错}cout<<++temp.step<<'\t'<<"#N"<<'\t'<<"="<<'\t'<<"#"<<' '<<'\t'<<"接受";}void main(){int n,i,j; //终结符的个数cout<<"输入终结符的个数:";cin>>n;cout<<endl;cout<<n<<'\n';cout<<"输入终结符";for(i=0;i<n;i++)cin>>b[i];b[n]='#';for(i=0;i<n+1;i++)for(j=0;j<n+1;j++){cout<<b[i]<<"与"<<b[j]<<"的优先关系:";cin>>precedence[i][j];while(!(precedence[i][j]=='>'||precedence[i][j]=='<'||precedence[i][j]=='=' ||precedence[i][j]=='/')){ cout<<"没有此优先关系,请重新输入";cin>>precedence[i][j];}}cout<<"算术优先关系表\n"<<"===============================================\n";for(i=0;i<n+2;i++)for(j=0;j<n+2;j++){if(i==0){if(j==0)cout<<' ';else cout<<b[j-1]<<' ';}else {if(j==0)cout<<b[i-1];else cout<<precedence[i-1][j-1]<<' ';}if(j==n+1)cout<<endl;}cout<<"===============================================\n";anolyze();}。

算符优先分析法

算符优先分析法

华中师范大学计算机科学系算符优先分析法学号:2009210580姓名:王晔成绩:一实验目的设计、编制并调试一个算符优先分析算法,加深对此分析法的理解二实验过程2.1实验过程先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。

分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。

1 若f(θ1)<=g(θ2),则θ2进算符栈,并继续顺序往下扫描,分析过程从头开始2 如f(θ1)>g(θ2),则产生对操作数栈顶的若干项进行θ1运算的中间代码,并从运算符栈顶移去θ1,并从操作数栈顶移去若干项,然后把执行θ1的结果压入操作数栈。

接着以运算符栈新的项目与θ2进行上述优先数的比较,即重复(1)(2),3 重复(1)(2)直到“$”与“$”配对为止。

关键代码#include <stdio.h>#include <string.h>#include <ctype.h>char calculator_stack[100],prog[1000];int operator_stack[100];int c_top=0,o_top=0,p;char ch;int f[255]={0};int g[255]={0};void Init(){f['*']=f['/']=5;f['+']=f['-']=3;f['$']=0;g['*']=g['/']=4;g['+']=g['-']=2;g['$']=0;}int main(){int i,sum=0,oper1,oper2,result;Init();calculator_stack[c_top++]='$';p=0;printf("请输入正确的代码,以#结束:\n"); do{ch=getchar();prog[p++]=ch;}while(ch!='#');prog[p]=0;printf("%s\n",prog);p=0;bool flag;for(i=0;prog[i];i++){if(isalpha(prog[i])){flag=1;continue;}else if(isdigit(prog[i])){if(flag)continue;else{sum=sum*10+prog[i]-'0';if(!isdigit(prog[i+1])){operator_stack[o_top++]=sum;sum=0;}flag=0;}}else if(prog[i]==' ' || prog[i]=='\t' || prog[i]=='\n'){flag=0;continue;}else if(prog[i]=='#')break;else{flag=0;if(prog[i]=='*' || prog[i]=='/' || prog[i]=='+' || prog[i]=='-' ||prog[i]=='$') {if(prog[i]!='$' && f[calculator_stack[c_top-1]]<=g[prog[i]]) calculator_stack[c_top++]=prog[i];else{while(1){oper2=operator_stack[--o_top];oper1=operator_stack[--o_top];ch=calculator_stack[c_top-1];if(ch=='*')result=oper1*oper2;else if(ch=='/'){if(oper2==0){printf("除零错误!\n");return 0;}result=oper1/oper2;}else if(ch=='+')result=oper1+oper2;else if(ch=='-')result=oper1-oper2;printf("%d = %d %c %d\n",result,oper1,ch,oper2); operator_stack[o_top++]=result;calculator_stack[--c_top];if(prog[i]=='$' && calculator_stack[c_top-1]=='$') return 0;if(f[calculator_stack[c_top-1]]<=g[prog[i]]){calculator_stack[c_top++]=prog[i];break;}}}}}}return 0;}。

编译原理实验 词法分析&语法分析程序

编译原理实验 词法分析&语法分析程序

编译原理实验词法分析程序实验一:词法分析程序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循环,运算结束!。

二语法分析程序(算符优先分析法)

二语法分析程序(算符优先分析法)

实验二语法分析程序(算符优先分析法)一、实验目的通过设计调试算符优先分析程序,加深对课堂教学的理解,深刻理解自底向上语法分析方法的归约过程,提高语法分析方法的实践能力。

二、实验要求(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)实验要求独立完成,不允许有抄袭现象。

(4)实验完成后,要求提交源程序和上交实验报告(包括源程序清单)。

(附:实验报告格式)三、实验内容(1)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(2)分析的句子为:(i+i)*i和i+i)*i(1)分析1,判断为算符优先文法:文法没有A->…BC…且BC均为非终结符,因此它为OG文法文法没有同时存在①A->…ab…或A->….aBb….②A->…aB…且B=>b….或B=>Cb….③A->…Bb….且B=>…a或B=>…aC文法为算符优先文法2,求FirstVT集和LastVT集FirstVT(E)={+, * , ( , i } LastVT(E)= {+, - , * , / , ) , i }FirstVT(T)={* , ( , i } LastVT(T)= {* , / , ( , i }FirstVT(F)={ ( , i } LastVT(F)={ ) , i }FirstVT(E’)={ #} LastVT(E’)={ #}3,根据FirstVT和LastVT集构造算符优先表(2)程序参考源码#include <iostream>#include <string>using namespace std;#define max 100char b[max]; //存放终结符char precedence[max][max];//存放优先关系struct opg{int step;string stack;char privior;char presentsignal;string leftstr;string explain;}temp;//存放一步int search(char ch){int i=0;while(ch!=b[i])i++;return i;}void anolyze(){//struct opg temp;temp.step=0;char s[max],c,a;string sentence;int m=0,q=0,flag=0,i=0; //flag标记着当前读到那个字符cout<<"输入要分析的句子:";cin>>sentence;int k=0;//s[k]='#';s[k]=sentence[flag++];s[k+1]='\0';int j=k;a=sentence[flag++]; //读入一个给a;temp.leftstr=sentence;while(temp.leftstr[i]!=a){ //while循环获得第一次的剩余字符串temp.leftstr[i]=' ';i++;}temp.leftstr[i]=' ';//把已经读过的字符赋空则就找到了剩余的串cout<<"步骤 "<<" 栈 "<<" 优先关系 "<<"当前符号"<<" 剩余字符串 "<<"移进或归约"<<endl;while(!(s[j]=='#'&&a=='#')){//栈顶和当前字符都是#if(!isupper(s[k]))j=k;//s[k]是终结符else j=k-1;m=search(s[j]);//获取要比较终结符所在行号q=search(a);//获取要比较终结符所在列号temp.step=temp.step+1;temp.stack=s;temp.privior=precedence[m][q];temp.presentsignal=a;cout<<temp.step<<'\t'<<temp.stack<<'\t'<<temp.privior<<'\t'<<temp.presentsignal <<temp.leftstr<<'\t';if(precedence[m][q]=='<'||precedence[m][q]=='=')//优先关系为<或={temp.explain="移进";cout<<temp.explain<<endl;k=k+1;s[k]=a;s[k+1]='\0';//赋上字符串的终结标准,相当于一个栈a=sentence[flag++];//读入一个给a;temp.leftstr[++i]=' ';//每读入一个句子中一个字符把此位置赋空,作为剩余串}else if(precedence[m][q]=='>')//优先关系为>{temp.explain="归约";cout<<temp.explain<<endl;//cout<<s[j]<<s[k]<<a;do{c=s[j];if (!isupper(s[j-1]))//s[j-1]是终结符(即不是大写字母)j=j-1;elsej=j-2;m=search(s[j]);q=search(c);}while(precedence[m][q]=='=');k=j+1;s[k]='N';s[k+1]='\0';}//出错else {cout<<"不是该文法可以识别的句子";break;}//出错}cout<<++temp.step<<'\t'<<"#N"<<'\t'<<"="<<'\t'<<"#"<<' '<<'\t'<<"接受";}void main(){int n,i,j; //终结符的个数cout<<"输入终结符的个数:";cin>>n;cout<<endl;cout<<n<<'\n';cout<<"输入终结符";for(i=0;i<n;i++)cin>>b[i];b[n]='#';for(i=0;i<n+1;i++)for(j=0;j<n+1;j++){cout<<b[i]<<"与"<<b[j]<<"的优先关系:";cin>>precedence[i][j];while(!(precedence[i][j]=='>'||precedence[i][j]=='<'||precedence[i][j]=='=' ||precedence[i][j]=='/')){ cout<<"没有此优先关系,请重新输入";cin>>precedence[i][j];}}cout<<"算术优先关系表\n"<<"===============================================\n";for(i=0;i<n+2;i++)for(j=0;j<n+2;j++){if(i==0){if(j==0)cout<<' ';else cout<<b[j-1]<<' ';}else {if(j==0)cout<<b[i-1];else cout<<precedence[i-1][j-1]<<' ';}if(j==n+1)cout<<endl;}cout<<"===============================================\n";anolyze();}。

实验2 语法分析(算符优先分析)

实验2 语法分析(算符优先分析)

实验2 语法分析(算符优先分析)一、实验任务:算术表达式的文法:E→ E+T | E-T | TT→ T*F | T/F | FF→(E)| i根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确。

二、实验时间:上机2次。

三、实验过程和指导:(一)准备:1.确定算术表达式的文法,设计出算符优先关系表;2.考虑好设计方案,设计出模块结构、测试数据;3.初步编制好程序。

(二)上机实验:上机调试,发现错误,分析错误,逐渐修改完善。

(三)程序要求:程序输入/输出示例:如参考C语言的运算符。

输入如下表达式(以分号为结束)和输出结果:(1)10输出:正确(2)1+2*(15-6)输出:正确(3)(1+2)/3+4- (11+6/7)输出:正确(4)((1-2)/3+4输出:错误,出错位置是(5)1+2-3+(*4/5)输出:错误,出错位置是注意:1.为降低难度,表达式中不含变量(只含无符号整数);2.可以直接调用此法分析程序,取得单词;3.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好,最好有详细的出错位置和出错性质说明);4.测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。

同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;5.对学有余力的同学,可增加功能:当判断一个表达式正确时,输出计算结果,计算过程用浮点表示,但要注意不要被0除。

(四)练习该实验的目的和思路:程序比较复杂,需要利用到大量的编译原理,也用到了大量编程技巧和数据结构,通过这个练习可极大提高编程能力。

程序规模大概为300行。

通过练习,掌握对表达式进行处理的一种方法。

(五)为了能设计好程序,注意以下事情:1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。

2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。

3.编程时注意编程风格:空行的使用、注释的使用、缩进的使用、变量合理命名等。

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

if(Stack[k]=='+'||Stack[k]=='*'||Stack[k]=='i'||Stack[k]=='('||Stack[k
{ printf("错误!该句子不是该文法的合法句子!\n"); break; } p=oppriority[z][n]; 号 if(p=='$') { printf("错误!该句子不是该文法的合法句子!\n"); return; } if(p=='>') { for( ; ; ) { Q=Stack[j]; if(Stack[j-1]=='+'||Stack[j-1]=='*'||Stack[j1]=='i'||Stack[j-1]=='('||Stack[j-1]==')'||Stack[j-1]=='#') j=j-1; else j=j-2; z1=located(Stack[j]); n1=located(Q); p1=oppriority[z1][n1]; if(p1=='<') 归约为N { //把AnalyseStack[j+1]~AnalyseStack[k] //用p存放这个两者比较的有限关系符
华北水利水电学院编译原理实验报告
2013~2014学年 第 一 学期 2012 级 计算机科学与技术 专业 班级: 196 学号: 2012196 姓名: 李明月 1、 实验题目:
算符优先分析程序
2、 实验内容:
(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表 (要求算符优先关系表 输出到屏幕或者输出到文件); (2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确 的算术表达式(要求输出归约过程) (3)给定表达式文法为: G(E’): E’→#E# E→E+T | T T→T*F |F F→(E)|i (4)分析的句子为: (i+i)*i和i+i)*i
printf("-----------------------------------------\n"); printf("请输入要进行分析的句子(以#号结束输入):\n"); gets(storage);//将输入的字符串存到数组中 printf("步骤 归约\n"); k=0; Stack[k]='#'; Stack[k+1]='\0'; int length,i; //初始化剩余字符串数组为输入串 length=strlen(storage);// 栈 当前符号 剩余输入串 移进或
printf("错误!该句子不是该文法的合法句子! \n"); break; } } } } } int located(char x) { int m; if(x=='+') m=0; if(x=='*') m=1; if(x=='i') m=2; if(x=='(') m=3; if(x==')') m=4; if(x=='#') m=5; return m; } void change()//将后一个字符往前移动 { //查出某个字符在优先表中的位置
for(i=0;i<length;i++) { remain[i]=storage[i]; } remain[i]='\0'; judge();//对所输入的句子进行算符优先分析过程的函数 } void judge()//对所输入的句子进行算符优先分析过程的函数 { int i,j,f,z,z1,n,n1,z2,n2; int count=0;//操作的步骤数 char a; //用于存放正在分析的字符 char p,Q,p1,p2; f=strlen(storage); for(i=0;i<=f;i++) { a=storage[i]; if(i==0) change(); j=k; else j=k-1; z=located(Stack[j]); if(a=='+'||a=='*'||a=='i'||a=='('||a==')'||a=='#') n=located(a); else //如果句子含有不是终结符集合里的其它字符,不合法 //获得栈中元素的位置 //让a为当前要分析的字符 //第一个元素不做处理,直接往后移动 //测出数组的长度
3、 程序源代码:
#include<stdlib.h> #include<stdio.h> #include<string.h> #include<iostream.h> char oppriority[6][6]={{'>','<','<','<','>','>'}, {'>','>','<','<','>','>'}, {'>','>','$','$','>','>'},{'<','<','<','<','=','$'}, {'>','>','$','$','>','>'},{'<','<','<','<','$','='}}; 优先关系表数组 char storage[100]; input) char remain[100]; char Stack[100]; void judge(); int void change(); 个字符 int k; void main() { printf("文法为:\n"); printf("E'->#E#\n"); printf("E→E+T|T\n"); printf("T→T*F|F\n"); printf("F→(E)|i\n"); printf("文法可拆分为:\n"); printf("(0)E'->#E#\n"); //存放剩余串 //分析栈 //对所输入的句子进行算符优先分析过程的函数 //判断字符X在算符优先关系表中的位置 //移进时处理剩余字符串,即去掉剩余字符串第一 //存放输入的要进行分析的句子(原来是 //算符
else { if(p=='=') { z2=located(Stack[j]); n2=located('#'); p2=oppriority[z2][n2]; if(p2=='=') { count++; printf("(%d) \n",count,Stack,a,remain); printf("该句子是该文法的合法句子。\n"); break; } else { count++; printf("(%d) \n",count,Stack,a,remain); k=k+1; Stack[k]=a; change(); } } else { %s\t%8c%17s\t 移进 %s\t%8c%17s\t 接受
count++; printf("(%d) \n",count,Stack,a,remain); k=j+1; i--; Stack[k]='E'; int r,r1; r=strlen(Stack); for(r1=k+1;r1<r;r1++) Stack[r1]='\0'; break; } else continue; } } else { if(p=='<') { count++; printf("(%d) \n",count,Stack,a,remain); k=k+1; Stack[k]=a; change(); } %s\t%8c%17s\t 移进 //表示移进 %s\t%8c%17s\t 归约
ห้องสมุดไป่ตู้
多。
located(char x);
printf("(1)E->E+T\n"); printf("(2)E->T\n"); printf("(3)T->T*F\n"); printf("(4)T->F\n"); printf("(5)F->(E)\n"); printf("(6)F->i\n"); printf("根据FIRSTVT集和LASTVT集可以得出算符优先分析表。 \n"); printf("-----------------------------------------\n"); printf(" printf(" printf(" printf(" printf(" printf(" printf(" printf(" + * i ( ) # + > > > < > < 算符优先关系表\n"); * < > > < > < < < < < i < < ( < < ) > > > = > #\n"); >\n"); >\n"); >\n"); \n"); >\n"); =\n");
相关文档
最新文档