public BlockStatement( LocalVarDecl[] arLocals, // can be null if we have no locals Statement[] arStatements // never null ) { // If we have any locals in this block statement, then we // also need to have a scope to hold them. if (arLocals == null) { m_arLocals = new LocalVarDecl[0]; } else { m_arLocals = arLocals; // @todo - decorate name w/ filerange? //m_scopeLocals = new Scope("block_scope", null); } // May have an empty statement block, so arStatements.Length could be 0 // but at least expect an array. Debug.Assert(arStatements != null); m_arStatements = arStatements; // @todo - fix this if (arStatements.Length == 0) this.m_filerange = new FileRange(); else this.m_filerange = arStatements[0].Location; }
// Do the real work protected void ParseStatementOrLocal_Helper(out Statement s, out LocalVarDecl v) { s = null; v = null; // For each statement, we know which type based off the first token. // Expect for an identifier, in which case it could be a few things. Token t = m_lexer.PeekNextToken(); #if false // Skip past any ';' (as empty statements) while(t.TokenType == Token.Type.cSemi) { ConsumeNextToken(); t = m_lexer.PeekNextToken(); } #endif if (IsStartOfExp(t)) { FileRange f = BeginRange(); // This could be either an expression or a type Exp e = ParseExp(); t = m_lexer.PeekNextToken(); // Case 1 - Var declaration: // If an identifier follows, then we just read a type and this is // a var declaration: // Type id ';' // Type id '=' exp ';' if (t.TokenType == Token.Type.cId) { TypeSig tSig = this.ConvertExpToType(e); Identifier id = ReadExpectedIdentifier(); v = new LocalVarDecl(id, tSig); // Check for optional assignment (if there's an '=' after the name) Token t3 = m_lexer.PeekNextToken(); if (t3.TokenType == Token.Type.cAssign) { ConsumeNextToken(); // '=' Exp eRHS = ParseExp(); // exp ReadExpectedToken(Token.Type.cSemi); // ';' SimpleObjExp oleft = new SimpleObjExp(id); StatementExp se = new AssignStmtExp(oleft, eRHS); s = new ExpStatement(se); se.SetLocation(EndRange(f)); } else { ReadExpectedToken(Token.Type.cSemi); // ';' } return; } // end decl case // Case 2 - label declaration else if (t.TokenType == Token.Type.cColon) { SimpleObjExp o2 = e as SimpleObjExp; if (o2 != null) { ConsumeNextToken(); // ':' s = new LabelStatement(o2.Name); return; // skip reading a ';' } ThrowError(new ParserErrorException(Code.cBadLabelDef, t.Location, "Bad label definition (labels must be a single identifier)")); } // end case for label decls // Expect a StatementExp else if (t.TokenType == Token.Type.cSemi) { ReadExpectedToken(Token.Type.cSemi); // Else we must be a StatementExp StatementExp se = e as StatementExp; if (se == null) //this.ThrowError_ExpectedStatementExp(e.Location); ThrowError(E_ExpectedStatementExp(e.Location)); se.SetLocation(EndRange(f)); s = new ExpStatement(se); return; } ThrowError(E_UnexpectedToken(t)); } // end start of expressions switch(t.TokenType) { // Empty statement case Token.Type.cSemi: ConsumeNextToken(); s = new EmptyStatement(); break; // Return -> 'return' ';' // | 'return' exp ';' case Token.Type.cReturn: { ConsumeNextToken(); t = m_lexer.PeekNextToken(); Exp e = null; if (t.TokenType != Token.Type.cSemi) { e = ParseExp(); } ReadExpectedToken(Token.Type.cSemi); s = new ReturnStatement(e); } break; // Note that the semi colons are included inthe stmt // IfSmt -> 'if' '(' exp ')' stmt:then // IfSmt -> 'if' '(' exp ')' stmt:then 'else' stmt:else case Token.Type.cIf: { ConsumeNextToken(); // 'if' ReadExpectedToken(Token.Type.cLParen); Exp exp = ParseExp(); ReadExpectedToken(Token.Type.cRParen); Statement sThen = ParseStatement(); Statement sElse = null; Token t2 = m_lexer.PeekNextToken(); if (t2.TokenType == Token.Type.cElse) { ConsumeNextToken(); // 'else' sElse = ParseStatement(); } s = new IfStatement(exp, sThen, sElse); } break; case Token.Type.cSwitch: s = ParseSwitchStatement(); break; // Throw an expression // ThrowStmt -> 'throw' objexp case Token.Type.cThrow: { ConsumeNextToken(); // 'throw' Exp oe = null; if (m_lexer.PeekNextToken().TokenType != Token.Type.cSemi) { oe = ParseExp(); } ReadExpectedToken(Token.Type.cSemi); s = new ThrowStatement(oe); } break; // try-catch-finally case Token.Type.cTry: s = ParseTryCatchFinallyStatement(); break; // while loop // 'while' '(' exp ')' stmt case Token.Type.cWhile: { ConsumeNextToken(); // 'while' ReadExpectedToken(Token.Type.cLParen); Exp e = ParseExp(); ReadExpectedToken(Token.Type.cRParen); Statement body = ParseStatement(); s = new WhileStatement(e, body); } break; // do loop // 'do' stmt 'while' '(' exp ')' ';' case Token.Type.cDo: { ConsumeNextToken(); // 'do' Statement body = ParseStatement(); ReadExpectedToken(Token.Type.cWhile); ReadExpectedToken(Token.Type.cLParen); Exp e = ParseExp(); ReadExpectedToken(Token.Type.cRParen); ReadExpectedToken(Token.Type.cSemi); s = new DoStatement(e, body); } break; // goto // 'goto' id:label ';' case Token.Type.cGoto: { ConsumeNextToken(); // 'goto' Identifier id = ReadExpectedIdentifier(); // id:label ReadExpectedToken(Token.Type.cSemi); // ';' s = new GotoStatement(id); } break; // break // 'break' ';' case Token.Type.cBreak: ConsumeNextToken(); ReadExpectedToken(Token.Type.cSemi); s = new BreakStatement(); break; // Continue // 'continue' ';' case Token.Type.cContinue: ConsumeNextToken(); ReadExpectedToken(Token.Type.cSemi); s = new ContinueStatement(); break; // For-loop case Token.Type.cFor: s = ParseForStatement(); break; // For-each // -> 'foreach' '(' Type id 'in' exp:collection ')' stmt case Token.Type.cForEach: s = ParseForeachStatement(); break; // BlockStatement - can be nested inside each other // start with a '{', no terminating semicolon case Token.Type.cLCurly: { s = ParseStatementBlock(); } break; default: ThrowError(E_UnexpectedToken(t)); // unrecognized statement break; } // end switch // Must have come up with something Debug.Assert(s != null || v != null); }
//----------------------------------------------------------------------------- // Parse a single statement or local var decl (we can't tell which yet) // Note that may be statement may be a block (which is just fine) // for a construct like 'int x = 3' (decl & assignment), we'll yeild // both s & v. Else the out params will be null if we don't have them. //----------------------------------------------------------------------------- protected void ParseStatementOrLocal(out Statement s, out LocalVarDecl v) { // Wrap the worker to ensure that we have proper line number info FileRange f = BeginRange(); // Do the real work ParseStatementOrLocal_Helper(out s, out v); if (s != null) { s.SetLocation(EndRange(f)); } }
protected LocalVarDecl[] LocalVarDeclFromArray(ArrayList alParams) { LocalVarDecl[] v = new LocalVarDecl[alParams.Count]; for(int i = 0; i < alParams.Count; i++) v[i] = (LocalVarDecl) alParams[i]; return v; }
public void ResolveHandler(ISemanticResolver s) { // Catch blocks can declare an identifier if (IdVarName != null) { m_var = new LocalVarDecl(IdVarName, m_type); Body.InjectLocalVar(m_var); } this.m_type.ResolveType(s); Body.ResolveStatement(s); // Catch type must be of type System.Exception if (m_var != null) { s.EnsureAssignable(m_var.Symbol.m_type.CLRType, typeof(System.Exception), IdVarName.Location); } // Catch type must be of type System.Exception //TypeEntry tSystem_Exception =s.ResolveCLRTypeToBlueType(typeof(System.Exception)); //s.EnsureDerivedType(tSystem_Exception, m_type.TypeRec, new FileRange()); }
public void InjectLocalVar(LocalVarDecl l) { //m_scopeLocals = new Scope("block_scope", null); LocalVarDecl[] ar2 = new LocalVarDecl[Locals.Length + 1]; ar2[0] = l; for(int i = 0; i < Locals.Length; i++) ar2[i + 1] = Locals[i]; m_arLocals = ar2; }
public ForeachStatement( LocalVarDecl var, Exp expCollection, Statement body ) { Debug.Assert(var != null); Debug.Assert(expCollection != null); m_var = var; m_expCollection = expCollection; m_stmtBody = body; }