使用ply与ast模块构建抽象语法树的示例或文档有哪些?
使用PLY与Python ast模块构建语法树的实用示例
以下是最小可运行的实现示例,可直接运行调试理解逻辑:
前置依赖安装
执行命令安装所需模块:pip install ply astor
完整实现示例
1. 词法分析器实现
import ply.lex as lex import ast # 定义词法单元类型 tokens = ( 'NUMBER', 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'LPAREN', 'RPAREN', ) # 定义符号匹配规则 t_PLUS = r'\+' t_MINUS = r'-' t_TIMES = r'\*' t_DIVIDE = r'/' t_LPAREN = r'\(' t_RPAREN = r'\)' def t_NUMBER(t): r'\d+' t.value = int(t.value) return t # 忽略空白字符 t_ignore = ' \t' def t_error(t): print(f"非法字符: {t.value[0]}") t.lexer.skip(1) lexer = lex.lex()
2. 语法分析器实现(直接生成Python AST)
import ply.yacc as yacc # 算术表达式优先级定义 precedence = ( ('left', 'PLUS', 'MINUS'), ('left', 'TIMES', 'DIVIDE'), ) def p_expression_plus(p): 'expression : expression PLUS term' p[0] = ast.BinOp(left=p[1], op=ast.Add(), right=p[3]) def p_expression_minus(p): 'expression : expression MINUS term' p[0] = ast.BinOp(left=p[1], op=ast.Sub(), right=p[3]) def p_expression_term(p): 'expression : term' p[0] = p[1] def p_term_times(p): 'term : term TIMES factor' p[0] = ast.BinOp(left=p[1], op=ast.Mult(), right=p[3]) def p_term_div(p): 'term : term DIVIDE factor' p[0] = ast.BinOp(left=p[1], op=ast.Div(), right=p[3]) def p_term_factor(p): 'term : factor' p[0] = p[1] def p_factor_num(p): 'factor : NUMBER' p[0] = ast.Constant(value=p[1]) def p_factor_expr(p): 'factor : LPAREN expression RPAREN' p[0] = p[2] def p_error(p): print(f"语法错误在: {p.value if p else '文件末尾'}") parser = yacc.yacc()
3. 效果测试
import astor # 测试用输入表达式 input_expr = "3 + 4 * (10 - 2)" # 解析生成AST ast_root = parser.parse(input_expr) # 补全Python AST必填的位置信息 ast.fix_missing_locations(ast_root) # 打印生成的Python代码 print(astor.to_source(ast_root)) # 执行AST验证结果 print(eval(compile(ast_root, filename='<ast>', mode='eval')))
核心注意事项
- 所有Python AST节点的属性需符合Python官方ast模块定义,可先通过
ast.dump(ast.parse("对应Python代码"), indent=2)打印目标结构,再对应写PLY生成规则 - 若要转译为Python之外的语言,可自行遍历生成的AST节点,按目标语言的语法规则拼接输出即可
- 复杂语法可通过扩展tokens、语法规则,对应生成ast.Assign、ast.FunctionDef、ast.If等节点实现
内容的提问来源于stack exchange,提问作者beton
相关产品推荐
相关产品推荐

