Java 数学表达式解析入门指南

1. 工作流程

在进行 Java 数学表达式解析之前,我们首先需要理解整个过程。以下是解析数学表达式的基本步骤:

步骤 内容 描述
1 定义语法规则 确定我们支持的表达式(如加减乘除等)
2 词法分析 将输入字符串转化为一系列的符号(Token)
3 语法分析 将符号组成语法树
4 计算表达式 根据语法树计算最终的结果

接下来,我们将详细讲解每一个步骤以及相应的代码。

2. 定义通信结构

我们将使用一个简单的类来表示我们支持的符号(Token)。以下是 Token 类的定义:

// 定义 Token 类
public class Token {
    public enum Type {
        NUMBER, OPERATOR, LPAREN, RPAREN
    }

    public Type type; // Token 类型
    public String value; // Token 值

    // 构造函数
    public Token(Type type, String value) {
        this.type = type;
        this.value = value;
    }
}

3. 词法分析

词法分析的目的是将输入的字符串转换为 Token 列表。以下是词法分析的代码实现:

import java.util.ArrayList;
import java.util.List;

// 词法分析器
public class Lexer {
    private String input; // 输入字符串
    private int position; // 当前位置

    public Lexer(String input) {
        this.input = input.replaceAll("\\s+", ""); // 去掉空格
        this.position = 0;
    }

    public List<Token> tokenize() {
        List<Token> tokens = new ArrayList<>();

        while (position < input.length()) {
            char currentChar = input.charAt(position);

            // 如果是数字
            if (Character.isDigit(currentChar)) {
                StringBuilder number = new StringBuilder();
                while (position < input.length() && Character.isDigit(input.charAt(position))) {
                    number.append(input.charAt(position++));
                }
                tokens.add(new Token(Token.Type.NUMBER, number.toString()));
            } 
            // 如果是操作符
            else if ("+-*/".indexOf(currentChar) != -1) {
                tokens.add(new Token(Token.Type.OPERATOR, String.valueOf(currentChar)));
                position++;
            }
            // 左括号
            else if (currentChar == '(') {
                tokens.add(new Token(Token.Type.LPAREN, String.valueOf(currentChar)));
                position++;
            }
            // 右括号
            else if (currentChar == ')') {
                tokens.add(new Token(Token.Type.RPAREN, String.valueOf(currentChar)));
                position++;
            } else {
                throw new IllegalArgumentException("Invalid character: " + currentChar);
            }
        }

        return tokens;
    }
}

4. 语法分析

接下来,我们需要基于 Token 构建语法树。以下是一个简单的语法分析器实现:

import java.util.List;

// 语法分析器
public class Parser {
    private List<Token> tokens;
    private int currentTokenIndex = 0;

    public Parser(List<Token> tokens) {
        this.tokens = tokens;
    }

    // 表达式解析
    public int parse() {
        return expression();
    }

    private int expression() {
        int result = term();

        while (currentTokenIndex < tokens.size() &&
                (tokens.get(currentTokenIndex).value.equals("+") || tokens.get(currentTokenIndex).value.equals("-"))) {
            Token operator = tokens.get(currentTokenIndex++);
            int nextTerm = term();

            if (operator.value.equals("+")) {
                result += nextTerm;
            } else {
                result -= nextTerm;
            }
        }
        return result;
    }

    private int term() {
        int result = factor();

        while (currentTokenIndex < tokens.size() &&
                (tokens.get(currentTokenIndex).value.equals("*") || tokens.get(currentTokenIndex).value.equals("/"))) {
            Token operator = tokens.get(currentTokenIndex++);
            int nextFactor = factor();

            if (operator.value.equals("*")) {
                result *= nextFactor;
            } else {
                result /= nextFactor;
            }
        }
        return result;
    }

    private int factor() {
        Token token = tokens.get(currentTokenIndex++);
        if (token.type == Token.Type.NUMBER) {
            return Integer.parseInt(token.value);
        } else if (token.type == Token.Type.LPAREN) {
            int result = expression();
            currentTokenIndex++; // Skip RPAREN
            return result;
        }
        throw new IllegalArgumentException("Unexpected token: " + token.value);
    }
}

5. 计算表达式

在解析完成后,我们可以通过以下代码进行表达式计算:

public class Calculator {
    public static void main(String[] args) {
        String expression = "3 + 5 * (2 - 8)";
        Lexer lexer = new Lexer(expression);
        List<Token> tokens = lexer.tokenize();
        
        Parser parser = new Parser(tokens);
        int result = parser.parse();

        System.out.println("Result: " + result); // 输出计算结果
    }
}

综上所述

以上代码展示了如何利用 Java 实现一个简单的数学表达式解析器。通过逐步解析输入,利用词法分析、语法分析以及实际的计算,我们可以轻松地处理各种数学表达式。

甘特图

以下是整个项目时间安排的甘特图:

gantt
    title 数学表达式解析项目
    dateFormat  YYYY-MM-DD
    section 词法分析
    定义词法分析器        :a1, 2023-10-01, 5d
    实现 tokenize 方法     :after a1  , 5d
    section 语法分析
    定义语法分析器      :after a1  , 5d
    实现 parse 方法       :after a2  , 5d
    section 整合与测试
    整合 Lexer 和 Parser   :after a2, 5d
    实现主执行程序        :after a3, 3d

序列图

以下是整个过程的序列图:

sequenceDiagram
    participant U as 用户
    participant C as Calculator
    participant L as Lexer
    participant P as Parser
    U->>C: 输入数学表达式
    C->>L: 创建 Lexer
    L-->>C: 返回 Token 列表
    C->>P: 创建 Parser
    P-->>C: 返回计算结果
    C->>U: 输出结果

通过这篇文章,相信你已经对如何解析 Java 数学表达式有了一个全方位的理解。希望能在今后的编程实践中,帮助你加深对语言特性及设计模式的理解!