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

C初始化语句无效词法单元识别异常问题求助

修复C初始化语句词法单元识别的两个核心问题

问题根源分析

  1. 空白字符未过滤:代码中定义了isValidLexeme但未实际调用,导致空白lexeme被送入标识符检查逻辑,触发无意义的Invalid identifier: 错误。
  2. 状态变量逻辑完全错误:isInvalidIdentifier的逻辑颠倒,一旦标记为true,后续有效元素会被错误加入无效列表;同时未区分=、;、,等语法符号,将其当作标识符检查。
  3. 无上下文的遍历逻辑:没有遵循C初始化语句的语法结构(类型 → 标识符 → [= 常量] → [, 标识符 → ...] → ;),所有非类型的lexeme都被当作标识符验证,忽略了不同位置的元素类型要求。

修复后的完整代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LexemeValidator {
    private static ArrayList<String> findInvalidLexemes(String[] lexemes) {
        ArrayList<String> invalidLexemes = new ArrayList<>();
        if (lexemes == null || lexemes.length == 0) {
            return invalidLexemes;
        }

        // 跟踪当前语法状态
        enum LexState {
            EXPECT_TYPE, EXPECT_IDENTIFIER, EXPECT_ASSIGN, EXPECT_CONSTANT, EXPECT_SEPARATOR
        }

        LexState currentState = LexState.EXPECT_TYPE;

        for (String lexeme : lexemes) {
            // 先过滤空白lexeme
            if (!isValidLexeme(lexeme)) {
                continue;
            }

            switch (currentState) {
                case EXPECT_TYPE:
                    if (lexeme.equals("int") || lexeme.equals("float")) {
                        currentState = LexState.EXPECT_IDENTIFIER;
                    } else {
                        invalidLexemes.add("Invalid data type: " + lexeme);
                        // 类型错误后继续处理后续元素
                        currentState = LexState.EXPECT_IDENTIFIER;
                    }
                    break;

                case EXPECT_IDENTIFIER:
                    if (isValidIdentifier(lexeme)) {
                        currentState = LexState.EXPECT_ASSIGN;
                    } else {
                        invalidLexemes.add("Invalid identifier: " + lexeme);
                        // 标识符错误后,等待分隔符切换状态
                        currentState = LexState.EXPECT_SEPARATOR;
                    }
                    break;

                case EXPECT_ASSIGN:
                    if (lexeme.equals("=")) {
                        currentState = LexState.EXPECT_CONSTANT;
                    } else if (lexeme.equals(",")) {
                        currentState = LexState.EXPECT_IDENTIFIER;
                    } else if (lexeme.equals(";")) {
                        currentState = LexState.EXPECT_TYPE;
                    } else {
                        // 省略赋值符号的情况,直接进入分隔符状态
                        currentState = LexState.EXPECT_SEPARATOR;
                    }
                    break;

                case EXPECT_CONSTANT:
                    if (lexeme.matches("\\d+(\\.\\d+)?")) {
                        if (!isValidInt(lexeme) && !isValidFloat(lexeme)) {
                            invalidLexemes.add("Invalid constant value: " + lexeme);
                        }
                    } else {
                        invalidLexemes.add("Invalid constant value: " + lexeme);
                    }
                    currentState = LexState.EXPECT_SEPARATOR;
                    break;

                case EXPECT_SEPARATOR:
                    if (lexeme.equals(",")) {
                        currentState = LexState.EXPECT_IDENTIFIER;
                    } else if (lexeme.equals(";")) {
                        currentState = LexState.EXPECT_TYPE;
                    }
                    // 其他符号直接跳过,不报错
                    break;
            }
        }

        return invalidLexemes;
    }

    private static boolean isValidLexeme(String lexeme) {
        return lexeme != null && !lexeme.isBlank();
    }

    private static boolean isValidIdentifier(String identifier) {
        if (identifier == null) {
            return false;
        }

        String regex = "^([a-zA-Z_$][a-zA-Z\\d_$]*)$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(identifier);

        if (!m.matches()) {
            return false;
        }

        String[] reservedKeywords = {"int", "float", "double", "char", "short", "long", "unsigned", "signed",
                "void", "for", "while", "do", "if", "else", "switch", "case", "break", "continue",
                "return", "goto", "struct", "union", "typedef", "enum", "static", "extern", "const",
                "volatile", "register", "auto"};
        return !Arrays.asList(reservedKeywords).contains(identifier);
    }

    private static boolean isValidFloat(String lexeme) {
        try {
            float floatValue = Float.parseFloat(lexeme);
            return floatValue >= 0 && floatValue <= 3.4028235E38;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    private static boolean isValidInt(String lexeme) {
        try {
            int intValue = Integer.parseInt(lexeme);
            return intValue >= 0 && intValue <= 2147483647;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    // 测试方法
    public static void main(String[] args) {
        String input = "int 2323 = 23. y = notvalid, z;";
        String[] lexemes = input.split("(?<=\\W)|(?=\\W)"); // 按非单词字符分割,保留符号
        ArrayList<String> result = findInvalidLexemes(lexemes);
        for (String error : result) {
            System.out.println(error);
        }
    }
}

关键改动说明

  1. 过滤空白单元:遍历前调用isValidLexeme跳过空白字符,解决空白被当作无效标识符的问题。
  2. 语法状态跟踪:新增LexState枚举,严格按照C初始化语句的语法流程切换状态,确保只在正确阶段检查对应类型的lexeme。
  3. 区分语法符号:=、;、,仅作为状态切换触发条件,不进行标识符或常量验证,避免错误标记。
  4. 修正状态逻辑:移除错误的isInvalidIdentifier变量,改为基于语法状态的精准检查,解决第一个无效标识符后后续元素错误标记的问题。
  5. 完善常量检查:仅在EXPECT_CONSTANT状态下验证常量,合并int和float有效性判断,避免重复检查。

测试结果

输入"int 2323 = 23. y = notvalid, z;",输出与预期一致:

Invalid identifier: 2323
Invalid identifier: notvalid

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:37:06