0

我正在使用 PLY。这是parser.out我的状态之一:

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

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

文档说:

然后使用这些值将数值优先级值和关联性方向附加到每个语法规则。这总是通过查看最右侧终端符号的优先级来确定。

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

更新:完整的语法:

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
4

1 回答 1

4

你的基本问题是你需要两个前瞻标记来做你想做的事——当到目前为止看到的输入是 acourse并且前瞻是 aOR_CONJ你不知道是减少course到 acourse_data还是在不前瞻两个标记的情况下转移到之后的令牌OR_CONJ。有很多方法可以解决这个问题

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

  • 使用 lexer hack 进行前瞻 - 基本上让词法分析器OR_CONJ根据以下标记是否为 a返回两个不同的标记COURSE_NUMBER

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

请注意,您给定的语法也与三个或更多课程在单个语句中关联的方式有关。这很容易通过将语法重写为更清晰的左递归形式来解决:

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-token 前瞻问题。重构它以使其消失的一种方法是使其COURSE_NUMBER本身有效course并在后传递中将其与前一个重新组合(或者如果它是a 中的第一个course则给出错误)。那么规则 4 变为:coursestatement

Rule 4    course -> COURSE_NUMBER

你没有冲突。

于 2010-06-14T00:04:12.527 回答