package projeto.generation; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import projeto.Arquivo; import projeto.analysis.DepthFirstAdapter; import projeto.analysis.IdentificationTable; import projeto.analysis.SemanticAnalyserException; import projeto.node.AAndMulOp; import projeto.node.AAssignStatement; import projeto.node.ABlock; import projeto.node.ABoolType; import projeto.node.ABooleanFactor; import projeto.node.ACharFactor; import projeto.node.ACharType; import projeto.node.ACmdListStatement; import projeto.node.AComplexExpression; import projeto.node.AComplexFactor; import projeto.node.AComplexTerm; import projeto.node.ADifferentRelOp; import projeto.node.ADivMulOp; import projeto.node.AEqualsRelOp; import projeto.node.AExpression; import projeto.node.AExpressionFactor; import projeto.node.AFalseBooleanLiteral; import projeto.node.AForStatement; import projeto.node.AFormalParam; import projeto.node.AFunctionDecl; import projeto.node.AFunctionFactor; import projeto.node.AFunctionHeading; import projeto.node.AFunctionStatement; import projeto.node.AGreaterThanRelOp; import projeto.node.AIdentList; import projeto.node.AIfThenElseStatement; import projeto.node.AIntType; import projeto.node.AIntegerFactor; import projeto.node.ALessThanRelOp; import projeto.node.AMinusAddOp; import projeto.node.AMultMulOp; import projeto.node.AOrAddOp; import projeto.node.APlusAddOp; import projeto.node.APrintStatement; import projeto.node.APrintlnStatement; import projeto.node.AProgram; import projeto.node.AReturnStatement; import projeto.node.ASeqIdentList; import projeto.node.ASimpleExpression; import projeto.node.ASimpleStatement; import projeto.node.AStmtList; import projeto.node.AStringFactor; import projeto.node.AStringType; import projeto.node.ATerm; import projeto.node.ATrueBooleanLiteral; import projeto.node.AVarDecl; import projeto.node.AVarSection; import projeto.node.AVariableFactor; import projeto.node.AVoidType; import projeto.node.AWhileStatement; import projeto.node.Node; import projeto.node.PFunctionDecl; import projeto.node.PStatement; import projeto.node.PType; import projeto.node.Start; import projeto.node.TIdent; import projeto.node.TIf; import projeto.node.TReturn; public class CodeGenerator extends DepthFirstAdapter { private String nomeDaClasse; private Arquivo arquivo; private int contadorLabels; private IdentificationTable table; public enum Type { CHAR, INTEGER, BOOLEAN, STRING } ; public CodeGenerator() { this.table = new IdentificationTable(); } public CodeGenerator(String source, String diretorioSaida) { // this.nomeDoArquivo = source; this.nomeDaClasse = source.substring(0, source.length() - 4); this.arquivo = new Arquivo(diretorioSaida + "\\" + this.nomeDaClasse + ".il", diretorioSaida + "\\" + this.nomeDaClasse + ".il"); this.contadorLabels = 1; this.table = new IdentificationTable(); } public Type getActualType(PType node) { if (node instanceof ACharType) { return Type.CHAR; } else if (node instanceof AIntType) { return Type.INTEGER; } else if (node instanceof ABoolType) { return Type.BOOLEAN; } else if (node instanceof AStringType) { return Type.STRING; } else { throw new IllegalArgumentException(); } } //pronto public void inStart(Start node) { this.table.openScope(); defaultIn(null); } //pronto public void outStart(Start node) { this.table.closeScope(); } //pronto public void defaultIn(@SuppressWarnings("unused") Node node) { // Do nothing } //pronto public void defaultOut(@SuppressWarnings("unused") Node node) { // Do nothing } //pronto public void caseStart(Start node) { this.arquivo.println(".assembly extern mscorlib {}"); this.arquivo.println(".assembly " + nomeDaClasse + "{"); this.arquivo.println(".ver 1:0:1:0"); this.arquivo.println("}"); this.arquivo.println(".module " + this.nomeDaClasse + ".exe"); this.arquivo.println(""); inStart(node); node.getPProgram().apply(this); node.getEOF().apply(this); outStart(node); } //pronto public void inAProgram(AProgram node) { defaultIn(node); } //pronto public void outAProgram(AProgram node) { defaultOut(node); } //pronto public void caseAProgram(AProgram node) { this.arquivo.println(".class private auto ansi " + this.nomeDaClasse + " extends [mscorlib]System.Object"); this.arquivo.println("{"); inAProgram(node); if(node.getVarSection() != null) { node.getVarSection().apply(this); } { List copy = new ArrayList(node.getFunctionDecl()); for(PFunctionDecl e : copy) { e.apply(this); } } this.arquivo.println("}"); outAProgram(node); } //pronto public void inABlock(ABlock node) { defaultIn(node); } //pronto public void outABlock(ABlock node) { defaultOut(node); } //pronto public void caseABlock(ABlock node) { inABlock(node); if(node.getLeftBracket() != null) { node.getLeftBracket().apply(this); } if (node.parent() instanceof AProgram) { this.arquivo.println(".method static void main() cil managed {"); this.arquivo.println(".entrypoint"); this.arquivo.println(".maxstack 15 \n"); } if(node.getStmtList() != null) { node.getStmtList().apply(this); } if(node.getRightBracket() != null) { node.getRightBracket().apply(this); } if (node.parent() instanceof AProgram) { this.arquivo.println("ret"); this.arquivo.println("}\n"); } outABlock(node); } //pronto public void inACharType(ACharType node) { defaultIn(node); } //pronto public void outACharType(ACharType node) { defaultOut(node); } //pronto public void caseACharType(ACharType node) { inACharType(node); if(node.getChar() != null) { node.getChar().apply(this); //this.arq.println(Instrucoes.CHAR); } outACharType(node); } //pronto public void inAIntType(AIntType node) { defaultIn(node); } //pronto public void outAIntType(AIntType node) { defaultOut(node); } //pronto public void caseAIntType(AIntType node) { inAIntType(node); if(node.getInt() != null) { node.getInt().apply(this); //this.arq.print(Instrucoes.INT); } outAIntType(node); } //pronto public void inABoolType(ABoolType node) { defaultIn(node); } //pronto public void outABoolType(ABoolType node) { defaultOut(node); } //pronto public void caseABoolType(ABoolType node) { inABoolType(node); if(node.getBool() != null) { node.getBool().apply(this); //this.arq.println(Instrucoes.BOOL); } outABoolType(node); } //pronto public void inAStringType(AStringType node) { defaultIn(node); } //pronto public void outAStringType(AStringType node) { defaultOut(node); } //pronto public void caseAStringType(AStringType node) { inAStringType(node); if(node.getString() != null) { node.getString().apply(this); //this.arq.println(Instrucoes.STRING); } outAStringType(node); } //pronto public void inAVoidType(AVoidType node) { defaultIn(node); } //pronto public void outAVoidType(AVoidType node) { defaultOut(node); } //pronto public void caseAVoidType(AVoidType node) { inAVoidType(node); if(node.getVoid() != null) { node.getVoid().apply(this); //this.arq.println(Instrucoes.STRING); } outAVoidType(node); } //TODO falta public void inAVarSection(AVarSection node) { defaultIn(node); } //TODO falta public void outAVarSection(AVarSection node) { defaultOut(node); } //pronto public void inAVarDecl(AVarDecl node) { AIdentList identList = ((AIdentList) node.getIdentList()); TIdent identifier = identList.getIdent(); if (!this.table.isDeclared( identifier.getText())) { this.table.enter(identifier.getText(), this.getActualType(node.getType())); } LinkedList seqIdentList = identList.getSeqIdentList(); Iterator iteratorIdentList = seqIdentList.iterator (); while (iteratorIdentList.hasNext()) { ASeqIdentList current = (ASeqIdentList) iteratorIdentList.next(); identifier = (TIdent) current.getIdent(); if (!this.table.isDeclared( identifier.getText())) { this.table.enter(identifier.getText(), this.getActualType(node.getType())); } } } //pronto public void outAVarDecl(AVarDecl node) { defaultOut(node); } public void caseAVarDecl(AVardecl node) { inAVardecl(node); if(node.getIdentlist() != null){ int nivel = this.tabela.nivelatual; if(nivel == Entrada.GLOBAL){ node.getIdentlist().apply(this); this.arq.print("\n"); } else if(nivel == Entrada.LOCAL){ this.arq.print(".locals init (" ); node.getIdentlist().apply(this); this.arq.println(")\n"); } } if(node.getColon() != null){ node.getColon().apply(this); } if(node.getType() != null){ node.getType().apply(this); } if(node.getSemicolon() != null){ node.getSemicolon().apply(this); } outAVardecl(node); } public void inAIdentList(AIdentList node) { defaultIn(node); } public void outAIdentList(AIdentList node) { defaultOut(node); } public void inASeqIdentList(ASeqIdentList node) { defaultIn(node); } public void outASeqIdentList(ASeqIdentList node) { defaultOut(node); } public void inAExpression(AExpression node) { defaultIn(node); } //implementar public void outAExpression(AExpression node) { Type expressionType = (Type)this.table.retrieve(node.getSimpleExpression()); LinkedList list = node.getComplexExpression(); for (Iterator iter = list.iterator(); iter.hasNext();) { AComplexExpression element = (AComplexExpression) iter.next(); Type expressionType2 = (Type)this.table.retrieve(element.getSimpleExpression()); if (! (expressionType == expressionType2)){ throw new SemanticAnalyserException("[" + expressionType.toString() + "," + expressionType2.toString() + "] Erro de tipo."); } Type opType = (Type) this.table.retrieve(element.getRelOp()); if(opType == Type.INTEGER && expressionType2 == Type.BOOLEAN){ throw new SemanticAnalyserException("[" + opType.toString() + "," + expressionType2.toString() + "] Erro de tipo."); } } } //?? public void inAComplexExpression(AComplexExpression node) { defaultIn(node); } //?? public void outAComplexExpression(AComplexExpression node) { defaultOut(node); } public void inASimpleExpression(ASimpleExpression node) { } public void outASimpleExpression(ASimpleExpression node) { Type type1; if (node.getTerm() != null) { type1 = (Type)this.table.retrieve(node); }else { type1 = (Type)this.table.retrieve(node.getTerm()); } LinkedList list = node.getComplexTerm(); for (Iterator iter = list.iterator(); iter.hasNext();) { AComplexExpression element = (AComplexExpression) iter.next(); Type type2 = (Type)this.table.retrieve(element); if(type1 != type2){ throw new SemanticAnalyserException("[" + type1.toString() + "," + type2.toString() + "] Erro de tipo."); } } } //?? public void inAComplexTerm(AComplexTerm node) { defaultIn(node); } //?? public void outAComplexTerm(AComplexTerm node) { defaultOut(node); } public void inATerm(ATerm node) { defaultIn(node); } public void outATerm(ATerm node) { //erro aki Type factorType = (Type)this.table.retrieve(node.getFactor()); if(node.getComplexFactor().size() != 0 && (factorType == Type.BOOLEAN || factorType == Type.INTEGER)) { LinkedList list = node.getComplexFactor(); for (Iterator iter = list.iterator(); iter.hasNext();) { AComplexFactor element = (AComplexFactor) iter.next(); Type complexFactorType = (Type)this.table.retrieve(element); if(factorType != complexFactorType){ throw new SemanticAnalyserException("[" + factorType.toString() + "," + complexFactorType.toString() + "] Erro de tipo."); } } } else { throw new SemanticAnalyserException("[" + factorType.toString() + "," + Type.BOOLEAN + " ou " + Type.INTEGER+ "] Erro de tipo."); } } //?? public void inAComplexFactor(AComplexFactor node) { defaultIn(node); } //?? public void outAComplexFactor(AComplexFactor node) { defaultOut(node); } public void inAFunctionFactor(AFunctionFactor node) { defaultIn(node); } public void outAFunctionFactor(AFunctionFactor node) { defaultOut(node); } public void inAVariableFactor(AVariableFactor node) { defaultIn(node); } public void outAVariableFactor(AVariableFactor node) { defaultOut(node); } public void inAIntegerFactor(AIntegerFactor node) { defaultIn(node); } public void outAIntegerFactor(AIntegerFactor node) { this.table.enter(node, Type.INTEGER); } public void inACharFactor(ACharFactor node) { defaultIn(node); } public void outACharFactor(ACharFactor node) { this.table.enter(node, Type.CHAR); } public void inAStringFactor(AStringFactor node) { defaultIn(node); } public void outAStringFactor(AStringFactor node) { this.table.enter(node, Type.STRING); } public void inABooleanFactor(ABooleanFactor node) { this.table.enter(node, Type.BOOLEAN); } public void outABooleanFactor(ABooleanFactor node) { defaultOut(node); } public void inAExpressionFactor(AExpressionFactor node) { defaultIn(node); } public void outAExpressionFactor(AExpressionFactor node) { this.table.enter(node, (Type)this.table.retrieve(node.getExpression())); } public void inATrueBooleanLiteral(ATrueBooleanLiteral node) { defaultIn(node); } public void outATrueBooleanLiteral(ATrueBooleanLiteral node) { defaultOut(node); } public void inAFalseBooleanLiteral(AFalseBooleanLiteral node) { defaultIn(node); } public void outAFalseBooleanLiteral(AFalseBooleanLiteral node) { defaultOut(node); } public void inAGreaterThanRelOp(AGreaterThanRelOp node) { defaultIn(node); } public void outAGreaterThanRelOp(AGreaterThanRelOp node) { defaultOut(node); } public void inALessThanRelOp(ALessThanRelOp node) { defaultIn(node); } public void outALessThanRelOp(ALessThanRelOp node) { defaultOut(node); } public void inAEqualsRelOp(AEqualsRelOp node) { defaultIn(node); } public void outAEqualsRelOp(AEqualsRelOp node) { defaultOut(node); } public void inADifferentRelOp(ADifferentRelOp node) { defaultIn(node); } public void outADifferentRelOp(ADifferentRelOp node) { defaultOut(node); } public void inAPlusAddOp(APlusAddOp node) { defaultIn(node); } public void outAPlusAddOp(APlusAddOp node) { defaultOut(node); } public void inAMinusAddOp(AMinusAddOp node) { defaultIn(node); } public void outAMinusAddOp(AMinusAddOp node) { defaultOut(node); } public void inAOrAddOp(AOrAddOp node) { defaultIn(node); } public void outAOrAddOp(AOrAddOp node) { defaultOut(node); } public void inAMultMulOp(AMultMulOp node) { defaultIn(node); } public void outAMultMulOp(AMultMulOp node) { defaultOut(node); } public void inADivMulOp(ADivMulOp node) { defaultIn(node); } public void outADivMulOp(ADivMulOp node) { defaultOut(node); } public void inAAndMulOp(AAndMulOp node) { defaultIn(node); } public void outAAndMulOp(AAndMulOp node) { defaultOut(node); } public void inAFunctionStatement(AFunctionStatement node) { defaultIn(node); } public void outAFunctionStatement(AFunctionStatement node) { defaultOut(node); } public void inAAssignStatement(AAssignStatement node) { defaultIn(node); } public void outAAssignStatement(AAssignStatement node) { defaultOut(node); } public void inAPrintlnStatement(APrintlnStatement node) { defaultIn(node); } public void outAPrintlnStatement(APrintlnStatement node) { defaultOut(node); } public void inAPrintStatement(APrintStatement node) { defaultIn(node); } public void outAPrintStatement(APrintStatement node) { defaultOut(node); } public void inACmdListStatement(ACmdListStatement node) { defaultIn(node); } public void outACmdListStatement(ACmdListStatement node) { defaultOut(node); } public void inAIfThenElseStatement(AIfThenElseStatement node) { defaultIn(node); } public void outAIfThenElseStatement(AIfThenElseStatement node)throws RuntimeException { Type expressionType = (Type)this.table.retrieve(node.getExpression()); if (! (expressionType == Type.BOOLEAN)) { TIf ifToken = node.getIf(); throw new SemanticAnalyserException("[" + ifToken.getLine() + "," + ifToken.getPos() + "] expressao booleana esperada"); } } public void inAWhileStatement(AWhileStatement node) { defaultIn(node); } public void outAWhileStatement(AWhileStatement node) { defaultOut(node); } public void inAForStatement(AForStatement node) { defaultIn(node); } public void outAForStatement(AForStatement node) { defaultOut(node); } public void inAReturnStatement(AReturnStatement node) { defaultIn(node); } public void outAReturnStatement(AReturnStatement node) { defaultOut(node); } public void inAStmtList(AStmtList node) { defaultIn(node); } public void outAStmtList(AStmtList node) { defaultOut(node); } public void inASimpleStatement(ASimpleStatement node) { defaultIn(node); } public void outASimpleStatement(ASimpleStatement node) { defaultOut(node); } public void inAFunctionDecl(AFunctionDecl node) { defaultIn(node); } //function_decl = function_heading block; //function_heading = function type ident left_paren formal_param? right_paren; //block = left_bracket (statement semicolon)* right_bracket; //stmt_list = simple_statement*; //simple_statement = statement semicolon; public void outAFunctionDecl(AFunctionDecl node) { AFunctionHeading functionHeading = (AFunctionHeading) node.getFunctionHeading(); Type returnType = this.getActualType(functionHeading.getType ()); ABlock block = (ABlock) node.getBlock(); //ACompoundStmt compoundStmt = (ACompoundStmt) block.getStmtListgetCompoundStmt(); AStmtList stmtList = (AStmtList) block.getStmtList(); LinkedList linkedStmtList = stmtList.getSimpleStatement(); Iterator iteratorStmtList = linkedStmtList.iterator(); while (iteratorStmtList.hasNext()) { ASimpleStatement simpleStatement = (ASimpleStatement) iteratorStmtList.next(); PStatement statement = simpleStatement.getStatement(); if (statement instanceof AReturnStatement) { AReturnStatement returnStatement = (AReturnStatement) statement; Type expressionType = (Type)this.table.retrieve(returnStatement.getExpression()); if (returnType != expressionType) { if (! (returnType == Type.STRING && expressionType == Type.CHAR)) { TReturn returnToken = returnStatement.getReturn(); throw new SemanticAnalyserException("[" + returnToken.getLine () + "," + returnToken.getPos() + "] esperada expressao do tipo " + returnType.toString()); } } } } this.table = this.table.closeScope(); } //function_heading = function type ident left_paren formal_param? right_paren; //this.getActualType(node.getType()) public void inAFunctionHeading(AFunctionHeading node)throws RuntimeException { AFormalParam formalParam = (AFormalParam) node.getFormalParam(); if (formalParam != null) { this.table.enter (node.getIdent().getText(),this.getActualType(formalParam.getType())); //new FunctionAttribute(this.getActualType(formalParam.getType()), this.getActualType(node.getType()))); } else { this.table.enter (node.getIdent().getText(), this.getActualType(node.getType())); //new FunctionAttribute(null, this.getActualType(node.getType()))); } //opa this.table = this.table.openScope(); } public void outAFunctionHeading(AFunctionHeading node) { defaultOut(node); } public void inAFormalParam(AFormalParam node) { defaultIn(node); } public void outAFormalParam(AFormalParam node) { defaultOut(node); } }