Ejemplo n.º 1
0
        private ASTStatementBase ParseSwitch()
        {
            Require(TokenType.SWITCH);

            if (_switchLevel > 0)
            {
                throw new ParserException("Nested switch statements are currently not supported.", _lexer.Line, _lexer.Character);
            }

            Require(TokenType.LEFT_PARENTHESIS);

            ASTExpressionBase check = ParseExpression();

            Require(TokenType.RIGHT_PARENTHESIS);

            Require(TokenType.LEFT_BRACE);

            ASTSwitch switchStatement = new ASTSwitch(check);

            while (!Match(TokenType.RIGHT_BRACE))
            {
                if (Match(TokenType.END_OF_FILE))
                {
                    throw new ParserException("'}' expected!", _lexer.Line, _lexer.Character);
                }

                if (Match(TokenType.DEFAULT))
                {
                    Require(TokenType.DEFAULT);
                    Require(TokenType.COLON);
                    _switchLevel++;
                    switchStatement.AddCase(null, ParseStatement());
                    _switchLevel--;
                    if (!Match(TokenType.RIGHT_BRACE))
                    {
                        throw new ParserException("A default case must be the final case of a switch statement.", _lexer.Line, _lexer.Character);
                    }
                    break;
                }

                Require(TokenType.CASE);
                ASTExpressionBase _case = ParseExpression();
                if (_case == null)
                {
                    throw new ParserException("Identifier expected.", _lexer.Line, _lexer.Character);
                }

                Require(TokenType.COLON);

                if (Match(TokenType.CASE) || Match(TokenType.DEFAULT))
                {
                    switchStatement.AddCase(_case, null);
                }
                else
                {
                    _switchLevel++;
                    switchStatement.AddCase(_case, ParseStatement());
                    _switchLevel--;
                }

                /* for now, I don't think forcing the scripter to use braces to have a "break;" after a case is necessary, eg. in the situation of
                 * case 5:
                 * {
                 *  print("hello");
                 *  break;
                 * }
                 *
                 * you might as well just type
                 * case 5:
                 *  print("hello");
                 *  break;
                 */
                if (Match(TokenType.BREAK))                                                   // so let's allow that
                {
                    Consume();                                                                // consume 'break'
                    Require(TokenType.SEMICOLON);                                             // require ';'
                    var currentCase = switchStatement.Cases[switchStatement.Cases.Count - 1]; // get statement of current case
                    // and add the 'break' to the end of it
                    switchStatement.Cases[switchStatement.Cases.Count - 1] = (currentCase.expression,
                                                                              new ASTBlock(new List <ASTStatementBase>
                    {
                        currentCase.statement, new ASTBreak()
                    }));
                }
            }

            Require(TokenType.RIGHT_BRACE);

            if (switchStatement.Cases.Count == 0)
            {
                throw new ParserException("Empty switch statements are not allowed.", _lexer.Line, _lexer.Character);
            }

            return(switchStatement);
        }
Ejemplo n.º 2
0
 public bool Visit(ASTSwitch node)
 {
     throw new NotImplementedException();
 }