一、实验目的
了解预测分析器的基本构成,掌握自顶向下的预测语法分析程序的手工构造方法。
二、实验内容
已知文法G[S]:
S->AT
A->BU
T->+AT|$
U->*BU|$
B->(S)|m
其中,$表示空串。
对该文法构造预测分析表,并手工构造预测分析程序,对输入串m+m*m#进行语法分析,并根据栈的变化状态输出分析过程。
三、实验要求:
1、判断上述文法G[S]是否LL(1)文法,若不是,将其转变为LL(1)文法;
2、对转变后的LL(1)文法建立预测分析表;
3、根据清华大学出版、吕映之等编著的《编译原理》教材教材第五章Page 88的图5.11手工构造预测分析程序;
4、用预测分析程序对键盘输入串m+m*m#进行语法分析,并根据栈的变化状态输出给定串的具体分析过程。
四、Python代码实现
# 分析栈、剩余输入串栈
class Stack(): # 定义类
def __init__(self): # 产生一个空的容器
self.__list = []
def size(self): # 返回栈中元素个数
return len(self.__list)
def push(self, item): # 入栈
self.__list.append(item)
def push_list(self, list): # 末尾添加多个元素
for i in range(len(list)):
self.push(list[i])
def pop(self): # 出栈
return self.__list.pop()
def peek(self): # 返回栈顶元素
return self.__list[-1]
def is_empty(self): # 判断是否已为空
return not self.__list
def pos_output(self): # 正序排列
string = ""
for i in range(self.size()):
string += self.__list[i]
return string
def res_output(self): # 逆序排列
string = ""
for i in range(self.size()-1, -1, -1):
string += self.__list[i]
return string
# 预测分析表
preAnalysisTable = {
'S': {'+': None, '*': None, '(': "AT", ')': None, 'm': "AT", '#': None},
'A': {'+': None, '*': None, '(': "BU", ')': None, 'm': "BU", '#': None},
'T': {'+': "+AT", '*': None, '(': None, ')': "$", 'm': None, '#': "$"},
'U': {'+': "$", '*': "*BU", '(': None, ')': "$", 'm': None, '#': "$"},
'B': {'+': None, '*': None, '(': "(S)", ')': None, 'm': "m", '#': None},
}
# 非终止符
VN = ['S', 'A', 'T', 'U', 'B']
# 终止符
VT = ['+', '*', '(', ')', 'm', '#']
# 记录分析结果
analyzeResult = False
# 记录分析步骤
analyzeStep = 0
# 字符串翻转
def reverseString(string):
return string[::-1]
# 检查输入串
def checkString(string):
stringLegal = True
if (len(string) == 0):
print("输入串不能为空!")
stringLegal = False
if (string[-1] != "#"):
print("输入串缺少结束符'#'!")
stringLegal = False
for i in range(len(string)):
if(string[i] not in VT and string[i] not in VN):
print("输入出错:存在既不是终结符也不是非终结符的字符!")
stringLegal = False
break
return stringLegal
# 初始化两个栈
def initStack(string):
# 分析栈,入栈#S
initString = "S#"
analysisStack = Stack()
analysisStack.push_list(reverseString(initString))
# 当前输入串入栈
currentStack = Stack()
currentStack.push_list(reverseString(string))
# 调用分析函数
toAnalyze(analysisStack, currentStack)
# 输出分析过程
def processOutput(analyzeStep, analysisStack, currentStack, process):
print("|{:^5}|{:^15}|{:^15}|{:^20}|".format(analyzeStep, analysisStack.pos_output(), currentStack.res_output(), process))
# 根据栈中内容进行分析
def toAnalyze(analysisStack, currentStack):
global analyzeResult
global analyzeStep
analyzeStep += 1
analysisStack_top = analysisStack.peek()
currentStack_top = currentStack.peek()
if(analysisStack_top=='#' and currentStack_top=='#' and analysisStack.size()==1 and currentStack.size()==1):
processOutput(analyzeStep, analysisStack, currentStack, "接受")
analyzeResult = True
return
else:
if(analysisStack_top in VN):
targetPos = preAnalysisTable[analysisStack_top][currentStack_top]
if(targetPos == None):
# processOutput(analyzeStep, analysisStack, currentStack, analysisStack_top + '->' + targetPos)
print("分析出错:"+analysisStack_top+"->"+currentStack_top+"推导为None!")
analyzeResult = False
return
elif(targetPos == '$'):
processOutput(analyzeStep, analysisStack, currentStack, analysisStack_top + '->' + '$')
analysisStack.pop()
toAnalyze(analysisStack, currentStack)
else:
processOutput(analyzeStep, analysisStack, currentStack, analysisStack_top + '->' + targetPos)
analysisStack.pop()
analysisStack.push_list(reverseString(targetPos))
toAnalyze(analysisStack, currentStack)
elif(analysisStack_top in VT):
if(analysisStack_top == currentStack_top):
processOutput(analyzeStep, analysisStack, currentStack, analysisStack_top + "匹配")
analysisStack.pop()
currentStack.pop()
toAnalyze(analysisStack, currentStack)
else:
print("分析出错:"+analysisStack_top+"->"+currentStack_top)
analyzeResult = False
return
if __name__ == '__main__':
print("请输入待分析的字符串:")
string = input()
# 滤空格
string = string.replace(" ", "")
if(checkString(string)):
print("|{:^4}|{:^13}|{:^12}|{:^15}|".format('步骤', '分析栈', '当前输入串', '推导所用产生式或匹配情况'))
initStack(string)
if(analyzeResult):
print("由以上分析可知,该串是文法的合法句子。\n")
else:
print("由以上分析可知,该串不是文法的合法句子。\n")