如何在PLY中配置默认TEXT Token以捕获非匹配内容?
PLY Lex 实现TEXT与多信号Token的正确分词
你的问题核心是PLY的lexer匹配规则导致TEXT吃掉了全部内容——[\s\S]+是贪婪匹配,会优先匹配最长的字符串,直接覆盖了后面的信号规则。这里给你一个简洁的方案,不用写复杂正则,还能轻松扩展十多种信号:
解决方案代码
import ply.lex as lex import re # 把所有信号按「Token名称: 匹配字符串」的格式存字典,新增信号直接加这里 signals = { 'SIGNAL1': 'HELP!', 'SIGNAL2': 'OVER HERE!' } # 生成Token列表:先TEXT,再所有信号 tokens = ['TEXT'] + list(signals.keys()) # 动态生成TEXT的正则:匹配任意字符,直到遇到任意一个信号(非贪婪模式) escaped_signals = [re.escape(signal_str) for signal_str in signals.values()] t_TEXT = r'(?:(?!' + '|'.join(escaped_signals) + r').)+' # 动态绑定每个信号的Token规则(自动转义特殊字符,避免正则冲突) for token_name, signal_str in signals.items(): globals()[f't_{token_name}'] = re.escape(signal_str) # 测试示例 data = "some random text HELP! lorem ipsum OVER HERE! more end text" lexer = lex.lex() lexer.input(data) while True: tok = lexer.token() if not tok: break print(f'({tok.type}, "{tok.value}")')
代码说明
- 信号管理:把所有信号放进字典,新增信号只需要在字典里加键值对,不用改其他逻辑,适合你十多种信号的场景。
- TEXT正则生成:用
(?!信号)的负向前瞻语法,让TEXT只匹配「不会触发任何信号的连续字符」,自动停在信号前,避免贪婪吃掉全部内容。 - 自动转义:用
re.escape()处理信号字符串,比如HELP!里的!是正则特殊字符,转义后不会引发匹配错误。
执行结果
运行后会输出:
(TEXT, "some random text ") (SIGNAL1, "HELP!") (TEXT, " lorem ipsum ") (SIGNAL2, "OVER HERE!") (TEXT, " more end text")
内容的提问来源于stack exchange,提问作者Anne Aunyme
相关产品推荐
相关产品推荐

