字符串模板和语法谓词

时间:2013-05-29 10:02:50

标签: antlr stringtemplate

我正在尝试修复我的TreeWalker,以便它可以根据是否找到括号来实现不同的字符串模板。

即。在以下公式中:x - (y - z) 使用括号将改变公式的值。没有括号,公式变为x - y - z,这是错误的。我试图使用一个不同的字符串模板减去和减去括号。具体如下:

minus(op1,op2)              ::= "$op1$ - $op2$"
minusb(op1,op2)             ::= "($op1$ - $op2$)"

我尝试使用的TreeWalker部分如下所示。这只是一个更大的TreeWalker的一部分。

additiveExpr
scope { bool aFlag }
@init {bool aFlag = true; }
    :   ^(PLUS
          { $additiveExpr::aFlag = false;
            $formula::mFlag = false;
          }
          op1=expression op2=expression)
        -> {$additiveExpr::aFlag}?
           plusb(op1={$op1.st},op2={$op2.st})
        -> plus(op1={$op1.st},op2={$op2.st})
    |   ^(MINUS
          {
            $additiveExpr::aFlag = false;
            $formula::mFlag = false;
          }
          op1=expression op2=expression)
        -> {$additiveExpr::aFlag}?
           minusb(op1={$op1.st},op2={$op2.st})
        -> minus(op1={$op1.st},op2={$op2.st})

在上面的规则中,aFlag总是返回false,生成没有括号的模板。我很难理解为什么当有一个括号时它不会返回。

如果有帮助,我可以发布解析器的其他部分。

我已经知道条件部分是由句法谓词决定的。当additiveExpr之前的标记是一个括号(词法分析器标记OPEN'('))时,我需要语法谓词表达式为true。这是否需要从Parser传递给TreeWalker或者我可以从这里解决吗?是等效的解析器代码

absExpr returns [string ret_type]
    :   ABS^ OPEN! additiveExpr CLOSE!
        {$ret_type = "numeric"; }
    |   additiveExpr
        {$ret_type = $additiveExpr.ret_type; }
    ;

additiveExpr returns [string ret_type]
    :   m=multiplicativeExpr ((PLUS|MINUS)^ multiplicativeExpr )*
        {$ret_type =  $m.ret_type; }
    ;

编辑:

最新的解析器部分:

absExpr returns [string ret_type] 
    :   ABS^ OPEN additiveExpr CLOSE
        {$ret_type =  $additiveExpr.ret_type; }
    |   (OPEN additiveExpr CLOSE)=> OPEN additiveExpr CLOSE
        {$ret_type =  $additiveExpr.ret_type; }
    |   additiveExpr
        {$ret_type = $additiveExpr.ret_type; }
    ;

1 个答案:

答案 0 :(得分:0)

我可能会尝试类似以下内容而不是使用语义谓词。您只需要确保使用解析器语法中!规则中的additiveExpr运算符,或OPENCLOSE令牌将无法供您的树木步行者使用。

additiveExpr
    :   ^(PLUS OPEN op1=expression op2=expression CLOSE)
        -> plusb(op1={$op1.st},op2={$op2.st})
    |   ^(PLUS op1=expression op2=expression)
        -> plus(op1={$op1.st},op2={$op2.st})
    |   ^(MINUS OPEN op1=expression op2=expression CLOSE)
        -> minusb(op1={$op1.st},op2={$op2.st})
    |   ^(MINUS op1=expression op2=expression)
        -> minus(op1={$op1.st},op2={$op2.st})
    ;

上一个回答:

我很难确切地说出你希望它如何发挥作用。可能有问题的一件事就是初始化:

scope { bool aFlag }
@init {bool aFlag = true; }

这声明了2个具有相同名称aFlag的不同变量。其中一个将出现在范围类中,另一个将是additiveExpr方法中的局部变量。您可能打算这样做:

scope { bool aFlag }
@init { $additiveExpr::aFlag = true; }