java 公式解析器学习与开发(1)

本文主要探讨如何使用 Java 实现一个简单的算术表达式求值器。以下是一个基于双栈算法(Two-Stack Algorithm)的基础实现示例。

核心代码实现

public class Evaluate {
    public static void main(String[] args) { 
        Stack<String> ops  = new Stack<String>();
        Stack<Double> vals = new Stack<Double>();
        
        // 示例表达式:完全括号化的中缀表达式,元素间以空格分隔
        String[] strs = "( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )".split(" ");
        int i = 0;
        
        while (i < strs.length) {
            String s = strs[i];
            if      (s.equals("("))               ; // 忽略左括号
            else if (s.equals("+"))    ops.push(s);
            else if (s.equals("-"))    ops.push(s);
            else if (s.equals("*"))    ops.push(s);
            else if (s.equals("/"))    ops.push(s);
            else if (s.equals("sqrt")) ops.push(s);
            else if (s.equals(")")) {
                // 遇到右括号,弹出操作符与操作数进行计算
                String op = ops.pop();
                double v = vals.pop();
                if      (op.equals("+"))    v = vals.pop() + v;
                else if (op.equals("-"))    v = vals.pop() - v;
                else if (op.equals("*"))    v = vals.pop() * v;
                else if (op.equals("/"))    v = vals.pop() / v;
                else if (op.equals("sqrt")) v = Math.sqrt(v);
                vals.push(v);
            }
            else vals.push(Double.parseDouble(s));
            i++;
        }
        System.out.println(vals.pop());
    }
}

使用说明与限制

上述程序实现了一个简单的算术表达式计算逻辑,但在使用时有以下严格限制:

  1. 必须添加括号:表达式必须是完全括号化的(Fully Parenthesized),即每个操作符及其对应的操作数都必须被括号括起来。
  2. 空格分隔:各个分词(Token)之间必须有空格,以便程序通过 split(" ") 区分计算结构。

只有满足以上条件,程序才能正确解析并区分出运算的层级结构。

原理简述

中缀表达式(Infix Expression)是人们常用的算术表示方法。在通用的中缀记法中,通常依赖运算符优先级来确定计算顺序;但在上述算法实现中,括号是必需的

计算过程中必须用括号将操作符和对应的操作数括起来,用于明确指示运算的次序。这种处理方式简化了语法解析的复杂度,无需处理运算符优先级表,即可通过栈结构直接完成求值。

说明:本文代码示例使用了 Java 传统的 Stack 类。在现代 Java 开发中,Stack 类已被视为遗留类(Legacy),官方建议优先使用 Deque 接口及其实现类(如 ArrayDeque)来替代。此外,该算法适用于教学演示或特定场景,实际生产环境中的表达式解析通常涉及更复杂的词法分析与语法树构建。