简单的数学表达式解析器

时间:2012-11-29 12:37:41

标签: antlr

我有一个简单的数学表达式解析器,我想自己构建AST(意味着没有ast解析器)。但每个节点只能容纳两个操作数。所以2 + 3 + 4会产生这样的树:

        +
       / \
      2   +
         / \
        3   4

问题是,我无法让我的语法进行递归,这里只是“添加”部分:

add returns [Expression e]
  : op1=multiply { $e = $op1.e; Print.ln($op1.text); } 
    ( '+' op2=multiply   { $e = new AddOperator($op1.e, $op2.e); Print.ln($op1.e.getClass(), $op1.text, "+", $op2.e.getClass(), $op2.text); }
    | '-' op2=multiply   { $e = null; } // new MinusOperator    
    )*
  ;

但是在一天结束时,这将产生一棵树,如:

     +
    / \
   2   4

我知道问题出在哪里,这是因为“添加”可能永远或无限地出现(*),但我不知道如何解决这个问题。我想到了类似的东西:

“添加”部分:

add returns [Expression e]
  : op1=multiply { $e = $op1.e; Print.ln($op1.text); } 
    ( '+' op2=(multiply|add)   { $e = new AddOperator($op1.e, $op2.e); Print.ln($op1.e.getClass(), $op1.text, "+", $op2.e.getClass(), $op2.text); }
    | '-' op2=multiply   { $e = null; } // new MinusOperator    
    )?
  ;

但是这会给我一个反复的错误。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我没有完整的语法来测试此解决方案,但考虑将其替换(来自问题中的第一个add规则):

$e = new AddOperator($op1.e, $op2.e);

有了这个:

$e = new AddOperator($e, $op2.e);  //$e instead of $op1.e

这样,('+' multiply)*上的每次迭代都会延伸e而不是替换它。

可能需要花一点时间才能做到正确,或者您可能需要在规则中使用临时Expression来管理事情。只需确保循环创建的最后一个表达式位于=运算符右侧的某个位置,如$e = new XYZ($e, $rhs.e);中所示。