程序功能描述
针对CP语言中简单算术表达式文法G[E]:
E→TE’
E’→ATE’|ε
T→FT’
T’→MFT’ |ε
F→(E) | i
A → + | -
M → * | /
打印出对应的FIRST、FOLLOW集,构造预测分析表,并编写LL(1)语法分析程序,并给出测试句子的分析过程。
能够根据表达式文法构造出fist集,follow集,和预测表。并且能够对输入的表达式给出分析过程,并且判断是否为LL语法。
主要数据结构描述
Firstbox、followbox字典:构建元素映射到多个元素(集合)的字典
ss栈:分析过程中的分析表
数组:存储y数据
设计方法
- LL:左扫描,左推导。
1.从文件或其他方式导入\储存文法(实质就是几行符号流) 并把其中的终结字符和非终结字符存在数组\列表里
2.把文法每行的“或”(|)切分成两个即A->B|C 切分为A->B和A->C - 求FIRST集的算法思想
若X->a…,则将终结符a加入FIRST(X)中;
若X->e ,则将终结符e加入FIRST(X)中(e表示空集);
若 X->BCD…E,则将First(B)所有元素(除了空集)加入 First(X),然后检测First(B),若First(B)中不存在空集, 即e,则停止,若存在则向B的后面查看,将First(C)中所有元素(除了空集)加入First(X),然后再检测First(C)中是否有e…直 到最后,若E之前的所有非终结符的First集中都含有e,则检测到E时,将First(E)也加入First(X),若First(E)中含有e,则将 e加入First(X)。 - 求FOLLOW集的算法思想
对于文法G中每个非终结符A构造FOLLOW(A)的办法是,连续使用下面的规则,直到每个FOLLOW不在增大为止.
(1) 对于文法的开始符号S,置#于FOLLOW(S)中;
(2) 若A->aBb是一个产生式,则把FIRST(b){ε}加至FOLLOW(B)中;
(3) 若A->aB是一个产生式,或A->aBb是一个产生式而b=>ε(即ε∈FIRST(b))则把FOLLOW(A)加至FOLLOW(B)中 - 生成预测分析表的算法思想
构造分析表M的算法是:
(1) 对文法G的每个产生式A->a执行第二步和第三步;
(2) 对每个终结符a∈FIRST(a),把A->a加至M[A,a]中;
(3) 若ε∈FIRST(a),则把任何b∈FOLLOW(A)把A->a加至M[A,b]中; - 对符号串的分析过程
预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号行事的,对于任何(X,a),总控程序
每次都执行下述三种可能的动作之一;
(1) 若X=a=‘符号’,则宣布分析成功,停止分析过程.
(2) 若X=a≠”$”,则把X从STACK栈顶逐出,让a指向下一个输入符号.
(3) 若X是一个非终结符,则查看分析表M,若M[A,a]中存放着关于X的一个产生式,那么,首先把X逐出STACK栈顶,然后
把产生式的右部符号串按反序一一推进STACK栈(若右部符号为ε,则意味着不推什么东西进栈).在把产生式的右部
函数定义
Fist(item)函数,在切分后的文法中 如果A->a…… (a为终结字符)则把a放入A的follow中 如果A->B ……(B为非终结) 则先递归求B的first,然后放入A的first。
def first(item):
if item[1] in vt:
firstbox[item[0]].add(item[1])
else:
for find in stack:
if find[0]==item[1]:
first(find)
firstbox[item[0]] = firstbox[item[1]]|firstbox[item[0]]
follow(vi_item)和函数。
存在 ……Ab(b为非终结),则把b放入A的follow ;存在AB(B为非终结),则把B的first放入A的follow;存在B=EAC,且C的first中含有‘ε’,则把B的follow放入A的follow;若A为某段的最后字符,则把‘$’放入A的follow;若B=……A,则把B的follow放入A的follow
def follow(vi_item):
for i in stack:
j=1
while j<len(i)-1:
if (i[j]==vi_item)&(i[j+1] in vt): # 存在 Ab 则把b放入
followbox[vi_item].add(i[j+1])
if (i[j]==vi_item)&(i[j+1] in vi): #存在AB 则把B的first放入
followbox[vi_item]=followbox[vi_item]|firstbox[i[j+1]]-{
'ε'}
if (i[j] in vi)&('ε' in firstbox[i[j+1]]): #存在 A=EBC 且C的first中有空
followbox[i[j]]=followbox[i[0]]|followbox[i[j]]
j+=1
if i[len(i)-1] ==vi_item:#为某行最后一个字符
followbox[vi_item].add('$')
if (i[0]==vi_item)&(i[len(i)-1] in vi):#A=....B
followbox[i[len(i)-1]]=followbox[vi_item