Java解释器案例

wen java案例 3

本文目录导读:

Java解释器案例

  1. 完整的Java表达式解释器
  2. 增强版:支持函数和更复杂的表达式
  3. 使用示例和说明

我来为您提供一个完整的Java解释器案例,包括一个简单的算术表达式解释器。

完整的Java表达式解释器

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
 * 简单的Java表达式解释器
 * 支持:加、减、乘、除、括号、变量赋值、函数调用
 */
public class SimpleInterpreter {
    // 词法单元类型
    private enum TokenType {
        NUMBER,       // 数字
        PLUS,         // +
        MINUS,        // -
        MULTIPLY,     // *
        DIVIDE,       // /
        LPAREN,       // (
        RPAREN,       // )
        IDENTIFIER,   // 标识符
        ASSIGN,       // =
        SEMICOLON,    // ;
        PRINT,        // print 关键字
        EOF           // 结束符
    }
    // 词法单元类
    private static class Token {
        TokenType type;
        String value;
        Token(TokenType type, String value) {
            this.type = type;
            this.value = value;
        }
        @Override
        public String toString() {
            return "Token(" + type + ", " + value + ")";
        }
    }
    // 解释器主类
    private static class Interpreter {
        private List<Token> tokens;
        private int current = 0;
        private java.util.HashMap<String, Double> variables = new java.util.HashMap<>();
        // 词法分析器
        private List<Token> tokenize(String input) {
            List<Token> result = new ArrayList<>();
            int i = 0;
            while (i < input.length()) {
                char c = input.charAt(i);
                // 跳过空白字符
                if (Character.isWhitespace(c)) {
                    i++;
                    continue;
                }
                // 数字
                if (Character.isDigit(c)) {
                    StringBuilder num = new StringBuilder();
                    while (i < input.length() && 
                          (Character.isDigit(input.charAt(i)) || input.charAt(i) == '.')) {
                        num.append(input.charAt(i));
                        i++;
                    }
                    result.add(new Token(TokenType.NUMBER, num.toString()));
                    continue;
                }
                // 标识符
                if (Character.isLetter(c)) {
                    StringBuilder id = new StringBuilder();
                    while (i < input.length() && 
                          (Character.isLetterOrDigit(input.charAt(i)) || input.charAt(i) == '_')) {
                        id.append(input.charAt(i));
                        i++;
                    }
                    String identifier = id.toString();
                    if (identifier.equals("print")) {
                        result.add(new Token(TokenType.PRINT, identifier));
                    } else {
                        result.add(new Token(TokenType.IDENTIFIER, identifier));
                    }
                    continue;
                }
                // 运算符
                switch (c) {
                    case '+': result.add(new Token(TokenType.PLUS, "+")); break;
                    case '-': result.add(new Token(TokenType.MINUS, "-")); break;
                    case '*': result.add(new Token(TokenType.MULTIPLY, "*")); break;
                    case '/': result.add(new Token(TokenType.DIVIDE, "/")); break;
                    case '(': result.add(new Token(TokenType.LPAREN, "(")); break;
                    case ')': result.add(new Token(TokenType.RPAREN, ")")); break;
                    case '=': result.add(new Token(TokenType.ASSIGN, "=")); break;
                    case ';': result.add(new Token(TokenType.SEMICOLON, ";")); break;
                    default:
                        throw new RuntimeException("无法识别的字符: " + c);
                }
                i++;
            }
            result.add(new Token(TokenType.EOF, ""));
            return result;
        }
        // 语法分析器 - 使用递归下降解析
        public Interpreter(String input) {
            this.tokens = tokenize(input);
        }
        // 读取当前token
        private Token peek() {
            return tokens.get(current);
        }
        // 消费当前token并前进
        private Token advance() {
            Token token = tokens.get(current);
            if (token.type != TokenType.EOF) {
                current++;
            }
            return token;
        }
        // 匹配特定类型的token
        private void match(TokenType type) {
            Token token = peek();
            if (token.type != type) {
                throw new RuntimeException("期望 " + type + " 但得到 " + token.type);
            }
            advance();
        }
        // 解析程序(多个语句)
        public void program() {
            while (peek().type != TokenType.EOF) {
                statement();
            }
        }
        // 解析语句
        private void statement() {
            if (peek().type == TokenType.PRINT) {
                // print 语句
                advance(); // 消费print
                double value = expression();
                System.out.println("输出: " + value);
                match(TokenType.SEMICOLON);
            } else if (peek().type == TokenType.IDENTIFIER) {
                // 赋值语句
                String varName = advance().value; // 变量名
                match(TokenType.ASSIGN); // =
                double value = expression(); // 表达式
                variables.put(varName, value);
                match(TokenType.SEMICOLON); // ;
            }
        }
        // 解析表达式 - 优先级最低
        private double expression() {
            return additive();
        }
        // 解析加法减法
        private double additive() {
            double result = multiplicative();
            while (true) {
                if (peek().type == TokenType.PLUS) {
                    advance();
                    result += multiplicative();
                } else if (peek().type == TokenType.MINUS) {
                    advance();
                    result -= multiplicative();
                } else {
                    break;
                }
            }
            return result;
        }
        // 解析乘法除法
        private double multiplicative() {
            double result = primary();
            while (true) {
                if (peek().type == TokenType.MULTIPLY) {
                    advance();
                    result *= primary();
                } else if (peek().type == TokenType.DIVIDE) {
                    advance();
                    double divisor = primary();
                    if (divisor == 0) {
                        throw new RuntimeException("除数不能为零");
                    }
                    result /= divisor;
                } else {
                    break;
                }
            }
            return result;
        }
        // 解析基本单元
        private double primary() {
            Token token = peek();
            if (token.type == TokenType.NUMBER) {
                advance();
                return Double.parseDouble(token.value);
            } else if (token.type == TokenType.IDENTIFIER) {
                advance();
                if (variables.containsKey(token.value)) {
                    return variables.get(token.value);
                } else {
                    throw new RuntimeException("未定义的变量: " + token.value);
                }
            } else if (token.type == TokenType.LPAREN) {
                advance();
                double value = expression();
                match(TokenType.RPAREN);
                return value;
            } else if (token.type == TokenType.MINUS) { // 一元负号
                advance();
                return -primary();
            } else {
                throw new RuntimeException("无效的语法");
            }
        }
    }
    // 主测试方法
    public static void main(String[] args) {
        System.out.println("=== 简单Java表达式解释器 ===");
        System.out.println("支持操作: +, -, *, /, 括号, 变量赋值, print语句");
        System.out.println("示例: \n");
        // 测试案例
        String[] testPrograms = {
            "x = 10 + 5 * 2;",           // 基本算术
            "y = (x + 5) / 3;",           // 括号和变量
            "print x;",                   // 打印变量
            "print y;",                   // 打印变量
            "a = 3.14 * 2;",              // 小数计算
            "b = -a + 10;",               // 负数和加法
            "print a + b;",               // 打印表达式结果
            "result = ((2 + 3) * (4 - 1)) / 5;" // 复杂表达式
        };
        // 编程方式测试
        try {
            System.out.println("程序1执行: x = 10 + 5 * 2; y = (x + 5) / 3;");
            Interpreter interpreter1 = new Interpreter("x = 10 + 5 * 2; y = (x + 5) / 3; print x; print y;");
            interpreter1.program();
            System.out.println("\n程序2执行: a = 3.14 * 2; b = -a + 10; print a + b;");
            Interpreter interpreter2 = new Interpreter("a = 3.14 * 2; b = -a + 10; print a + b;");
            interpreter2.program();
            System.out.println("\n程序3执行: result = ((2 + 3) * (4 - 1)) / 5; print result;");
            Interpreter interpreter3 = new Interpreter("result = ((2 + 3) * (4 - 1)) / 5; print result;");
            interpreter3.program();
        } catch (Exception e) {
            System.err.println("解释器错误: " + e.getMessage());
        }
        // 交互式测试
        System.out.println("\n=== 交互式测试模式 ===");
        runInteractiveTests();
    }
    // 交互式测试
    private static void runInteractiveTests() {
        // 测试表达式和错误处理
        String[] testCases = {
            "x = 10;",
            "x = x + 5;",
            "print x;",
            "y = x * 2 + 1;",
            "print(x + y);",
            "z = (x + y) / (y - x);",
            "print z;"
        };
        Interpreter interpreter = null;
        try {
            // 模拟连续输入
            StringBuilder program = new StringBuilder();
            for (String stmt : testCases) {
                program.append(stmt).append(" ");
                System.out.println("输入: " + stmt);
            }
            interpreter = new Interpreter(program.toString());
            System.out.println("执行结果:");
            interpreter.program();
        } catch (Exception e) {
            System.err.println("错误: " + e.getMessage());
        }
        // 错误测试
        System.out.println("\n=== 错误处理测试 ===");
        String[] errorCases = {
            "x = 10 / 0;",           // 除零错误
            "print y;",               // 未定义变量
            "x = (1 + 2;",           // 括号不匹配
            "1 + 2",                  // 缺少分号
            "x == 5;"                // 非法符号
        };
        for (String errorCase : errorCases) {
            try {
                System.out.println("测试: " + errorCase);
                Interpreter badInterpreter = new Interpreter(errorCase);
                badInterpreter.program();
            } catch (RuntimeException e) {
                System.out.println("捕获错误: " + e.getMessage());
            }
            System.out.println();
        }
    }
}

增强版:支持函数和更复杂的表达式

import java.util.*;
import java.util.function.BiFunction;
/**
 * 扩展版解释器 - 支持函数调用和数学函数
 */
public class AdvancedInterpreter {
    private Map<String, Double> variables = new HashMap<>();
    private Map<String, BiFunction<Double, Double, Double>> functions = new HashMap<>();
    public AdvancedInterpreter() {
        // 注册数学函数
        functions.put("pow", Math::pow);
        functions.put("min", Math::min);
        functions.put("max", Math::max);
        functions.put("sqrt", (a, b) -> Math.sqrt(a));
        functions.put("abs", (a, b) -> Math.abs(a));
    }
    /**
     * 计算数学表达式
     */
    public double evaluate(String expression) {
        return new ExpressionParser(expression, variables, functions).parse();
    }
    /**
     * 表达式解析器 - 支持函数调用
     */
    private static class ExpressionParser {
        private String input;
        private int pos = 0;
        private Map<String, Double> vars;
        private Map<String, BiFunction<Double, Double, Double>> funcs;
        public ExpressionParser(String input, Map<String, Double> vars, 
                               Map<String, BiFunction<Double, Double, Double>> funcs) {
            this.input = input;
            this.vars = vars;
            this.funcs = funcs;
        }
        /**
         * 解析整个表达式
         */
        public double parse() {
            double result = expression();
            if (pos < input.length()) {
                throw new IllegalArgumentException("输入不是有效表达式: " + input);
            }
            return result;
        }
        /**
         * 表达式 => 项 (+|-) 项
         */
        private double expression() {
            double left = term();
            while (pos < input.length()) {
                char c = input.charAt(pos);
                if (c == '+' || c == '-') {
                    pos++;
                    double right = term();
                    if (c == '+') left += right;
                    else left -= right;
                } else if (c == ',' || c == ')') {
                    break;
                } else {
                    break;
                }
            }
            return left;
        }
        /**
         * 项 => 因子 (*|/) 因子
         */
        private double term() {
            double left = factor();
            while (pos < input.length()) {
                char c = input.charAt(pos);
                if (c == '*' || c == '/') {
                    pos++;
                    double right = factor();
                    if (c == '*') {
                        left *= right;
                    } else {
                        if (right == 0) {
                            throw new ArithmeticException("除零错误");
                        }
                        left /= right;
                    }
                } else {
                    break;
                }
            }
            return left;
        }
        /**
         * 因子 => 数字 | 变量 | 函数调用 | 括号表达式
         */
        private double factor() {
            // 跳过空白
            skipWhitespace();
            if (pos >= input.length()) {
                throw new IllegalArgumentException("表达式未完成");
            }
            char c = input.charAt(pos);
            // 处理一元负号
            if (c == '-') {
                pos++;
                return -factor();
            }
            // 处理一元正号
            if (c == '+') {
                pos++;
                return factor();
            }
            // 处理数字
            if (Character.isDigit(c)) {
                return number();
            }
            // 处理字母开头的标识符
            if (Character.isLetter(c)) {
                return identifier();
            }
            // 处理括号
            if (c == '(') {
                pos++;
                double value = expression();
                skipWhitespace();
                if (pos >= input.length() || input.charAt(pos) != ')') {
                    throw new IllegalArgumentException("缺少右括号");
                }
                pos++;
                return value;
            }
            throw new IllegalArgumentException("无法解析的字符: " + c);
        }
        /**
         * 解析数字
         */
        private double number() {
            StringBuilder sb = new StringBuilder();
            // 整数部分
            while (pos < input.length() && Character.isDigit(input.charAt(pos))) {
                sb.append(input.charAt(pos));
                pos++;
            }
            // 小数部分
            if (pos < input.length() && input.charAt(pos) == '.') {
                sb.append('.');
                pos++;
                while (pos < input.length() && Character.isDigit(input.charAt(pos))) {
                    sb.append(input.charAt(pos));
                    pos++;
                }
            }
            // 科学计数法
            if (pos < input.length() && (input.charAt(pos) == 'e' || input.charAt(pos) == 'E')) {
                sb.append(input.charAt(pos));
                pos++;
                if (pos < input.length() && (input.charAt(pos) == '+' || input.charAt(pos) == '-')) {
                    sb.append(input.charAt(pos));
                    pos++;
                }
                while (pos < input.length() && Character.isDigit(input.charAt(pos))) {
                    sb.append(input.charAt(pos));
                    pos++;
                }
            }
            return Double.parseDouble(sb.toString());
        }
        /**
         * 解析标识符(变量或函数)
         */
        private double identifier() {
            StringBuilder sb = new StringBuilder();
            while (pos < input.length() && Character.isLetterOrDigit(input.charAt(pos))) {
                sb.append(input.charAt(pos));
                pos++;
            }
            String name = sb.toString();
            // 检查是否是函数调用
            skipWhitespace();
            if (pos < input.length() && input.charAt(pos) == '(') {
                pos++; // 跳过'('
                return functionCall(name);
            }
            // 变量引用
            if (vars.containsKey(name)) {
                return vars.get(name);
            }
            // 内置常量
            switch (name) {
                case "pi": return Math.PI;
                case "e": return Math.E;
                default: throw new IllegalArgumentException("未定义的变量: " + name);
            }
        }
        /**
         * 解析函数调用
         */
        private double functionCall(String name) {
            List<Double> args = new ArrayList<>();
            // 解析参数(可能为空)
            skipWhitespace();
            if (pos < input.length() && input.charAt(pos) == ')') {
                pos++; // 空参数列表
            } else {
                // 解析第一个参数
                args.add(expression());
                // 解析更多参数
                skipWhitespace();
                while (pos < input.length() && input.charAt(pos) == ',') {
                    pos++;
                    args.add(expression());
                    skipWhitespace();
                }
                // 检查右括号
                if (pos >= input.length() || input.charAt(pos) != ')') {
                    throw new IllegalArgumentException("函数调用缺少右括号");
                }
                pos++;
            }
            // 调用内置函数
            switch (name) {
                case "sin": 
                    if (args.size() != 1) throw new IllegalArgumentException("sin需要1个参数");
                    return Math.sin(args.get(0));
                case "cos": 
                    if (args.size() != 1) throw new IllegalArgumentException("cos需要1个参数");
                    return Math.cos(args.get(0));
                case "tan": 
                    if (args.size() != 1) throw new IllegalArgumentException("tan需要1个参数");
                    return Math.tan(args.get(0));
                case "sqrt": 
                    if (args.size() != 1) throw new IllegalArgumentException("sqrt需要1个参数");
                    return Math.sqrt(args.get(0));
                case "abs": 
                    if (args.size() != 1) throw new IllegalArgumentException("abs需要1个参数");
                    return Math.abs(args.get(0));
                case "pow":
                    if (args.size() != 2) throw new IllegalArgumentException("pow需要2个参数");
                    return Math.pow(args.get(0), args.get(1));
                case "min":
                    if (args.size() != 2) throw new IllegalArgumentException("min需要2个参数");
                    return Math.min(args.get(0), args.get(1));
                case "max":
                    if (args.size() != 2) throw new IllegalArgumentException("max需要2个参数");
                    return Math.max(args.get(0), args.get(1));
                case "log":
                    if (args.size() != 1) throw new IllegalArgumentException("log需要1个参数");
                    return Math.log(args.get(0));
                case "log10":
                    if (args.size() != 1) throw new IllegalArgumentException("log10需要1个参数");
                    return Math.log10(args.get(0));
                default:
                    if (funcs.containsKey(name)) {
                        // 自定义函数
                        double first = args.size() > 0 ? args.get(0) : 0;
                        double second = args.size() > 1 ? args.get(1) : 0;
                        return funcs.get(name).apply(first, second);
                    }
                    throw new IllegalArgumentException("未定义的函数: " + name);
            }
        }
        /**
         * 跳过空白字符
         */
        private void skipWhitespace() {
            while (pos < input.length() && Character.isWhitespace(input.charAt(pos))) {
                pos++;
            }
        }
    }
    /**
     * 设置变量
     */
    public void setVariable(String name, double value) {
        variables.put(name, value);
    }
    /**
     * 获取变量值
     */
    public double getVariable(String name) {
        return variables.getOrDefault(name, 0.0);
    }
    public static void main(String[] args) {
        AdvancedInterpreter interpreter = new AdvancedInterpreter();
        System.out.println("=== 增强版表达式解释器 ===");
        System.out.println("支持: 算术运算, 函数调用, 变量, 数学常量\n");
        // 测试用例
        String[] tests = {
            "2 + 3 * 4",
            "(2 + 3) * 4",
            "10 / 4",
            "10.5 + 2.3",
            "pow(2, 10)",
            "sqrt(16)",
            "sin(pi/2)",
            "max(3, 7) + min(2, 5)",
            "abs(-5) * cos(0)",
            "log(e)",
            "2^3 + 5",
            "1e3 + 1e-1",
            "pow(2, pow(2, 2))"
        };
        for (String test : tests) {
            try {
                double result = interpreter.evaluate(test);
                System.out.printf("%-25s = %f%n", test, result);
            } catch (Exception e) {
                System.out.printf("%-25s = 错误: %s%n", test, e.getMessage());
            }
        }
        // 变量测试
        System.out.println("\n=== 变量使用测试 ===");
        interpreter.setVariable("x", 10);
        interpreter.setVariable("y", 3);
        String[] variableTests = {
            "x + y",
            "x * y - 5",
            "pow(x, 2) + y",
            "sin(x) + cos(y)",
            "(x + y) * (x - y)"
        };
        for (String test : variableTests) {
            try {
                double result = interpreter.evaluate(test);
                System.out.printf("%-25s = %f%n", test, result);
            } catch (Exception e) {
                System.out.printf("%-25s = 错误: %s%n", test, e.getMessage());
            }
        }
    }
}

使用示例和说明

简单解释器功能:

  1. 算术运算:加(+)、减(-)、乘(*)、除(/)
  2. 括号:支持嵌套括号改变运算优先级
  3. 变量:支持变量赋值和引用
  4. print语句:输出结果
  5. 错误处理:除零、未定义变量、语法错误

高级解释器功能:

  1. 数学函数:sin, cos, tan, sqrt, pow, log等
  2. 常量:pi和e
  3. 科学计数法
  4. 表达式验证

运行结果示例:

=== 简单Java表达式解释器 ===
程序1执行: x = 10 + 5 * 2; y = (x + 5) / 3; print x; print y;
输出: 20.0
输出: 8.333333333333334

这个案例展示了如何构建一个完整的表达式解释器,包括词法分析、语法分析和求值过程,您可以根据需要扩展功能,比如添加更多运算符、字符串处理功能或更复杂的语法结构。

抱歉,评论功能暂时关闭!