1. 实验要求
(1)针对下列简单表达式文法G[E'],手工构造算符优先关系表。
E’→ #E#
E → E+T | T
T → T*F | F
F → P/F | P
P → (E) | i
(2)根据清华大学版《编译原理(第3版)》教材上算符优先分析算法思想及算法流程,构造算符优先语法分析程序。
(3)用该算符优先语法分析程序对任意给定的键盘输入串 i+i# 进行语法分析,并根据栈的变化状态输出给定串的具体分析过程。
2. 分析结果输出
3. Python代码实现
# 算符优先关系表表
OP_table = {
'+': {'+':'>', '*':'<', '/':'<', 'i':'<', '(':'<', ')':'>', '#':'>'},
'*': {'+':'>', '*':'>', '/':'<', 'i':'<', '(':'<', ')':'>', '#':'>'},
'/': {'+':'>', '*':'>', '/':'<', 'i':'<', '(':'<', ')':'>', '#':'>'},
'i': {'+':'>', '*':'>', '/':'>', 'i':None, '(':None, ')':'>', '#':'>'},
'(': {'+':'<', '*':'<', '/':'<', 'i':'<', '(':'<', ')':'=', '#':None},
')': {'+':'>', '*':'>', '/':'>', 'i':None, '(':None, ')':'>', '#':'>'},
'#': {'+':'<', '*':'<', '/':'<', 'i':'<', '(':'<', ')':None, '#':'='},
}
# 终止符
VT = ['+', '*', '/', 'i', '(', ')', '#']
# 句型
sentencePattern = ["N+N", "N*N", "N/N", "(N)", "i"]
# 记录分析结果
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):
print("输入出错:存在不是终结符的字符!")
stringLegal = False
break
return stringLegal
# 初始化两个栈
def initStack(string):
# 分析栈,入栈#
analysisStack = "#"
# 当前输入串入栈,即string逆序入栈
currentStack = reverseString(string)
# 调用分析函数
toAnalyze(analysisStack, currentStack)
# 寻找分析栈最顶终结符元素,返回该元素及其下标
def findVTele(string):
ele = '\0'
ele_index = 0
for i in range(len(string)):
if(string[i] in VT):
ele = string[i]
ele_index = i
return ele, ele_index
# 根据栈中内容进行分析
def toAnalyze(analysisStack, currentStack):
global analyzeResult
global analyzeStep
analyzeStep += 1
analysisStack_top, analysisStack_index = findVTele(analysisStack) # 分析栈最顶终结符元素及下标
currentStack_top = currentStack[-1] # 当前输入串栈顶
relation = OP_table[analysisStack_top][currentStack_top]
if(relation=='<'):
print("|{:^5}|{:^15}|{:^9}|{:^15}|{:^12}|".format(analyzeStep, analysisStack, relation,
reverseString(currentStack), '移进'))
analysisStack += currentStack_top
currentStack = currentStack[:-1]
toAnalyze(analysisStack, currentStack)
elif(relation=='>'):
print("|{:^5}|{:^15}|{:^9}|{:^15}|{:^12}|".format(analyzeStep, analysisStack, relation,
reverseString(currentStack), '归约'))
currenChar = analysisStack_top
string = ""
for i in range(len(analysisStack)-1, -1, -1):
if(analysisStack[i]>='A' and analysisStack[i]<='Z'):
string = analysisStack[i] + string
continue
elif(OP_table[analysisStack[i]][currenChar]=='<'):
break;
string = analysisStack[i] + string
currenChar = analysisStack[i]
if(string in sentencePattern):
analysisStack = analysisStack[0:i+1]
analysisStack += 'N'
toAnalyze(analysisStack, currentStack)
else:
print("归约出错!待归约串为:", string, "--->产生式右部无此句型!")
analyzeResult = False
return
elif(relation=='='):
if(analysisStack_top=='#' and currentStack_top=='#'):
print("|{:^5}|{:^15}|{:^9}|{:^15}|{:^12}|".format(analyzeStep, analysisStack, relation,
reverseString(currentStack), '接受'))
analyzeResult = True
return
else:
print("|{:^5}|{:^15}|{:^9}|{:^15}|{:^12}|".format(analyzeStep, analysisStack, relation,
reverseString(currentStack), '移进'))
analysisStack += currentStack_top
currentStack = currentStack[:-1]
toAnalyze(analysisStack, currentStack)
elif(relation==None):
print("|{:^5}|{:^15}|{:^9}|{:^15}|{:^12}|".format(analyzeStep, analysisStack, 'None',
reverseString(currentStack), '报错'))
analyzeResult = False
return
if __name__ == '__main__':
print("请输入待分析的字符串:")
string = input()
# 滤空格
string = string.replace(" ", "")
if(checkString(string)):
print("|{:^4}|{:^13}|{:^6}|{:^12}|{:^10}|".format('步骤', '分析栈', '优先关系', '当前输入串', '移进或归约'))
initStack(string)
if(analyzeResult):
print("由以上分析可知,该串是文法的合法句子。\n")
else:
print("由以上分析可知,该串不是文法的合法句子。\n")