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

Python PLY Lex正则匹配异常求助:TypeError未知文本问题

问题分析与解决方案

你的PLY Lex解析器出问题的核心原因是正则表达式中的^符号没有按你预期的方式工作。

在默认的正则模式下,^只会匹配整个输入字符串的起始位置,而不是每行的开头。你的原代码中,第一个#行能匹配成功是因为它刚好在输入的最开始,但后续的#行因为不是整个输入的开头,所以t_COMMENT的^\#.*\n根本匹配不到;同样,t_OTHER的^[^\#].*\n也只能匹配输入开头的非#行,后面的非#行同样无法被匹配。这些未被匹配的字符会不断累积,最终触发t_error抛出异常。

修复方案

我们需要启用正则的多行模式,让^匹配每行的开头,$匹配每行的结尾。有两种方式可以实现:

方式1:在正则中添加多行修饰符(?m)

修改你的正则表达式,给每个token的规则加上(?m)前缀,这样就能让^和$作用于每行:

from ply import lex

tokens = (
    'COMMENT',
    'OTHER'
)

# (?m)启用多行模式,^匹配每行开头,匹配整行注释
t_COMMENT = r'(?m)^#.*\n'
# 匹配每行开头非#的整行内容
t_OTHER = r'(?m)^[^#].*\n'

def t_error(t):
    # 处理空行(仅含换行符)的情况,避免触发错误
    if t.value[0] == '\n':
        t.lexer.skip(1)
    else:
        raise TypeError("Unknown text '%s'" % (t.value,))

# 初始化lexer
lexer = lex.lex()

# 你的输入内容
input_text = """# This is a real comment
#And this one also
#/*
# *
# *Variable de feeu
# */
ma_var: True
It is done, over, kaput
"""

# 解析并输出结果
lexer.input(input_text)
for tok in iter(lexer.token, None):
    print(repr(tok.type), repr(tok.value))

方式2:全局启用多行模式

在调用lex.lex()时传入reflags=re.MULTILINE参数,这样所有正则规则都会自动应用多行模式:

import re
from ply import lex

tokens = (
    'COMMENT',
    'OTHER'
)

# 现在^会匹配每行开头
t_COMMENT = r'^#.*\n'
t_OTHER = r'^[^#].*\n'

def t_error(t):
    if t.value[0] == '\n':
        t.lexer.skip(1)
    else:
        raise TypeError("Unknown text '%s'" % (t.value,))

# 全局启用多行模式
lexer = lex.lex(reflags=re.MULTILINE)

# 输入和解析部分与方式1一致

额外说明

  • 我在t_error中添加了对空行的处理:如果遇到单独的换行符,直接跳过,避免因为空行触发错误。
  • PLY的token匹配规则是最长匹配优先,如果多个规则都能匹配,会选择最长的那个;长度相同时,先定义的规则优先。这里我们的两个规则都是匹配整行,长度一致,所以先定义的COMMENT会优先匹配,符合你的需求。

运行修改后的代码,就能正确解析所有的注释行和非注释行啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:26:23