/// <summary> /// finds the correct symbol and sets the attributes of the idRecord /// </summary> /// <param name="idRecord"></param> public void ProcessId(ref IdentifierRecord idRecord) { Symbol symbol; foreach(SymbolTable st in symbolTableStack) { symbol = st.Find(idRecord.lexeme); if(symbol != null) { idRecord.symbolTable = st; idRecord.symbol = symbol; break; } } }
/// <summary> /// Parse ProcedureHeading /// </summary> /// <param name="procedureRecord"></param> private void ProcedureHeading(MethodRecord procedureRecord,ref IdentifierRecord identifierRecord) { procedureRecord.parameterList = new List<Parameter>(); switch(lookAheadToken.tag) { case Tags.MP_PROCEDURE: UsedRules.WriteLine("17"); Match((int)Tags.MP_PROCEDURE); Identifier(ref procedureRecord); identifierRecord.lexeme = procedureRecord.name; procedureRecord.parameterList = OptionalFormalParameterList( procedureRecord.parameterList); analyzer.SymbolTableInsert(procedureRecord); analyzer.ProcessId(ref identifierRecord); analyzer.CreateSymbolTable(procedureRecord.name); analyzer.ProcessMethod(identifierRecord, ref procedureRecord); analyzer.SymbolTableInsert(procedureRecord.parameterList); break; default: Error("Expecting ProcedureHeading but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Parse InitialValue /// </summary> /// <param name="initialValueRecord"></param> private void InitialValue(ref IdentifierRecord initialValueRecord) { VariableRecord ordinalExpressionRecord = new VariableRecord(); switch (lookAheadToken.tag) { case Tags.MP_LPAREN: case Tags.MP_PLUS: case Tags.MP_MINUS: case Tags.MP_INTEGER_LIT: case Tags.MP_NOT: case Tags.MP_IDENTIFIER: UsedRules.WriteLine("59"); analyzer.GenerateObjectScope(initialValueRecord, StoreMode.Store); OrdinalExpression(ref ordinalExpressionRecord); analyzer.GenerateAssign(initialValueRecord, ordinalExpressionRecord); break; default: Error("Expecting InitialValue but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Generates code for a read statement /// </summary> /// <param name="idRecord"></param> internal void GenerateReadStatement(IdentifierRecord idRecord) { cilOutput.WriteLine(" call string [mscorlib]System.Console::ReadLine()"); cilOutput.WriteLine(" call int32 [mscorlib]System.Int32::Parse(string)"); cilOutput.Write(" stfld\t"); GenerateFieldLocation(idRecord); }
/// <summary> /// Process a method /// </summary> /// <param name="identifierRecord"></param> /// <param name="methodRecord"></param> internal void ProcessMethod(IdentifierRecord identifierRecord,ref MethodRecord methodRecord) { if (identifierRecord.symbol.symbolType == SymbolType.FunctionSymbol || identifierRecord.symbol.symbolType == SymbolType.ProcedureSymbol) { methodRecord.name = identifierRecord.lexeme; methodRecord.returnType = identifierRecord.symbol.variableType; methodRecord.symbolType = identifierRecord.symbol.symbolType; } }
/// <summary> /// Generates code for pushing an Identifier /// </summary> /// <param name="idRecord"></param> /// <param name="factorRecord"></param> internal void GenerateIdPush(IdentifierRecord idRecord, ref VariableRecord factorRecord) { GenerateObjectScope(idRecord,StoreMode.Load); if (factorRecord.ioMode == IOMode.InOut) { cilOutput.Write(" ldflda\t"); } else { cilOutput.Write(" ldfld\t"); } if (idRecord.symbol.symbolType == SymbolType.FunctionSymbol) { cilOutput.WriteLine("class Program/" + idRecord.lexeme + "Delegate " + idRecord.symbolTable.cilScope + "/c__" + idRecord.symbolTable.name + "::d__" + idRecord.lexeme + Environment.NewLine); } else { GenerateFieldLocation(idRecord); } if (idRecord.symbol is ParameterSymbol) { if ((idRecord.symbol as ParameterSymbol).parameter.mode == IOMode.InOut) { cilOutput.WriteLine("ldind.i4"); } } factorRecord.variableType = idRecord.symbol.variableType; }
/// <summary> /// Generates code for a method declaration /// </summary> /// <param name="identifierRecord"></param> internal void GenerateMethodDeclaration(string identifierRecord) { string parameters = GenerateParameterString(symbolTableStack.Peek().symbolTable,true); VariableType returnType = VariableType.Void; if (symbolTableStack.Count == 1) { cilOutput.Write(".method private hidebysig static void "); cilOutput.WriteLine("b__" + identifierRecord + "() cil managed"); cilOutput.WriteLine("{"); cilOutput.WriteLine(" .entrypoint"); } else { IdentifierRecord idRecord = new IdentifierRecord(); idRecord.lexeme = identifierRecord; ProcessId(ref idRecord); returnType = idRecord.symbol.variableType; cilOutput.WriteLine(".method public hidebysig instance "+ Enumerations.GetDescription<VariableType>(returnType)); cilOutput.WriteLine("\tb__"+ identifierRecord + "(" + parameters + ") cil managed"); cilOutput.WriteLine("{"); } int stackCount = 2; int delegateCount = 0; string resultLocal = string.Empty; if (returnType != VariableType.Void) { stackCount++; resultLocal = "," + Environment.NewLine + "\t\t[1] " + Enumerations.GetDescription <VariableType>(returnType) + " result"; } stackCount += delegateCount; cilOutput.WriteLine(" .maxstack " + (stackCount + DELEGATE_EXTRA_SPACE) + Environment.NewLine); string cilScope = symbolTableStack.Peek().cilScope; cilOutput.WriteLine( " .locals init ([0] class " + cilScope + "/c__" + identifierRecord + " c__" + identifierRecord + "Obj" + resultLocal+ ")" + Environment.NewLine); cilOutput.WriteLine(" newobj\tinstance void " + cilScope + "/c__" + identifierRecord + "::.ctor()"); cilOutput.WriteLine(" stloc.0" + Environment.NewLine); GenerateDelegateInitilization(); if (symbolTableStack.Count > 1) { int scopeCount = 0; string newScope = symbolTableStack.Peek().cilScope + "/c__" + symbolTableStack.Peek().name; int index = newScope.LastIndexOf("/"); string oldScope = newScope.Substring(0, index); SymbolTable previousScope; SymbolTable symbolTable = symbolTableStack.Peek(); int count = 0; for(int i = 0;i <symbolTableStack.Count -1;i++) { cilOutput.WriteLine(" ldloc.0"); cilOutput.WriteLine(" ldarg.0"); //symbolTable = symbolTableStack.ElementAt(count); count++; previousScope = symbolTableStack.ElementAt(count); if (scopeCount > 0) { cilOutput.WriteLine(" ldfld\tclass " + previousScope.cilScope + "/c__" + previousScope.name + " " + oldScope + "::c__" + previousScope.name + "Obj"); } cilOutput.WriteLine(" stfld\tclass " + previousScope.cilScope + "/c__" + previousScope.name + " " + newScope + "::c__" + previousScope.name + "Obj" + Environment.NewLine); scopeCount++; } } }
/// <summary> /// Parse AssignmentStatement /// </summary> private void AssignmentStatement() { IdentifierRecord idRecord = new IdentifierRecord(); VariableRecord expressionRecord = new VariableRecord(); string idRecName = null; switch (lookAheadToken.tag) { case Tags.MP_IDENTIFIER: // Identifier ":=" Expression UsedRules.WriteLine("51"); Identifier(ref idRecName); idRecord.lexeme = idRecName; analyzer.ProcessId(ref idRecord); Match((int)Tags.MP_ASSIGN); analyzer.GenerateObjectScope(idRecord, StoreMode.Store); Expression(ref expressionRecord); analyzer.GenerateAssign(idRecord, expressionRecord); break; default: Error("Expecting AssignmentStatement but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Parse Block /// </summary> /// <param name="identifierRecord"></param> private void Block(IdentifierRecord identifierRecord) { switch (lookAheadToken.tag) { case Tags.MP_VAR: case Tags.MP_PROCEDURE: case Tags.MP_FUNCTION: case Tags.MP_BEGIN: UsedRules.WriteLine("4"); analyzer.GenerateClassDeclaration(identifierRecord.lexeme); VariableDeclarationPart(); analyzer.GenerateClassConstructor(identifierRecord.lexeme); ProcedureAndFunctionDeclarationPart(); analyzer.GenerateFields(); analyzer.GenerateClosingBrace(); analyzer.GenerateMethodDeclaration(identifierRecord.lexeme); StatementPart(); //analyzer.GenerateReferenceParameterReassignment(); analyzer.GenerateReturn(identifierRecord); break; default: Error("Expecting ProgramBlock found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Parse ReadParameterTail /// </summary> private void ReadParameterTail() { IdentifierRecord idRecord = new IdentifierRecord(); switch (lookAheadToken.tag) { case Tags.MP_COMMA: //"," ReadParameter ReadParameterTail UsedRules.WriteLine("44"); Match((int)Tags.MP_COMMA); ReadParameter(idRecord); analyzer.GenerateObjectScope(idRecord, StoreMode.Load); analyzer.GenerateReadStatement(idRecord); ReadParameterTail(); break; case Tags.MP_RPAREN: //lambda UsedRules.WriteLine("45"); break; default: Error("Expecting ReadParameterTail but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Parse ReadStatement /// </summary> private void ReadStatement() { IdentifierRecord idRecord = new IdentifierRecord(); switch(lookAheadToken.tag) { case Tags.MP_READ: UsedRules.WriteLine("43"); Match((int)Tags.MP_READ); Match((int)Tags.MP_LPAREN); ReadParameter(idRecord); analyzer.GenerateObjectScope(idRecord,StoreMode.Load); analyzer.GenerateReadStatement(idRecord); ReadParameterTail(); Match((int)Tags.MP_RPAREN); break; default: Error("Expecting Read but found " + lookAheadToken.tag); break; } }
/// <summary> /// Parse ReadParameter /// </summary> /// <param name="idRecord"></param> private void ReadParameter(IdentifierRecord idRecord) { switch(lookAheadToken.tag) { case Tags.MP_IDENTIFIER: string idRecName = null; UsedRules.WriteLine("46"); Identifier(ref idRecName); idRecord.lexeme = idRecName; analyzer.ProcessId(ref idRecord); break; default: Error("Expecting ID found " + lookAheadToken.tag); break; } }
/// <summary> /// Parse Program /// </summary> private void Program() { IdentifierRecord programIdentifierRecord = new IdentifierRecord(); string name = string.Empty; switch (lookAheadToken.tag) { case Tags.MP_PROGRAM: UsedRules.WriteLine("2"); ProgramHeading(ref name); programIdentifierRecord.lexeme = name; Match(';'); Block(programIdentifierRecord); analyzer.symbolTableStack.Pop(); Match('.'); analyzer.GenerateDelegateDeclaration(); analyzer.GenerateClosingBrace(); break; default: Error("Expecting Program found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Parse ProcedureStatement /// </summary> private void ProcedureStatement() { MethodRecord procedureRecord = new MethodRecord(SymbolType.ProcedureSymbol); IdentifierRecord identifierRecord = new IdentifierRecord(); List<Parameter> parameterList = new List<Parameter>(); procedureRecord.parameterList = new List<Parameter>(); switch (lookAheadToken.tag) { case Tags.MP_IDENTIFIER: UsedRules.WriteLine("63"); Identifier(ref procedureRecord); identifierRecord.lexeme = procedureRecord.name; analyzer.ProcessId(ref identifierRecord); analyzer.GenerateLoadDelegate(procedureRecord); analyzer.processParameters(identifierRecord, ref procedureRecord, ref parameterList); OptionalActualParameterList(parameterList); analyzer.GenerateCallMethod(procedureRecord); break; default: Error("Expecting ProcedureStatement but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Generates code for assignment statements /// </summary> /// <param name="idRecord"></param> /// <param name="expressionRecord"></param> internal void GenerateAssign(IdentifierRecord idRecord, VariableRecord expressionRecord) { switch (idRecord.symbol.symbolType) { case SymbolType.VariableSymbol: cilOutput.WriteLine(" stfld\t" + Enumerations.GetDescription<VariableType>(idRecord.symbol.variableType) + " " + idRecord.symbolTable.cilScope + "/c__" + idRecord.symbolTable.name + "::" + idRecord.lexeme + Environment.NewLine); break; case SymbolType.ParameterSymbol: if ((idRecord.symbol as ParameterSymbol).parameter.mode == IOMode.InOut) { cilOutput.WriteLine(" stind.i4"); } else { cilOutput.WriteLine(" stfld\t" + Enumerations.GetDescription<VariableType>(idRecord.symbol.variableType) + " " + idRecord.symbolTable.cilScope + "/c__" + idRecord.symbolTable.name + "::" + idRecord.lexeme + Environment.NewLine); } break; case SymbolType.FunctionSymbol: cilOutput.WriteLine(" stloc.1" + Environment.NewLine); break; } }
/// <summary> /// Parse Control Variable /// </summary> /// <param name="controlVariableRecord"></param> private void ControlVariable(ref IdentifierRecord controlVariableRecord) { switch(lookAheadToken.tag) { case Tags.MP_IDENTIFIER: string procedureIdentifier = null; UsedRules.WriteLine("58"); Identifier(ref procedureIdentifier); controlVariableRecord.lexeme = procedureIdentifier; analyzer.ProcessId(ref controlVariableRecord); break; default: Error("Expecting ControlVariable but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Writes the location and type for field /// </summary> /// <param name="idRecord"></param> internal void GenerateFieldLocation(IdentifierRecord idRecord) { cilOutput.Write(Enumerations.GetDescription<VariableType>( idRecord.symbol.variableType)); if (idRecord.symbol is ParameterSymbol) { if((idRecord.symbol as ParameterSymbol).parameter.mode == IOMode.InOut) { cilOutput.Write("*"); } } cilOutput.WriteLine(" " + idRecord.symbolTable.cilScope + "/c__" + idRecord.symbolTable.name + "::" + idRecord.lexeme); }
/// <summary> /// Parse Factor /// </summary> /// <param name="factorRecord"></param> private void Factor(ref VariableRecord factorRecord) { IdentifierRecord idRecord = new IdentifierRecord(); LiteralRecord litRecord = new LiteralRecord(); VariableType tempType = VariableType.Void; List<Parameter> parameterList = new List<Parameter>(); MethodRecord methodRecord = new MethodRecord(); methodRecord.parameterList = new List<Parameter>(); string idRecName = null; switch (lookAheadToken.tag) { case Tags.MP_INTEGER_LIT: UsedRules.WriteLine("94"); litRecord.lexeme = lookAheadToken.lexeme; litRecord.type = VariableType.Integer; Match((int)Tags.MP_INTEGER_LIT); analyzer.GenerateLitPush(litRecord, ref tempType); factorRecord.variableType = tempType; break; case Tags.MP_NOT: UsedRules.WriteLine("95"); Match((int)Tags.MP_NOT); Factor(ref factorRecord); break; case Tags.MP_LPAREN: UsedRules.WriteLine("96"); Match((int)Tags.MP_LPAREN); Expression(ref factorRecord); Match((int)Tags.MP_RPAREN); break; case Tags.MP_IDENTIFIER: UsedRules.WriteLine("97"); Identifier(ref idRecName); idRecord.lexeme = idRecName; analyzer.ProcessId(ref idRecord); analyzer.GenerateIdPush(idRecord, ref factorRecord); analyzer.processParameters(idRecord,ref methodRecord,ref parameterList); OptionalActualParameterList(parameterList); analyzer.ProcessMethod(idRecord,ref methodRecord); analyzer.GenerateCallMethod(methodRecord); break; default: Error("Expecting Factor but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Generates code for incrementing in a control structure /// </summary> /// <param name="controlLabelRecord"></param> /// <param name="p"></param> internal void GenerateIncrement(ref IdentifierRecord identifierRecord, string addingOperator) { cilOutput.WriteLine(" ldloc.0"); cilOutput.WriteLine(" ldloc.0"); cilOutput.Write(" ldfld\t"); GenerateFieldLocation(identifierRecord); cilOutput.WriteLine(" ldc.i4 1"); cilOutput.WriteLine(" " + addingOperator); cilOutput.Write(" stfld\t"); GenerateFieldLocation(identifierRecord); }
/// <summary> /// Parse ForStatement /// </summary> private void ForStatement() { IdentifierRecord controlVariableRecord = new IdentifierRecord(); VariableRecord finalValueRecord = new VariableRecord(); VariableRecord controlStatementRecord = new VariableRecord(); string controlLabelRecord = string.Empty; string loopLabel = string.Empty; ControlRecord stepValueRecord = new ControlRecord(); switch(lookAheadToken.tag) { case Tags.MP_FOR: UsedRules.WriteLine("57"); Match((int)Tags.MP_FOR); ControlVariable(ref controlVariableRecord); Match((int)Tags.MP_ASSIGN); InitialValue(ref controlVariableRecord); analyzer.GenerateLabel(ref controlLabelRecord); analyzer.GenerateIdPush(controlVariableRecord,ref controlStatementRecord); StepValue(ref stepValueRecord); FinalValue(ref finalValueRecord); analyzer.GenerateBranch(ref loopLabel, stepValueRecord.branchType); Match((int)Tags.MP_DO); Statement(); analyzer.GenerateIncrement(ref controlVariableRecord, stepValueRecord.addingOperator); analyzer.GenerateBranch(ref controlLabelRecord, BranchType.br); analyzer.GenerateLabel(ref loopLabel); break; default: Error("Expecting ForStatement found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Generates code for the object scope /// </summary> /// <param name="objectIdentifier"></param> internal void GenerateObjectScope(IdentifierRecord objectIdentifier, StoreMode mode) { if (objectIdentifier.symbol.symbolType != SymbolType.FunctionSymbol || mode == StoreMode.Load) { if (symbolTableStack.Count == 1) { cilOutput.WriteLine(" ldloc.0"); } else { int nestingLevelDifference = symbolTableStack.Count - 1 - objectIdentifier. symbolTable.nestingLevel; if (nestingLevelDifference < 1) { cilOutput.WriteLine(" ldloc.0"); } else { cilOutput.WriteLine(" ldarg.0"); if (nestingLevelDifference > 1) { cilOutput.WriteLine(" ldfld\tclass " + objectIdentifier.symbolTable. cilScope + "/c__" + objectIdentifier.symbolTable.name + " " + symbolTableStack.Peek().cilScope + "::c__" + objectIdentifier.symbolTable.name + "Obj"); } } } } if (objectIdentifier.symbol is ParameterSymbol) { if ((objectIdentifier.symbol as ParameterSymbol).parameter.mode == IOMode.InOut && mode == StoreMode.Store) { cilOutput.WriteLine(" ldfld\t" + Enumerations.GetDescription<VariableType> (objectIdentifier.symbol.variableType) + "* " + objectIdentifier.symbolTable.cilScope + "/c__" + objectIdentifier. symbolTable.name + "::" + objectIdentifier.symbol.name); } } }
/// <summary> /// Parse FunctionDeclaration /// </summary> private void FunctionDeclaration() { IdentifierRecord identifierRecord = new IdentifierRecord(); MethodRecord functionIdentifierRecord = new MethodRecord(SymbolType.FunctionSymbol); switch (lookAheadToken.tag) { case Tags.MP_FUNCTION: UsedRules.WriteLine("16"); FunctionHeading(functionIdentifierRecord,ref identifierRecord); Match(';'); Block(identifierRecord); analyzer.symbolTableStack.Pop(); Match(';'); break; default: Error("Expecting FunctionDeclaration but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Generates code for return statements /// </summary> internal void GenerateReturn(IdentifierRecord identifierRecord) { if (symbolTableStack.Peek().nestingLevel > 0 && identifierRecord.symbol.symbolType == SymbolType.FunctionSymbol) { cilOutput.WriteLine(" ldloc.1"); } cilOutput.WriteLine(" ret"); cilOutput.WriteLine("}"); }
/// <summary> /// Parse FunctionHeading /// </summary> /// <param name="functionRecord"></param> private void FunctionHeading(MethodRecord functionRecord, ref IdentifierRecord identifierRecord) { TypeRecord typeRecord = new TypeRecord(SymbolType.FunctionSymbol, VariableType.Void); functionRecord.parameterList = new List<Parameter>(); switch (lookAheadToken.tag) { case Tags.MP_FUNCTION: UsedRules.WriteLine("18"); Match((int)Tags.MP_FUNCTION); Identifier(ref functionRecord); identifierRecord.lexeme = functionRecord.name; functionRecord.parameterList = OptionalFormalParameterList( functionRecord.parameterList); Type(ref typeRecord); functionRecord.returnType = typeRecord.variableType; analyzer.SymbolTableInsert(functionRecord); analyzer.ProcessId(ref identifierRecord); analyzer.CreateSymbolTable(functionRecord.name); //analyzer.ProcessMethod(identifierRecord, ref functionRecord); analyzer.SymbolTableInsert(functionRecord.parameterList); break; default: Error("Expecting FunctionHeading but found " + lookAheadToken.lexeme); break; } }
/// <summary> /// Process Parameters /// </summary> /// <param name="identifierRecord"></param> /// <param name="procedureRecord"></param> /// <param name="parameterList"></param> internal void processParameters(IdentifierRecord identifierRecord, ref MethodRecord procedureRecord, ref List<Parameter> parameterList) { if (identifierRecord.symbol is ProcedureSymbol) { ProcedureSymbol pSymbol = identifierRecord.symbol as ProcedureSymbol; procedureRecord.parameterList = pSymbol.paramList; parameterList = new List<Parameter>(procedureRecord.parameterList); } }
/// <summary> /// Parse ProcedureDeclaration /// </summary> private void ProcedureDeclaration() { MethodRecord procedureIdentifierRecord = new MethodRecord(SymbolType.ProcedureSymbol); IdentifierRecord identifierRecord = new IdentifierRecord(); switch(lookAheadToken.tag) { case Tags.MP_PROCEDURE: UsedRules.WriteLine("15"); ProcedureHeading(procedureIdentifierRecord,ref identifierRecord); Match(';'); Block(identifierRecord); analyzer.symbolTableStack.Pop(); Match(';'); break; default: Error("Expecting ProcedureDeclaration but found " + lookAheadToken.lexeme); break; } }