public static void Main(string[] args) { bool mergeErrors = false, execution = true, immediate = false; string inputName = null; // ------------------------ process command line parameters: Console.WriteLine("Parva compiler 2.2017 October"); for (int i = 0; i < args.Length; i++) { if (args[i].ToLower().Equals("-l")) { mergeErrors = true; } else if (args[i].ToLower().Equals("-d")) { Parser.debug = true; } else if (args[i].ToLower().Equals("-n")) { execution = false; } else if (args[i].ToLower().Equals("-g")) { immediate = true; } else if (args[i].ToLower().Equals("-c")) { Parser.listCode = true; } else if (args[i].ToLower().Equals("-w")) { Parser.warnings = false; } else { inputName = args[i]; } } if (inputName == null) { Console.WriteLine("No input file specified"); Console.WriteLine("Usage: Parva [-l] [-d] [-n] [-g] source.pav"); Console.WriteLine("-l directs source listing to listing.txt"); Console.WriteLine("-d turns on debug mode"); Console.WriteLine("-n no execution after compilation"); Console.WriteLine("-g execute immediately after compilation (StdIn/StdOut)"); Console.WriteLine("-c produce .cod listing"); Console.WriteLine("-w supress warning messages"); System.Environment.Exit(1); } // ------------------------ parser and scanner initialization int pos = inputName.LastIndexOf('/'); if (pos < 0) { pos = inputName.LastIndexOf('\\'); } string dir = inputName.Substring(0, pos + 1); Scanner.Init(inputName); Errors.Init(inputName, dir, mergeErrors); PVM.Init(); Table.Init(); // ------------------------ compilation Parser.Parse(); Errors.Summarize(); // ------------------------ interpretation bool assembledOK = Parser.Successful(); int initSP = CodeGen.GetInitSP(); string codeName = newFileName(inputName, ".cod"); int codeLength = CodeGen.GetCodeLength(); PVM.ListCode(codeName, codeLength); if (!assembledOK || codeLength == 0) { Console.WriteLine("Unable to interpret code"); System.Environment.Exit(1); } else if (!execution) { Console.WriteLine("\nCompiled: exiting with no execution requested"); System.Environment.Exit(1); } else { if (immediate) { PVM.QuickInterpret(codeLength, initSP); } char reply = 'n'; do { Console.Write("\n\nInterpret [y/N]? "); reply = (Console.ReadLine() + " ").ToUpper()[0]; if (reply == 'Y') { PVM.Interpret(codeLength, initSP); } } while (reply == 'Y'); } } // Main
static void ReturnStatement() { Expect(return_Sym); CodeGen.LeaveVoidFunction(); ExpectWeak(semicolon_Sym, 6); }
static void Factor(out int type) { type = Types.noType; int size; DesType des; ConstRec con; if (la.kind == identifier_Sym) { Designator(out des); type = des.type; switch (des.entry.kind) { case Kinds.Var: CodeGen.Dereference(); break; case Kinds.Con: CodeGen.LoadConstant(des.entry.value); break; default: SemError("wrong kind of identifier"); break; } } else if (StartOf(15)) { Constant(out con); type = con.type; CodeGen.LoadConstant(con.value); } else if (la.kind == new_Sym) { Get(); BasicType(out type); type++; Expect(lbrack_Sym); Expression(out size); if (!IsArith(size)) { SemError("array size must be integer"); } CodeGen.Allocate(); Expect(rbrack_Sym); } else if (la.kind == bang_Sym) { Get(); Factor(out type); if (!IsBool(type)) { SemError("boolean operand needed"); } else { CodeGen.NegateBoolean(); } type = Types.boolType; } else if (la.kind == lparen_Sym) { Get(); Expression(out type); Expect(rparen_Sym); } else { SynErr(58); } }
static void HaltStatement() { Expect(halt_Sym); CodeGen.LeaveProgram(); ExpectWeak(semicolon_Sym, 6); }
static void AddExp(out int type) { int type2; int op; Label shortcircuit = new Label(!known); type = Types.noType; if (la.kind == plus_Sym) { Get(); Term(out type); if (!IsArith(type)) { SemError("arithmetic operand needed"); } } else if (la.kind == minus_Sym) { Get(); Term(out type); if (!IsArith(type)) { SemError("arithmetic operand needed"); } CodeGen.NegateInteger(); } else if (StartOf(13)) { Term(out type); } else { SynErr(55); } while (la.kind == plus_Sym || la.kind == minus_Sym || la.kind == barbar_Sym) { AddOp(out op); if (op == CodeGen.or) { CodeGen.BooleanOp(shortcircuit, CodeGen.or); } Term(out type2); switch (op) { case CodeGen.or: if (!IsBool(type) || !IsBool(type2)) { SemError("boolean operands needed"); } type = Types.boolType; break; default: if (!IsArith(type) || !IsArith(type2)) { SemError("arithmetic operands needed"); type = Types.noType; } CodeGen.BinaryOp(op); break; } } shortcircuit.Here(); }