Access and print AST from ply yacc(从PLY yacc访问并打印AST)
                            本文介绍了从PLY yacc访问并打印AST的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
                        
                        问题描述
我正在使用PLY编译一种语言(C-减法),以构建词法分析器和解析器。在PLY文档中很清楚,构建AST完全由用户决定(https://www.dabeaz.com/ply/ply.html#ply_nn2):
Yacc.py的输出通常是抽象语法树(AST)。但是,这完全由用户决定。那么,在我的词法分析器和解析器正常工作的情况下,我如何构建一个AST阅读器(因为正如文档中所说,输出是一个AST,所以我只需要访问它)?我正在尝试使用下面的代码,但仅收到
None作为响应。
AST代码:
def dumpast(node):
    _dumpast(node)
    print('pass 3')
    print('')
def _dumpast(node, level=0):
    if isinstance(node, tuple):
        indent(level)
        nchildren = len(node) - 1
        print("(%s" % node[0], end='')
        if nchildren > 0:
            print(" ", end='')
        for c in range(nchildren):
            _dumpast(node[c+1], level+1)
            if c != nchildren-1:
                print(' ', end='')
        print(")", end='')
    elif isinstance(node, list):
        indent(level)
        nchildren = len(node)
        print("[", end='')
        if nchildren > 0:
            print(" ", end='')
        for c in range(nchildren):
            _dumpast(node[c], level+1)
            if c != nchildren-1:
                print(' ', end='')
        print("]", end='')
    else:
        print("%s" % str(node), end='')
def indent(level):
    print('')
    for i in range(level):
        print('  |',end='')
和main.py:
import ply.yacc as yacc
import ply.lex as lex
from tabulate import tabulate
import sys
from lexer import *
from parser import Parser
from ast import dumpast
lexer = lex.lex()
print('pass 1')
parser = yacc.yacc(module=Parser)
with open(sys.argv[1], 'r') as f:
    dumpast(parser.parse(f.read(),lexer))
    print('pass 2')
响应:
通过%1
非第3页通过2
我做错了什么吗?或者,有没有人可以分享AST建筑教程来访问PLY?
编辑:包括parser.py以显示解析的工作原理:
import ply.yacc as yacc
import lexer
from state import state
class Parser():
    tokens = lexer.tokens
    def p_program(p):
        'program : declaration_list'
        state.ast = p[1]
        print('passou 4')
    def p_declaration_list(p):
        '''declaration_list : declaration_list declaration
                            | declaration'''
        if len(p) == 3:
            p[0] = p[1]
            p[0].append(p[2])
        else:
            p[0] = p[1]
    def p_declaration(p):
        '''declaration : var_declaration 
                       | fun_declaration'''
        state.ast = p[1]
    def p_var_declaration(p):
        '''var_declaration : type_specifier ID 
                           | type_specifier ID LBRACKET NUM RBRACKET'''
        if len(p) == 3:
            p[0] = ('ASSIGN', ('ID', p[1]))
        else:
            p[0] = ('ASSIGN', ('ID', p[1]), ('NUM', p[4]))
    def p_type_specifier(p):
        '''type_specifier : INT 
                          | VOID'''
        state.ast = p[1]
    def p_fun_declaration(p):
        'fun_declaration : type_specifier ID LPAREN params RPAREN compound_stmt'
        p[0] = ('ASSIGN', ('ID', p[1]), p[4], p[6])
    def p_params(p):
        '''params : param_list 
                  | VOID'''
        state.ast = p[1]
    def p_param_list(p):
        '''param_list : param_list COLON param 
                      | param'''
        if len(p) == 4:
            p[0] = p[1]
            p[0].append(p[3])
        else:
            p[0] = p[1]
    def p_param(p):
        '''param : type_specifier ID 
                 | type_specifier ID LBRACKET RBRACKET'''
        p[0] = ('ASSIGN', ('ID', p[1]))
        
    def p_compound_stmt(p):
        'compound_stmt : LKEY local_declarations statement_list RKEY'
        p[0] = (p[2], p[3])
    def p_local_declarations(p):
        '''local_declarations : local_declarations var_declaration
                              | empty'''
        if len(p) > 1:
            p[0] = (p[1], p[2])
        else:
            pass
    def p_statement_list(p):
        '''statement_list : statement_list statement
                          | empty'''
        if len(p) > 1:
            p[0] = p[1]
            p[0].append(p[3])
        else:
            pass
    def p_statement(p):
        '''statement : expression_stmt
                     | compound_stmt
                     | selection_stmt
                     | iteration_stmt
                     | return_stmt'''
        state.ast = p[1]
                    
    def p_expression_stmt(p):
        '''expression_stmt : expression SEMICOLON
                           | SEMICOLON'''
        if len(p) == 3:
            p[0] = p[1]
        else:
            pass
    def p_selection_stmt(p):
        '''selection_stmt : IF LPAREN expression RPAREN statement 
                          | IF LPAREN expression RPAREN statement ELSE statement'''
        if len(p) == 6:
            p[0] = ('IF', p[3], p[5], ('NIL',))
        else:
            p[0] = ('IF', p[3], p[5], p[7])
    def p_iteration_stmt(p):
        'iteration_stmt : WHILE LPAREN expression RPAREN statement'
        p[0] = ('WHILE', p[3], p[5])
    def p_return_stmt(p):
        '''return_stmt : RETURN SEMICOLON
                       | RETURN expression SEMICOLON'''
        if len(p) == 3:
            p[0] = ('RETURN',)
        else:
            p[0] = ('RETURN', p[2])
    def p_expression(p):
        '''expression : var EQUAL expression 
                      | simple_expression'''
        if len(p) > 2:
            p[0] = ('ASSIGN', (p[1], p[3]))
        else:
            p[0] = [p[1]]
    def p_var(p):
        '''var : ID 
               | ID LBRACKET expression RBRACKET'''
        if len(p) == 2:
            p[0] = ('ID', p[1])
        else:
            p[0] = (('ID', p[1]), [p[3]])
    def p_simple_expression(p):
        '''simple_expression : additive_expression relop additive_expression
                             | additive_expression'''
        if len(p) == 4:
            p[0] = (p[1], ('RELOP', p[2]), p[3])
        else:
            p[0] = [p[1]]
    def p_relop(p):
        '''relop : LESSOREQUAL
                 | LESS
                 | GREAT
                 | GREATOREQUAL
                 | DOUBLEEQUAL
                 | NOTEQUAL'''
        p[0] = ('RELOP', p[1])
    def p_additive_expression(p):
        '''additive_expression : additive_expression addop term 
                               | term'''
        if len(p) == 4:
            p[0] = (p[1], p[2], p[3])
        else:
            p[0] = p[1]
    def p_addop(p):
        '''addop : PLUS
                 | MINUS'''
        p[0] = p[1]
                 
    def p_term(p):
        '''term : term mulop factor 
                | factor'''
        if len(p) == 4:
            p[0] = (p[1], p[2], p[3])
        else:
            p[0] = p[1]
    def p_mulop(p):
        '''mulop : MULT
                 | DIV'''
        p[0] = p[1]
    def p_factor(p):
        '''factor : LPAREN expression RPAREN
                  | var 
                  | call 
                  | NUM'''
        if len(p) == 4:
            p[0] = p[2]
        elif p == 'NUM':
            p[0] = ('ASSIGN', ('NUM', p[1]))
        else:
            p[0] = p[1]
    def p_call(p):
        'call : ID LPAREN args RPAREN'
        p[0] = (('ID', p[1]), p[3])
    def p_args(p):
        '''args : arg_list 
                | empty'''
        if p == '':
            pass
        else:
            state.ast = p[1]
    def p_args_list(p):
        '''arg_list : arg_list COLON expression 
                    | expression'''
        if len(p) == 4:
            p[0] = p[1]
            p[0].append(p[3])
        else:
            p[0] = p[1]
    def p_error(p):
        if not p:
            print("SYNTAX ERROR AT EOF")
    def p_empty(p):
        'empty :'
        pass
推荐答案
parser.parse()返回顶层还原操作放置到p[0]中的任何内容。您的顶级缩减操作不会将任何内容放入p[0]。所以parse函数返回None,这就是您传递给AST转储程序的内容。
state.ast这样的状态(或全局)变量来从PLY解析器返回值;这是一种您可能从不同解析器生成器的解决方案中复制的模式。我注意到,您还将state.ast赋值给state.ast,而不是在其他操作中设置p[0],即使在解析器生成器中也不可能是正确的,因为解析器生成器没有提供更方便的机制来返回顶级结果。这些也需要更正。
                        这篇关于从PLY yacc访问并打印AST的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
				 沃梦达教程
				
			本文标题为:从PLY yacc访问并打印AST
				
        
 
            
        
             猜你喜欢
        
	     - ";find_element_by_name(';name';)";和&QOOT;FIND_ELEMENT(BY NAME,';NAME';)";之间有什么区别? 2022-01-01
 - CTR 中的 AES 如何用于 Python 和 PyCrypto? 2022-01-01
 - YouTube API v3 返回截断的观看记录 2022-01-01
 - 计算测试数量的Python单元测试 2022-01-01
 - 我如何透明地重定向一个Python导入? 2022-01-01
 - 检查具有纬度和经度的地理点是否在 shapefile 中 2022-01-01
 - 如何使用PYSPARK从Spark获得批次行 2022-01-01
 - 使用 Cython 将 Python 链接到共享库 2022-01-01
 - 使用公司代理使Python3.x Slack(松弛客户端) 2022-01-01
 - 我如何卸载 PyTorch? 2022-01-01
 
