You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用BufferedReader将行存入ArrayList并执行文件中的简化编程语句?

实现简化编程语言解释器的分步指南

我来一步步帮你拆解这个需求的实现细节——从读取文件到解析执行,每个环节都给你具体的代码和思路。

一、先把文件行存入ArrayList

首先要做的是用BufferedReader把文件里的代码行读取到ArrayList中,这样后续执行时可以方便地通过行号跳转。这里要注意自动关闭流,还要过滤空行避免干扰:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class SimpleInterpreter {
    private ArrayList<String> programLines = new ArrayList<>();

    // 加载文件到ArrayList
    public void loadProgram(String filePath) throws IOException {
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                String trimmedLine = line.trim();
                // 跳过空行,保留有效代码行
                if (!trimmedLine.isEmpty()) {
                    programLines.add(trimmedLine);
                }
            }
        }
    }
}

二、分词处理:正确拆分语句

因为你的语句用空格分隔,但像GOTO 'x line'这种带单引号的内容不能被空格拆碎,所以需要写一个智能分词方法,处理引号内的内容:

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

// 分词方法:处理带引号的完整token
private List<String> tokenizeLine(String line) {
    List<String> tokens = new ArrayList<>();
    StringBuilder currentToken = new StringBuilder();
    boolean inQuotes = false;

    for (char c : line.toCharArray()) {
        if (c == '\'') {
            // 切换引号状态,同时把引号加入token
            inQuotes = !inQuotes;
            currentToken.append(c);
        } else if (Character.isWhitespace(c) && !inQuotes) {
            // 非引号内的空格才作为分隔符
            if (currentToken.length() > 0) {
                tokens.add(currentToken.toString());
                currentToken.setLength(0);
            }
        } else {
            currentToken.append(c);
        }
    }
    // 加入最后一个token
    if (currentToken.length() > 0) {
        tokens.add(currentToken.toString());
    }
    return tokens;
}

比如输入IF count IS 0 THEN GOTO '5',会被拆成["IF", "count", "IS", "0", "THEN", "GOTO", "'5'"],完美保留引号内的行号。

三、核心执行逻辑

接下来要维护程序的执行状态:变量存储、当前行号,然后循环解析每行命令。这里用HashMap存变量,用switch处理不同命令:

import java.util.Map;
import java.util.HashMap;

private Map<String, Integer> variables = new HashMap<>();
private int currentLine = 0;

// 执行加载好的程序
public void executeProgram() {
    while (currentLine < programLines.size()) {
        String line = programLines.get(currentLine);
        List<String> tokens = tokenizeLine(line);

        if (tokens.isEmpty()) {
            currentLine++;
            continue;
        }

        String command = tokens.get(0).toUpperCase();
        switch (command) {
            case "PRINT":
                handlePrint(tokens);
                currentLine++;
                break;
            case "IF":
                boolean conditionMet = handleIf(tokens);
                if (conditionMet) {
                    // 处理THEN后的命令(比如GOTO)
                    List<String> thenTokens = tokens.subList(5, tokens.size());
                    handleThenCommand(thenTokens);
                } else {
                    currentLine++;
                }
                break;
            case "GOTO":
                handleGoto(tokens);
                // GOTO后直接跳转,不用自增行号
                break;
            case "END":
                return; // 终止程序
            default:
                // 处理变量赋值
                handleAssignment(tokens);
                currentLine++;
                break;
        }
    }
}

各命令的具体实现

1. 变量赋值

处理variable = expression格式,这里简化支持数值和变量引用,复杂表达式可以后续扩展:

private void handleAssignment(List<String> tokens) {
    if (tokens.size() < 3 || !tokens.get(1).equals("=")) {
        System.err.println("语法错误:无效赋值,行号 " + (currentLine + 1));
        currentLine++;
        return;
    }
    String varName = tokens.get(0);
    String expression = String.join(" ", tokens.subList(2, tokens.size()));

    try {
        // 先尝试解析为数字
        int value = Integer.parseInt(expression);
        variables.put(varName, value);
    } catch (NumberFormatException e) {
        // 数字解析失败,尝试读取已有变量
        if (variables.containsKey(expression)) {
            variables.put(varName, variables.get(expression));
        } else {
            System.err.println("语法错误:无效表达式,行号 " + (currentLine + 1));
        }
    }
}

2. PRINT命令

打印指定变量的值:

private void handlePrint(List<String> tokens) {
    if (tokens.size() < 2) {
        System.err.println("语法错误:PRINT缺少变量,行号 " + (currentLine + 1));
        return;
    }
    String varName = tokens.get(1);
    if (variables.containsKey(varName)) {
        System.out.println(variables.get(varName));
    } else {
        System.err.println("错误:变量 " + varName + " 未定义,行号 " + (currentLine + 1));
    }
}

3. GOTO命令

跳转到指定行(注意文件行号是从1开始,ArrayList是0索引,要转成索引):

private void handleGoto(List<String> tokens) {
    if (tokens.size() < 2) {
        System.err.println("语法错误:GOTO缺少行号,行号 " + (currentLine + 1));
        currentLine++;
        return;
    }
    String lineStr = tokens.get(1).replaceAll("'", ""); // 去掉单引号
    try {
        int targetLine = Integer.parseInt(lineStr) - 1; // 转成ArrayList索引
        if (targetLine >= 0 && targetLine < programLines.size()) {
            currentLine = targetLine;
        } else {
            System.err.println("错误:行号超出范围,行号 " + (currentLine + 1));
            currentLine++;
        }
    } catch (NumberFormatException e) {
        System.err.println("语法错误:无效行号格式,行号 " + (currentLine + 1));
        currentLine++;
    }
}

4. IF命令

处理IF variable IS value THEN ...的条件判断:

private boolean handleIf(List<String> tokens) {
    if (tokens.size() < 5 || !tokens.get(2).equals("IS") || !tokens.get(4).equals("THEN")) {
        System.err.println("语法错误:无效IF语句,行号 " + (currentLine + 1));
        return false;
    }
    String varName = tokens.get(1);
    String valueStr = tokens.get(3);

    if (!variables.containsKey(varName)) {
        System.err.println("错误:变量 " + varName + " 未定义,行号 " + (currentLine + 1));
        return false;
    }

    try {
        int targetValue = Integer.parseInt(valueStr);
        return variables.get(varName) == targetValue;
    } catch (NumberFormatException e) {
        System.err.println("语法错误:无效数值,行号 " + (currentLine + 1));
        return false;
    }
}

// 处理THEN后的命令
private void handleThenCommand(List<String> thenTokens) {
    String command = thenTokens.get(0).toUpperCase();
    switch (command) {
        case "GOTO":
            handleGoto(thenTokens);
            break;
        default:
            System.err.println("错误:不支持的THEN命令,行号 " + (currentLine + 1));
            currentLine++;
            break;
    }
}

四、测试示例

假设你的测试文件program.txt内容如下:

count = 0
PRINT count
IF count IS 0 THEN GOTO '4'
count = 2
PRINT count
count = 1
PRINT count
END

在main方法中调用执行:

public static void main(String[] args) {
    SimpleInterpreter interpreter = new SimpleInterpreter();
    try {
        interpreter.loadProgram("program.txt");
        interpreter.executeProgram();
    } catch (IOException e) {
        System.err.println("加载程序失败:" + e.getMessage());
    }
}

执行后会依次输出0、2、1,然后终止。

五、扩展建议

  • 支持复杂表达式:可以用递归下降解析器实现加减乘除,或者借助Java的ScriptEngineManager来计算表达式。
  • 支持字符串变量:把variables改成Map<String, Object>,处理字符串赋值和打印。
  • 增强错误处理:添加更详细的语法错误提示,比如指出错误位置。
  • 支持注释:读取文件时跳过以//或#开头的行。

内容的提问来源于stack exchange,提问作者Daria Jones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:58:26