2

我继承了一个 ANTLR 语法,现在我需要编写一个好的、旧的、类似 YACC/BISON 的解析器(具体来说,我将 PLY 用于 python)。有许多奇怪的规则,我现在正在努力解决以下问题:

factor : ('(' expr ')' | procedure | variable) ('.' variable | call)* '!'?

目前,我只有第一部分的规则,即

factor :  '(' expr ')' 
       | procedure 
       | variable

PLY 规则:

def p_factor_1(self, p):                                                                                                                                                                                       
    """ factor : LPAREN expr RPAREN """                                                                                                                                                                        
    p[0] = p[2]                                                                                                                                                                                                

def p_factor_2(self, p):                                                                                                                                                                                       
    """ factor : variable                                                                                                                                                                                      
               | procedure_definition                                                                                                                                                                          
    """                                                                                                                                                                                                        
    p[0] = p[1]  

我怎样才能把那件上衣变成真正适合 PLY 的东西?我需要合理的规则,这样我就可以为单个 expr、过程、变量构造一个 AST 节点,然后还可以为链接变量访问和链接调用构建一些节点。更糟糕的是还有“!” . 原始语法的创建者这样做是为了给予最高优先级的因式分解,但对于转换,这完全是痛苦的。

4

1 回答 1

2

有条不紊地去做:)

           V → ω X             V → V X                V → ω 
V → ω X? ⇒            V → X* ⇒            V → ω | ζ ⇒ 
           V → ω               V →                    V → ζ

当然,如果您必须在单个产品中执行以上操作中的一项以上,则需要引入新的非终端。

所以:

factor : ('(' expr ')' | procedure | variable) ('.' variable | call)* '!'?

A. 引入新的非终端:

factor          : factor-prefix factor-suffix '!'?
factor-prefix   : '(' expr ')' | procedure | variable
factor-suffix   : factor-continue*
factor-continue : '.' variable | call

B. 按上述规则替换

  factor          : factor-prefix factor-suffix '!'?
⇒
  factor          : factor-prefix factor-suffix '!'
  factor          : factor-prefix factor-suffix

  factor-prefix   : '(' expr ')' | procedure | variable
⇒
  factor-prefix   : '(' expr ')'
  factor-prefix   : procedure
  factor-prefix   : variable

  factor-suffix   : factor-continue*
⇒
  factor-suffix   : factor-suffix factor-continue
  factor-suffix   :

  factor-continue : '.' variable | call
⇒
  factor-continue : '.' variable
  factor-continue : call
于 2013-12-16T17:39:25.740 回答