将C语法转换为LL(1)

时间:2016-10-04 22:18:05

标签: parsing compiler-construction context-free-grammar ll

我目前正在为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

1 个答案:

答案 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

您可以对其他冲突进行类似的转换,但结果语法会变得非常笨拙。