提问人:Ackeem Mclennon 提问时间:11/17/2023 更新时间:11/17/2023 访问量:12
如何在PLY中正确实现抽象语法树?
How to Properly Implement an Abstract Syntax Tree in PLY?
问:
嗨,大家好,我对编译器设计比较陌生,我正在寻求一些关于创建 AST 以及在树上执行语义检查和代码生成的帮助。请参阅下面我的解析器的源代码。还要注意。我的词法分析器的实现工作正常,所以我选择省略它。
import ply.yacc as yacc
from adapscriptlexer import tokens
from Node import*
precedence = (
('nonassoc','GE', 'LE', 'EQ', 'NE', 'GT', 'LT', 'OR'),
('left', 'ADD', 'SUB'),
('left', 'MUL', 'DIV'),
('right', 'UNARY')
)
def p_program(p):
'''program : programStart'''
p[0] = p[1]
def p_programStart(p):
'''programStart : FUNC INIT "(" ")" "{" statements "}" '''
def p_statements(p):
'''statements : statement
| statements statement
'''
def p_statement(p):
'''statement : function_calls
| condition
| function_declarations
| expression
| loops
| RETURN expression
| PRINT "(" expression ")"
| assignment
'''
def p_function_declarations(p):
'''function_declarations : function_declaration'''
def p_function_declaration(p):
'''function_declaration : FUNC IDENTIFIER "(" ")" ":" datatype "{" function_body "}" '''
def p_function_body(p):
'''function_body : statements'''
def p_function_calls(p):
'''function_calls : IDENTIFIER "(" ")"
| IDENTIFIER "(" ")" function_calls
| IDENTIFIER "(" parameters ")"
| IDENTIFIER "(" parameters ")" function_calls'''
def p_parameters(p):
'''parameters : parameterList'''
def p_parameterList(p):
'''parameterList : parameter
| parameter "," parameterList'''
def p_parameter(p):
'''parameter : datatype IDENTIFIER'''
def p_datatype(p):
'''datatype : INT
| FLOAT
| STRING
| ADAPT
| VOID'''
def p_expression(p):
'''expression : atoms
| paren_expr
| binary_expr'''
def p_atom(p):
'''atoms : INT_VALUE
| FLOAT_VALUE
| STRING_VALUE
| variable'''
def p_variable(p):
'''variable : IDENTIFIER '''
def p_paren_expr(p):
'''paren_expr : "(" expression ")"'''
def p_binary_expr(p):
'''binary_expr : atoms ADD expression
| atoms SUB expression
| atoms MUL expression
| atoms DIV expression
| atoms OR expression
| atoms LE expression
| atoms GE expression
| atoms EQ expression
| atoms NE expression
| atoms GT expression
| atoms LT expression
| UNARY atoms
| atoms UNARY'''
p[0] = BinOpNode(p[2], p[1], p[3])
def p_assignment(p):
'''assignment : datatype IDENTIFIER EQUAL expression
| datatype IDENTIFIER EQUAL ACCEPT "(" ")" '''
def p_condition(p):
'''condition : IF expression "{" statements "}"
| IF expression "{" statements "}" ELSE "{" statements "}"'''
def p_loops(p):
'''loops : loop
| loop loops'''
def p_loop(p):
'''loop : forLoop
| whileLoop'''
def p_forLoop(p):
'''forLoop : FOR "(" expression ";" condition ";" expression ")" "{" statements "}"'''
def p_whileLoop(p):
'''whileLoop : WHILE "(" condition ")" "{" statements "}"'''
def p_error(p):
print(f"Syntax error at line {p.lineno}, position {p.lexpos}: Unexpected token '{p.value}'")
parser = yacc.yacc( debug=True)
try:
input = open("input3.txt", "r")
except EOFError:
print("End of file Error")
result = parser.parse(input.read())
if result is not None:
print(result)
我有一个 Node 的实用程序类,理论上应该为各种操作创建节点并评估这些节点:
def __init__(self, type, children=None, leaf=None):
self.type = type
if children:
self.children = children
else:
self.children = []
self.leaf = leaf
def semantic_analysis(self):
raise NotImplementedError("Subclass must implement semantic_analysis")
class BinOpNode(Node):
def __init__(self, operator, left, right):
super().__init__('binop', children=[left, right], leaf=operator)
def semantic_analysis(self):
# Perform semantic analysis on the operands
for child in self.children:
child.semantic_analysis()
# Check that the operands are of the correct type
left_type = type(self.children[0].leaf)
right_type = type(self.children[1].leaf)
if self.leaf in ['ADD', 'SUB', 'MUL', 'DIV']:
if not (left_type in [int, float] and right_type in [int, float]):
raise TypeError("Operands must be integers or floats for arithmetic operations")
elif self.leaf in ['GE', 'LE', 'EQ', 'NE', 'GT', 'LT']:
if not (left_type == right_type):
raise TypeError("Operands must be of the same type for comparison operations")
def evaluate(self):
left_value = self.children[0].evaluate()
right_value = self.children[1].evaluate()
if self.leaf == 'ADD':
return left_value + right_value
elif self.leaf == 'SUB':
return left_value - right_value
elif self.leaf == 'MUL':
return left_value * right_value
elif self.leaf== 'DIVIDE':
if right_value != 0:
return left_value / right_value
else:
raise ValueError("Division by zero")
到目前为止,我只设法实现了二进制操作。任何见解和帮助将不胜感激。
答: 暂无答案
评论