如何使用Python PLY实现部分解析(逐表达式返回结果)?
使用Python PLY实现逐句解析的生成器方案
问题需求
想要用Python PLY实现部分解析:不需要一次性解析全部源码,而是每解析完一个完整表达式(比如示例中的句子+句号)就yield结果,交还控制权,实现类似for sent in parser.partial_parse(data)的逐句处理效果。
原代码会一次性解析所有句子并返回汇总结果,示例代码如下:
import ply.lex as lex import ply.yacc as yacc data = '''\ a sentence. another sentence. ''' tokens = ('WORD', 'DOT') t_WORD = r'\w+' t_DOT = r'\.' t_ignore = ' \t\n' lexer = lex.lex() def p_text(p): '''text : text sentence DOT | sentence DOT''' p[0] = '\n'.join(p[1:-1]) def p_sentence(p): '''sentence : sentence WORD | WORD''' p[0] = ' '.join(p[1:]) parser = yacc.yacc() print(parser.parse(data)) # 一次性输出所有句子
实现方案
核心思路是调整语法规则为单句解析,再通过生成器循环驱动解析器,每次完成一个句子的解析就返回结果,直到输入耗尽。具体步骤如下:
- 修改语法规则:将顶层规则改为单个
sentence DOT,让解析器每次只处理一个完整句子 - 编写生成器函数:手动控制解析器循环,每次解析后返回结果,重置解析器状态继续处理剩余输入
修改后的完整代码:
import ply.lex as lex import ply.yacc as yacc data = '''\ a sentence. another sentence. ''' # 词法分析部分不变 tokens = ('WORD', 'DOT') t_WORD = r'\w+' t_DOT = r'\.' t_ignore = ' \t\n' lexer = lex.lex() # 语法规则调整:顶层规则为单个句子+句号 def p_single_sentence(p): '''single_sentence : sentence DOT''' p[0] = p[1] # 直接返回句子内容 def p_sentence(p): '''sentence : sentence WORD | WORD''' p[0] = ' '.join(p[1:]) # 错误处理:忽略无法解析的内容,继续后续解析 def p_error(p): if p: lexer.skip(1) else: pass parser = yacc.yacc() # 生成器函数:实现逐句解析 def partial_parse(parser, input_data): lexer.input(input_data) while True: parser.restart() # 重置解析器状态,准备下一次解析 result = parser.parse(lexer=lexer, tracking=True) if result is None: break # 没有更多输入,终止循环 yield result # 测试逐句处理 for sent in partial_parse(parser, data): print(f"处理句子:{sent}") # do_something_with(sent)
关键说明
parser.restart():每次解析完一个句子后重置解析器状态,避免残留状态影响下一次解析tracking=True:让解析器跟踪lexer的位置,确保后续解析从当前位置继续读取输入- 错误处理函数
p_error:遇到无法解析的内容时跳过单个字符,保证解析可以继续进行
内容的提问来源于stack exchange,提问作者raywib
相关产品推荐
相关产品推荐

