ConditionStatement.DebugStatement DebugStatement(IBlockNode Scope, IStatement Parent) { Step(); var s = new ConditionStatement.DebugStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == OpenParenthesis) { Step(); if (laKind == Identifier || laKind == Literal) { Step(); if (laKind == Literal) s.DebugIdentifierOrLiteral = t.LiteralValue; else s.DebugIdentifierOrLiteral = t.Value; } else SynErr(t.Kind, "Identifier or Literal expected, " + DTokens.GetTokenString(t.Kind) + " found"); Expect(CloseParenthesis); } s.ScopedStatement = Statement(Scope: Scope, Parent: s); if (laKind == Else) { Step(); s.ElseStatement = Statement(Scope: Scope, Parent: s); } s.EndLocation = t.EndLocation; return s; }
IStatement Statement(bool BlocksAllowed = true, bool EmptyAllowed = true, IBlockNode Scope = null, IStatement Parent=null) { IStatement ret = null; if (EmptyAllowed && laKind == Semicolon) { Step(); return null; } if (BlocksAllowed && laKind == OpenCurlyBrace) return BlockStatement(Scope,Parent); #region LabeledStatement (loc:... goto loc;) if (laKind == Identifier && Lexer.CurrentPeekToken.Kind == Colon) { Step(); ret = (new LabeledStatement() { StartLocation = t.Location, Identifier = t.Value, Parent = Parent }); LastParsedObject = ret; Step(); ret.EndLocation = t.EndLocation; return ret; } #endregion #region IfStatement else if (laKind == (If) || (laKind == Static && Lexer.CurrentPeekToken.Kind == If)) { bool isStatic = laKind==Static; if (isStatic) Step(); Step(); var dbs = new IfStatement() { StartLocation = t.Location, IsStatic = isStatic, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // IfCondition IfCondition(dbs); Expect(CloseParenthesis); // ThenStatement dbs.ThenStatement = Statement(Scope:Scope,Parent:dbs); // ElseStatement if (laKind == (Else)) { Step(); dbs.ElseStatement = Statement(Scope: Scope, Parent: dbs); } dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region WhileStatement else if (laKind == While) { Step(); var dbs = new WhileStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); dbs.Condition = Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region DoStatement else if (laKind == (Do)) { Step(); var dbs = new WhileStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); Expect(While); Expect(OpenParenthesis); dbs.Condition = Expression(Scope); Expect(CloseParenthesis); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region ForStatement else if (laKind == (For)) { Step(); var dbs = new ForStatement { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // Initialize if (laKind != Semicolon) dbs.Initialize = Statement(false, Scope: Scope, Parent: dbs); // Against the D language theory, blocks aren't allowed here! else Step(); // Enforce a trailing semi-colon only if there hasn't been an expression (the ; gets already skipped in there) // Expect(Semicolon); // Test if (laKind != (Semicolon)) dbs.Test = Expression(Scope); Expect(Semicolon); // Increment if (laKind != (CloseParenthesis)) dbs.Increment= Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region ForeachStatement else if (laKind == (Foreach) || laKind == (Foreach_Reverse)) { Step(); var dbs = new ForeachStatement() { StartLocation = t.Location, IsReverse = t.Kind == Foreach_Reverse, Parent=Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); var tl = new List<DVariable>(); bool init = true; while (init || laKind == (Comma)) { if (!init) Step(); init = false; var forEachVar = new DVariable(); LastParsedObject = forEachVar; forEachVar.StartLocation = la.Location; if (laKind == (Ref)) { Step(); forEachVar.Attributes.Add(new DAttribute(Ref)); } if (laKind == (Identifier) && (Lexer.CurrentPeekToken.Kind == (Semicolon) || Lexer.CurrentPeekToken.Kind == Comma)) { Step(); forEachVar.Name = t.Value; } else { forEachVar.Type = Type(); if (laKind == Identifier) { Expect(Identifier); forEachVar.Name = t.Value; } } forEachVar.EndLocation = t.EndLocation; tl.Add(forEachVar); } dbs.ForeachTypeList = tl.ToArray(); Expect(Semicolon); dbs.Aggregate = Expression(Scope); // ForeachRangeStatement if (laKind == DoubleDot) { Step(); //TODO: Put this in the expression variable Expression(); } Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region [Final] SwitchStatement else if ((laKind == (Final) && Lexer.CurrentPeekToken.Kind == (Switch)) || laKind == (Switch)) { var dbs = new SwitchStatement { StartLocation = la.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (Final)) { dbs.IsFinal = true; Step(); } Step(); Expect(OpenParenthesis); dbs.SwitchExpression = Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region CaseStatement else if (laKind == (Case)) { Step(); var dbs = new SwitchStatement.CaseStatement() { StartLocation = la.Location, Parent = Parent }; LastParsedObject = dbs; dbs.ArgumentList = Expression(Scope); Expect(Colon); // CaseRangeStatement if (laKind == DoubleDot) { Step(); Expect(Case); dbs.LastExpression = AssignExpression(); Expect(Colon); } var sl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: dbs); if (stmt != null) { stmt.Parent = dbs; sl.Add(stmt); } } dbs.ScopeStatementList = sl.ToArray(); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Default else if (laKind == (Default)) { Step(); var dbs = new SwitchStatement.DefaultStatement() { StartLocation = la.Location, Parent = Parent }; LastParsedObject = dbs; Expect(Colon); var sl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: dbs); if (stmt != null) { stmt.Parent = dbs; sl.Add(stmt); } } dbs.ScopeStatementList = sl.ToArray(); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Continue | Break else if (laKind == (Continue)) { Step(); var s = new ContinueStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } else if (laKind == (Break)) { Step(); var s = new BreakStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region Return else if (laKind == (Return)) { Step(); var s = new ReturnStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind != (Semicolon)) s.ReturnExpression = Expression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region Goto else if (laKind == (Goto)) { Step(); var s = new GotoStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.StmtType = GotoStatement.GotoStmtType.Identifier; s.LabelIdentifier = t.Value; } else if (laKind == Default) { Step(); s.StmtType = GotoStatement.GotoStmtType.Default; } else if (laKind == (Case)) { Step(); s.StmtType = GotoStatement.GotoStmtType.Case; if (laKind != (Semicolon)) s.CaseExpression = Expression(Scope); } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region WithStatement else if (laKind == (With)) { Step(); var dbs = new WithStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // Symbol dbs.WithExpression = Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region SynchronizedStatement else if (laKind == (Synchronized)) { Step(); var dbs = new SynchronizedStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (OpenParenthesis)) { Step(); dbs.SyncExpression = Expression(Scope); Expect(CloseParenthesis); } dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region TryStatement else if (laKind == (Try)) { Step(); var s = new TryStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; s.ScopedStatement = Statement(Scope: Scope, Parent: s); if (!(laKind == (Catch) || laKind == (Finally))) SemErr(Catch, "At least one catch or a finally block expected!"); var catches = new List<TryStatement.CatchStatement>(); // Catches while (laKind == (Catch)) { Step(); var c = new TryStatement.CatchStatement() { StartLocation = t.Location, Parent = s }; LastParsedObject = c; // CatchParameter if (laKind == (OpenParenthesis)) { Step(); if (laKind == CloseParenthesis) { SemErr(CloseParenthesis, "Catch parameter expected, not ')'"); Step(); } else { var catchVar = new DVariable(); LastParsedObject = catchVar; var tt = la; //TODO? catchVar.Type = BasicType(); if (laKind != Identifier) { la = tt; catchVar.Type = new IdentifierDeclaration("Exception"); } Expect(Identifier); catchVar.Name = t.Value; Expect(CloseParenthesis); c.CatchParameter = catchVar; } } c.ScopedStatement = Statement(Scope: Scope, Parent: c); c.EndLocation = t.EndLocation; catches.Add(c); } if(catches.Count>0) s.Catches = catches.ToArray(); if (laKind == (Finally)) { Step(); var f = new TryStatement.FinallyStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = f; f.ScopedStatement = Statement(); f.EndLocation = t.EndLocation; s.FinallyStmt = f; } s.EndLocation = t.EndLocation; return s; } #endregion #region ThrowStatement else if (laKind == (Throw)) { Step(); var s = new ThrowStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; s.ThrowExpression = Expression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region ScopeGuardStatement else if (laKind == (DTokens.Scope) && Lexer.CurrentPeekToken.Kind==OpenParenthesis) { Step(); var s = new ScopeGuardStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == OpenParenthesis) { Expect(OpenParenthesis); if(Expect(Identifier) && t.Value!=null) // exit, failure, success { s.GuardedScope = t.Value.ToLower(); } Expect(CloseParenthesis); } s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion #region AsmStmt else if (laKind == (Asm)) { Step(); var s = new AsmStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; Expect(OpenCurlyBrace); var l=new List<string>(); var curInstr = ""; while (!IsEOF && laKind != (CloseCurlyBrace)) { if (laKind == Semicolon) { l.Add(curInstr.Trim()); curInstr = ""; } else curInstr += laKind==Identifier? la.Value: DTokens.GetTokenString(laKind); Step(); } Expect(CloseCurlyBrace); s.EndLocation = t.EndLocation; return s; } #endregion #region PragmaStatement else if (laKind == (Pragma)) { var s=_Pragma(); s.Parent = Parent; s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion #region MixinStatement //TODO: Handle this one in terms of adding it to the node structure else if (laKind == (Mixin)) { // TemplateMixin if (Peek(1).Kind != OpenParenthesis) return TemplateMixin(); else { Step(); var s = new MixinStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; Expect(OpenParenthesis); s.MixinExpression = AssignExpression(Scope); Expect(CloseParenthesis); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } } #endregion #region Conditions if (laKind == Debug) { Step(); var s = new ConditionStatement.DebugStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == OpenParenthesis) { Step(); if (laKind == Identifier || laKind == Literal) { Step(); if (laKind == Literal) s.DebugIdentifierOrLiteral = t.LiteralValue; else s.DebugIdentifierOrLiteral = t.Value; } else SynErr(t.Kind, "Identifier or Literal expected, "+DTokens.GetTokenString(t.Kind)+" found"); Expect(CloseParenthesis); } s.ScopedStatement = Statement(Scope: Scope, Parent: s); if (laKind == Else) { Step(); s.ElseStatement = Statement(Scope: Scope,Parent:s); } s.EndLocation = t.EndLocation; return s; } if (laKind == Version) { Step(); var s = new ConditionStatement.VersionStatement() { StartLocation = t.Location, Parent = Parent }; if (laKind == OpenParenthesis) { Step(); if (laKind == Identifier || laKind == Literal || laKind==Unittest) { Step(); if(laKind==Unittest) s.VersionIdentifierOrLiteral = "unittest"; else if(laKind==Literal) s.VersionIdentifierOrLiteral=t.LiteralValue; else s.VersionIdentifierOrLiteral=t.Value; } else SynErr(t.Kind, "Identifier or Literal expected, " + DTokens.GetTokenString(t.Kind) + " found"); Expect(CloseParenthesis); } s.ScopedStatement = Statement(Parent:s); if (laKind == Else) { Step(); s.ElseStatement = Statement(Parent:s); } s.EndLocation = t.EndLocation; return s; } #endregion #region (Static) AssertExpression else if (laKind == Assert || (laKind == Static && PK(Assert))) { var s = new AssertStatement() { StartLocation = la.Location, IsStatic = laKind == Static, Parent = Parent }; LastParsedObject = s; if (s.IsStatic) Step(); s.AssertExpression = AssignExpression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region D1: VolatileStatement else if (laKind == Volatile) { Step(); var s = new VolatileStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; s.ScopedStatement = Statement(Scope: Scope,Parent:s); s.EndLocation = t.EndLocation; return s; } #endregion // ImportDeclaration else if (laKind == Import) ImportDeclaration(); else if (!(ClassLike[laKind] || BasicTypes[laKind] || laKind == Enum || Modifiers[laKind] || laKind==PropertyAttribute || laKind == Alias || laKind == Typedef) && IsAssignExpression()) { var s = new ExpressionStatement() { StartLocation = la.Location, Parent = Parent }; LastParsedObject = s; // a==b, a=9; is possible -> Expressions can be there, not only single AssignExpressions! s.Expression = Expression(Scope); if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } else { var s = new DeclarationStatement() { StartLocation = la.Location, Parent = Parent }; LastParsedObject = s; s.Declarations = Declaration(Scope); if (Scope != null && s.Declarations != null && s.Declarations.Length > 0) foreach (var decl in s.Declarations) decl.Parent = Scope; s.EndLocation = t.EndLocation; return s; } return null; }