实验二语法分析算符优先法
算符优先语法分析设计原理与实现技术实验报告
算符优先语法分析设计原理与实现技术实验报告变更说明一、实验目的:本实验的目的在于在教师的引导下以问题回朔与思维启发的方式,使学生在不断的探究过程中掌握编译程序设计和构造的基本原理和实现技术,启迪学生的抽象思维、激发学生的学习兴趣、培养学生的探究精神和专业素养,从而提高学生发现问题、分析问题和解决问题的能力。
二、实验内容:[实验项目]实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
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)语法分析实验报告
专题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 语法分析(算符优先分析)一、实验任务:算术表达式的文法: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. 理解算符优先分析法的原理和过程。
2. 掌握算符优先分析法的实现方法。
3. 通过实验加深对自底向上语法分析方法的理解。
二、实验内容1. 算符优先分析法原理介绍算符优先分析法是一种自底向上的语法分析方法,它通过比较相邻算符的优先次序来识别句型中的句柄,进而执行归约。
该方法的核心是确立文法的终结符之间的优先关系。
2. 实验步骤(1)判断文法是否为OG文法:OG文法要求所有产生式右部至少有一个终结符。
(2)判断文法是否为OPG文法:计算FIRSTVT集、LASTVT集,并构建算符优先矩阵。
(3)对句子进行分析:根据分析表判断句子是否为文法的句子。
(4)实现程序:从文件和键盘读取输入,将结果输出到指定文件和屏幕,并具有一致性。
3. 实验数据(1)文法:g[e]:e->e+t|t(2)测试句子:12+t, t+12, 12+13t, 12+t13三、实验过程1. 判断文法是否为OG文法根据给定的文法,我们可以看到所有产生式右部至少有一个终结符,因此该文法为OG文法。
2. 判断文法是否为OPG文法,并构建算符优先矩阵(1)计算FIRSTVT集FIRSTVT(e) = {t}FIRSTVT(t) = {t}(2)计算LASTVT集LASTVT(e) = {t}LASTVT(t) = {t}(3)构建算符优先矩阵| + - ( ) t e $+ > - - - > > -- > - - - > > -> > > > > > >( > > > > > > >) - - - - - - -t - - - - - - -e - - - - - - -$ - - - - - - -3. 对句子进行分析(1)分析句子“12+t”根据分析表,我们可以得到以下分析过程:12+t -> 12+t -> 12+t -> t -> t(2)分析句子“t+12”根据分析表,我们可以得到以下分析过程:t+12 -> t+12 -> t+12 -> t+12 -> t+12 -> t -> t (3)分析句子“12+13t”根据分析表,我们可以得到以下分析过程:12+13t -> 12+13t -> 12+13t -> 12+13t -> 12+13t -> t -> t(4)分析句子“12+t13”根据分析表,我们可以得到以下分析过程:12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> t13 -> t13 -> t13 -> t -> t四、实验结果1. 测试句子“12+t”分析结果:正确2. 测试句子“t+12”分析结果:正确3. 测试句子“12+13t”分析结果:正确4. 测试句子“12+t13”分析结果:正确五、实验总结通过本次实验,我们深入了解了算符优先分析法的原理和实现方法。
实验算符优先分析法
实验名称:实验任务:对下述描述算符表达式的算符优先文法GE,给出算符优先分析的实验结果;实验内容:有上下无关文法如下:E->E+T|E-T|TT->TF|T/F|FF->E|i说明:优先关系矩阵的构造过程:1 = 关系由产生式 F->E 知‘’=‘’FIRSTVT集及LASTVT集FIRSTVTE={ +,-,,/,,i }FIRSTVTF={ ,i }FIRSTVTT={ ,/,,i }LASTVTE={ +,-,,/,,i }LASTVTF={ ,i }LASTVTT={ ,/,,i }2 < 关系+T 则有:+ < FIRSTVTT-T 则有:- < FIRSTVTTF 则有: < FIRSTVTF/F 则有:/ < FIRSTVTFE 则有: < FIRSTVTE3 > 关系E+ 则有: LASTVTE > +E- 则有: LASTVTE > -T 则有: LASTVTT >T/ 则有: LASTVTT > /E 则有: LASTVTE >4请大家画出优先关系矩阵终结符之间的优先关系是唯一的,所以该文法是算符优先文法; 程序的功能描述:程序由文件读入字符串以结束,然后进行算符优先分析,分析过程中如有错误,则终止程序并报告错误位置,最终向屏幕输出移近——规约过程;5依据文法和求出的相应FirstVT和 LastVT 集生成算符优先分析表; 算法描述如下:for 每个形如 P->X1X2…Xn的产生式dofor i =1 to n-1 dobeginif Xi和Xi+1都是终结符 thenXi = Xi+1if i<= n-2, Xi和Xi+2 是终结符, 但Xi+1 为非终结符thenXi = Xi+2if Xi为终结符, Xi+1为非终结符 thenfor FirstVT 中的每个元素 a doXi < aif Xi为非终结符, Xi+1为终结符 thenfor LastVT 中的每个元素 a doa > Xi+1end6构造总控程序算法描述如下:stack S; k = 1; //符号栈S的使用深度Sk = ‘’REPEAT把下一个输入符号读进a中;If Sk VT thenj = kelsej = k-1;While Sj > a doBeginRepeatQ = Sj;if Sj-1 VT thenj = j-1elsej = j-2until Sj < Q;把Sj+1…Sk归约为某个N,并输出归约为哪个符号;K = j+1;Sk = N;end of whileif Sj < a or Sj = a thenbegin k = k+1; Sk = a endelse error //调用出错诊察程序until a = ‘’7代码如下:include ""include ""include ""char data2020; //算符优先关系char s100; //模拟符号栈schar lable20; //文法终极符集char input100; //文法输入符号串char string2010; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1; //转化后文法规则个数char st1030; //用来存储文法规则char first1010; //文法非终结符FIRSTVT集char last1010; //文法非终结符LASTVT集int fflag10={0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag10={0}; //标志第i个非终结符的LASTVT集是否已求出int deal; //对输入串的分析int zhongjiechar c; //判断字符c是否是终极符int xiabiaochar c; //求字符c在算符优先关系表中的下标void outint j,int k,char s; //打印s栈void firstvtchar c; //求非终结符c的FIRSTVT集void lastvtchar c; //求非终结符c的LASTVT集void table; //创建文法优先关系表void main{int i,j,k=0;printf"请输入文法规则数:";scanf"%d",&r;printf"请输入文法规则:\n";fori=0;i<r;i++{scanf"%s",sti; //存储文法规则,初始化FIRSTVT集和LASTVT集/firsti0=0; /firsti0和lasti0分别表示sti0非终极符的FIRSTVT集和LASTVT集中元素的个数/lasti0=0;}fori=0;i<r;i++ //判断文法是否合法{forj=0;stij='\0';j++{ifsti0<'A'||sti0>'Z'{printf"不是算符文法\n";exit-1;}ifstij>='A'&&stij<='Z'{ifstij+1>='A'&&stij+1<='Z'{printf"不是算符文法\n";exit-1;}}}}fori=0;i<r;i++{forj=0;stij='\0';j++{ifstij<'A'||stij>'Z'&&stij='-'&&stij='>'&&stij='|'lablek++=stij;}}lablek='';lablek+1='\0';table;printf"每个非终结符的FIRSTVT集为:\n"; //输出每个非终结符的FIRSTVT集fori=0;i<r;i++{printf"%c: ",sti0;forj=0;j<firsti0;j++{printf"%c ",firstij+1;}printf"\n";}printf"每个非终结符的LASTVT集为:\n"; //输出每个非终结符的LASTVT集fori=0;i<r;i++{printf"%c: ",sti0;forj=0;j<lasti0;j++{printf"%c ",lastij+1;}printf"\n";}printf"算符优先分析表如下:\n";fori=0;lablei='\0';i++printf"\t%c",lablei;printf"\n";fori=0;i<k+1;i++{printf"%c\t",lablei;forj=0;j<k+1;j++{printf"%c\t",dataij;}printf"\n";}printf"请输入文法输入符号串以结束:";scanf"%s",input;deal;}void table{char text2010;int i,j,k,t,l,x=0,y=0;int m,n;x=0;fori=0;i<r;i++{firstvtsti0;lastvtsti0;}fori=0;i<r;i++{textxy=sti0;y++;forj=1;stij='\0';j++{ifstij=='|'{textxy='\0';x++;y=0;textxy=sti0;y++;textxy++='-';textxy++='>';}else{textxy=stij;y++;}}textxy='\0';x++;y=0;}r1=x;printf"转化后的文法为:\n";fori=0;i<x;i++ //输出转化后的文法规则串{printf"%s\n",texti;}fori=0;i<x;i++ /求每个终结符的推导结果去掉"->"后的转化文法,用于最后的规约/ {stringi0=texti0;forj=3,l=1;textij='\0';j++,l++stringil=textij;stringil='\0';}fori=0;i<x;i++{forj=1;textij+1='\0';j++{ifzhongjietextij&&zhongjietextij+1{m=xiabiaotextij;n=xiabiaotextij+1;datamn='=';}iftextij+2='\0'&&zhongjietextij&&zhongjietextij+2&&zhongjietextij+1{m=xiabiaotextij;n=xiabiaotextij+2;datamn='=';}ifzhongjietextij&&zhongjietextij+1{fork=0;k<r;k++{ifstk0==textij+1break;}m=xiabiaotextij;fort=0;t<firstk0;t++{n=xiabiaofirstkt+1;datamn='<';}}ifzhongjietextij&&zhongjietextij+1{fork=0;k<r;k++{ifstk0==textijbreak;}n=xiabiaotextij+1;fort=0;t<lastk0;t++{m=xiabiaolastkt+1;datamn='>';}}}}m=xiabiao'';fort=0;t<first00;t++{n=xiabiaofirst0t+1;datamn='<';}n=xiabiao'';fort=0;t<last00;t++{m=xiabiaolast0t+1;datamn='>';}datann='=';}void firstvtchar c //求FIRSTVT集{int i,j,k,m,n;fori=0;i<r;i++{ifsti0==cbreak;}iffflagi==0{n=firsti0+1;m=0;do{ifm==2||stim=='|'{ifzhongjiestim+1{firstin=stim+1;n++;}else{ifzhongjiestim+2{firstin=stim+2;n++;}ifstim+1=c{firstvtstim+1;forj=0;j<r;j++{ifstj0==stim+1break;}fork=0;k<firstj0;k++{int t;fort=0;t<n;t++{iffirstit==firstjk+1break;}ift==n{firstin=firstjk+1;n++;}}}}}m++;}whilestim='\0';firstin='\0';firsti0=--n;fflagi=1;}}void lastvtchar c //求LASTVT集{int i,j,k,m,n;fori=0;i<r;i++{ifsti0==cbreak;}iflflagi==0{n=lasti0+1;m=0;do{ifstim+1=='\0'||stim+1=='|'{ifzhongjiestim{lastin=stim;n++;}else{ifzhongjiestim-1{lastin=stim-1;n++;}ifstim=c{lastvtstim;forj=0;j<r;j++{ifstj0==stimbreak;}fork=0;k<lastj0;k++{int t;fort=0;t<n;t++{iflastit==lastjk+1break;}ift==n{lastin=lastjk+1;n++;}}}}}m++;}whilestim='\0';lastin='\0';lasti0=--n;lflagi=1;}}int deal{int i,j;int x,y;int z; //输入串的长度k=1;sk=''; //栈置初值fori=0;inputi='\0';i++; //计算输入串的长度z=i--;i=0;whilea=inputi='\0'{ifzhongjieskj=k;elsej=k-1;x=xiabiaosj;y=xiabiaoa;ifdataxy=='>'{out1,k,s;printf"%c",a;outi+1,z,input;printf"规约\n";do{q=sj;ifzhongjiesj-1j=j-1;else j=j-2;x=xiabiaosj;y=xiabiaoq;}whiledataxy='<';int m,n,N;form=j+1;m<=k;m++{forN=0;N<r1;N++forn=1;stringNn='\0';n++{ifzhongjiesm&&zhongjiestringNn{ifzhongjiesm+1&&zhongjiestringNn+1&&sm+1==stringNn+1{sj+1=stringN0;break;}}elseifzhongjiesmifsm==stringNn{sj+1=stringN0;break;}}}k=j+1;ifk==2&&a==''{out1,k,s;printf"%c",a;outi+1,z,input;printf"结束\n";printf"输入串符合文法的定义\n";return 1; //输入串符合文法的定义}}elseifdataxy=='<'||dataxy=='='{ //移进out1,k,s;printf"%c",a;outi+1,z,input;printf"移进\n";k++;sk=a;i++;}else{printf"\nflase";return 0;}}printf"\nflase";return 0;}void outint j,int k,char s{int n=0;int i;fori=j;i<=k;i++{printf"%c",si;n++;}for;n<15;n++{printf" ";}}int xiabiaochar c //求字符c在算符优先关系表中的下标{int i;fori=0;lablei='\0';i++{ifc==lableireturn i;}return -1;}int zhongjiechar c //判断字符c是否是终极符{int i;fori=0;lablei='\0';i++{ifc==lableireturn 1;}return 0;}实验结果:。
算符优先分析法
G[E]: E→E+E|E-E|E*E|E/E|EE|(E)|-E|id
由于该文法是一个二义文法,它的句子往往有不同的规范推导和 归约,实际运算会得到不同结果,但按传统的习惯规定优先级和 结合律进行归约,优先级从高到低为:乘幂运算符,乘、除运算符, 加、减运算符;同级运算符服从左结合原则;有括号时,先括号 内后括号外。 则文法的句子id+id-id*(id+id)的归约过程为:
N1…Ni-1<· Ni …… Nj · >Nj+1…Nn
2.
句型中Ni„„Nj是句柄,语法分析程序可以通过寻找 Ni-1<· Ni和Nj· >Nj+1这两个关系来确定句柄的头尾,从 而确定句柄进行归约。
帮助理解 abce # 控制程序 # ce # b a #
G[S]: S→aBe B→bc bce # 控制程序 e #
知识点
算符优先分析法的算法简单、直观、易于理解,所以通常作为学 习其它自下而上语法分析的基础。 需复习有关语法分析的知识有:什么是语言、文法、句子、句型、 短语、简单短语、句柄、最右推导、规范归约基本概念。 本章重难点 算符文法的形式。 对一个给定的算符文法能构造算符优先关系分析表,并能判别所 给文法是否为 算符优先文法。 分清规范句型的句柄和最左素短语的区别,进而分清算符优先归 约和规范归约的区别。(在分析过程中如何寻找可归约串) 对一个给定的输入串能应用算符优先关系分析表给出分析(归约) 步骤,并最终判断所给输入串是否为该文法的句子。
输出带
2
2,3
2,3,4
2,3,4,1
S
a
A A b b
c
B e d
C.4-算符优先分析法-实验报告
学号
成绩
实 验 报 告
实验题目:算符优先分析法
课程名称:编译原理
主讲教师:
班 级:
实验日期:
提交日期:
1、
实验目的:
采用算符优先分析法对表达式(不包含括号运算)进行分析,并给出四元式。
二、实验内容
在实验1、2的基础上,用算符优先分析法编制语法分析程序。
分析过程:先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。分析过程从头开始,并重复进行;若读来的是运算符θ2 则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
结果
四、我的感想
这次试验可以说是前两个试验的综合了,程序中也很多用到了前两次的代码。对于我自己来说,最难的部分在于将这些思想转换成代码实现出来,很大一部分在于自己平时没有多打代码以及就是对算符优先分析的思想理解得还不够透彻。在写main函数时,因为要调用很多函数,刚开始写的时候陷入了死循环,以及栈函数的各种调用发生错误,说明自己思路还不够清晰。因为这次实验是在考完试后做的,之前对算符优先分析以及四元式的理解不够明白,在这个实验实现成功后,自己能够透彻地了解,知道了算符文法的形式,对给定的算符文法能构造算符优先关系分析表,并判别所给出的文法是否为算符优先文法。同时我也算符优先文法的优缺点以及实际应用中的局限性。
三、程序的改写:
因为这次的实验与前面两次的实验有很大的重合,所以会用到很多之前两次的代码。首先,定义函数:
其中本次需要写的函数有:入栈优先函数f,比较优先函数g,compare,middle,栈函数以及主函数。
1.入栈优先函数f
书上已经给出了入栈优先函数的表,根据输入的符号赋予数值,以便后面方便比较。
实验二--语法分析(算符优先)
实验二语法分析算符优先分析程序一. 实验要求⑴选择最有代表性的语法分析方法, 如算符优先法、递归子程序法或LR分析法⑵选择对各种常见程序语言都用的语法结构, 如赋值语句(尤指表达式)作为分析对象, 并且与所选语法分析方法要比较贴切。
⑶实习时间为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三、实验主要代码# define MAX 100char *SR;//输入串char SY[MAX];//移近或规约后剩余串char S[MAX];//堆栈char grammer[10][30];//保存输入的语法规则char chanshengshi[20][10];char feizhongjie[10];//存放非终结符char zhongjie[15];//存放终结符int numf=0;//非终结符个数int num=0;//终结符个数int M=0;//转换后产生式个数char Relation[6][6];//存放优先关系int FIRSTVT[3][6];//存放firstvt集int LASTVT[3][6];//存放lastvt集int type(char s)//在终结符串里查找字符a若a在其中返回下标, 否则返回-1{int len=strlen(zhongjie);int tp=-1;for(int i=0;i<len;i++){if(s==zhongjie[i]){ tp=i; break; }}return tp;}int type_fei(char s){int len=strlen(feizhongjie);int tp=-1;for(int i=0;i<len;i++){ if(s==feizhongjie[i]){ tp=i; break; }}return tp;}void transproduct(int n)//原始产生式处理{int x=0,y=0;for(int i=0;i<n;i++){for(int j=0;grammer[i][j]!='\0';j++){if(grammer[i][0]<'A'||grammer[i][0]>'Z'){ cout<<"该文法不是算符文发!"<<endl; return; }else{if(type_fei(grammer[i][0])<0)feizhongjie[numf++]=grammer[i][0];//获取非终结符符号}if(grammer[i][j]>='A'&&grammer[i][j]<='Z'){if(grammer[i][j+1]>='A'&&grammer[i][j+1]<='Z'){ cout<<"该文法不是算符文发!"<<endl; return; }}}}for(i=0;i<n;i++){for(int j=0;grammer[i][j]!='\0';j++){if((grammer[i][j]>'Z'||grammer[i][j]<'A')&&grammer[i][j]!='-'&&grammer[i][j]!='>'&&grammer[i][j]!='|'){ if(type(grammer[i][j])<0) zhongjie[num++]=grammer[i][j];//获取终结符符号} }} zhongjie[num]='#';zhongjie[num+1]='\0'; x=1;for(i=0;i<n;i++)//转换产生式从第二行开始存{chanshengshi[x][y]=grammer[i][0]; y++;for(int j=1;grammer[i][j]!='\0';j++){if(grammer[i][j]=='|'){ chanshengshi[x][y]='\0'; x++; y=0; chanshengshi[x][y]=grammer[i][0]; y++;chanshengshi[x][y++]='-'; chanshengshi[x][y++]='>';}else{ chanshengshi[x][y]=grammer[i][j]; y++; }}chanshengshi[x][y]='\0'; x++; y=0;}chanshengshi[0][0]=feizhongjie[0];//将开始符号以#_#形式存入第一行产生式数组, 以便优先关系构造时使用chanshengshi[0][1]='-'; c hanshengshi[0][2]='>'; chanshengshi[0][3]='#';chanshengshi[0][4]=feizhongjie[0]; chanshengshi[0][5]='#'; chanshengshi[0][6]='\0';M=x; cout<<"转换后产生式如下: "<<endl;for(int j=0;j<x;j++){ cout<<chanshengshi[j]<<endl; } cout<<"产生式包含的终结符有: ";for(i=0;i<=num;i++){ cout<<zhongjie[i]<<" "; } cout<<endl; cout<<"产生式包含的非终结符有: ";for(i=0;i<numf;i++){ cout<<feizhongjie[i]<<" "; } cout<<endl;}void fristvt()//计算firstvt集并填入FIRSTVT中{int r1,x,y;for(int i=0;i<numf;i++){ for(int j=0;j<num;j++) FIRSTVT[i][j]=0; }for(i=1;i<=M;i++){ r1=type_fei(chanshengshi[i][0]); x=type(chanshengshi[i][3]); y=type(chanshengshi[i][4]);if(x>=0){ FIRSTVT[r1][x]=1;}else{ if(y>=0) FIRSTVT[r1][y]=1; }}for(i=M;i>=1;i--){int y=type(chanshengshi[i][3]);if(y<0){ int m=type_fei(chanshengshi[i][0]); int m1=type_fei(chanshengshi[i][3]);if(m!=m1){ for(int t=0;t<num;t++) if(FIRSTVT[m1][t]!=0){ FIRSTVT[m][t]=FIRSTVT[m1][t]; }}}}cout<<"非终结符的firstvt集: "<<endl;for(i=0;i<numf;i++){ cout<<feizhongjie[i]<<" ";for(int j=0;j<num;j++){ if(FIRSTVT[i][j]!=0){ cout<<zhongjie[j]<<" "; }} cout<<endl;}}void lastvt()//求非终结符的lastvt集{int d=0, r1,x,y;for(int i=0;i<numf;i++){ for(int j=0;j<num;j++) LASTVT[i][j]=0; }for(i=1;i<=M;i++){ r1=type_fei(chanshengshi[i][0]);//判断是否为非终结符for(int cl=0;chanshengshi[i][cl]!='\0';cl++){ d=cl; }x=type(chanshengshi[i][d]); y=type(chanshengshi[i][d-1]);if(x>=0){ LASTVT[r1][x]=1; }else{ if(y>=0) LASTVT[r1][y]=1; }}for(i=M;i>=1;i--){int y=type(chanshengshi[i][3]);if(y<0){ int m=type_fei(chanshengshi[i][0]); int m1=type_fei(chanshengshi[i][3]);if(m!=m1){ for(int t=0;t<num;t++)if(LASTVT[m1][t]!=0){ LASTVT[m][t]=LASTVT[m1][t]; }}}} cout<<"非终结符的lastvt集: "<<endl;for(i=0;i<numf;i++){ cout<<feizhongjie[i]<<" ";for(int j=0;j<num;j++){ if(LASTVT[i][j]!=0){ cout<<zhongjie[j]<<" "; }} cout<<endl;}}void creatRelation()///创建优先关系表{ int a=strlen(feizhongjie),b=strlen(zhongjie),c=strlen(*chanshengshi),x,x1,y,y1,f;for(int i=0;i<=c;i++){ int j=strlen(chanshengshi[i]);for(int v=3;v<j;v++){ x=type(chanshengshi[i][v]); x1=type_fei(chanshengshi[i][v]); y=type(chanshengshi[i][v+1]);y1=type_fei(chanshengshi[i][v+1]); f=type(chanshengshi[i][v+2]);if((x>=0)&&(y>=0)){ Relation[x][y]='='; }if((v<=(j-2))&&x>=0&&f>=0&&y<0){ Relation[x][f]='=';}if(x>=0&&y<0){ for(int h=0;h<b;h++)if(FIRSTVT[y1][h]==1) { Relation[x][h]='<'; }}if(x<0&&y>=0){ for(int g=0;g<b;g++){ if(LASTVT[x1][g]==1) { Relation[g][y]='>'; }}}}}}char charcomplete(char a,char b)//优先关系比较, 返回优先关系, 若无返回${char ret='$';int x=type(a),y=type(b); if(x>=0&&y>=0) ret=Relation[x][y]; return ret;}void deelSY()//剩余串向前移一位{ int i,j; i=strlen(SY);for(j=0;j<i;j++){ SY[j]=SY[j+1]; } SY[i-1]='\0';}void main(){ int numP=0; cout<<"请输入产生式规则数: "; cin>>numP; cout<<"请输入产生式: "<<endl;for(int i=0;i<numP;i++){ cin>>grammer[i]; } transproduct(numP); fristvt(); lastvt(); creatRelation();cout<<"产生式的终结符对应的优先关系如下: "<<endl;printRelent();//输出优先关系; char str[20];cout<<" 请输入原文件名(包括后缀名): ";while(true){ cin>>str;if((fp=fopen(str,"r"))==NULL; cout<<"输入错误, 请检查文件名"<<endl; else break;}fseek(fp,0,SEEK_END); int n=ftell(fp),p=0; char ch; SR=new char [n];fseek(fp,0,SEEK_SET); while(ch!=EOF){ ch=fgetc(fp); SR[p]=ch; SY[p]=ch; p++;}char a,Q,N,B; int step=0;cout<<"步骤"<<"\t"<<"符号栈"<<"\t\t"<<"输入串"<<"\t\t\t"<<"动作"<<endl;int k=1,j=0,m=1,R,r=strlen(*chanshengshi); S[k]='#'; a=SR[k]; B=charcomplete(S[k],a);deelSY(); cout<<step<<"\t"<<S[k]<<"\t\t"<<SY<<"\t\t"<<"预备"<<endl;do{a=SR[m]; m++; if(type(a)>=0) j=k; else j=k-1; B=charcomplete(S[j],a);while(B=='>'){ do{ Q=S[j]; if(type(S[j-1])>=0) j--; else j=j-2;B=charcomplete(S[j],Q);}while(B!='<');for(int w=j+1;w<=k;w++) //将S[j+1]。
算符优先实验报告
算符优先实验报告算符优先实验报告引言算符优先是一种用于描述和分析算术表达式的语法分析方法。
在本次实验中,我们将通过编写一个算符优先分析器来深入理解算符优先算法的原理和应用。
实验目的1. 了解算符优先算法的基本原理和概念;2. 掌握算符优先算法的具体实现方法;3. 实现一个简单的算符优先分析器,用于分析和判断输入的算术表达式是否符合文法规则。
实验过程1. 算符优先的基本原理算符优先算法是一种自底向上的语法分析方法,用于判断算术表达式中运算符的优先级关系。
它通过构建一个算符优先关系表来实现对表达式的分析和判断。
2. 算符优先的概念和定义算符优先表是一个二维表格,行和列分别表示算术表达式中的运算符。
表格中的每个元素表示两个运算符之间的优先关系,可以是大于、小于或等于。
根据这个表格,我们可以判断两个相邻的运算符之间的优先级关系。
3. 算符优先分析器的实现为了实现一个算符优先分析器,我们首先需要构建算符优先表。
算符优先表的构建需要根据文法规则和运算符的优先级来确定。
在本次实验中,我们假设算术表达式中只包含加法和乘法运算符,并且加法运算符的优先级高于乘法运算符。
4. 算符优先分析的过程算符优先分析的过程可以分为两个步骤:扫描和规约。
在扫描过程中,我们从左到右扫描输入的算术表达式,并将扫描到的运算符和操作数依次入栈。
在规约过程中,我们根据算符优先表中的优先关系,将栈中的符号进行规约,直到最终得到一个唯一的非终结符号。
实验结果与分析通过实验,我们成功实现了一个简单的算符优先分析器,并对不同的算术表达式进行了分析和判断。
实验结果表明,算符优先分析器能够准确地判断算术表达式的语法正确性,并且能够正确地处理运算符的优先级关系。
结论算符优先算法是一种常用的语法分析方法,能够有效地判断算术表达式的语法正确性。
通过本次实验,我们深入理解了算符优先算法的原理和应用,并成功实现了一个简单的算符优先分析器。
这对我们进一步学习和应用语法分析方法具有重要的意义。
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
+
-
*
/
(
)
#
+
>
>
<
<
<
>
>
-
>
>
<
<
<
>
>
*
>
>
>
>
<
>
>
/
>
>
>>
(
<
<
<
<
<
=
)
>
>
>
>
简单优先和算符优先分析方法
简单优先和算符优先分析方法简单优先分析(Simple Precedence Parsing)和算符优先分析(Operator Precedence Parsing)是两种常用的自底向上的语法分析方法。
它们是基于符号优先级的理念,通过比较符号之间的优先级关系,来进行语法分析。
1.简单优先分析简单优先分析是一种自底向上的语法分析方法,它利用一个优先级表来确定符号之间的优先关系。
简单优先分析的算法如下:(1)将输入串和符号栈初始化为空。
(2)从输入串中读入第一个输入符号a。
(3)将a与栈顶的符号进行比较:a.如果a的优先级大于栈顶符号的优先级,将a推入符号栈,并读入下一个输入符号。
b.如果a的优先级小于栈顶符号的优先级,将栈中的符号做规约操作,直到栈顶的符号优先级不小于a。
然后,将a推入符号栈。
c.如果a和栈顶符号优先级相等,栈顶的符号出栈,并将a推入符号栈。
(4)重复步骤(3)直到输入串为空。
(5)如果符号栈中只有一个符号且为文法的开始符号,则分析成功。
简单优先分析的优先级表一般由语法规则和符号之间的优先关系组成。
我们可以通过构造优先级关系表来实现简单优先分析。
2.算符优先分析算符优先分析是一种自底向上的语法分析方法,它也是基于符号优先级的理念,但是相对于简单优先分析,算符优先分析更加灵活,并且允许处理左递归的文法。
算符优先分析的算法如下:(1)将输入串和符号栈初始化为空。
(2)从输入串中读入第一个输入符号a。
(3)将a与栈顶的符号进行比较:a.如果a的优先级大于栈顶符号的优先级,将a推入符号栈,并读入下一个输入符号。
b.如果a的优先级小于栈顶符号的优先级,将栈中的符号做规约操作,直到栈顶的符号优先级不小于a。
然后,将a推入符号栈。
c.如果a和栈顶符号优先级相等,根据符号栈中符号的类型执行相应的操作(如归约、移进等)。
(4)重复步骤(3)直到输入串为空。
(5)如果符号栈中只有一个符号且为文法的开始符号,则分析成功。
编译原理算符优先算法语法分析实验报告
编译原理算符优先算法语法分析实验报告实验报告:算符优先算法的语法分析一、实验目的本次实验旨在通过算符优先算法对给定的文法进行语法分析,实现对给定输入串的分析过程。
通过本次实验,我们能够了解算符优先算法的原理和实现方式,提升对编译原理的理解和应用能力。
二、实验内容1.完成对给定文法的定义和构造2.构造算符优先表3.实现算符优先分析程序三、实验原理算符优先算法是一种自底向上的语法分析方法,通过构造算符优先表来辅助分析过程。
算符优先表主要由终结符、非终结符和算符优先关系组成,其中算符优先关系用1表示优先关系,用2表示不优先关系,用0表示无关系。
算符优先分析程序的基本思路是:根据算符优先关系,依次将输入串的符号压栈,同时根据优先关系对栈内符号进行规约操作,最终判断输入串是否属于给定文法。
四、实验步骤1.定义和构造文法在本次实验中,我们假设给定文法如下:1)E->E+T,T2)T->T*F,F3)F->(E),i2.构造算符优先表根据给定文法,构造算符优先表如下:+*()i#+212112*222112(111012222122i222222#1112203.实现算符优先分析程序我们可以用C语言编写算符优先分析程序,以下是程序的基本框架:```c#include <stdio.h>//判断是否为终结符int isTerminal(char c)//判断条件//匹配符号int match(char stack, char input)//根据算符优先关系表进行匹配//算符优先分析程序void operatorPrecedence(char inputString[]) //定义栈char stack[MAX_SIZE];//初始化栈//将#和起始符号入栈//读入输入串//初始化索引指针//循环分析输入串while (index <= inputLength)//判断栈顶和输入符号的优先关系if (match(stack[top], inputString[index])) //栈顶符号规约} else//符号入栈}//计算新的栈顶}//判断是否成功分析if (stack[top] == '#' && inputString[index] == '#')printf("输入串符合给定文法!\n");} elseprintf("输入串不符合给定文法!\n");}```五、实验结果经过实验,我们成功实现了算符优先算法的语法分析。
编译原理算符优先算法语法分析实验报告
数学与计算机学院编译原理实验报告年级专业学号姓名成绩实验题目算符优先分析法分析器的设计实验日期一、实验目的:设计一个算符优先分析器,理解优先分析方法的原理。
二、实验要求:设计一个算符优先分析器三、实验内容:使用算符优先分析算法分析下面的文法:E’→#E#E →E+T | TT →T*F | FF →P^F | PP →(E) | i其中i可以看作是一个终结符,无需作词法分析。
具体要求如下:1、如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况;2、如果输入符号串不是正确句子,则指示出错位置。
四、实验结果及主要代码:1.主要代码void operatorp(){char s[100];char a,Q;int k,j,i,l;string input,temp;cin>>input;cout<<"步骤"<<'\t'<<"栈"<<'\t'<<"优先关系"<<'\t'<<"当前符号"<<'\t'<<"剩余输入串"<<'\t'<<"移进或归约"<<endl;k=1;s[k]='#';i=1;do{a=input[0];temp="";for(l=1;l<();l++)temp+=input[l];input=temp;if(svt(s[k])) j=k;else j=k-1;while (search(s[j],a)=='>'){cout<<'('<<i<<')'<<'\t'; //步骤temp="";for(l=1;l<k+1;l++)temp+=s[l];cout<<temp<<'\t'; //栈cout<<'>'<<'\t'<<setw(10); //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串i++;for(;;){Q=s[j];if(svt(s[j-1])) j=j-1;else j=j-2;if(search(s[j],Q)=='<'){cout<<"归约"<<endl;//归约break;}}temp="";for(l=j+1;l<k+1;l++)temp+=s[l];for(l=0;l<6;l++)if(temp==key[l]){k=j+1;s[k]=v[l];break;}}cout<<'('<<i<<')'<<'\t'; //步骤temp="";for(l=1;l<k+1;l++)temp+=s[l];cout<<temp<<'\t'; //栈if(search(s[j],a)=='<'){cout<<'<'<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"移进"<<endl;i++;k=k+1;s[k]=a;} //移进else if(search(s[j],a)=='Y'){cout<<'='<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"接受"<<endl;i++;}else{cout<<''<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"出错"<<endl;exit(0);}//出错}while(a!='#');}2.实验结果。
5 语法分析(2)_ 算符优先分析法
F i
22
识别句型i+(i+i)*i得到的语法树 识别句型i+(i+i)*i得到的语法树
E Z F i ( F i + F E + ) F i T *
(a) 算符优先 分析技术得到 得到的语法树
Z
E T
+ T F
T * F i
F F i i
(b) 一般分析 技术得到得到 的语法树
( E
T
E +
) T F i
5.2.2 算符优先分析法概述
• 算符优先文法
– 算符优先分析是一种分析过程比较迅速的自底向上 的分析方法,特别有利于表达式的分析, 的分析方法,特别有利于表达式的分析,便于手工 实现。它不是一种严格的最左归约, 实现。它不是一种严格的最左归约,即不是一种规 范归约方法。在算符优先分析方法中, 范归约方法。在算符优先分析方法中,可归约串就 是最左素短语。 是最左素短语。 – 所谓算符优先就是借鉴了程序语言中,表达式运算 所谓算符优先就是借鉴了程序语言中, 的不同优先顺序,在算符, 的不同优先顺序,在算符,即非终结符之间定义某 种优先归约的关系,从而在句型中寻找可归约串。 种优先归约的关系,从而在句型中寻找可归约串。 由于非终结符关系的定义和普通算术表达式的算符 如加减乘除)运算的优先关系一致, (如加减乘除)运算的优先关系一致,所以得名算 符优先分析方法。 符优先分析方法。
自顶向下分析算法的基本思想为: 自顶向下分析算法的基本思想为: 若Z ⇒ S
G[Z] +
则 S ∈ L(G[Z])
否则 S ∉ L(G[Z])
存在主要问题: 存在主要问题: 左递归问题 回溯问题
主要方法: 主要方法: • 递归子程序法 • LL分析法 LL分析法
算符优先分析法详解
四川大学计算机学院 金军
12
2
优先表构造算法
FOR 每一条产生式P→X1X2…Xn FOR i:=1 TO n-1 DO BEGIN IF Xi 和 Xi+1 均为终结符 THEN 置 Xi=Xi+1 IF I<=n-2且Xi和Xi+2都为终结符,而Xi+1 为非终结符, THEN置Xi=Xi+2 IF Xi为终结符而Xi+1为非终结符 THEN FOR FISTVT(Xi+1)中的每个a DO 置 Xi< a IF Xi为非终结符而Xi+1为终结符THEN FOR LASTVT(Xi)中的每个a DO 置 Xi >a END
四川大学计算机学院 金军
1
算符优先文法
现在按照算符优先分析法的设计思路,构 造一种文法,通过它可以自动产生终结符 的优先关系表。
算符优先文法
一个文法,如果它的任何产生式的右部都 不含两个相继(并列)的非终结符,即不 含如下形式的产生式右部:
…QR…
则我们称该文法为算符文法。 在后面的定义中,a、b代表任意终结符; P、Q、R代表任意非终结符;‘…’代表有 终结符和非终结符组成的任意序列,包括 空字。
LASTVT(U)的构造:
若有产生式U → …a或U → …aV,则 a∈LASTVT(U); 若a∈LASTVT(V),且有产生式U → …V,则 a∈LASTVT(U)。
四川大学计算机学院 金军 9 四川大学计算机学院 金军 10
FIRSTVT构造算法
建立一个二维布尔数组F[P, a],使得F[P, a]为真的条件适当且仅当a∈FIRSTVT(P); 再用一个栈STACK,把所有初值为真的数 组元素F[P, a]的符号对(P, a)全都放到栈 中,对栈施加如下操作:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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");