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

Java Lexer中Switch语句无法识别空格与"+"运算符的问题求助

词法分析器空格与运算符识别问题排查

实现的词法分析器通过cursor跟踪处理位置,输入"10 + 15 * (10 + 3 * 3 - 2)"时,能正常处理数字,但cursor到达位置2(对应空格字符)时,Switch语句无法识别空格与"+"运算符,抛出错误"Expected a valid token at position: 2",无法推进到"+"运算符。

相关代码

Main类

import Class.Parser;
import Class.Lexer;
import Model.Token;

import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception {
          Lexer lexer = new Lexer("10 + 15 * (10 + 3 * 3 - 2)");
          List <Token> tokens = lexer.getTokens();
    }
}

Lexer类

package Class;
import Model.Spec;
import Model.Token;
import Model.TokenType;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.ToIntFunction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Lexer {
    private String _input;
    private int _cursor;

    public Lexer() {
        this._cursor = 0;
    }

    public Lexer(String _Input) {
        this._input = _Input;
        this._cursor = 0;
    }

    public List<Token> getTokens() throws Exception {
        List<Token> tokens = new ArrayList<>();
        if (this._cursor < this._input.length() != true) {
            return null;
        }
        String input = this._input.substring(this._cursor);
        while (this._cursor < this._input.length()) {
            switch (input) {
                case "":
                case "\n":
                case "\t":
                case "\s":
                    break;
                case "+":
                    tokens.add(new Token(TokenType.PLUS, "+"));
                    break;
                case "-":
                    tokens.add(new Token(TokenType.MINUS, "-"));
                    break;
                case "*":
                    tokens.add(new Token(TokenType.MULTIPLY, "*"));
                    break;
                case "/":
                    tokens.add(new Token(TokenType.DIVIDE, "/"));
                    break;
                case "(":
                    tokens.add(new Token(TokenType.HAAKJEOPEN, "("));
                    break;
                case ")":
                    tokens.add(new Token(TokenType.HAAKJESLUIT, ")"));
                    break;
                default:
                    if (Character.isDigit(this._input.charAt(this._cursor))) {
                        StringBuilder number = new StringBuilder();
                        while (this._cursor < this._input.length() && Character.isDigit(this._input.charAt(this._cursor))) {
                            number.append(this._input.charAt(this._cursor));
                            this._cursor++;
                        }
                        tokens.add(new Token(TokenType.NUMERICAL, number.toString()));
                        this._cursor--;
                    }
                    else {
                        throw new Exception("Expected a valid token at position:" + " " + this._cursor);
                    }
            }
            this._cursor++;
        }
        tokens.add(new Token(TokenType.EOF, "EOF"));
        return tokens;
    }
}

问题原因

  1. Switch判断对象错误:代码中switch (input)的input是从当前cursor到末尾的完整子串(比如cursor在位置2时,input是" + 15 * (10 + 3 * 3 - 2)"),而非当前cursor指向的单个字符,导致无法匹配case中定义的单个空格、运算符等字符,直接进入default分支抛出错误。
  2. 空格匹配错误:Java中普通字符串匹配空格需用" ",代码中使用的"\s"是正则表达式的空格写法,实际会被解析为ASCII换页符(\u000C),无法匹配输入中的空格。
  3. 冗余变量与cursor操作问题:String input = this._input.substring(this._cursor);是冗余变量,且数字处理后_cursor--会抵消循环末尾的_cursor++,逻辑冗余。

修复方案

修改Lexer类的getTokens方法,核心调整如下:

  • 将Switch判断对象改为当前cursor指向的单个字符_input.charAt(_cursor)
  • 修正空格匹配为" "
  • 移除冗余的input变量
  • 调整数字处理的cursor逻辑,避免重复递减

修改后的Lexer类代码

package Class;
import Model.Token;
import Model.TokenType;
import java.util.ArrayList;
import java.util.List;

public class Lexer {
    private String _input;
    private int _cursor;

    public Lexer() {
        this._cursor = 0;
    }

    public Lexer(String _Input) {
        this._input = _Input;
        this._cursor = 0;
    }

    public List<Token> getTokens() throws Exception {
        List<Token> tokens = new ArrayList<>();
        if (_cursor >= _input.length()) {
            return tokens;
        }

        while (_cursor < _input.length()) {
            char currentChar = _input.charAt(_cursor);
            switch (currentChar) {
                case ' ':
                case '\n':
                case '\t':
                    // 跳过空白字符,不生成token
                    break;
                case '+':
                    tokens.add(new Token(TokenType.PLUS, "+"));
                    break;
                case '-':
                    tokens.add(new Token(TokenType.MINUS, "-"));
                    break;
                case '*':
                    tokens.add(new Token(TokenType.MULTIPLY, "*"));
                    break;
                case '/':
                    tokens.add(new Token(TokenType.DIVIDE, "/"));
                    break;
                case '(':
                    tokens.add(new Token(TokenType.HAAKJEOPEN, "("));
                    break;
                case ')':
                    tokens.add(new Token(TokenType.HAAKJESLUIT, ")"));
                    break;
                default:
                    if (Character.isDigit(currentChar)) {
                        StringBuilder number = new StringBuilder();
                        while (_cursor < _input.length() && Character.isDigit(_input.charAt(_cursor))) {
                            number.append(_input.charAt(_cursor));
                            _cursor++;
                        }
                        tokens.add(new Token(TokenType.NUMERICAL, number.toString()));
                        // 回退cursor,避免循环末尾的cursor++跳过下一个字符
                        _cursor--;
                    } else {
                        throw new Exception("Expected a valid token at position:" + " " + _cursor);
                    }
            }
            _cursor++;
        }
        tokens.add(new Token(TokenType.EOF, "EOF"));
        return tokens;
    }
}

内容的提问来源于stack exchange,提问作者Cezar P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:45:13