我目前正在为C-构建编译器。我目前正在研究解析器,出于某种原因,我似乎无法解决来自EXPRESSION生产的第一组碰撞(终端ID)起源。下面,是我现在的语法的一个子集,有人可以指出我正确的方向如何解决冲突(或转换为等效的LL(1)可解析语法)。
EXPRESSION -> id VAR eq EXPRESSION | SIMPLEEXPRESSION
VAR -> lbracket EXPRESSION rbracket | empty
SIMPLEEXPRESSION -> ADDITIVEEXPRESSION FADDITIVEEXPRESSION
FADDITIVEEXPRESSION -> RELOP ADDITIVEEXPRESSION | empty
RELOP -> ltoreq | lt | gt | gtoreq | doubleeq | noteq
ADDITIVEEXPRESSION -> TERM ADDITIVEEXPRESSION1
ADDITIVEEXPRESSION1 -> ADDOP TERM ADDITIVEEXPRESSION1 | empty
ADDOP -> plus | minus
TERM -> FACTOR TERM1
TERM1 -> MULOP FACTOR TERM1 | empty
MULOP -> times | divide
FACTOR -> lparen EXPRESSION rparen | id FACTOR1 | num
FACTOR1 -> a | b
答案 0 :(得分:1)
C对LL(1)解析不太适合,所以你在这里尝试做的事情可能很难实现,甚至可能都不可能用于完整的语法。
但对于手头的问题,对于顶级制作
EXPRESSION -> id VAR eq EXPRESSION | SIMPLEEXPRESSION
很容易看出id
可以作为替代方案的开头,因此LL(1)解析器将不知道选择哪个替代方案。
直接问题的一个解决方案是将EXPRESSION
生产分成两个备选方案,一个始终以id
终端开头,另一个从不这样做:
EXPRESSION -> EXPRESSION_id | EXPRESSION_non_id
对于id
替代方案,我们需要预先设置id
终端,然后创建id
- 仅显示以下产品的版本:
EXPRESSION_id -> id (VAR eq EXPRESSION | SIMPLEEXPRESSION_id)
同样,对于非id
方,我们会创建以下作品的非id
版本:
EXPRESSION_non_id -> SIMPLEEXPRESSION_non_id
完成语法所需的子制作将如下所示:
SIMPLEEXPRESSION_id -> ADDITIVEEXPRESSION_id FADDITIVEEXPRESSION
ADDITIVEEXPRESSION_id -> TERM_id ADDITIVEEXPRESSION1
TERM_id -> FACTOR_id TERM1
FACTOR_id -> FACTOR1
SIMPLEEXPRESSION_non_id -> ADDITIVEEXPRESSION_non_id FADDITIVEEXPRESSION
ADDITIVEEXPRESSION_non_id -> TERM_non_id ADDITIVEEXPRESSION1
TERM_non_id -> FACTOR_non_id TERM1
FACTOR_non_id -> lparen EXPRESSION rparen | num
您可以对其他冲突进行类似的转换,但结果语法会变得非常笨拙。