1

我正在尝试修复我的 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,生成不带括号的模板。我很难理解为什么当有括号时它不会返回 true。

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

我已经弄清楚条件部分是由句法谓词决定的。当additiveExpr之前的标记是方括号时,我需要语法谓词表达式为真(词法分析器标记OPEN'(')。这需要从解析器传递到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; }
    ;
4

1 回答 1

0

我可能会尝试以下类似的方法,而不是使用语义谓词。您只需确保不在解析器语法中的规则中使用!运算符,否则and标记将无法供您的 tree walker 使用。additiveExprOPENCLOSE

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; }
于 2013-06-13T15:24:44.847 回答