/// <summary> /// Starts executing all quadruples until all of them have been processed. /// </summary> public static async Task Execute() { Utilities.vmExecuting = true; quadruples = QuadrupleManager.GetQuadruples(); while (!endExecution) { int instructionToExecute = currentInstruction; await ExecuteInstruction(); // increment current instruction counter only if we didn't do a jump if (instructionToExecute == currentInstruction) { currentInstruction++; } } quadruples = new List <Quadruple>(); currentInstruction = 0; endExecution = false; savedInstructionPointer = new Stack <int>(); localMemoryAllocations = new Stack <int>(); CallStack = new Stack <Tuple <string, int> >(); LastFunctionCalled = new Stack <Function>(); funcToAdd = new Stack <Tuple <string, int> >(); }
/// <summary> /// Function called when a <see cref="AssignBlock"/> block is read. /// Checks whether the assignment is to a variable or to an asset's attribute, and /// calls the corresponding functions that handle the assignment. /// Called by <see cref="INSTRUCTION"/>. /// </summary> void ASSIGNMENT() { Expect(32); // set Expect(1); // id string id = t.val; if (la.kind == 22) // '.' { try { QuadrupleManager.ReadAssetId(id); Get(); ATTRIBUTE(); // we don't need to verify the attribute as the UI forces the user to select a valid one } catch (Exception e) { SemErr(e.Message); } } else { try { QuadrupleManager.ReadIDVariable(id); } catch (Exception e) { SemErr(e.Message); } } Expect(33); // '=' SUPER_EXP(); try { QuadrupleManager.AssignEnd(); } catch (Exception e) { SemErr(e.Message); } }
/// <summary> /// Called when a <see cref="ReturnBlock"/> block is read. /// Verifies the structure of the return and calls the corresponding functions that /// handle the return expression. /// Called by <see cref="INSTRUCTION"/>. /// </summary> void RETURN() { Expect(52); // "return" SUPER_EXP(); try { QuadrupleManager.ReturnEnd(); } catch (Exception e) { SemErr(e.Message); } }
/// <summary> /// Function called when a <see cref="FunctionCall"/> block is found. /// Verifies that the call's structure is correct and calls <see cref="QuadrupleManager"/> /// to carry out the necessary actions given the instruction. /// Called by <see cref="FACTOR"/>. /// </summary> void CALL_TO_FUNCTION() { Expect(19); // "call" Expect(1); // id string functionId = t.val; try { QuadrupleManager.CallFunctionBeforeParameters(functionId); } catch (Exception e) { SemErr(e.Message); } Expect(10); // '(' try { QuadrupleManager.CallFunctionOpeningParenthesis(); } catch (Exception e) { SemErr(e.Message); } if (StartOf(3)) { SUPER_EXP(); // result of parameter try { QuadrupleManager.CallFunctionParameter(); while (la.kind == 11) // ',' { Get(); SUPER_EXP(); // result of parameter QuadrupleManager.CallFunctionParameter(); } } catch (Exception e) { SemErr(e.Message); } } Expect(12); // ')' try { QuadrupleManager.CallFunctionClosingParenthesis(); } catch (Exception e) { SemErr(e.Message); } try { QuadrupleManager.CallFunctionEnd(); } catch (Exception e) { SemErr(e.Message); } }
/// <summary> /// Verifies that the general structure of the program is correct. /// Called by <see cref="Marbles"/>. /// </summary> void PROGRAM() { while (la.kind == 18) // "asset" { int index = CREATE_ASSET(); try { MemoryManager.SetAssetInMemory((Asset)Utilities.finalAssetsInCanvas[index]); } catch (Exception e) { SemErr(e.Message); } } AssetIndex = 0; while (la.kind == 16) // "var" // receive new variable to be created { Variable newGlobalVariable = CREATE_VAR(); // try to add it to globals try { MemoryManager.AddGlobalVariable(newGlobalVariable); } catch (Exception e) { SemErr(e.Message); } } while (la.kind == 9) // "function" { CREATE_FUNCTION(); } Expect(6); // "instructions" Expect(7); // '{' QuadrupleManager.UpdateBeginQuadruple(); while (StartOf(1)) { INSTRUCTION(); } Expect(8); // '}' }
/// <summary> /// Function called when a <see cref="DoBlock"/> block is read. /// Verifies the id of the asset by calling <see cref="QuadrupleManager.ReadAssetId(string)"/> /// and calls <see cref="ACTION"/> to handle the action to perform. /// Called by <see cref="INSTRUCTION"/>. /// </summary> void DO() { Expect(21); // "do" Expect(1); // id try { QuadrupleManager.ReadAssetId(t.val); } catch (Exception e) { SemErr(e.Message); } Expect(22); // '.' ACTION(); }
/// <summary> /// Function called when a <see cref="CREATE_FUNCTION"/> block is found. /// Verifies that the definition structure of a function is correct. /// Creates a <see cref="Function"/> object based on the definition. /// Called by <see cref="PROGRAM"/>. /// </summary> void CREATE_FUNCTION() { Expect(9); // "function" SemanticCubeUtilities.DataTypes functionType = TYPE_FUNC(); Expect(1); // id string functionName = t.val; Function newFunction = new Function(functionName, functionType); try { QuadrupleManager.EnterFunction(newFunction); } catch (Exception e) { SemErr(e.Message); } Expect(10); // '(' if (la.kind == 13 || la.kind == 14 || la.kind == 15) // "text" || "number" || "bool" { SemanticCubeUtilities.DataTypes parameterType = TYPE_VAR(); Expect(1); // id string parameterName = t.val; try { QuadrupleManager.CreateFunction_LoadParameter(functionName, new Variable(parameterName, parameterType)); } catch (Exception e) { SemErr(e.Message); } while (la.kind == 11) // ',' { Get(); parameterType = TYPE_VAR(); Expect(1); // id parameterName = t.val; try { QuadrupleManager.CreateFunction_LoadParameter(functionName, new Variable(parameterName, parameterType)); } catch (Exception e) { SemErr(e.Message); } } } Expect(12); // ')' Expect(7); // '{' while (la.kind == 16) // "var" // add variables to the local variables directory { var localVariable = CREATE_VAR(); try { QuadrupleManager.CreateFunction_LoadLocalVariable(functionName, localVariable); } catch (Exception e) { SemErr(e.Message); } } try { FunctionDirectory.GetFunction(newFunction.GetName()).SetQuadrupleStart(QuadrupleManager.GetCounter()); } catch (Exception e) { SemErr(e.Message); } while (StartOf(1)) { INSTRUCTION(); } Expect(8); // '}' try { QuadrupleManager.ExitFunction(); // releases local variable and generates quadruple 'endProc' } catch (Exception e) { SemErr(e.Message); } }
/// <summary> /// The highest abstraction level for an expression. This type of expression includes /// logical and relational operations. /// This function is called everywhere where any type of expression can be expected to be. /// </summary> void SUPER_EXP() { EXP_L(); while (la.kind == 34) // or { Get(); QuadrupleManager.PushOperator(SemanticCubeUtilities.Operators.or); EXP_L(); try { QuadrupleManager.PopOperator(SemanticCubeUtilities.OperatorToPriority(SemanticCubeUtilities.Operators.or)); } catch (Exception e) { SemErr(e.Message); } } }
/// <summary> /// This level of abstraction of an expression includes logical expressions. /// Called everywhere where a logical or normal expression can be expected to be. /// </summary> void EXP_L() { EXP_R(); while (la.kind == 35) // "and" { Get(); QuadrupleManager.PushOperator(SemanticCubeUtilities.Operators.and); EXP_R(); try { QuadrupleManager.PopOperator(SemanticCubeUtilities.OperatorToPriority(SemanticCubeUtilities.Operators.and)); } catch (Exception e) { SemErr(e.Message); } } }
/// <summary> /// This level of abstraction of an expression includes relational expressions. /// Called everywhere where a relational or normal expression can be expected to be. /// </summary> void EXP_R() { EXP(); if (StartOf(5)) { OP(); SemanticCubeUtilities.Operators op = SemanticCubeUtilities.GetOperatorFromString(t.val); QuadrupleManager.PushOperator(op); EXP(); try { QuadrupleManager.PopOperator(SemanticCubeUtilities.OperatorToPriority(op)); } catch (Exception e) { SemErr(e.Message); } } }
/// <summary> /// Called by <see cref="DO"/> after identifying the asset to perform the action. /// Checks which action is going to be performed (verifying that it is a valid one) /// and passes on this information to the functions that handle the action's code /// generation. /// </summary> void ACTION() { Utilities.AssetAction action; if (StartOf(4)) { if (la.kind == 23) // "move_x" { action = Utilities.AssetAction.move_x; Get(); Expect(10); // '(' } else if (la.kind == 24) // "move_y" { action = Utilities.AssetAction.move_y; Get(); Expect(10); // '(' } else if (la.kind == 25) // "rotate" { action = Utilities.AssetAction.rotate; Get(); Expect(10); // '(' } else // "set_position" { action = Utilities.AssetAction.set_position; Get(); Expect(10); // '(' SUPER_EXP(); Expect(11); // ',' } SUPER_EXP(); Expect(12); // ')' try { QuadrupleManager.DoBlock_ReadAssetAction(action); } catch (Exception e) { SemErr(e.Message); } } else if (la.kind == 27) // "spin" { action = Utilities.AssetAction.spin; Get(); Expect(10); // ( Expect(12); // ) try { QuadrupleManager.DoBlock_ReadAssetAction(action); } catch (Exception e) { SemErr(e.Message); } } else { SynErr(57); } }
/// <summary> /// Called when a <see cref="WhileBlock"/> block is read. /// Verifies the structure of the While loop and calls the corresponding functions that /// handle the code generation for the loop. /// Called by <see cref="INSTRUCTION"/>. /// </summary> void WHILE() { Expect(30); // "while" QuadrupleManager.WhileBeforeCondition(); Expect(10); // '(' SUPER_EXP(); Expect(12); // ')' QuadrupleManager.WhileAfterCondition(); Expect(7); // '{' while (StartOf(1)) { INSTRUCTION(); } Expect(8); // '}' QuadrupleManager.WhileEnd(); }
/// <summary> /// Called when an <see cref="IfBlock"/> block is read. /// Verifies the structure of the IF condition and calls the corresponding /// functions that handle the code generation for the condition. /// Called by <see cref="INSTRUCTION"/>. /// </summary> void IFF() { Expect(31); // "if" Expect(10); // '(' SUPER_EXP(); Expect(12); // ')' try { QuadrupleManager.IfAfterCondition(); } catch (Exception e) { SemErr(e.Message); } Expect(7); // '{' while (StartOf(1)) { INSTRUCTION(); } Expect(8); // '}' try { QuadrupleManager.IfEnd(); } catch (Exception e) { SemErr(e.Message); } }
/// <summary> /// Called when a <see cref="ForBlock"/> block is read. /// Verifies the structure of the For loop and calls the corresponding functions that /// handle the code generation for the loop. /// Called by <see cref="INSTRUCTION"/>. /// </summary> void FOR() { Expect(28); // "for" Expect(10); // '(' SUPER_EXP(); Expect(12); // ')' try { QuadrupleManager.ForAfterCondition(); } catch (Exception e) { SemErr(e.Message); } Expect(29); // "loops" Expect(7); // '{' while (StartOf(1)) { INSTRUCTION(); } Expect(8); // '}' QuadrupleManager.ForEnd(); }
/// <summary> /// Function called when a <see cref="ConstantBoolean"/> is read. Calls the corresponding /// functions in <see cref="QuadrupleManager"/> that handles the expression. /// Called by <see cref="FACTOR"/>. /// </summary> void BOOL() { if (la.kind == 2) // true { Get(); try { QuadrupleManager.ReadConstantBool(true); } catch (Exception e) { SemErr(e.Message); } } else if (la.kind == 3) // false { Get(); try { QuadrupleManager.ReadConstantBool(false); } catch (Exception e) { SemErr(e.Message); } } else { SynErr(62); } }
/// <summary> /// Called when an <see cref="AssetAttribute"/> block is read. /// Checks which attribute was selected and calls <see cref="QuadrupleManager.ReadAssetAttribute(MemoryManager.AssetAttributes)"/> /// to handle the code generation for this call. /// Called by <see cref="ASSIGNMENT"/> and <see cref="FACTOR"/>. /// </summary> void ATTRIBUTE() { switch (la.kind) { case 46: { // "value" Get(); QuadrupleManager.ReadAssetAttribute(MemoryManager.AssetAttributes.number); break; } case 47: { // "label" Get(); QuadrupleManager.ReadAssetAttribute(MemoryManager.AssetAttributes.label); break; } case 48: { // "position_x" Get(); QuadrupleManager.ReadAssetAttribute(MemoryManager.AssetAttributes.x); break; } case 49: { // "position_y" Get(); QuadrupleManager.ReadAssetAttribute(MemoryManager.AssetAttributes.y); break; } case 50: { // "width" Get(); QuadrupleManager.ReadAssetAttribute(MemoryManager.AssetAttributes.width); break; } case 51: { // "height" Get(); QuadrupleManager.ReadAssetAttribute(MemoryManager.AssetAttributes.height); break; } default: SynErr(58); break; } }
/// <summary> /// Calls <see cref="FACTOR"/> and checks whether a multiplication or division is pending and /// if the next token is a multiplication or division. /// Called by <see cref="EXP"/>. /// </summary> void TERM() { FACTOR(); try { QuadrupleManager.PopOperator(SemanticCubeUtilities.OperatorToPriority(SemanticCubeUtilities.Operators.multiply)); } catch (Exception e) { SemErr(e.Message); } while (la.kind == 38 || la.kind == 39) // '*' or '/' { if (la.kind == 38) // '*' { Get(); QuadrupleManager.PushOperator(SemanticCubeUtilities.Operators.multiply); } else // '/' { Get(); QuadrupleManager.PushOperator(SemanticCubeUtilities.Operators.divide); } FACTOR(); try { QuadrupleManager.PopOperator(SemanticCubeUtilities.OperatorToPriority(SemanticCubeUtilities.Operators.multiply)); } catch (Exception e) { SemErr(e.Message); } } }
/// <summary> /// Function called when an expression is found. /// Checks for pending addition or substraction operations, and checks if the next /// token is an addition or substraction. /// </summary> void EXP() { TERM(); try { QuadrupleManager.PopOperator(SemanticCubeUtilities.OperatorToPriority(SemanticCubeUtilities.Operators.plus)); } catch (Exception e) { SemErr(e.Message); } while (la.kind == 36 || la.kind == 37) // '+' or '-' { if (la.kind == 36) // '+' { Get(); QuadrupleManager.PushOperator(SemanticCubeUtilities.Operators.plus); } else // '-' { Get(); QuadrupleManager.PushOperator(SemanticCubeUtilities.Operators.minus); } TERM(); try { QuadrupleManager.PopOperator(SemanticCubeUtilities.OperatorToPriority(SemanticCubeUtilities.Operators.plus)); } catch (Exception e) { SemErr(e.Message); } } }
/// <summary> /// This event is invoked when the user clicks the Compile button. /// The function prepares to compile by resetting all necessary values back /// to default and then begins compilation. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void CompileButton_Click(object sender, RoutedEventArgs e) { Utilities.linesOfCodeCount = 0; Utilities.linesOfCode = new List <CodeLine>(); ErrorPrinter.errorCount = 0; ErrorPrinter.errorList = new Dictionary <int, List <string> >(); FunctionDirectory.Reset(); MemoryManager.Reset(); QuadrupleManager.Reset(); UserControl main = new UserControl(); ///* Utilities.BlockToLineErrors.Clear(); BlocksWithErrorsInOrder.Clear(); Utilities.errorsInLines.Clear(); AssetListViewContainer.PrintCode(); VariableListViewContainer.PrintCode(); FunctionListViewContainer.PrintCode(); Utilities.linesOfCode.Add(new CodeLine("instructions {", main, Utilities.linesOfCodeCount + 1)); Utilities.linesOfCodeCount++; InstructionListViewContainer.PrintCode(); Utilities.linesOfCode.Add(new CodeLine("}", main, Utilities.linesOfCodeCount + 1)); Utilities.linesOfCodeCount++; WriteCodeToFile(out string filePath); //*/ /* * string directoryPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "MarblesOutput"); * Directory.CreateDirectory(directoryPath); * string filePath = Path.Combine(directoryPath, "testMarblesCode2.txt"); */ AnalyzeCode(filePath); MemoryManager.PrintMemory(); QuadrupleManager.PrintQuadruples(); Debug.WriteLine(ErrorPrinter.errorCount + " error(s) found."); ErrorPrinter.PrintErrors(); if (ErrorPrinter.errorCount == 0) { Utilities.GreenCompile(); Utilities.EnableRunButton(); CompileButton.Background = Utilities.CompileButtonColor; CompileButton.IsEnabled = Utilities.CompileButtonEnabled; } else { Utilities.RedCompile(); Utilities.DisableRunButton(); FillErrorsDictionary(); SetErrorsInUI(); CompileButton.Background = Utilities.CompileButtonColor; CompileButton.IsEnabled = Utilities.CompileButtonEnabled; } }
/// <summary> /// This is the lowest level of abstraction for an expression. Checks which is the /// factor being used as an expression, retrieves this information, and calls the /// necessesary functions in <see cref="QuadrupleManager"/> that handles each case /// individually. /// Called by <see cref="TERM"/>. /// </summary> void FACTOR() { if (la.kind == 10) // '(' // push a fake bottom { QuadrupleManager.PushFakeBottom(); Get(); SUPER_EXP(); Expect(12); // ')' // exit fake bottom QuadrupleManager.PopFakeBottom(); } else if (StartOf(6)) { if (la.kind == 37) // negative sign { Get(); QuadrupleManager.PushOperator(SemanticCubeUtilities.Operators.negative); } if (la.kind == 4) // number constant { Get(); try { QuadrupleManager.ReadConstantNumber(Int32.Parse(t.val)); } catch (Exception e) { SemErr(e.Message); } } else if (la.kind == 1) // id { Get(); string id = t.val; if (la.kind == 22) // '.' character { try { QuadrupleManager.ReadAssetId(id); Get(); ATTRIBUTE(); // we don't need to verify the attribute as the UI forces the user to select a valid one } catch (Exception e) { SemErr(e.Message); } } else { try { QuadrupleManager.ReadIDVariable(id); } catch (Exception e) { SemErr(e.Message); } } } else if (la.kind == 19) // "call" { CALL_TO_FUNCTION(); } else if (la.kind == 2 || la.kind == 3) // true or false { BOOL(); } else if (la.kind == 5) // string constant { Get(); try { QuadrupleManager.ReadConstantText(t.val); } catch (Exception e) { SemErr(e.Message); } } else { SynErr(60); // invalid FACTOR } try { QuadrupleManager.PopOperator(SemanticCubeUtilities.OperatorToPriority(SemanticCubeUtilities.Operators.negative)); } catch (Exception e) { SemErr(e.Message); } } else { SynErr(61); // invalid FACTOR } }
/// <summary> /// Entry point for the Marbles grammar. /// Called by <see cref="Parse"/>. /// </summary> void Marbles() { QuadrupleManager.AddQuadruple(new Quadruple(Utilities.QuadrupleAction.Goto, -1, -1, -1)); PROGRAM(); QuadrupleManager.AddQuadruple(new Quadruple(Utilities.QuadrupleAction.end, -1, -1, -1)); }
/// <summary> /// Function called when a <see cref="StopBlock"/> block is found. /// Calls the corresponding function in <see cref="QuadrupleManager"/>. /// Called by <see cref="INSTRUCTION"/>. /// </summary> void STOP() { Expect(20); // "stop" QuadrupleManager.ReadStop(); }