LL(1)文法满足下面的条件:
- 文法不含左递归
- 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。即,若A→α1|α2|...|αn,则FIRST(αi)∩FIRST(αj)=∅ ,其中(i≠j)
- 对文法中的每个非终结符A,若它存在某个侯选首符集包含ε,则FIRST(A)∩FOLLOW(A)=∅
文法通过左递归消除、消除回溯、提取左公共因子可以满足LL(1)的条件,成为LL(1)文法。
预测分析程序实现步骤:
- 构造文法非终结符的FIRST集
- 构造文法非终结符的FOLLOW集
- 构造文法的预测分析表
- 构造控制程序
1、构造文法非终结符的FIRST集
假设A有n个侯选α1,α2,...,αn,即A→α1|α2|...|αn。侯选式α的FIRST集形式化描述:FIRST(α)={a | α
讯享网a...,a∈
},若α
ε,则ε∈FIRST(α).。那么FIRST(A) = FIRST(α1)∪FIRST(α2)∪...∪FIRST(αn)
实现:
# 求FIRST(α) 用'@'表示'ε' def formula_first(self,str): first_keys = self.firstSET.keys() str_len = len(str) if str_len == 1: if str in self.terSymbol or str == '@':return [str] elif str in first_keys: return self.followSET.get(str) else: return [] i = 0 first_set = [] while i < str_len - 1: if str[i] in self.terSymbol: if str[i] not in first_set: first_set.append(str[i]) return first_set if str[i+1] == "'": if str[i:i+2] in first_keys: str_firstSet = self.firstSET.get(str[i:i+2]) for terSym in str_firstSet: if terSym not in first_set: first_set.append(terSym) if '@' not in str_firstSet: return first_set else: for index in range(len(first_set)): if first_set[index] == '@': del first_set[index] break i += 2 else: return first_set else: if str[i] in first_keys: str_firstSet = self.firstSET.get(str[i]) for terSym in str_firstSet: if terSym not in first_set: first_set.append(terSym) if '@' not in str_firstSet: return first_set else: for index in range(len(first_set)): if first_set[index] == '@': del first_set[index] break i += 1 else: return first_set # 边界处理 if i == str_len: # 侯选式最后一个字符是"p'" first_set.append('@') else: # 侯选式最后一个字符是'p' if str[i] in first_keys: str_firstSet = self.firstSET.get(str[i]) for terSym in str_firstSet: if terSym not in first_set: first_set.append(terSym) if '@' not in str_firstSet: return first_set else: first_set.append('@') return first_set def first_set(self): #终结符的first集 for terSym in self.terSymbol: self.firstSET.update({terSym:[terSym]}) #非终结符的first集 change_flag = True while change_flag: change_flag = False for formula in self.formulaSet: left = "" right = "" if formula[1] == "'": left = formula[0:2] right = formula[4:] else: left = formula[0] right = formula[3:] firstSet = [] for candidate in right.split("|"): candidate_firstSet = self.formula_first(candidate) for terminate in candidate_firstSet: if terminate not in firstSet: firstSet.append(terminate) keys = self.firstSET.keys() if left in keys: oldSet = self.firstSET.get(left) for symbol in firstSet: if symbol not in oldSet: change_flag = True oldSet.append(symbol) self.firstSET.update({left: oldSet}) else: change_flag = True self.firstSET.update({left: firstSet})
讯享网
2、构造文法非终结符的FOLLOW集
假设S是文法G的开始符号,对于G的非终结符A,定义FOLLOW(A) = {a | S
...Aa...,a∈
}。特别的,若S
...A,则规定'#'∈FOLLOW(A)。
构造规则:
- 对于文法的开始符号S,置#于FOLLOW(S)中;
- 若A→αBβ是一个产生式,则把FIRST(β)\{ε}加入FOLLOW(B)中;
- 若A→αB是一个产生式,或若A→αBβ是一个产生式且β
ε(即ε∈FIRST(β)),则把FOLLOW(A)加入FOLLOW(B)中。
实现:
讯享网 def update_follow(self,A,B,β): # A->αBβ update_flag = False keys = self.followSET.keys() follow_B = [] first_β = self.formula_first(β) for terSym in first_β: if terSym != '@' and terSym not in follow_B: follow_B.append(terSym) if '@' in first_β: if A in keys: follow_A = self.followSET.get(A) for terSym in follow_A: if terSym not in follow_B: follow_B.append(terSym) if B in keys: old_follow_B = self.followSET.get(B) for terSym in follow_B: if terSym not in old_follow_B: old_follow_B.append(terSym) update_flag = True self.followSET.update({B:old_follow_B}) else: update_flag = True self.followSET.update({B: follow_B}) return update_flag def follow_set(self): self.followSET.update({self.startSymbol:['#']}) # 置'#'于开始符合follow集 change_flag = True while change_flag: change_flag = False for formula in self.formulaSet: left = "" right = "" if formula[1] == "'": left = formula[0:2] right = formula[4:] else: left = formula[0] right = formula[3:] for candidate in right.split("|"): if candidate == '@': continue candidate_len = len(candidate) i = 0 while i < candidate_len: if candidate[i] in self.terSymbol: i += 1 continue if i < candidate_len-1: if candidate[i+1] == "'": change_flag = self.update_follow(left,candidate[i:i+2],candidate[i+2:]) i += 2 else: change_flag = self.update_follow(left,candidate[i],candidate[i+1:]) i += 1 else: change_flag = self.update_follow(left,candidate[i],"") i += 1
3、构造预测分析表M
算法:

- 对于文法G的每个产生式A→α,执行第2和3;
- 对于每个终结符a∈FIRST(α),把A→α加入M[A,a]中;
- 若ε∈FIRST(α),对每个终结符b∈FOLLOW(A)把A→α加入M[A,b]中;
- 把所有无定义的M[A,a]标上出错标志。
实现:
def update_table(self,left,char,candidate): if char == '@': return Mi = self.M.get(left) # 获取表中的一行 if Mi: Mij = Mi.get(char) # 获取表中的一个单元 if Mij: if candidate not in Mij: Mij.append(candidate) else: Mij = [candidate] Mi.update({char: Mij}) else: Mi = {char: [candidate]} self.M.update({left: Mi}) def prediction_analysis_table(self): for formula in self.formulaSet: left = "" right = "" if formula[1] == "'": left = formula[0:2] right = formula[4:] else: left = formula[0] right = formula[3:] for candidate in right.split("|"): first_α = self.formula_first(candidate) for a in first_α: self.update_table(left,a,candidate) if '@' in first_α: for b in self.followSET.get(left): self.update_table(left, b, candidate)
4、控制程序
预测分析模型:

总控程序总是按照S栈顶符号X和当前输入符号a的情况执行下面的动作:
- 若X = a = '#',则表示分析成功,停止分析过程。
- 若X = a ≠ '#',则把X从栈S中弹出,输入符号指向a的下一个输入符号。
- 若X是一个非终结符,查看预测分析表M。若M[X,a]存放X的一个产生式,那么把X从栈S中弹出,然后将产生式→的右部符号串逆序入栈S(若右部符号是ε,表示没有元素入栈)。若M[X,a]存放出错标志,提示错误,停止分析过程。
实现:
讯享网def control_program(S,str,pa): S.push('#') S.push(pa.startSymbol) str_len = len(str) i = 0 while i < str_len: X = S.peek() if X in pa.terSymbol: if X == str[i]: # X==str[i] 不等于‘#’ S.pop() i += 1 else: print("error") # X不等于str[i] break elif X == '#': if X == str[i]: print("success") break else: print("error") break else: MI = pa.M.get(X) if MI is None: print("error") break else: candidate = MI.get(str[i]) if candidate is not None: S.pop() formula = candidate[0] if formula != '@': index = len(formula) - 1 # 逆序入栈 while index >= 0: if formula[index] == "'": S.push(formula[index - 1:index + 1]) index -= 2 else: S.push(formula[index]) index -= 1 else: print("error") break
测试
测试数据(输入串、文法开始符号、文法终结符、文法非终结符、文法产生式):
i*i+i# E i + * ( ) E E' T T' F E->TE' E'->+TE'|@ T->FT' T'->*FT'|@ F->(E)|i
测试结果:
success
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/36059.html