为何我的PLY解析器无法正确对Anytree节点进行分组?
问题根源
- 重复包装Node对象:所有语法规则返回的
p[n]本身已经是Node实例,你在为父节点指定children时额外嵌套了一层Node(p[n]),这会导致原有节点被转为字符串作为新节点的名称,原有的子树结构完全丢失。 - GROUP节点命名错误:直接使用LPAREN的token值
(作为分组节点的名称,不符合显示需求。 - 忽略字符规则不全:仅忽略制表符,未忽略空格,输入带空格的表达式会触发非法字符报错。
- 缺少运算符优先级声明:未定义运算符优先级和结合性,后续处理混合运算表达式时会出现移进归约冲突,导致解析逻辑错误。
修复后完整代码
import ply.yacc as yacc from anytree import Node, RenderTree import ply.lex as lex # 初始化token名称 tokens = ( 'INTEGER', 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'LPAREN', 'RPAREN', ) # 定义token正则规则 t_PLUS = r'\+' t_MINUS = r'-' t_TIMES = r'\*' t_DIVIDE = r'/' t_LPAREN = r'\(' t_RPAREN = r'\)' # 整数token处理 def t_INTEGER(t): r'\d+' t.value = int(t.value) return t # 忽略空格和制表符 t_ignore = ' \t' # 非法字符处理 def t_error(t): print("Illegal character '%s'" % t.value[0]) t.lexer.skip(1) # 构建词法分析器 lexer = lex.lex() # 定义运算符优先级和结合性 precedence = ( ('left', 'PLUS', 'MINUS'), ('left', 'TIMES', 'DIVIDE'), ) # 二元运算语法规则 def p_expression_binop(p): '''expression : expression PLUS expression | expression MINUS expression | expression TIMES expression | expression DIVIDE expression ''' # 直接使用已生成的Node对象,不要二次包装 p[0] = Node(p[2], children=[p[1], p[3]]) # 分组语法规则 def p_expression_group(p): 'expression : LPAREN expression RPAREN' # 分组节点命名为GROUP,直接传入子节点不二次包装 p[0] = Node('GROUP', children=[p[2]]) # 整数语法规则 def p_expression_number(p): 'expression : INTEGER' p[0] = Node(str(p[1])) def p_error(p): print("Input syntax error ") # 构建语法分析器 treeParser = yacc.yacc() while True: try: s = input("Calculate this >") except EOFError: break if not s: break ParsTree = treeParser.parse(s) print(RenderTree(ParsTree))
测试效果
输入 (2)+(2) 输出如下:
Calculate this >(2)+(2) Node('/+') ├── Node('/+/GROUP') │ └── Node('/+/GROUP/2') └── Node('/+/GROUP') └── Node('/+/GROUP/2')
完全符合预期的树结构。
内容的提问来源于stack exchange,提问作者Ha33i Tari
相关产品推荐
相关产品推荐

