繁体   English   中英

使用Java的递归表达式求值程序

[英]Recursive expression evaluator using Java

我将编写一个表达式求值程序,它只进行加法和减法。 我有一个简单的算法来做到这一点; 但是,我有一些实施问题。

我认为表达式为(它是一个字符串)

"(" <expression1> <operator> <expression2> ")"

这是我的算法

String evaluate( String expression )

   if expression is digit
      return expression

   else if expression is "(" <expression1> <operator> <expression2> ")"
      cut the brackets out of it
      expression1 = evaluate( <expression1> )
      operator = <operator>
      expression2 = evaluate( <expression2> )

   if operator is +
      expression1 + expression2

   else if operator is -
      expression1 - expression2 

我的问题是从<expression1>解析<expression1><operator><expression2> 我怎样才能做到这一点?

注意:我不是要求代码。 我需要的只是一个想法。

谢谢,

-Ali

我的问题是从表达式解析<expression1>,<operator>和<expression2>

不要这样做,然后:)当你看到一个左括号时,你做递归调用表达式。 在表达结束时,要么你找到另一个运算符(所以你毕竟不是在表达式的末尾),或者右括号,在这种情况下你从评价中返回。

要么使用解析器生成器,如JavaCUPANTLR 写下你的表达式的BNF并生成一个解析器。 这是一个可以帮助您入门的示例语法:

Expression ::= Digit
            |  LeftBracket Expression Plus Expression RightBracket
            |  LeftBracket Expression Minus Expression RightBracket
            |  LeftBracket Expression RightBracket

这样做的“哈克”的方式自己会去寻找第一)回溯到最近的(看括号自由的表达,简单地之间的分裂上操作符号和评估。

使用StringTokenizer将输入字符串拆分为括号,运算符和数字,然后迭代您的标记,对每个开放的parens进行递归调用,并为每个紧密括号退出方法。

我知道你没有要求代码,但这适用于有效的输入:

public static int eval(String expr) {
    StringTokenizer st = new StringTokenizer(expr, "()+- ", true);
    return eval(st);
}

private static int eval(StringTokenizer st) {
    int result = 0;
    String tok;
    boolean addition = true;
    while ((tok = getNextToken(st)) != null) {
        if (")".equals(tok))
            return result;
        else if ("(".equals(tok))
            result = eval(st);
        else if ("+".equals(tok))
            addition = true;
        else if ("-".equals(tok))
            addition = false;
        else if (addition)
            result += Integer.parseInt(tok);
        else
            result -= Integer.parseInt(tok);
    }
    return result;
}

private static String getNextToken(StringTokenizer st) {
    while (st.hasMoreTokens()) {
        String tok = st.nextToken().trim();
        if (tok.length() > 0)
            return tok;
    }
    return null;
}

它需要更好地处理无效输入,但你明白了......

我建议将中缀输入更改为后缀,然后对其进行评估,而不是减少表达式中缀。 已经有很好的定义算法,并没有固有的多嵌套括号解析问题。

看看Shunting Yard算法转换为postfix / RPN,然后使用Postfix Operations使用堆栈对其进行评估。 这很快(O(n))且可靠。

HTH

我建议采取更类似于中描述的一种方法这个旧的,但(在我看来)相关系列的编译器设计的文章。 我发现使用解析部分表达式的小函数/方法非常有效。

此方法允许您将解析方法分解为许多子方法,这些子方法的名称和执行顺序紧跟在您可能用于描述要解析的表达式的EBNF之后

也许为表达式运算符创建正则表达式 ,然后使用匹配来识别和分解您的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM