options { JAVA_UNICODE_ESCAPE = false; IGNORE_CASE = true; } PARSER_BEGIN(MiniPascalParser) import java.util.Vector; import java.util.Stack; public class MiniPascalParser { static private class ArrayInformation { int inicio, fim; String tipo; } static String className; static ByteCodeManager byteCodeManager = new ByteCodeManager(); static ByteCodeWriter byteCode; static ArrayInformation lastArrayInformation = new ArrayInformation(); static boolean lastTypeWasArray; static Vector tiposParametros; //ultimo metodo header lido static Stack pParametros = new Stack(); static Estrutura estruturaRetorno; static Vector nomesIdentifiers; static String CTE = ""; static Vector vectorCTE = new Vector(); static Vector localIdentifiers; static Vector localIdentifiersTypes; static Vector globalIdentifiers; static Vector globalIdentifiersTypes; static TabelaVariaveis tabelaVariaveisGlobais; static TabelaVariaveis tabelaVariaveisLocais; static TabelaMetodos tabelaMetodos = new TabelaMetodos(); static String lastStandartType; public static void main(String args[]) { MiniPascalParser parser; if (args.length == 0) { parser = new MiniPascalParser(System.in); } else if (args.length == 1) { try { parser = new MiniPascalParser(new java.io.FileInputStream(args[0])); } catch (java.io.FileNotFoundException e) { return; } } else { return; } try { parser.Program(); //System.out.println("Parsing OK"); } catch (ParseException e) { System.out.println(e.getMessage()); } } } PARSER_END(MiniPascalParser) // ******************************** Espacos ************************************ SKIP : { " " | "\t" | "\n" | "\r" | "\f" } // ****************************** Comentarios ********************************** MORE : { "{" : COMENTARIO } SPECIAL_TOKEN : { "}" : DEFAULT } MORE : { < ~[] > } // ************************* Palavras Reservadas ******************************* TOKEN : { < REAL: "real" > | < INTEGER: "integer" > | < IF: "if" > | < THEN: "then" > | < ELSE: "else" > | < BEGIN: "begin" > | < END: "end" > | < PROGRAM: "program" > | < PROCEDURE: "procedure" > | < FUNCTION: "function" > | < VAR: "var" > | < ARRAY: "array" > | < OF: "of" > | < WHILE: "while" > | < DO: "do" > } // ******************************** Literais *********************************** TOKEN : { < NUM: ( )? ()? > | < #DIGITS: (["0"-"9"])+ > | < #EXPOENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | < #FRACTION: "." > } // ******************************* Separadores ********************************* TOKEN : { < LPAREN: "(" > | < RPAREN: ")" > | < LBRACKET: "[" > | < RBRACKET: "]" > | < SEMICOLON: ";" > | < COMMA: "," > | < DOT: "." > } // ******************************* Operadores ********************************** TOKEN : { < RELOP: ( "=" | "<>" | "<" | ">" | "<=" | ">=" | ">" ) > | < ADD: "+" > | < MINUS: "-" > | < NOT: "not" > | < OR: "or" > | < MULOP: ( "*" | "/" | "div" | "mod" | "and" ) > | < ASSIGN_OP: ":=" > } TOKEN : { < ID: (|)* > | < #LETTER: ["a"-"z", "A"-"Z" ] > | < #DIGIT: ["0"-"9"] > } // ***************************************************************************** // ** A GRAMATICA COMECA AQUI ** // ***************************************************************************** void Program() : {} { "program" { className = getToken(0).image; byteCodeManager.addClass(className, "java/lang/Object"); byteCodeManager.addPrintMethodHeader(); byteCode = new ByteCodeWriter(className+".class"); byteCode.writeHeader(); } "(" IdentifierList() ")" ";" Declarations() { tabelaVariaveisLocais = new TabelaVariaveis(); tiposParametros = new Vector(); tiposParametros.addElement("real"); tabelaMetodos.addMetodo("writeln", "", "", tabelaVariaveisLocais, tiposParametros); } SubprogramDeclarations() { Vector mainParameters = new Vector(); mainParameters.addElement("[Ljava/lang/String;"); byteCodeManager.addMethod(className, "main", "", mainParameters); } { CTE = ""; vectorCTE = new Vector(); localIdentifiers = new Vector(); localIdentifiersTypes = new Vector(); localIdentifiers.addElement("main"); localIdentifiersTypes.addElement(""); localIdentifiers.addElement("args"); localIdentifiersTypes.addElement("[Ljava/lang/String;"); } CompoundStatement() "." { //Ultima entrada dos vetores de identifier devem correponder ao valor de retorno localIdentifiers.addElement(localIdentifiers.remove(0)); localIdentifiersTypes.addElement(localIdentifiersTypes.remove(0)); byteCodeManager.setMethodCode(localIdentifiers, localIdentifiersTypes, CTE, Util.get1to1(vectorCTE)); byteCode.writeBytes(byteCodeManager.getByteCode()); byteCode.close(); } } void Declarations() : { boolean ehGlobal; TabelaVariaveis tabela; if (tabelaVariaveisGlobais == null) { //se eh a primeira vez que entra aqui, entao trabalha-se sobre as variaveis //globais tabelaVariaveisGlobais = new TabelaVariaveis(); tabela = tabelaVariaveisGlobais; globalIdentifiers = new Vector(); globalIdentifiersTypes = new Vector(); ehGlobal = true; } else { ehGlobal = false; //senao, trabalha-se sobra a tabela de var. locais, que ja foi inicializada //quando da declaracao do parametros -> -> tabela = tabelaVariaveisLocais; } } { ( "var" IdentifierList() ":" Type() { if (lastTypeWasArray) { for (int i=0; i { lastArrayInformation.inicio = Integer.parseInt(getToken(0).image); } ".." { lastArrayInformation.fim = Integer.parseInt(getToken(0).image); } "]" "of" StandartType() { lastArrayInformation.tipo = getToken(0).image; } ) } void StandartType() : {} { ( "integer" | "real" ) { lastStandartType = getToken(0).image; } } void SubprogramDeclarations() : {} { ( SubprogramDeclaration() ";" { CTE += "RETURN;\n"; vectorCTE.addElement("RETURN"); } )* } void SubprogramDeclaration() : { } { SubprogramHead() Declarations() CompoundStatement() { localIdentifiers.addElement(localIdentifiers.remove(0)); localIdentifiersTypes.addElement(localIdentifiersTypes.remove(0)); byteCodeManager.setMethodCode(localIdentifiers, localIdentifiersTypes, CTE, Util.get1to1(vectorCTE)); } } void SubprogramHead() : { String nome; String label; String retorno; } { ( "function" { nome = getToken(0).image; } Arguments() ":" StandartType() { label = NewTempGenerator.newLabel(); CTE = ""; vectorCTE = new Vector(); localIdentifiers.insertElementAt(nome, 0); localIdentifiersTypes.insertElementAt(getToken(0).image, 0); tabelaMetodos.addMetodo(nome, label, getToken(0).image, tabelaVariaveisLocais, tiposParametros); byteCodeManager.addMethod(className, nome, getToken(0).image, tiposParametros); } ";" | "procedure" { nome = getToken(0).image; } Arguments() { label = NewTempGenerator.newLabel(); CTE = ""; vectorCTE = new Vector(); localIdentifiers.insertElementAt(nome, 0); localIdentifiersTypes.insertElementAt("", 0); tabelaMetodos.addMetodo(nome, label, "", tabelaVariaveisLocais, tiposParametros); byteCodeManager.addMethod(className, nome, "", tiposParametros); } ";" ) } void Arguments() : { localIdentifiers = new Vector(); localIdentifiersTypes = new Vector(); tabelaVariaveisLocais = new TabelaVariaveis(); tiposParametros = new Vector(); } { ( "(" ParameterList() ")" )? } void ParameterList() : {} { IdentifierList() ":" Type() { if (lastTypeWasArray) { //for necessario para casos como a, b :integer for (int i=0; i { nomesIdentifiers.addElement(getToken(0).image); } ( "," { nomesIdentifiers.addElement(getToken(0).image); } )* } void CompoundStatement() : {} { "begin" OptionalStatement() "end" } void OptionalStatement() : {} { [ StatementList() ] } void StatementList() : {} { Statement() ( ";" Statement() )* } void Statement() : { Estrutura estrutura = new Estrutura(); String toThenLabel, toEndLabel, toElseLabel, inicioLabel; } { LOOKAHEAD(2) ( Variable() { //CTE += estruturaRetorno.toStringCTE(); //Util.mergeVectors(vectorCTE, estruturaRetorno.toVectorCTE(localIdentifiers, localIdentifiersTypes, tabelaMetodos)); estrutura = estruturaRetorno; } { estrutura.sinal = getToken(0).image; } Expression() { estrutura.e1 = estruturaRetorno; estruturaRetorno = estrutura; } { CTE += estruturaRetorno.toStringCTE(); Util.mergeVectors(vectorCTE, estruturaRetorno.toVectorCTE(localIdentifiers, localIdentifiersTypes, tabelaMetodos)); } ) | ProcedureStatement() { CTE += estruturaRetorno.toStringCTE(); Util.mergeVectors(vectorCTE, estruturaRetorno.toVectorCTE(localIdentifiers, localIdentifiersTypes, tabelaMetodos)); } | CompoundStatement() |( "if" Expression() { CTE += estruturaRetorno.toStringCTE(); Util.mergeVectors(vectorCTE, estruturaRetorno.toVectorCTE(localIdentifiers, localIdentifiersTypes, tabelaMetodos)); toElseLabel = NewTempGenerator.newLabel(); CTE += "IF_NOT "+estruturaRetorno.place +" GOTO "+toElseLabel+";\n"; switch (estruturaRetorno.tipo) { case Estrutura.C_INTEGER: vectorCTE.addElement("CARREGA_C_I "+estruturaRetorno.place); break; case Estrutura.V_INTEGER: vectorCTE.addElement("CARREGA_V_I "+estruturaRetorno.place); break; case Estrutura.C_REAL: vectorCTE.addElement("CARREGA_C_R "+estruturaRetorno.place); break; case Estrutura.V_REAL: vectorCTE.addElement("CARREGA_V_I "+estruturaRetorno.place); break; case Estrutura.M_INTEGER: case Estrutura.M_REAL: break; case Estrutura.A_INTEGER: case Estrutura.A_REAL: vectorCTE.addElement("CARREGA_A "+estruturaRetorno.place); break; } vectorCTE.addElement("IF_NOT "+toElseLabel); //vectorCTE.addElement("IF_NOT "+estruturaRetorno.place +" GOTO "+toElseLabel); } "then" Statement() { toEndLabel = NewTempGenerator.newLabel(); CTE += "GOTO "+toEndLabel+";\n"; vectorCTE.addElement("GOTO "+toEndLabel); CTE += ":"+toElseLabel + ";\n"; vectorCTE.addElement(":"+toElseLabel); } [ LOOKAHEAD(1) "else" Statement() ] { CTE += ":"+toEndLabel + ";\n"; vectorCTE.addElement(":"+toEndLabel); } ) | "while" Expression() { inicioLabel = NewTempGenerator.newLabel(); CTE += ":"+inicioLabel +";\n"; vectorCTE.addElement(":"+inicioLabel); CTE += estruturaRetorno.toStringCTE(); Util.mergeVectors(vectorCTE, estruturaRetorno.toVectorCTE(localIdentifiers, localIdentifiersTypes, tabelaMetodos)); toEndLabel = NewTempGenerator.newLabel(); CTE += "IF_NOT "+estruturaRetorno.place +" GOTO "+toEndLabel+";\n"; switch (estruturaRetorno.tipo) { case Estrutura.C_INTEGER: vectorCTE.addElement("CARREGA_C_I "+estruturaRetorno.place); break; case Estrutura.V_INTEGER: vectorCTE.addElement("CARREGA_V_I "+estruturaRetorno.place); break; case Estrutura.C_REAL: vectorCTE.addElement("CARREGA_C_R "+estruturaRetorno.place); break; case Estrutura.V_REAL: vectorCTE.addElement("CARREGA_V_I "+estruturaRetorno.place); break; case Estrutura.M_INTEGER: case Estrutura.M_REAL: break; case Estrutura.A_INTEGER: case Estrutura.A_REAL: vectorCTE.addElement("CARREGA_A "+estruturaRetorno.place); break; } vectorCTE.addElement("IF_NOT "+toEndLabel); } "do" Statement() { CTE += "GOTO "+inicioLabel+";\n"; vectorCTE.addElement("GOTO "+inicioLabel); CTE += ":"+toEndLabel + ";\n"; vectorCTE.addElement(":"+toEndLabel); } } void Variable() : { Estrutura estrutura = new Estrutura(); } { { estrutura.place = getToken(0).image; int index = localIdentifiers.indexOf(getToken(0).image); String tipo; if (index != -1) { tipo = (String)localIdentifiersTypes.elementAt(index); if (tipo.equals("integer")) estrutura.tipo = Estrutura.V_INTEGER; else estrutura.tipo = Estrutura.V_REAL; } else { index = globalIdentifiers.indexOf(getToken(0).image); if (index != -1) { tipo = (String)globalIdentifiersTypes.elementAt(index); if (tipo.equals("integer")) estrutura.tipo = Estrutura.A_INTEGER; else estrutura.tipo = Estrutura.A_REAL; } else { System.err.println("Warning: unresolved symbol "+getToken(0).image); System.exit(1); estrutura.tipo = Estrutura.INDEFINIDO; } } } [ "[" Expression() { estrutura.e1 = estruturaRetorno; } "]" ] { if (estrutura.e1 != null) { //array estrutura.place = "[@"+estrutura.place + "+" + estrutura.e1.place+"]"; estrutura.sinal = "[]"; } estruturaRetorno = estrutura; } } void ProcedureStatement() : { Estrutura estrutura = new Estrutura(); } { { if (getToken(0).image.equals("writeln")) { vectorCTE.addElement("LOAD_OUT"); } //estrutura.place = tabelaMetodos.getLabel(getToken(0).image); estrutura.place = getToken(0).image; String tipo = tabelaMetodos.getTipo(getToken(0).image); if (tipo == null) { System.err.println("Erro at Procedure Statement: "+getToken(0).image+" nao encontrado em:\n"+ tabelaMetodos); System.exit(1); } if (tipo.equals("integer")) estrutura.tipo = Estrutura.M_INTEGER; //real else if (tipo.equals("real")) estrutura.tipo = Estrutura.M_REAL; //void -> "" else estrutura.tipo = Estrutura.M_VOID; estrutura.sinal = "call"; } "(" ExpressionList() ")" { Vector parametros = (Vector)pParametros.pop(); estrutura.parametros = parametros; estruturaRetorno = estrutura; } } void ExpressionList() : { Vector parametros = new Vector(); pParametros.push(parametros); } { [ Expression() { parametros.addElement(estruturaRetorno); } ( "," Expression() { parametros.addElement(estruturaRetorno); } )* ] } void Expression() : { Estrutura estrutura = null; String tokenSinal; } { SimpleExpression() { if (estrutura == null) estrutura = estruturaRetorno; } ( { tokenSinal = getToken(0).image; } SimpleExpression() { Estrutura tempEstrutura = new Estrutura(); tempEstrutura.sinal = tokenSinal; tempEstrutura.place = NewTempGenerator.newTemp(); tempEstrutura.tipo = Estrutura.V_TEMPORARIA; localIdentifiers.addElement(tempEstrutura.place); localIdentifiersTypes.addElement("temporary"); tempEstrutura.e1 = estrutura; tempEstrutura.e2 = estruturaRetorno; estrutura = tempEstrutura; } ) * { estruturaRetorno = estrutura; } } void SimpleExpression() : { Estrutura estrutura = null; String tokenSinal; } { [Sign()] Term() { if (estrutura == null) estrutura = estruturaRetorno; } ( AddOp() { tokenSinal = getToken(0).image; } [Sign()] Term() { Estrutura tempEstrutura = new Estrutura(); tempEstrutura.sinal = tokenSinal; tempEstrutura.place = NewTempGenerator.newTemp(); tempEstrutura.tipo = Estrutura.V_TEMPORARIA; localIdentifiers.addElement(tempEstrutura.place); localIdentifiersTypes.addElement("temporary"); tempEstrutura.e1 = estrutura; tempEstrutura.e2 = estruturaRetorno; estrutura = tempEstrutura; } )* { estruturaRetorno = estrutura; } } void Term() : { Estrutura estrutura = null; String tokenSinal; } { Factor() { if (estrutura == null) estrutura = estruturaRetorno; } ( ( { tokenSinal = getToken(0).image; } Factor() { Estrutura tempEstrutura = new Estrutura(); tempEstrutura.sinal = tokenSinal; tempEstrutura.place = NewTempGenerator.newTemp(); tempEstrutura.tipo = Estrutura.V_TEMPORARIA; localIdentifiers.addElement(tempEstrutura.place); localIdentifiersTypes.addElement("temporary"); tempEstrutura.e1 = estrutura; tempEstrutura.e2 = estruturaRetorno; estrutura = tempEstrutura; } )* ) { estruturaRetorno = estrutura; } } void Factor() : {} { ( ( LOOKAHEAD(2, "(") ProcedureStatement() | Variable() ) | { estruturaRetorno = new Estrutura(); estruturaRetorno.place = getToken(0).image; if (getToken(0).image.indexOf(".") == -1) { //inteiro (nao tem . no meio) estruturaRetorno.tipo = Estrutura.C_INTEGER; } else { estruturaRetorno.tipo = Estrutura.C_REAL; } } | "(" Expression() ")" | "not" Factor() { Estrutura tempEstrutura = new Estrutura(); tempEstrutura.place = NewTempGenerator.newTemp(); tempEstrutura.tipo = Estrutura.V_TEMPORARIA; tempEstrutura.sinal = "not"; localIdentifiers.addElement(tempEstrutura.place); localIdentifiersTypes.addElement("temporary"); tempEstrutura.e1 = estruturaRetorno; estruturaRetorno = tempEstrutura; } ) } void Sign() : {} { "+" | "-" } void AddOp() : {} { "+" | "-" | "or" }