/// <summary> /// Tries to consume a token of the given type /// </summary> /// <param name="val">The value of the token, can be null to ignore</param> /// <param name="type">The type of the token, can be null to ignore</param> /// <returns>A bool signifying if the symbol could be matched or not</returns> protected bool Match(int p, string val, Lexer.Token.TokenType? type) { bool ok = true; if (val != null && lookahead.Value != val) ok = false; else if (type.HasValue && lookahead.Type != type.Value) ok = false; if (!ok && p == 1) SyntaxError(string.Format("{0}: expected '{1}', got instead '{2}', a {3}", lookahead.Line, val ?? type.Value.ToString(), lookahead.Value, lookahead.Type.ToString())); if (lookahead.Type != Lexer.Token.TokenType.EndOfFile) lookahead = lexer.GetNextToken(); return ok; }
/// <summary> /// The main function. Runs the parser over the stream and /// returns whether or not the stream is valid. /// </summary> /// <returns>A bool indicating whether or not the stream is valid syntactically</returns> public bool Parse() { // first parse the program // phase 1 CompilerStack.Clear(); CompilerStack.Push(new StackFrame(this)); lexer.Reset(); lookahead = lexer.GetNextToken(); SemanticInfo si = new SemanticInfo(); bool ok1 = NTF_Prog(1, si) && Match(1, Lexer.Token.TokenType.EndOfFile); ComputeClassSizes(); // phase 2 CompilerStack.Clear(); CompilerStack.Push(new StackFrame(this)); si = new SemanticInfo(); lexer.Reset(); lookahead = lexer.GetNextToken(); bool ok2 = NTF_Prog(2, si) && Match(2, Lexer.Token.TokenType.EndOfFile); si.Code.Insert(0, "stack res 5000\nalign\n"); si.Code.Append( @" putint align add r2,r0,r0 % Initialize buffer's index i cge r3,r1,r0 % True if N >= 0 bnz r3,putint1 % Branch if True (N >= 0) sub r1,r0,r1 % N = -N putint1 modi r4,r1,10 % Rightmost digit addi r4,r4,48 % Convert to ch divi r1,r1,10 % Truncate rightmost digit sb putint9(r2),r4 % Store ch in buffer addi r2,r2,1 % i++ bnz r1,putint1 % Loop if not finished bnz r3,putint2 % Branch if True (N >= 0) addi r3,r0,45 sb putint9(r2),r3 % Store '-' in buffer addi r2,r2,1 % i++ add r1,r0,r0 % Initialize output register (r1 = 0) putint2 subi r2,r2,1 % i-- lb r1,putint9(r2) % Load ch from buffer putc r1 % Output ch bnz r2,putint2 % Loop if not finished addi r1,r0,13 % load new line putc r1 % print it addi r1,r0,10 % new feed thingie putc r1 jr r15 % return to the caller putint9 res 12 % loacl buffer (12 bytes) align getint add r1,r0,r0 % n := 0 (result) add r2,r0,r0 % c := 0 (character) add r3,r0,r0 % s := 0 (sign) getint1 getc r2 % read c ceqi r4,r2,32 bnz r4,getint1 % skip blanks ceqi r4,r2,43 bnz r4,getint2 % branch if c is '+' ceqi r4,r2,45 bz r4,getint3 % branch if c is not '-' addi r3,r0,1 % s := 1 (number is negative) getint2 getc r2 % read c getint3 ceqi r4,r2,10 bnz r4,getint5 % branch if c is \n cgei r4,r2,48 bz r4,getint4 % c < 0 clei r4,r2,57 bz r4,getint4 % c > 9 muli r1,r1,10 % n := 10 * n add r1,r1,r2 % n := n + c subi r1,r1,48 % n := n - '0' j getint2 getint4 addi r2,r0,63 % c := '?' putc r2 % write c j getint % Try again getint5 bz r3,getint6 % branch if s = 0 (number is positive) sub r1,r0,r1 % n := -n getint6 jr r15 % return "); Log(LogType.Code, si.Code.ToString()); // then write out the debug information Log(LogType.SymbolTable, Global.ToString()); foreach (string error in Errors) Log(LogType.Error, error); foreach (string warning in Warnings) Log(LogType.Warning, warning); // and flush the streams foreach (TextWriter tw in Output.Values) tw.Flush(); return ok1 && ok2; }
/// <summary> /// Skips all the errors until the next (maybe valid) token /// </summary> /// <param name="tokens">The list of "valid" tokens</param> /// <returns>true if there has been an error that was skipped, false otherwise</returns> protected bool SkipErrors(int p, params object[] tokens) { if (ValidLookAhead(tokens)) return false; if (p == 1) SyntaxError(string.Format("{0}:unexpected token '{1}' of type '{2}'", lookahead.Line, lookahead.Value, lookahead.Type)); do { if (lookahead.Type == Lexer.Token.TokenType.EndOfFile) break; lookahead = lexer.GetNextToken(); } while (!ValidLookAhead(tokens)); if (p == 1) Warning(string.Format("{0}:Resuming parsing near the token '{1}' of type '{2}'", lookahead.Line, lookahead.Value, lookahead.Type)); return true; }