1、7) 对任意句子使用当前文法归约,打印分析过程。 4、采用的数据结构 两个结构体:/分析各非终结符的FIRSTVT集和LASTVT集时的栈元素typedef struct char nonterm; /非终结符 char term; /终结符StackElement;/存放(A,a)的栈的初始化 StackElement *top; /栈顶 StackElement *bottom; /栈底 int stacksize; /个数stack;5、算法描述 算符优先分析法的具体过程如下:1) 按照实现定义的文件路径,使用ReadFile()函数中,将需要分析的文法通过输入流文件打开函数open()
2、复制到senrowcol中。2) 利用FirstVt( )构造产生式senrowcol的非终结符的FirstVt表。先找出形如A-a(a为第一个终结符)的产生式,把(A,a)压入Operator栈中。从Operator栈顶抛出项(A,a),填入first表相应位置。在找出形如B-A的产生式,把(B,a)压入Operator栈中。循环直到Operator栈为空,此时FirstVt表构造完毕。3) 将产生式右部翻转,调用FirstVt函数求出LastVt表。4) 调用OpPriotable()构造算符优先关系表opTable。先把产生式中所有终结符填入opTable表第一行和第一列,然后利用产生式
3、和FirstVt表LastVt表分别找出满足=关系、关系的算符填表。若相应位已有关系,说明两个终结符之间至少有两种优先关系,该文法不是算符优先文法。5) 调用InputAnalyse()对输入句子进行分析。初始化分析栈S,依次判断当前输入符a和分析栈中离栈顶最近的终结符S j 的关系,若S j a ,则a移近,若S j a,将S j -1到栈顶S k 规约,若S j = a ,如果S j =#,则接受,如果S j !=#,则移进。直到接受或者出错,算符优先分析结束。6、运行结果1. 非算符优先文法的文法分析结果:2. 是算符优先文法的文法分析结果:成功归约句子:归约句子失败:7、调试情况如下所
4、示为测试的文法:其中文法不是算符优先文法,文法是算符优先文法。8、设计技巧及体会将算符优先法的手工分析过程用程序的方式写出来,实现了算符优先法的判断过程,很容易理解。通过本次实验,我对算符优先法的分析过程更加熟练了,同时让我对本章内容有了更深入的理解。9、源程序清单(电子版)#include#include using namespace std;#define row 20#define col 20#define SIZE 20/两个重要结构体的定义/FIRSTVT表或LASTVT表中一个表项(A,a)结构体的初始化typedef struct/读文件函数int ReadFile(char
5、 sencol) ifstream fin; int i = 0; fin.open(e:/in2.txt,ios:in); cout 文法的产生式为: sen0; for (i = 1; !fin.eof(); i+) fin seni; cout seni = S.stacksize)栈已满,无法插入! else S.top-nonterm = e.nonterm;term = e.term; S.top+;/弹出栈顶(A,a)元素StackElement Pop(stack & StackElement e; e.nonterm = 0; e.term = if (S.top = S.b
6、ottom)栈为空,无法进行删除操作! S.top-; e.nonterm = S.top-nonterm; e.term = S.top-term; return e;/终结符与非终结符的判断函数(布尔类型)bool TerminalJud(char c) if (c = A & c Z) return false; /非终结符返回false return true; /终结符返回true/判断非终结符在first表中是否已存在bool ItemJud(char firstcol, int first_len, char C) for (int i = 0; i first_len; if
7、(firsti0 = C) return true; /如果first表中已存在此非终结符c,则返回true/FIRSTVT表和LASTVT表中表项的初始化void ItemInit(char sencol, char firstcol, char lastcol, int sen_len, int &first_len) int i; first_len = 1; /是当前first和last表的长度 / 初始化表 first00 = sen00; last00 = sen00;sen_len; if (TerminalJud(seni0) = false & ItemJud(first,
8、first_len, seni0) = false) firstfirst_len0=seni0; lastfirst_len0=seni0; first_len+; /构造FIRSTVT集void FirstVt(char sencol, char firstcol, int sen_len, int first_len) /sen_len是产生式的个数 StackElement DFS, recordSIZE; stack Operator; /创建存放(A,a)的栈 int i,j,r=0; InitStack(Operator); /第一次扫描,将能直接得出的first(A,a)放进栈
9、中 for (i = 0; sen_len; for (j = 3; senij ! j+) /候选式开始处 if (TerminalJud(senij) = true) /遇到的第一个终结符压入 int exist = 0; DFS.nonterm = seni0; DFS.term = senij; for (int i1 = 0; r; i+) /当前(A,a)是否已在栈中 if (recordi1.nonterm = seni0 & recordi1.term = senij) exist = 1; break; /如果不在则压入栈中 recordr.nonterm=seni0; re
10、cordr.term=senij; if (exist = 0) Insert(Operator,DFS); recordr.nonterm = seni0; recordr.term = senij; r+; break; /第二次扫描,考虑候选式第一个符号为非终结符的情况 int locationcol; /记录first表中放入终结符的位置first_len; i+) locationi = 1; while (!ifEmpty(Operator) int exist = 0; /标志位,记录即将入栈的元素是否已经存在 StackElement IDElement,DElement; D
11、Element=Pop(Operator); /弹出栈顶元素 for (i = 0; if (firsti0 = DElement.nonterm) int n = locationi; firstin = DElement.term; /将终结符填入相应的first表中 locationi+; for (j = 0; j j+) if (senj3 = DElement.nonterm) /找出能推出当前非终结符的产生式的左部 IDElement.nonterm = senj0; IDElement.term = DElement.term; /判断将要放进栈里的元素曾经是否出现过,若没有,
12、才压入栈 for (int r0 = 0; r0 r0+) /r记录record数组中的元素个数 if (recordr0.nonterm = IDElement.nonterm & recordr0.term = IDElement.term) /已存在在栈中 exist=1; if (exist = 0) /不存在则压入栈中 Insert(Operator,IDElement); recordr.nonterm = IDElement.nonterm; recordr.term = IDElement.term;/构造LASTVT集void LastVt(char sencol, char
13、 lastcol, int sen_len, int first_len) /first_len表示last 表的行数 int i, j, i1, j1; char c, recordrowcol = ; for(j = 0;j+) recordij = senij; j = j - 1; for (i1 = 3, j1 = j; i1 j1; i1+, j1-) /做翻转,就可以用求first的方法求last c = recordii1; recordii1 = recordij1; recordij1 = c; FirstVt(record, last, sen_len, first_le
14、n);/判断非终结符在term表中是否已存在bool TermTableJud(char termcol, int term_len, char C) for(int i = 0; term_len; if (termi = C) /如果first表中已存在此非终结符,则返回1/构造算符优先关系表bool OpPriotable(char sencol, char firstcol, char lastcol, char opTablecol, int sen_len, int first_len, int &opTable_len) int i, j, term_len=0; int i2,
15、 i3, opr, opc; char c1, c2, c3; char termSIZE= i+) /一维数组term记录关系表中存在的所有终结符= if (TerminalJud(senij) = true) if (TermTableJud(term, term_len, senij) = false) /term_len记录term表的长度 termterm_len = senij; term_len+; /得到终结符表 /给优先关系表赋初值,都等于空 term_len + 1; j opTableij = /设置优先关系表的表头,即将所有终结符存储 opTablei0 = termi
16、 - 1; opTable0i = termi - 1; /找等于关系 /形如 #E# 的情况 for (j = 5;j+) if (TerminalJud(senij - 2) = true & TerminalJud(senij - 1) = false & TerminalJud(senij) = true) c1=senij-2; c2=senij; /在opTable表中找到该存入的行标opr for (opr = 1; opr opr+) if (opTableopr0 = c1) /在opTable表中找到该存入的列标opc for (opc = 1; opc opc+) if(
17、opTable0opc = c2) /若这两者优先级关系之前已定义了,则表示该文法非算符优先 if (opTableopropc !) cout 不是算符优先文法! return false; else opTableopropc = /形如 () 的情况 for (j = 4; if (TerminalJud(senij - 1) = true & c1 = senij - 1; c2 = senij; /在opTable表中找到该存入的列标j2 if (opTable0opc = c2) /找小于关系 /形如 aA 情况 if (TerminalJud(senij) = true & Te
18、rminalJud(senij+1) = false) c1 = senij; /c1记录终结符 c2 = senij+1; /c2记录非终结符 /找出非终结符在first表中的列标opc for (opc = 0; if (firstopc0 = c2) for (i2 = 1; firstopci2 ! i2+) c3 = firstopci2; for (i3 = 1; i3 i3+) if (opTable0i3 = c3) if (opTableopri3 ! cout return false; else opTableopri3 = break; /找大于关系 /形如Aa情况 if (TerminalJud(senij) = false & senij + 1 ! TerminalJud(senij + 1) = true) /c1记录非终结符 c2 = senij + 1; /c2记录终结符 /在opTable表中找到该存入的列标j1 if (opTable0opr = c2)
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1