编译原理(3)算符优先语法分析程序设计(Python实现)

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")

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值