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

自制Python编译器词法分析将符号识别为换行问题求助

问题原因分析

你遇到的异常是两个问题共同导致的:

  • 第一个是明确的语法错误:你定义的LETTER数组中,大写字母'M'的末尾缺少逗号,Python会自动拼接相邻的字符串字面量,导致'M'和下一行开头的'N'被合并为'MN'存入数组。这会导致大写字母列表缺失单独的'M'和'N',后续识别包含大写M、N的标识符时会出错。
  • 第二个是你当前异常输出的核心原因:你使用文本模式打开文件,Python的文本模式会自动对不同平台的换行符做转换(比如Windows下\r\n会被转换为\n),但seek()和tell()操作的是文件的原始字节偏移,而非转换后的字符位置。你在识别标识符的逻辑中执行input_file.seek(input_file.tell() - 1)时,偏移计算可能出现错位,导致回退后没有指向预期的;符号,反而指向了换行符的字节位置,所以下次读取字符时拿到的是换行而非分号,表现为分号被当成了换行处理。
    你在prod和;之间加空格、多加分号等操作能恢复正常,是因为这些场景下回退的偏移位置刚好对齐了单字节字符的边界,没有触发换行转换的偏移错位问题。
修复方案
  1. 先修复LETTER数组的语法错误,在大写'M'后面补充逗号:
LETTER = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
          'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
          'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
          'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
          'X', 'Y', 'Z']
  1. 彻底规避文本模式文件指针的坑,建议将文件内容一次性读入内存,用下标指针操作字符流,逻辑更可控,也不会出现偏移错位问题:
WHITESPACE = [' ', '\n', '\r', '\v', '\t', '\f']
SYMBOL = [';', ':', ',', '[', ']', '{', '}', '(', ')', '+', '-', '*', '=', '<']

# 替换原有的文件打开和读取逻辑
with open('input.txt', 'r', encoding='utf-8') as f:
    content = f.read()
ptr = 0
line_num = 1

def get_token():
    global ptr, line_num
    if ptr >= len(content):
        return None
    value = content[ptr]
    ptr += 1

    if value in WHITESPACE:
        start = line_num
        if value == '\n':
            line_num += 1
        return "whitespace", value, start
    
    elif value in LETTER:
        while ptr < len(content):
            input_char = content[ptr]
            ptr +=1
            if input_char in LETTER:
                value += input_char
            elif input_char in SYMBOL or input_char in WHITESPACE:
                ptr -=1
                return 'id', value, line_num
            else:
                value += input_char
                return 'invalid', value, line_num
        return 'id', value, line_num
    elif value in SYMBOL:
        return 'symbol', value, line_num
    else:
        return 'invalid', value, line_num

# 调用逻辑不变
while True:
    token = get_token()
    if token:
        print(f"({token[2]}, {token[0]}, {token[1]})")
    else:
        break

内容的提问来源于stack exchange,提问作者negar.n

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 00:15:06