使用PLY处理带转义换行的单行注释时的匹配错误问题
问题原因
你遇到的问题核心是正则分支的匹配优先级问题:
- 你原来使用的正则
r'.|\\\n'会优先匹配左侧的单个任意字符(.),当遇到反斜杠\时,会先匹配单个\作为普通注释内容,剩下的换行符\n就会触发COMMENT状态的结束规则,导致换行后的内容直接回到初始状态被解析为普通token。 - 普通换行的结束规则本身没有问题,问题是转义换行的组合
\\\n没有被优先匹配,提前吃掉反斜杠加换行的两个字符。
修复方案
调整COMMENT状态的规则顺序,把转义换行的匹配放在最高优先级,单独作为规则实现,确保转义换行不会被拆分匹配:
- 优先匹配转义换行
\\\n,匹配到直接丢弃,保持在COMMENT状态 - 匹配所有非换行的注释内容,直接丢弃
- 最后匹配普通换行,结束注释切回初始状态
修改后示例代码
import ply.lex as lex states = ( ('COMMENT', 'exclusive'), ) # 按需添加你需要的其他token tokens = ('NUMBER',) # 初始状态匹配# 进入注释状态 def t_begin_COMMENT(t): r'\#' t.lexer.begin('COMMENT') # 最高优先级:匹配转义换行,直接丢弃 def t_COMMENT_escaped_newline(t): r'\\\n' pass # 匹配所有非换行的注释内容,直接丢弃 def t_COMMENT_content(t): r'[^\n]' pass # 匹配普通换行,结束注释 def t_COMMENT_end(t): r'\n' t.lexer.begin('INITIAL') def t_COMMENT_error(t): t.lexer.skip(1) # 示例数字token规则 def t_NUMBER(t): r'\d+' t.value = int(t.value) return t # 初始状态忽略空格 t_ignore = ' \t' def t_error(t): t.lexer.skip(1) # 测试 lexer = lex.lex() string = "# test \\\ns \n4" lexer.input(string) for tok in lexer: print(tok)
运行上述代码只会输出NUMBER: 4,符合预期。
内容的提问来源于stack exchange,提问作者Awerde
相关产品推荐
相关产品推荐

