def p_matrix(self, p): """matrix : '[' matrix_body ']' | '[' ']'""" if len(p) == 3: p[0] = AST.Vector([]) else: p[0] = AST.Vector(p[2])
def visitFunctionDecl(self, ctx: GrammarParser.FunctionDeclContext): decl_info_list = [ self.extract_decl(ctx.pureDecl(i)) for i in range(len(ctx.pureDecl())) ] my_ast = AST.FunctionDeclaration(decl_info_list[0][0]) my_ast.set_source_loc(source_from_ctx(ctx)) # set type & arg_count of function my_st_entry = FuncEntry(decl_info_list[0][1]) my_st_entry.arg_count = len(decl_info_list) - 1 self.enter_scope(my_ast) # add variable decls for each argument & add arguments info to function's st entries for arg_nr in range(1, len(decl_info_list)): arg_ctx = ctx.pureDecl(arg_nr) arg = AST.Variable(decl_info_list[arg_nr][0]) arg.set_source_loc(source_from_ctx(arg_ctx)) decl = AST.Decl() decl.set_source_loc(source_from_ctx(arg_ctx)) decl.add_child(arg) my_ast.add_child(decl) self._current_sym_table[arg.get_name()] = VarEntry( decl_info_list[arg_nr][1]) my_st_entry.arg_types.append(decl_info_list[arg_nr][1]) self.exit_scope(my_ast) # save function's st entry self._current_sym_table[decl_info_list[0][0]] = my_st_entry return my_ast
def p_if_instruction(self, p): """if_instruction : IF '(' condition ')' instruction %prec IF | IF '(' condition ')' instruction ELSE instruction""" if len(p) == 8: p[0] = AST.IfElseInstruction(p[3], p[5], p[7], p.lineno(1)) else: p[0] = AST.IfInstruction(p[3], p[5], p.lineno(2))
def p_ID(self, p): """variable_expression : ID | ID '[' expression ',' expression ']'""" if len(p) == 2: p[0] = AST.Variable(p[1], p.lineno(1)) else: p[0] = AST.MatrixElement(p[1], p[3], p[5], p.lineno(2))
def p_vector(self, p): """vector : '[' vector_body ']' | '[' ']'""" if len(p) == 3: p[0] = AST.Vector([]) else: p[0] = AST.Vector(p[2])
def visitCastOp(self, ast: AST.CastOp): self.visitChildren(ast) conv_type = ast.get_conversion_type() if conv_type in { AST.conv_type.BOOL_TO_INT, AST.conv_type.BOOL_TO_CHAR, AST.conv_type.CHAR_TO_INT, AST.conv_type.INT_TO_CHAR }: ast.set_adress(self.get_adress_of(ast.get_child(0))) return adress = self.gen_stack_adress() reg = self.get_reg(check_if_floating(ast)) ast.set_adress(adress) var_reg = self.load_in_reg(ast.get_child(0)) if conv_type == AST.conv_type.INT_TO_BOOL: self.gen_comp_instr(reg, var_reg, '$zero', AST.NotEqual(), False) elif conv_type in { AST.conv_type.INT_TO_FLOAT, AST.conv_type.BOOL_TO_FLOAT, AST.conv_type.CHAR_TO_FLOAT }: self.gen_int_to_float(var_reg, reg) elif conv_type in { AST.conv_type.FLOAT_TO_INT, AST.conv_type.FLOAT_TO_CHAR }: self.gen_float_to_int(reg, var_reg) elif conv_type == AST.conv_type.FLOAT_TO_BOOL: freg = self.get_reg(floating=True) self.gen_load(freg, self.get_fp_constant(0), True) self.gen_comp_instr(reg, var_reg, freg, AST.NotEqual(), True) self.gen_sw(reg, adress, check_if_floating(ast)) self.reset_reg()
def p_print_instruction(self, p): """print_instruction : PRINT expression_list ';' | PRINT '"' expression_list '"' ';' """ if len(p) == 6: p[0] = AST.PrintInstructions(p[3], p.lineno(1)) else: p[0] = AST.PrintInstructions(p[2], p.lineno(1))
def visitControl(self, ctx: GrammarParser.ControlContext): my_ast = None token_type = ctx.getChild(0).getSymbol().type if token_type == GrammarParser.BREAK_KW: my_ast = AST.Break() if token_type == GrammarParser.CONT_KW: my_ast = AST.Continue() my_ast.set_source_loc(source_from_ctx(ctx)) return my_ast
def p_expression_lists(self, p): """expression_lists : expression_lists ';' expression_list | expression_list """ if len(p) == 4: p[0] = AST.ListsOfExpressions(p.lineno(2)) p[0].flat_expressions(p[1].expression_lists, p[3]) else: p[0] = AST.ListsOfExpressions(p.lineno(1)) p[0].append_expression(p[1])
def visitReturnStatement(self, ctx: GrammarParser.ReturnStatementContext): my_ast = AST.ReturnStatement() my_ast.set_source_loc(source_from_ctx(ctx)) if ctx.getChildCount() > 1: my_ast.add_child(self.visit(ctx.getChild(1))) else: void = AST.Literal(value=None) void.set_source_loc(source_from_ctx(ctx)) void.set_type(TypeClass([TypeComponents.VOID])) my_ast.add_child(void) return my_ast
def p_compound_assignment(self, p): """compound_assignment_instruction : variable_expression ADDASSIGN expression ';' | variable_expression SUBASSIGN expression ';' | variable_expression MULASSIGN expression ';' | variable_expression DIVASSIGN expression ';' """ p[0] = AST.CompoundAssignment(p[1], p[2], p[3], p.lineno(2))
def visitWhileConstr(self, ctx: GrammarParser.WhileConstrContext): my_ast = AST.WhileStatement() self.enter_scope(my_ast) my_ast.set_check(self.visit(ctx.parenCond())) my_ast.set_contents(self.visit(ctx.stateOrScope())) my_ast.set_source_loc(source_from_ctx(ctx)) self.exit_scope(my_ast) return my_ast
def visitDoc(self, ctx): my_ast = AST.Doc() my_ast.IO = ctx.STDIO() is not None self.enter_scope(my_ast) my_ast.add_childs(self.visitBlock(ctx.block())) my_ast.set_source_loc(source_from_ctx(ctx)) self.exit_scope(my_ast) return my_ast
def p_expression_list(self, p): """expression_list : expression_list ',' expression | expression """ p[0] = AST.ListOfExpressions(p.lineno(1)) if len(p) == 4: p[0].flat_expressions(p[1].expression_list, p[3]) else: p[0].append_expression(p[1])
def visitScanf(self, ctx): my_ast = AST.Scanf(ctx.getChild(2).getText()) my_ast.set_source_loc(source_from_ctx(ctx)) for index in range(1, ctx.getChildCount()): if isinstance(ctx.getChild(index), GrammarParser.ExprContext): my_ast.add_child(self.visit(ctx.getChild(index))) pass return my_ast
def visitFunctionCall(self, ctx: GrammarParser.FunctionCallContext): my_ast = AST.FunctionCall(ctx.getChild(0).getText()) for a in range(1, len(ctx.children)): if isinstance(ctx.getChild(a), GrammarParser.FunctionArgumentContext): my_ast.add_child(self.visit(ctx.getChild(a))) my_ast.set_source_loc(source_from_ctx(ctx)) return my_ast
def p_instructions(self, p): """instructions : instructions instruction | instruction """ if len(p) == 3: p[1].instructions.append(p[2]) p[0] = p[1] else: p[0] = AST.Instructions() p[0].instructions.append(p[1])
def get_adress_of(self, ast: AST.Component): if isinstance(ast, AST.Indir): reg = self.get_reg() self.gen_load(reg, self.get_adress_of(ast.get_child(0))) return '0(' + reg + ')' elif isinstance(ast, AST.Index): self.visitChildren(ast) reg = self.get_reg() reg2 = self.get_reg() self.gen_load_im(reg, 4) self.gen_load(reg2, ast.get_child(1).get_adress()) self.gen_math_instr(reg, reg, reg2, AST.Prod()) self.gen_load_adress(reg2, self.get_adress_of(ast.get_child(0))) self.gen_math_instr(reg, reg, reg2, AST.Sum()) self.decrease_reg(1, floating=False) return '0(' + reg + ')' else: return ast.get_adress()
def visitDecl(self, ctx): my_ast = AST.Decl() decl_info = self.extract_decl(ctx.pureDecl()) var = AST.Variable(decl_info[0]) var.set_source_loc(source_from_ctx(ctx)) my_ast.add_child(var) self._current_sym_table[decl_info[0]] = VarEntry(decl_info[1], None) my_ast.set_source_loc(source_from_ctx(ctx)) if ctx.ASSIGN_OP() is not None: assign = AST.AssignOp() assign.add_child(my_ast) assign.add_child(self.visit(ctx.expr())) assign.set_source_loc(source_from_ctx(ctx)) return assign else: return my_ast
def visitIfConstr(self, ctx: GrammarParser.IfConstrContext): my_ast = AST.IfStatement() self.enter_scope(my_ast) my_ast.set_condition(self.visit(ctx.parenCond())) my_ast.set_then(self.visit(ctx.stateOrScope(0))) if len(ctx.stateOrScope()) == 2: my_ast.set_else(self.visit(ctx.stateOrScope(1))) my_ast.set_source_loc(source_from_ctx(ctx)) self.exit_scope(my_ast) return my_ast
def aggregateResult(self, aggregate: AST.DummyNode, nextResult): if nextResult is None: return aggregate elif aggregate is None: return nextResult elif not isinstance(aggregate, AST.DummyNode): aggregate = AST.DummyNode([aggregate, nextResult]) else: aggregate.add_child(nextResult) return aggregate
def visitForConstr(self, ctx: GrammarParser.ForConstrContext): my_ast = AST.ForStatement() self.enter_scope(my_ast) params = [self.visit(ctx.general_expr(i)) for i in range(3)] my_ast.set_init(params[0]) my_ast.set_check(params[1]) my_ast.set_advance(params[2]) my_ast.set_contents(self.visit(ctx.stateOrScope())) my_ast.set_source_loc(source_from_ctx(ctx)) self.exit_scope(my_ast) return my_ast
def full_fold(self, ast: AST.Composite, op): children = self.visitChildren(ast) if self.is_foldable(children): children = [child.get_value() for child in children] new_val = op(*children) new_val = self.fix_type(new_val, ast.get_type()) new_lit = AST.Literal(new_val) new_lit.set_type(ast.get_type()) ast.get_parent().replace_child(ast, new_lit) return new_lit return ast
def visitSwitchConstr(self, ctx: GrammarParser.SwitchConstrContext): my_ast = AST.SwitchStatement() self.enter_scope(my_ast) my_ast.set_condition(self.visit(ctx.parenCond())) for branch_ctx in ctx.caseBranch(): my_ast.add_branch(self.visit(branch_ctx)) if ctx.defaultBranch(): my_ast.add_branch(self.visit(ctx.defaultBranch())) my_ast.set_source_loc(source_from_ctx(ctx)) self.exit_scope(my_ast) return my_ast
def p_constant(self, p): """expression : FLOATNUM | INTNUM | STRING """ if re.match(r"\d*\.\d+", str(p[1])): type = 'float' elif re.match(r"\d+", str(p[1])): type = 'int' else: type = 'string' p[0] = AST.Constant(p[1], type, p.lineno(1))
def visitNot(self, ast: AST.Not): self.visitChildren(ast) self.store_rcounter(check_if_floating(ast)) adress = self.gen_stack_adress() ast.set_adress(adress) reg = self.get_reg() self.gen_load_im(reg, 1) self.gen_comp_instr(reg, reg, self.load_in_reg(ast.get_child(0)), AST.NotEqual(), False) self.gen_sw(reg, adress, False) self.restore_tcounter(floating=check_if_floating(ast))
def visitArrayLit(self, ctx: GrammarParser.ArrayLitContext ): # not very type-safe at all (nor safe in general) my_ast = AST.Literal(value=[]) element = None for child in ctx.literal(): element = self.visit(child) my_ast.get_value().append(element.get_value()) my_type: TypeClass = deepcopy(element.get_type()) my_type.pushType(TypeComponents.ARR) my_ast.set_type(my_type) my_ast.set_source_loc(source_from_ctx(ctx)) return my_ast
def p_binary_expression(self, p): """expression : expression '+' expression | expression '-' expression | expression '*' expression | expression '/' expression | expression EQ expression | expression NOTEQ expression | expression LESS expression | expression GREATER expression | expression LESSEQ expression | expression GREATEREQ expression | expression DOTADD expression | expression DOTSUB expression | expression DOTMUL expression | expression DOTDIV expression """ p[0] = AST.BinaryExpression(p[1], p[2], p[3], p.lineno(2))
def get_AST_from_raw(raw: str) -> AST: ''' Get an AST from raw text Parameters ---------- raw : str raw text Returns ------- An unparsed AST object Raises ------ PyllowException if something like a syntax error is present in `raw` ''' return AST(get_tokens_from_raw(raw))
def visitFunctionDef(self, ctx: GrammarParser.FunctionDefContext): decl = self.visitFunctionDecl(ctx.functionDecl()) my_ast = AST.FunctionDefinition(decl.get_name()) my_ast.set_source_loc(source_from_ctx(ctx)) self.enter_scope(my_ast) # add definitions of arguments for child_nr in range(decl.get_child_count()): var: AST.Variable = decl.get_child(child_nr).get_child(0) self._current_sym_table[var.get_name()] = var.get_st_entry() my_ast.swap_children(decl) # make function body my_ast.add_child(self.visit(ctx.stateOrScope()), 0) self.exit_scope(my_ast) # add function to ST # self._current_sym_table[my_ast.get_name()] = decl.get_st_entry() # due to weird way st works w/ "current symbol table", the entry is already there return my_ast