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

如何修复JavaScript Lexer将浮点数拆分为标识符与数字的问题?

修复Lexer浮点数识别问题的方案

问题根源

你的Lexer当前先检查字符是否属于字母数字(正则[a-zA-Z0-9]包含数字),所以当遇到浮点数的整数部分(比如7.24里的7)时,会优先进入字母数字处理分支,把7单独识别为数字/标识符,剩下的.24会被拆分为dot和number,导致浮点数被拆分。

修复步骤

1. 调整判断顺序:数字逻辑优先于字母数字逻辑

把数字识别的代码块移到字母数字识别的前面,确保数字开头的字符(包括带小数点的)先被处理。

2. 修正数字处理逻辑,避免单独小数点误判

在数字处理分支里,要确保:

  • 如果第一个字符是小数点,后面必须跟数字,否则抛出错误或者识别为单独的dot
  • 限制小数点只能出现一次

3. 保留单独小数点处理分支

合法浮点数的小数点由数字逻辑处理,单独的小数点(比如对象属性访问场景)仍由专门分支处理,避免冲突。

修改后的完整代码

function lexer(input) {
    const tokens = [];
    const keywords = new Set(['let', 'var', 'const', 'def', 'float', 'floater', 'double', 'int', 'integer', 'bool', 'boolean', 'string', 'char']);
    const alphaNumericRegex = /[a-zA-Z0-9]/;
    const digitRegex = /\d/;

    let current = 0;
    const length = input.length;

    while (current < length) {
        let char = input[current];

        // 跳过空白符
        if (char === ' ' || char === '\n') {
            current++;
            continue;
        }

        // 优先处理数字(包括浮点数)
        if (digitRegex.test(char) || (char === '.' && digitRegex.test(input[current + 1]))) {
            let numStart = current;
            let hasDecimal = false;
        
            while (digitRegex.test(char) || (!hasDecimal && char === '.')) {
                if (char === '.') {
                    hasDecimal = true;
                    // 确保小数点后有数字,否则报错
                    if (!digitRegex.test(input[current + 1])) {
                        throw new SyntaxError("Invalid number: trailing decimal point");
                    }
                }
                char = input[++current];
            }
        
            const numStr = input.slice(numStart, current);
            const num = parseFloat(numStr);
        
            if (isNaN(num)) {
                throw new SyntaxError("Invalid number");
            }
        
            tokens.push({ 
                type: Number.isInteger(num) ? 'integer' : 'float', 
                value: num 
            });
            continue;
        }

        // 处理字母数字(关键字/标识符)
        if (alphaNumericRegex.test(char)) {
            const wordStart = current;
            while (alphaNumericRegex.test(char)) {
                char = input[++current];
            }
            const word = input.slice(wordStart, current);

            if (keywords.has(word)) {
                tokens.push({ type: 'keyword', value: word });
            } else {
                tokens.push({ type: 'identifier', value: word });
            }
            continue;
        }

        // 处理字符串
        if (char === '"') {
            const strStart = ++current;
            while (input[current] !== '"') {
                if (++current >= length) throw new SyntaxError("Unterminated string literal");
            }
            const str = input.slice(strStart, current++);
            tokens.push({ type: 'string', value: str });
            continue;
        }

        // 处理字符字面量
        if (char === '\'') {
            const charValue = input[++current];
            if (input[++current] === '\'') {
                tokens.push({ type: 'char', value: charValue });
                current++;
            } else {
                throw new SyntaxError("Invalid character literal");
            }
            continue;
        }

        // 处理赋值符号
        if (char === '=') {
            tokens.push({ type: 'assign' });
            current++;
            continue;
        }

        // 处理分号
        if (char === ';') {
            tokens.push({ type: 'semicolon' });
            current++;
            continue;
        }

        // 处理单独的小数点(比如对象属性访问的点)
        if (char === '.') {
            tokens.push({ type: 'dot' });
            current++;
            continue;
        }

        // 未知字符跳过(可改为抛出错误)
        current++;
    }

    return tokens;
}

const code = `let value = 7.24;
var count = 5;
const pi = 3.14;
bool isTrue = true;
string message = "Hello";
char initial = 'A';`;

console.log(JSON.stringify(lexer(code), null, 2));

关键修改说明

  • 数字逻辑前置:确保7.24这类字符串会被完整识别,而不会被拆分为整数和小数点+小数两部分。
  • 小数点合法性校验:避免单独的.被误判为浮点数,同时防止出现7.这类不合法的数字格式。
  • 区分数值类型:将原统一的number类型拆分为integer和float,让token类型更精准(不需要的话可改回number)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:37:03