def visitStReturn(self, ctx): coord = self._ctx_coord(ctx) if ctx.ret: kid = self.visit(ctx.expr()) else: kid = Ast("VOID", coord=coord) return Ast("RETURN", [kid], coord=coord)
def visitParam(self, ctx): coord = self._ctx_coord(ctx) typeSpec = self.visit(ctx.typeSpec()) tName = typeSpec.name tRank = typeSpec.rank tCoord = typeSpec.coord typeAst = Ast("TYPE", type_name=tName, rank=tRank, coord=tCoord) name = ctx.ID().getText() return Ast('PARAM', [typeAst], coord=coord, name=name)
def visitECast(self, ctx): coord = self._ctx_coord(ctx) typeSpec = self.visit(ctx.typeSpec()) tName = typeSpec.name tRank = typeSpec.rank tCoord = typeSpec.coord typeCastTo = Ast("TYPE", type_name=tName, rank=tRank, coord=tCoord) exprToCast = self.visit(ctx.expr()) return Ast("CAST", [typeCastTo, exprToCast], coord=coord)
def visitStIf(self, ctx): coord = self._ctx_coord(ctx) ifExpr = self.visit(ctx.ifExpr) ifStmnt = self.visit(ctx.ifStmnt) if ctx.elseStmnt: elseStmnt = self.visit(ctx.elseStmnt) else: elseStmnt = Ast("BLOCK", coord=coord) kids = [ifExpr] kids.append(ifStmnt) kids.append(elseStmnt) return Ast("IF", kids, coord=coord)
def visitInitParam(self, ctx): coord = self._ctx_coord(ctx) if ctx.typeSpec(): typeSpec = self.visit(ctx.typeSpec()) tName = typeSpec.name tRank = typeSpec.rank tCoord = typeSpec.coord typeAst = Ast("TYPE", type_name=tName, rank=tRank, coord=tCoord) else: typeAst = Ast('TYPE', type_name='$inferred', coord=coord) name = ctx.ID().getText() init = self.visit(ctx.init()) return Ast('INIT_PARAM', [typeAst, init], coord=coord, name=name)
def visitArray(self, ctx): coord = self._ctx_coord(ctx) if ctx.elements: elements = [self.visit(element) for element in ctx.elements] else: elements = [self.visit(element) for element in ctx.nested] return Ast("INITS", elements, coord=coord)
def visitEFnCall(self, ctx): coord = self._ctx_coord(ctx) fnName = self.visit(ctx.expr()) params = self.visit(ctx.actualParams()) kids = [fnName] kids.extend(params) return Ast("APP", kids, coord=coord)
def visitStWhile(self, ctx): coord = self._ctx_coord(ctx) expr = self.visit(ctx.expr()) stmnt = self.visit(ctx.statement()) kids = [expr] kids.append(stmnt) return Ast("WHILE", kids, coord=coord)
def visitParams(self, ctx): coord = self._ctx_coord(ctx) if ctx.formals: params = [self.visit(formal) for formal in ctx.formals] else: params = [] params += [self.visit(initFormal) for initFormal in ctx.initFormals] return Ast('PARAMS', params, coord=coord)
def defn(self): """Return AST for a defn""" defn_coord = self.lookahead.coord self.match('FN') self.match('PAREN', '(') name = self.lookahead.lexeme self.match('ID') params_coord = self.lookahead.coord params = self.params() params_ast = Ast('PARAMS', params, coord=params_coord, arity=len(params)) self.match('PAREN', ')') expr = self.expr() self.match('SEMI') return Ast('DEFN', [params_ast, expr], name=name, coord=defn_coord)
def visitFnDefinition(self, ctx): coord = self._ctx_coord(ctx) proto = self.visit(ctx.fnHeader()) body = self.visit(ctx.block()) return Ast('DEFN', [proto.returnType, proto.params, body], kind=proto.kind, isStatic=proto.isStatic, name=proto.name, coord=coord)
def visitClassDefinition(self, ctx): classBody = self._visit_kids(ctx) coord = self._ctx_coord(ctx) return Ast('CLASS', classBody, type_name=ctx.typeName.text, super_name="Object" if ctx.superName == None else ctx.superName.text, coord=coord)
def param_to_arg(self, glob): retVal = [] for i in range(len(glob)): retVal += [ Ast("REF", name=glob[i].name, coord=glob[i].coord, offset=glob[i].offset) ] return retVal
def visitEAddSub(self, ctx): coord = self._ctx_coord(ctx) operator = ctx.operator.text if operator == "+": op = "ADD" if operator == "-": op = "SUB" leftOperand = self.visit(ctx.left) rightOperand = self.visit(ctx.right) return Ast("OP2", [leftOperand, rightOperand], op=op, coord=coord)
def transform(self, ast): if ast.tag == 'LET': return self.let_transform(ast) xkids = [self.transform(k) for k in ast.kids] if ast.tag == 'PROGRAM': return Ast('PROGRAM', xkids + self.aux_defs) else: new_ast = copy.copy(ast) new_ast.kids = xkids return new_ast
def visitConstrProto(self, ctx): coord = self._ctx_coord(ctx) isStatic = True name = ctx.TYPE_ID().getText() params = self.visit(ctx.params()) returnType = Ast('TYPE', type_name='$inferred', rank=0, coord=coord) return WalnutAstBuilder.Proto(kind='constructor', isStatic=True, name=name, returnType=returnType, params=params)
def params(self): """Return list of ASTs for formal parameters""" if self.look('ID'): coord = self.lookahead.coord param_ast = Ast('PARAM', name=self.lookahead.lexeme, coord=coord) self.match('ID') params = self.params() params.insert(0, param_ast) return params else: return []
def visitVarDec(self, ctx): isStatic = ctx.isStatic != None kind = ctx.kind.text coord = self._ctx_coord(ctx) type_name = "" rank = 0 if ctx.typeSp: typeInfo = self.visit(ctx.typeSp) type_name = typeInfo.name rank = typeInfo.rank else: type_name = "$inferred" type_ast = Ast("TYPE", type_name=type_name, rank=rank, coord=coord) rest = self._visit_kids(ctx) children = [type_ast] children.extend(rest) return Ast('DECLS', children, isStatic=isStatic, kind=kind, coord=coord)
def visitEMulDivMod(self, ctx): coord = self._ctx_coord(ctx) operator = ctx.operator.text if operator == "*": op = "MUL" if operator == "/": op = "DIV" if operator == "%": op = "REM" leftOperand = self.visit(ctx.left) rightOperand = self.visit(ctx.right) return Ast("OP2", [leftOperand, rightOperand], op=op, coord=coord)
def let_transform(self, ast): idexp = ast.kids[0] bodyexp = ast.kids[1] ids = [] exps = [] for x in range(len(idexp.kids)): # separate IDs from EXPRs if x % 2 == 0: ids.append(idexp.kids[x]) elif x % 2 == 1: exps.append(idexp.kids[x]) params = [] for y in range(len(ids)): # populate a list of param asts with IDs params.append(Ast('PARAM', name=ids[y].name, coord=ids[y].coord)) transformed_exps = [self.transform(k) for k in exps] transformed_body = self.transform(bodyexp) scope = ids[0].scope globs = self.get_globals(bodyexp, scope) params += globs params_ast = Ast('PARAMS', params, coord=ast.coord, arity=len(params)) newName = f'_{self.fnName}' self.fnName += 1 self.fnParams.append(set()) self.aux_defs += [ Ast('DEFN', [params_ast, transformed_body], name=newName, coord=ast.coord) ] globsAsArgs = self.param_to_arg(globs) appParams = [] appParams += transformed_exps appParams += globsAsArgs args_ast = Ast('ARGS', appParams, coord=ast.coord, arity=len(appParams), offset=ast.coord) return Ast('APP', [args_ast], name=newName, coord=ast.coord)
def expr(self): "Return expr AST" coord = self.lookahead.coord if self.look('INT'): value = int(self.lookahead.lexeme) self.match('INT') return Ast('INT', value=value, coord=coord) elif self.look('ID'): name = self.lookahead.lexeme self.match('ID') return Ast('REF', name=name, coord=coord) elif self.look('PAREN', '('): self.match('PAREN', '(') fn_coord = self.lookahead.coord name = self.lookahead.lexeme if self.look('ID'): self.match('ID') args_coord = self.lookahead.coord args = self.args() args_ast = Ast('ARGS', args, coord=args_coord, arity=len(args)) self.match('PAREN', ')') return Ast('APP', [args_ast], name=name, coord=fn_coord) elif self.look("LET", "let"): self.match('LET') idExp_coord = self.lookahead.coord idExpList = self.idExp(0) idExpList_ast = Ast("LETIDEXPR", idExpList, coord=idExp_coord, arity=(len(idExpList) / 2)) self.match('IN') bodyExp_ast = self.expr() self.match("PAREN", ")") return Ast('LET', [idExpList_ast, bodyExp_ast], coord=fn_coord) elif (self.look('OP') and Parser.BINARY_OPS.get(self.lookahead.lexeme, None)): op = Parser.BINARY_OPS[self.lookahead.lexeme] self.match('OP') return Ast(op, [self.expr(), self.expr()], coord=coord) elif self.look('OP', '?'): self.match('OP') return Ast('IF', [self.expr(), self.expr(), self.expr()], coord=coord) else: raise SyntaxError("Expression expected")
def visitFnProto(self, ctx): isStatic = ctx.isStatic != None name = ctx.ID().getText() typeSpec = self.visit(ctx.typeSpec()) tName = typeSpec.name tRank = typeSpec.rank tCoord = typeSpec.coord returnType = Ast("TYPE", type_name=tName, rank=tRank, coord=tCoord) params = self.visit(ctx.params()) return WalnutAstBuilder.Proto(kind='function', isStatic=isStatic, name=name, returnType=returnType, params=params)
def global_to_param(self, ast, scope): retVal = [] if ast.tag == 'REF': if ast.scope == scope: pass elif ast.scope < scope: if ast.name in self.fnParams[self.fnName]: pass else: retVal.append( Ast("PARAM", name=ast.name, coord=ast.coord, offset=ast.offset)) self.fnParams[self.fnName].add(ast.name) return retVal
def main(argv=None): if argv is None: argv = sys.argv curWorld.top = Ast(ast.PROGRAM, None) if len(argv) > 1: for p in argv[1:]: if p.endswith(".n"): loadFile(p) else: if loadScript(p) < 0: return 0 nLoop() return 0
def visitArrConstruction(self, ctx): coord = self._ctx_coord(ctx) if ctx.prim: typeName = ctx.primitiveType().getText() else: typeName = ctx.TYPE_ID().getText() rank = 0 if ctx.idxs: idxs = [self.visit(exp) for exp in ctx.idxs] rank = len(ctx.idxs) else: idxs = [] return Ast("NEW_ARRAY", idxs, type_name=typeName, rank=rank, coord=coord)
def scan1(self): inputValue = self.tex.get("1.0", "end-1c") tkinter.messagebox.showwarning(title=None, message=inputValue) # asc.texto = inputValue.lower() asc.texto = "CREATE DATABASE casa" sentencias = asc.parse(inputValue) self.sentencias = sentencias tkinter.messagebox.showwarning(title=None, message="1 asc") Ent = Entorno.Entorno(None) ast = Ast.Ast(sentencias) bandera = False if (sentencias != None): for x in sentencias: try: a = True if (ast.exist_label(x)): valueaagregar = Error("SEMANTICO", "Ya existe la variable " + x.value, x.line, x.column) Reporte.agregar(valueaagregar) else: ast.agregarlabel(x) except: pass tkinter.messagebox.showwarning(title=None, message="2") A = ast.getlabels() if (A != None): for W in A: try: if (W.ejecutar(Ent, ast) == True): break except: pass else: valueaagregar = Error("SEMANTICO", "Arbol vacio para compilar ", 0, 0) Reporte.agregar(valueaagregar) self.ent = Ent self.ast = ast
def visitERelation(self, ctx): coord = self._ctx_coord(ctx) operator = ctx.operator.text if operator == "==": op = "EQ" if operator == "!=": op = "NE" if operator == "<": op = "LT" if operator == ">": op = "GT" if operator == "<=": op = "LE" if operator == ">=": op = "GE" leftOperand = self.visit(ctx.left) rightOperand = self.visit(ctx.right) return Ast("OP2", [leftOperand, rightOperand], op=op, coord=coord)
def scan1(self): SentenciasR = Sentencias.ReporteD() SentenciasR.Abrir() ast = [] Ent = [] execr = N.Nodo() execr.start() inputValue=self.tex.get("1.0","end-1c") tkinter.messagebox.showwarning(title=None, message=inputValue) # asc.texto = inputValue.lower() asc.texto ="CREATE DATABASE casa" sentencias = asc.parse(inputValue) self.sentencias = sentencias #tkinter.messagebox.showwarning(title=None, message="1 asc") Ent = Entorno.Entorno(None) print("recorrera") ast = Ast.Ast(sentencias) bandera = False if(sentencias != None): for x in sentencias: try: a = True print("testeara --- ") print(x.id) if(ast.exist_label(x)): print("Ya existe la variable ") print("Ya existe la variable ",x.id) valueaagregar = Datos("SEMANTICO","Ya existe la variable "+x.id,x.line,x.column) Reporte.agregar(valueaagregar) else: print("testeara -exist_label ") print(x.id) ast.agregarlabel(x) except: pass #tkinter.messagebox.showwarning(title=None, message="2") print("parseara") A = ast.getlabels() if(A != None): print("1 ") for W in A: try: print("ejecutara2 ---------------------- ", W) except: pass for W in A: try: print("ejecutara ---------------------- ", W) print("2 ") print("3 ") try: W.ejecutar(Ent,ast) print("4b ") except: print("3b ") pass except: pass print("4 ") else: valueaagregar = Datos("SEMANTICO","Arbol vacio para compilar ",0,0) Reporte.agregar(valueaagregar) self.ent = Ent self.ast = ast
def runCompiler(input_file, file_name, stage, opt_stage, debug_stage): # scan, parse, ast, semantic, irt, codegen if (stage == "scan" or stage == "parse" or stage == "ast" or stage == "semantic" or stage == "irt" or stage == "codegen"): debug = False if (("scan" in debug_stage)): debug = True sc = Scanner.Scanner() rf = ReadFile.ReadFile() wf = WriteFile.WriteFile() # set de input file rf.set_file(f"decafs/{input_file}.decaf") # call scanner class and scan for tokens in input file token_list, error_list = sc.scan(rf.file_to_string(), debug) string_list = [] for token in token_list: string_list.append(token.pretty_print()) # write file in output/ wf.write_file(file_name, string_list) # write file in output/ error1 = len(error_list) wf.write_file_append("error_list", error_list) if (stage == "parse" or stage == "ast" or stage == "semantic" or stage == "irt" or stage == "codegen"): debug = False if (("parse" in debug_stage)): debug = True pr = Parser.Parser() main_program, error_list = pr.parse(token_list, debug) # write file in output/ wf.write_file_append("error_list", error_list) error2 = len(error_list) if (stage == "ast" or stage == "semantic" or stage == "irt" or stage == "codegen"): debug = False if (("ast" in debug_stage)): debug = True ast = Ast.Ast() ast.ast(main_program, debug) if (stage == "semantic" or stage == "irt" or stage == "codegen"): debug = False if (("semantic" in debug_stage)): debug = True sm = Semantic.Semantic() error_list = sm.semantic(main_program, debug) # write file in output/ wf.write_file_append("error_list", error_list) error3 = len(error_list) if (stage == "irt" or stage == "codegen"): if (error1 == 0 and error2 == 0 and error3 == 0): debug = False if (("irt" in debug_stage)): debug = True irt = Irt.Irt() irt_list = irt.irt(main_program, debug) else: print("There are errors in the error_log") if (stage == "codegen"): if (error1 == 0 and error2 == 0 and error3 == 0): codegen = Codegen.Codegen() code_list, code_list_2 = codegen.codegen(main_program, debug) wf.write_file_no_extension("program.asm", code_list) wf.write_file_no_extension("program.py", code_list_2) else: print("There are errors in the error_log") # TODO write file asm or py from code_list # print("CODEGEN not ready") if (stage != "scan" and stage != "parse" and stage != "ast" and stage != "semantic" and stage != "irt" and stage != "codegen"): print("stage value not defined") print(input_file, file_name, stage, opt_stage, debug_stage)
def visitArrayInit(self, ctx): name = ctx.name.text coord = self._ctx_coord(ctx) expr = self.visit(ctx.array()) children = [expr] return Ast("INIT_DECL", children, name=name, coord=coord)