这个语法不明确吗?生产应用对单义语法有影响吗?

问题描述

我正在使用LR(1)解析器,我写了一个简单的示例,这里是

import time
def parse3(input):
    # e -> e '+' A | A
    # A -> '1' | '2'
    stack = []

    while True:
        try:
            print(stack)
            time.sleep(1)
            # try to reduce
            if stack[-1][0] == 'A':
                t = stack.pop()
                new = f"e{t}"
                stack.append(new)
                print(f"reduce e{t} <- {t}")
            elif stack[-1][0] in ('1','2'):
                t = stack.pop()
                new = f"A{t}"
                stack.append(new)
                print(f"reduce A <- {t}")
            elif stack[-3][0] == 'e' and stack[-2] == '+' and stack[-1][0] == 'A':
                t3 = stack.pop()
                t2 = stack.pop()
                t1 = stack.pop()
                stack.append(f"e{t2}{t1}{t3}")
                print("reduce e <- e + A")
            else:
                raise RuntimeError(f"Parse error {stack}")
            continue
        except IndexError:
            # shift
            t = input.pop(0)
            stack.append(t)
            print(f"shift {t}")
            continue

        if len(stack) == 1 and not input:
            return stack[0]


print(parse3("1 + 2".split()))

我正在使用前缀表示法以某种易于可视化和打印友好的方式创建解析树。这是语法

e -> e '+' A | A
A -> '1' | '2'

这是1 + 2解析的输出

[]
shift 1
['1']
reduce A <- 1
['A1']
reduce eA1 <- A1
['eA1']
shift +
['eA1','+']
shift 2
['eA1','+','2']
reduce A <- 2
['eA1','A2']
reduce eA2 <- A2
['eA1','eA2']
Traceback (most recent call last):
  File "parse2.py",line 233,in <module>
    print(parse3("1 + 2".split()))
  File "parse2.py",line 220,in parse3
    raise RuntimeError(f"Parse error {stack}")
RuntimeError: Parse error ['eA1','eA2']

我的问题是它减少了reduce eA2 <- A2。然后,我将其放入堆栈['eA1','eA2']中,由于没有e -> e + e生产规则,因此解析器退出并出现错误。如果e -> e '+' A规则在生效之前就被应用了,那么这听起来好像是一个模棱两可的语法问题,但是我不知道如何证明或解决这个问题。非正式地讲,如果语法是明确的,那么定单或生产规则的应用将无关紧要。但是如果我必须诉诸某种生产规则优先权,对吗?

一个问题是,编程语言语法是否模棱两可?编译器如何处理?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)