public abstract void VisitCaseLabel(Case p);
Statement tstmt() { int l = next.line; int c = next.col; Statement s, s1, s2; Expression e; if (t == TokenKind.OpeningCurlyBrace) return block(); else if (t == TokenKind.If) { move(); e = expr(); if (t == TokenKind.Then) move(); s = stmt(); if (t == TokenKind.Else) { move(); return new If(e, s, stmt(), l, c); } return new If(e, s, l, c); } else if (t == TokenKind.While) { move(); e = expr(); if (t == TokenKind.Do) move(); return new While(e, stmt(), l, c); } else if (t == TokenKind.Do) { move(); s = stmt(); match(Token.Until, Error.ExpectedUntil); return new Do(s, expr(), l, c); } else if (t == TokenKind.For) { // "For" is very weird in GM. Any legal statement including control flow and blocks can be used in for. // example of legal "for" statements: // for (i = 0 i<3; {case 3:exit};;;)func(); move(); match(Token.OpeningParenthesis); s1 = stmt(); //match(Token.Semicolon); // Taken care of by stmt(); e = expr(); match(Token.Semicolon); s2 = stmt(); match(Token.ClosingParenthesis); return new For(s1, e, s2, stmt(), l, c); } else if (t == TokenKind.Break) { move(); return new Break(l, c); } else if (t == TokenKind.Continue) { move(); return new Continue(l, c); } else if (t == TokenKind.Exit) { move(); return new Exit(l, c); } else if (t == TokenKind.Return) { move(); return new Return(expr(), l, c); } else if (t == TokenKind.Repeat) { move(); return new Repeat(expr(), stmt(), l, c); } else if (t == TokenKind.Var) { move(); List<string> strs = new List<string>(); while (t == TokenKind.Identifier) { if (peek().t == TokenKind.OpeningParenthesis) break; if (Context.IsBuiltIn(next.lexeme)) error(Error.BuiltinVariable); strs.Add(next.lexeme); move(); if (t == TokenKind.Comma) move(); } return new Var(strs.ToArray(), l, c); } else if (t == TokenKind.Globalvar) { move(); List<string> strs = new List<string>(); while (t == TokenKind.Identifier) { if (peek().t == TokenKind.OpeningParenthesis) break; if (Context.IsBuiltIn(next.lexeme)) error(Error.BuiltinVariable); strs.Add(next.lexeme); move(); if (t == TokenKind.Comma) move(); } return new Globalvar(strs.ToArray(), l, c); } else if (t == TokenKind.With) { move(); e = expr(); if (t == TokenKind.Do) move(); return new With(e, stmt(), l, c); } else if (t == TokenKind.Default) { move(); match(Token.Colon); return new Default(l, c); } else if (t == TokenKind.Case) { move(); Case @case = new Case(expr(), l, c); // @ since case is a keyword match(Token.Colon); return @case; } else if (t == TokenKind.Switch) { move(); e = expr(); match(Token.OpeningCurlyBrace); List<Statement> lst = new List<Statement>(); while (t != TokenKind.ClosingCurlyBrace && t != TokenKind.Eof) { lst.Add(stmt()); while (t == TokenKind.Semicolon) move(); } match(Token.ClosingCurlyBrace); return new Switch(e, lst.ToArray(), l, c); } else if (t == TokenKind.Identifier) { if (peek().t == TokenKind.OpeningParenthesis) { string str = next.lexeme; if (!Context.Resources.FunctionExists(str)) { error(Error.UnknownFunction, str); } move(); move(); List<Expression> exprs = new List<Expression>(); if (t != TokenKind.ClosingParenthesis && t != TokenKind.Eof) { exprs.Add(expr()); } while (t == TokenKind.Comma) { move(); exprs.Add(expr()); } match(Token.ClosingParenthesis); IFunction f = Context.Resources.GetFunction(str); if ((f.Argc != -1 && exprs.Count != f.Argc) || exprs.Count > 16) error(Error.WrongArgumentNumber); return new CallStatement(f, exprs.ToArray(), l, c); } else { return assign(); } } else { return assign(); } }