void IfHeader() { Expect((int)TokenEnum.If); Expect((int)TokenEnum.LeftParenthesis); Expression(); try { GraphicFooType type = Quadruple.typeStack.Pop(); if (Semantics.ExpectType(type, GraphicFooType.Boolean)) { string id = Quadruple.operandStack.Pop(); Quadruple.CreateGotoFalseQuadruple(id); Quadruple.PushJump(); } else { SemErr( (int)SemanticEnum.TypeMismatch, "expected boolean, found " + type ); } } catch (InvalidOperationException) { SynErr((int)TokenEnum.NoExpression); } Expect((int)TokenEnum.RightParenthesis); }
void EndIf() { Expect((int)TokenEnum.EndIf); if (!Quadruple.PopJump()) { SynErr((int)TokenEnum.EndIf); } }
/// <summary> /// Executes a goto operation. /// </summary> /// <returns><c>true</c>, if goto operation was executed, <c>false</c> otherwise.</returns> /// <param name="q">Q.</param> /// <param name="condition">If set to <c>true</c> condition.</param> private static bool ExecuteGotoOperation(Quadruple q, bool condition) { bool?v1Value = CastToBoolean(q.v1); bool v1; v1 = v1Value ?? default(bool); return(v1 == condition); }
/// <summary> /// Creates a jump quadruple. /// </summary> /// <param name="goTo">Go to.</param> /// <param name="condition">Condition.</param> private static void CreateJumpQuadruple( Operators goTo, Variable condition = null) { Quadruple quadruple = new Quadruple(goTo, condition); PushQuadruple(quadruple); }
/// <summary> /// Creates an expression quadruple. /// </summary> /// <param name="operators">Operators.</param> private static void CreateExpressionQuadruple( Operators[] operators) { // Get index of fake bottom int index = (hierarchyStack.Count > 0) ? hierarchyStack.Peek() : 0; if (operatorStack.Count > index && operators.Contains(operatorStack.Peek())) { // Pop types GraphicFooType t2 = typeStack.Pop(); GraphicFooType t1 = typeStack.Pop(); if (t1 != GraphicFooType.Invalid && t2 != GraphicFooType.Invalid) { // Pop operands string id2 = operandStack.Pop(); string id1 = operandStack.Pop(); // Find variables Variable v1 = ProgramMemory.FindVariable(scope, id1); Variable v2 = ProgramMemory.FindVariable(scope, id2); // Pop operator Operators op = operatorStack.Pop(); // Check association rules GraphicFooType resultingType = AssociationRules.GetOperationType(op, t1, t2); // Create new temporary variable Variable temp; if (scope == null) { temp = ProgramMemory.AddGlobalTemporary(resultingType); } else { temp = scope.AddTemporaryVariable(resultingType); } // Push temp operandStack.Push(temp.name); typeStack.Push(temp.type); // Create quadruple Quadruple qudruple = new Quadruple( op, v1, v2, temp ); PushQuadruple(qudruple); } } }
public Parser(Scanner scanner) { this.scanner = scanner; errors = new Errors(); // Memory ProgramMemory.Initialize(); // Stacks Quadruple.Initialize(); }
/// <summary> /// Creates an assignation quadruple. /// </summary> /// <param name="variableId">Variable identifier.</param> /// <param name="targetId">Target identifier.</param> public static void CreateAssignationQuadruple( string variableId, string targetId) { Variable variable = ProgramMemory.FindVariable(scope, variableId); Variable target = ProgramMemory.FindVariable(scope, targetId); Quadruple quadruple = new Quadruple(Operators.Assignation, variable, target); PushQuadruple(quadruple); }
/// <summary> /// Creates a return assignation quadruple. /// </summary> /// <param name="variableId">Variable identifier.</param> /// <param name="targetId">Target identifier.</param> public static void CreateReturnAssignationQuadruple( string variableId, string targetId) { Procedure variable = ProgramMemory.ReadProcedure(variableId); Variable target = ProgramMemory.FindVariable(scope, targetId); Quadruple quadruple = new Quadruple(Operators.ReturnAssignation, target, variable); PushQuadruple(quadruple); }
/// <summary> /// Matchs the function parameters. /// </summary> /// <param name="procedure">Procedure.</param> /// <param name="parameters">Parameters.</param> private static void MatchParameters( Procedure procedure, VariableBlock parameters) { // Check parameter count consistency int procedureParameterCount = procedure.GetParameterCount(); int parameterCallCount = parameters.GetCount(); if (procedureParameterCount != parameterCallCount) { Console.WriteLine( "Call to {1}, with wrong numer of parameters ({2})", procedure.name, parameterCallCount ); return; } List <Variable> parameterList = parameters.ToList(); List <Variable> procedureParameterList = procedure.GetParameters().ToList(); // Assign parameters for (int i = 0; i < parameterCallCount; i++) { if (parameterList [i].type == procedureParameterList [i].type) { // TODO define paramX Quadruple param = new Quadruple( Operators.Param, ProgramMemory.FindVariable( scope, parameterList [i].name ), procedure.GetParameters().GetVariableAt(i) ); PushQuadruple(param); } else { Console.WriteLine( "On call to {1}, parameter [{2}] {3} does not match the expected type {4}", procedure.name, i, procedureParameterList [i].name, procedureParameterList [i].type.ToString() ); return; } } }
/// <summary> /// Executes a relational operation. /// </summary> /// <param name="q">Q.</param> private static void ExecuteRelationalOperation(Quadruple q) { float?v1Value = CastToNumeric(q.v1); float?v2Value = CastToNumeric(q.v2); switch (q.op) { case Operators.Greater: q.target.value = v1Value > v2Value; break; case Operators.Lesser: q.target.value = v1Value < v2Value; break; } }
/// <summary> /// Creates the function call quadruples. /// </summary> /// <param name="id">Identifier.</param> /// <param name="parameters">Parameters.</param> public static void CreateFunctionCallQuadruples( string id, VariableBlock parameters) { Procedure procedure = ProgramMemory.ReadProcedure(id); // Expand procedure Quadruple expand = new Quadruple(Operators.Expand, procedure); PushQuadruple(expand); // Assign parameters MatchParameters(procedure, parameters); // Go subroutine Quadruple goSub = new Quadruple(Operators.GoSub, procedure); PushQuadruple(goSub); }
void Print() { Expect((int)TokenEnum.Print); Expect((int)TokenEnum.LeftParenthesis); Expression(); Expect((int)TokenEnum.RightParenthesis); Expect((int)TokenEnum.Semicolon); string temp = string.Empty; try { temp = Quadruple.operandStack.Pop(); } catch (InvalidOperationException) { SynErr((int)TokenEnum.NoExpression); } Quadruple.CreatePrintQuadruple(temp); }
/// <summary> /// Parser function that generates function call quadruples. /// While checking semantics. /// </summary> void CallFunction() { Expect((int)TokenEnum.Function); Expect((int)TokenEnum.Id); string id = GetLastTokenValue(); Expect((int)TokenEnum.LeftParenthesis); VariableBlock parameters = new VariableBlock(); if (StartOf((int)TokenEnum.String)) { Expression(); string paramId = Quadruple.operandStack.Pop(); GraphicFooType type = Quadruple.typeStack.Pop(); Variable parameter = new Variable(paramId, type); if (parameter.type == GraphicFooType.Invalid) { SemErr((int)SemanticEnum.Variable); } parameters.AddVariable(parameter); while (la.kind == (int)TokenEnum.Comma) { Get(); Expression(); paramId = Quadruple.operandStack.Pop(); type = Quadruple.typeStack.Pop(); parameter = new Variable(paramId, type); if (parameter.type == GraphicFooType.Invalid) { SemErr((int)SemanticEnum.Variable); } parameters.AddVariable(parameter); } } Expect((int)TokenEnum.RightParenthesis); Quadruple.CreateFunctionCallQuadruples(id, parameters); if (la.kind == (int)TokenEnum.Assignation) { Get(); Expect((int)TokenEnum.Id); string varId = GetLastTokenValue(); Quadruple.CreateReturnAssignationQuadruple(id, varId); } Expect((int)TokenEnum.Semicolon); }
void Assignation(string type = "") { bool assign = false; Expect((int)TokenEnum.Id); string id = GetLastTokenValue(); Variable variable = ProgramMemory.FindVariable(scope, id); if (variable == null && type == "") { SemErr((int)SemanticEnum.NotDeclared); } if (la.kind == (int)TokenEnum.Assignation) { Get(); Expression(); assign = true; } Expect((int)TokenEnum.Semicolon); if (type != "") { if (scope == null) { ProgramMemory.AddGlobalVariable(id, type); } else { scope.AddVariable(id, type); } } if (assign) { try { string temp = Quadruple.operandStack.Pop(); Quadruple.CreateAssignationQuadruple(temp, id); } catch (InvalidOperationException) { SynErr((int)TokenEnum.NoExpression); } } }
/// <summary> /// Prints program output. /// </summary> /// <param name="q">Q.</param> private static void Print(Quadruple q) { Type printType = q.v1.GetNativeType(); if (printType == typeof(float)) { output += "Program Output: " + (q.v1.value as float?) + "\n"; Console.WriteLine("Program Output: " + (q.v1.value as float?)); } else if (printType == typeof(bool)) { output += "Program Output: " + (q.v1.value as bool?) + "\n"; Console.WriteLine("Program Output: " + (q.v1.value as bool?)); } else if (printType == typeof(string)) { Console.WriteLine("Program Output: " + (q.v1.value as string)); output += "Program Output: " + (q.v1.value as string) + "\n"; } }
void Condition() { IfHeader(); while (StartOf((int)TokenEnum.Number)) { Statute(); } if (la.kind == (int)TokenEnum.Else) { Get(); Quadruple.PopJump(1); Quadruple.CreateGotoQuadruple(); Quadruple.PushJump(); while (StartOf((int)TokenEnum.Number)) { Statute(); } } EndIf(); }
/// <summary> /// Creates a return quadruple. /// </summary> /// <returns>The return quadruple.</returns> /// <param name="id">Identifier.</param> public static SemanticEnum CreateReturnQuadruple(string id) { Variable returnVariable = null; if (id != "") { returnVariable = ProgramMemory.FindVariable(scope, id); } // Validate return type SemanticEnum returnStatus = Semantics.ValidateReturn(scope.type, returnVariable); if (returnStatus == SemanticEnum.ValidReturn) { scope.SetEnd(Quadruple.quadruples.Count); Quadruple quadruple = new Quadruple(Operators.Return, returnVariable); PushQuadruple(quadruple); } return(returnStatus); }
/// <summary> /// Sends plain code to compile . /// </summary> /// <returns>The plain code to compile .</returns> /// <param name="stringToCompile">String to compile.</param> public static string SendToCompilePlainCode(string stringToCompile) { Scanner scanner = new Scanner(stringToCompile); Parser parser = new Parser(scanner); parser.Parse(); Quadruple.DebugQuadruples(); // ProgramMemory.DebugProgramMemory (); string errorMessage = (!string.IsNullOrEmpty(parser.errors.errorMessage)) ? parser.errors.errorMessage : "None"; if (errorMessage == "None") { VirtualMachine.Execute(); errorMessage = VirtualMachine.output; } return(errorMessage); }
void Expression() { Exp(); if (StartOf((int)TokenEnum.True)) { Operators op; if (la.kind == (int)TokenEnum.Greater) { Get(); op = Operators.Greater; } else if (la.kind == (int)TokenEnum.Lesser) { Get(); op = Operators.Lesser; } else if (la.kind == (int)TokenEnum.Unequal) { Get(); op = Operators.Unequal; } else if (la.kind == (int)TokenEnum.Equals) { Get(); op = Operators.Equal; } else if (la.kind == (int)TokenEnum.Concatenation) { Get(); op = Operators.Concatenation; } else { op = Operators.InvalidOperator; SynErr((int)TokenEnum.InvalidOperator); } Quadruple.operatorStack.Push(op); Exp(); Quadruple.CreateRelationalQuadruple(); } }
/// <summary> /// Executes a logical operation. /// </summary> /// <param name="q">Q.</param> private static void ExecuteLogicalOperation(Quadruple q) { bool?v1Value = CastToBoolean(q.v1); bool?v2Value = CastToBoolean(q.v2); bool v1, v2; v1 = v1Value ?? default(bool); v2 = v2Value ?? default(bool); switch (q.op) { case Operators.Or: q.target.value = v1 || v2; break; case Operators.And: q.target.value = v1 && v2; break; } }
/// <summary> /// Executes an equality operation. /// </summary> /// <param name="q">Q.</param> private static void ExecuteEqualityOperation(Quadruple q) { if (q.v1.GetNativeType() == typeof(float)) { q.target.value = (q.v1.value as float?) == (q.v2.value as float?); } else if (q.v1.GetNativeType() == typeof(bool)) { q.target.value = (q.v1.value as bool?) == (q.v2.value as bool?); } else if (q.v1.GetNativeType() == typeof(string)) { q.target.value = (q.v1.value as string).Equals(q.v2.value as string); } if (q.op == Operators.Unequal) { q.target.value = !(q.target.value as bool?); } }
void Function() { scope = FunctionHeader(); Quadruple.scope = scope; while (StartOf((int)TokenEnum.Id)) { Declaration(); } while (StartOf((int)TokenEnum.Number)) { Statute(); } string id = ""; id = Return(); SemanticEnum returnStatus = Quadruple.CreateReturnQuadruple(id); if (returnStatus != SemanticEnum.ValidReturn) { SemErr((int)returnStatus); } EndFunction(); }
/// <summary> /// Executes a procedure expansion. /// </summary> /// <param name="q">Q.</param> private static void ExecuteProcedureExpansion(Quadruple q) { Procedure p = q.call; Dictionary <int, Quadruple> quadruples = new Dictionary <int, Quadruple> (); VariableBlock block = new VariableBlock(); clones.Push(block); for (int i = p.index; i <= p.end; i++) { Quadruple original = Quadruple.quadruples [i]; Quadruple clone = new Quadruple( original.op, CloneOrFindVariable(original.v1), CloneOrFindVariable(original.v2), CloneOrFindVariable(original.target), original.call, original.jumpIndex ); quadruples.Add(i, clone); } programStack.Push(quadruples); return; }
/// <summary> /// Run the specified quadruples at start. /// </summary> /// <param name="quadruples">Quadruples.</param> /// <param name="start">Start.</param> private static void Run( Dictionary <int, Quadruple> quadruples, int start) { end = false; int index = start; while (true) { if (!quadruples.ContainsKey(index)) { return; } Quadruple q = quadruples [index]; Console.WriteLine( "Executing [" + index + "/" + (quadruples.Count - 1) + "]" ); switch (q.op) { case Operators.Assignation: q.target.value = q.v1.value; index++; break; case Operators.ReturnAssignation: try { q.v1.value = returns.Pop().value; Console.WriteLine(q.v1.value as float?); } catch (InvalidOperationException) { } index++; break; case Operators.Param: clones.Peek().ReadVariable(q.target.name).value = q.v1.value; index++; break; case Operators.Plus: case Operators.Minus: case Operators.Multiplication: case Operators.Division: ExecuteArithmeticOperation(q); index++; break; case Operators.Greater: case Operators.Lesser: ExecuteRelationalOperation(q); index++; break; case Operators.Equal: case Operators.Unequal: ExecuteEqualityOperation(q); index++; break; case Operators.Or: case Operators.And: ExecuteLogicalOperation(q); index++; break; case Operators.Goto: index = q.jumpIndex; break; case Operators.GotoT: index = (ExecuteGotoOperation(q, true)) ? q.jumpIndex : index + 1; break; case Operators.GotoF: index = (ExecuteGotoOperation(q, false)) ? q.jumpIndex : index + 1; break; case Operators.Expand: ExecuteProcedureExpansion(q); index++; break; case Operators.GoSub: goSubJumps.Push(index); exec = programStack.Peek(); Run(exec, q.call.index); index++; break; case Operators.Return: if (q.v1 != null) { returns.Push(q.v1); } if (goSubJumps.Count == 0) { end = true; index++; return; } else { index = goSubJumps.Pop() + 1; Run(programStack.Pop(), index); } break; case Operators.Print: Print(q); index++; break; default: index++; break; } if (end && index == (quadruples.Count)) { Console.WriteLine("kill switch"); return; } } }
void EndLoop() { Expect((int)TokenEnum.EndWhile); Quadruple.CreateGotoQuadruple(); Quadruple.PopTwoJumps(); }
/// <summary> /// Pushes a quadruple to the main dictionary. /// </summary> /// <param name="quaduple">Quaduple.</param> public static void PushQuadruple(Quadruple quaduple) { quadruples.Add(quadruples.Count, quaduple); }