Python/YACC:解决移位/归约冲突

2023-12-26

我正在使用 PLY。这是我的州之一解析器输出:

state 3

    (5) course_data -> course .
    (6) course_data -> course . course_list_tail
    (3) or_phrase -> course . OR_CONJ COURSE_NUMBER
    (7) course_list_tail -> . , COURSE_NUMBER
    (8) course_list_tail -> . , COURSE_NUMBER course_list_tail

  ! shift/reduce conflict for OR_CONJ resolved as shift
    $end            reduce using rule 5 (course_data -> course .)
    OR_CONJ         shift and go to state 7
    ,               shift and go to state 8

  ! OR_CONJ         [ reduce using rule 5 (course_data -> course .) ]

    course_list_tail               shift and go to state 9

我想解决这个问题:

if OR_CONJ is followed by COURSE_NUMBER:
    shift and go to state 7
else:
    reduce using rule 5 (course_data -> course .)

如何修复我的解析器文件以反映这一点?我是否需要通过回溯并尝试不同的规则来处理语法错误?

The 文档 http://www.dabeaz.com/ply/ply.html#ply_nn28 says:

然后使用这些值附加一个 数值优先值和 每个的关联方向 语法规则。这总是 通过查看确定 最右边终端的优先级 象征。

如果规则没有终端怎么办?

UPDATE:完整语法:

Grammar

Rule 0     S' -> statement
Rule 1     statement -> course_data
Rule 2     or_phrase -> statement OR_CONJ statement
Rule 3     or_phrase -> course OR_CONJ COURSE_NUMBER
Rule 4     statement -> or_phrase
Rule 5     course_data -> course
Rule 6     course_data -> course course_list_tail
Rule 7     course_list_tail -> , COURSE_NUMBER
Rule 8     course_list_tail -> , COURSE_NUMBER course_list_tail
Rule 9     course -> DEPT_CODE COURSE_NUMBER

你的基本问题是,当到目前为止看到的输入是一个时,你需要两个前瞻令牌来执行你想要的操作course前瞻是OR_CONJ你不知道是否要减少course to a course_data或在不向前查看两个标记的情况下转移到之后的标记OR_CONJ。有多种方法可以解决这个问题

  • 使用 LR(2) 或 LR(k) 或 GLR 解析器生成器——任何都可以处理这个问题。

  • 使用词法分析器进行前瞻——基本上让词法分析器返回两个不同的OR_CONJ令牌取决于以下令牌是否是COURSE_NUMBER or not.

  • 考虑语法以消除冲突,这可能会导致语法解析的内容与您想要的稍有不同(需要一些额外的解析后检查以拒绝一些无效的构造),并且通常会使语法更难理解。

请注意,您给出的语法对于三个或更多课程在单个语句关联中的连接方式也是不明确的。通过将语法重写为更清晰的左递归形式,可以轻松解决此问题:

Rule 1    statement -> course
Rule 2    statement -> statement OR_CONJ course
Rule 3    course -> DEPT_CODE course_list
Rule 4    course -> DEPT CODE course_list OR_CONJ COURSE_NUMBER
Rule 5    course_list -> COURSE_NUMBER
Rule 6    course_list -> course_list , COURSE_NUMBER

对于 LL 解析器生成器,这也可以重写为右递归,但它仍然存在 2 令牌先行问题。重构它以使其消失的一种方法是COURSE_NUMBER本身就是一个有效的course并将其与之前的重新组合course在后通过中(或者如果是第一个则给出错误course in a statement)。那么规则 4 就变成:

Rule 4    course -> COURSE_NUMBER

并且你们没有冲突。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python/YACC:解决移位/归约冲突 的相关文章

随机推荐