Beispiel #1
0
        private ScriptConditionStatement ParseElseStatement(bool isElseIf)
        {
            // Case of elsif
            if (_isLiquid && isElseIf)
            {
                return(ParseIfStatement(false, ScriptKeyword.Else()));
            }

            // unit test: 200-if-else-statement.txt
            var nextToken = PeekToken();

            if (!_isLiquid && nextToken.Type == TokenType.Identifier && GetAsText(nextToken) == "if")
            {
                var elseKeyword = ScriptKeyword.Else();
                ExpectAndParseKeywordTo(elseKeyword);
                return(ParseIfStatement(false, elseKeyword));
            }

            var elseStatement = Open <ScriptElseStatement>();

            ExpectAndParseKeywordTo(elseStatement.ElseKeyword); // Parse else statement

            // unit test: 201-if-else-error4.txt
            if (ExpectEndOfStatement())
            {
                elseStatement.Body = ParseBlockStatement(elseStatement);
            }
            return(Close(elseStatement));
        }
Beispiel #2
0
        private ScriptIfStatement ParseIfStatement(bool invert, ScriptKeyword elseKeyword = null)
        {
            // unit test: 200-if-else-statement.txt
            var ifStatement = Open <ScriptIfStatement>();

            ifStatement.ElseKeyword = elseKeyword;

            if (_isLiquid && elseKeyword != null)
            {
                // Parse elseif
                Open(ifStatement.IfKeyword);
                NextToken();
                Close(ifStatement.IfKeyword);
            }
            else
            {
                if (_isLiquid && invert)         // we have an unless
                {
                    Open(ifStatement.IfKeyword); // still transfer trivias to IfKeyword
                    NextToken();
                    Close(ifStatement.IfKeyword);
                }
                else
                {
                    ExpectAndParseKeywordTo(ifStatement.IfKeyword); // Parse if keyword
                }
            }

            var condition = ExpectAndParseExpression(ifStatement, allowAssignment: false);

            // Transform a `if condition` to `if !(condition)`
            if (invert)
            {
                var invertCondition = ScriptUnaryExpression.Wrap(ScriptUnaryOperator.Not, ScriptToken.Exclamation(), ScriptNestedExpression.Wrap(condition, _isKeepTrivia), _isKeepTrivia);
                condition = invertCondition;
            }

            ifStatement.Condition = condition;

            if (ExpectEndOfStatement())
            {
                ifStatement.Then = ParseBlockStatement(ifStatement);
            }

            return(Close(ifStatement));
        }
Beispiel #3
0
 public ScriptEndStatement()
 {
     EndKeyword        = ScriptKeyword.End();
     CanSkipEvaluation = true;
 }
Beispiel #4
0
 public ScriptBreakStatement()
 {
     BreakKeyword = ScriptKeyword.Break();
 }
        private ScriptFunction ParseFunctionStatement(bool isAnonymous)
        {
            var scriptFunction = Open <ScriptFunction>();

            var previousExpressionLevel = _expressionLevel;

            try
            {
                // Reset expression level when parsing
                _expressionLevel = 0;

                if (isAnonymous)
                {
                    scriptFunction.NameOrDoToken = ExpectAndParseKeywordTo(ScriptKeyword.Do());
                }
                else
                {
                    scriptFunction.FuncToken     = ExpectAndParseKeywordTo(ScriptKeyword.Func());
                    scriptFunction.NameOrDoToken = ExpectAndParseVariable(scriptFunction);
                }

                // If we have parenthesis, this is a function with explicit parameters
                if (Current.Type == TokenType.OpenParen)
                {
                    scriptFunction.OpenParen = ParseToken(TokenType.OpenParen);
                    var  parameters   = new ScriptList <ScriptParameter>();
                    bool hasTripleDot = false;
                    bool hasOptionals = false;

                    bool isFirst = true;
                    while (true)
                    {
                        // Parse any required comma (before each new non-first argument)
                        // Or closing parent (and we exit the loop)
                        if (Current.Type == TokenType.CloseParen)
                        {
                            scriptFunction.CloseParen = ParseToken(TokenType.CloseParen);
                            scriptFunction.Span.End   = scriptFunction.CloseParen.Span.End;
                            break;
                        }

                        if (!isFirst)
                        {
                            if (Current.Type == TokenType.Comma)
                            {
                                PushTokenToTrivia();
                                NextToken();
                                FlushTriviasToLastTerminal();
                            }
                            else
                            {
                                LogError(Current, "Expecting a comma to separate arguments in a function call.");
                            }
                        }

                        isFirst = false;

                        // Else we expect an expression
                        if (IsStartOfExpression())
                        {
                            var parameter = Open <ScriptParameter>();
                            var arg       = ExpectAndParseVariable(scriptFunction);
                            if (!(arg is ScriptVariableGlobal))
                            {
                                LogError(arg.Span, "Expecting only a simple name parameter for a function");
                            }

                            parameter.Name = arg;

                            if (Current.Type == TokenType.Equal)
                            {
                                if (hasTripleDot)
                                {
                                    LogError(arg.Span, "Cannot declare an optional parameter after a variable parameter (`...`).");
                                }

                                hasOptionals = true;
                                parameter.EqualOrTripleDotToken = ScriptToken.Equal();
                                ExpectAndParseTokenTo(parameter.EqualOrTripleDotToken, TokenType.Equal);

                                parameter.Span.End = parameter.EqualOrTripleDotToken.Span.End;

                                var defaultValue = ExpectAndParseExpression(parameter);
                                if (defaultValue is ScriptLiteral literal)
                                {
                                    parameter.DefaultValue = literal;
                                    parameter.Span.End     = literal.Span.End;
                                }
                                else
                                {
                                    LogError(arg.Span, "Expecting only a literal for an optional parameter value.");
                                }
                            }
                            else if (Current.Type == TokenType.TripleDot)
                            {
                                if (hasTripleDot)
                                {
                                    LogError(arg.Span, "Cannot declare multiple variable parameters.");
                                }

                                hasTripleDot = true;
                                hasOptionals = true;
                                parameter.EqualOrTripleDotToken = ScriptToken.TripleDot();
                                ExpectAndParseTokenTo(parameter.EqualOrTripleDotToken, TokenType.TripleDot);
                                parameter.Span.End = parameter.EqualOrTripleDotToken.Span.End;
                            }
                            else if (hasOptionals)
                            {
                                LogError(arg.Span, "Cannot declare a normal parameter after an optional parameter.");
                            }

                            parameters.Add(parameter);
                            scriptFunction.Span.End = parameter.Span.End;
                        }
                        else
                        {
                            LogError(Current, "Expecting an expression for argument function calls instead of this token.");
                            break;
                        }
                    }

                    if (scriptFunction.CloseParen == null)
                    {
                        LogError(Current, "Expecting a closing parenthesis for a function call.");
                    }

                    // Setup parameters once they have been all parsed
                    scriptFunction.Parameters = parameters;
                }

                ExpectEndOfStatement();
                // If the function is anonymous we don't expect an EOS after the `end`
                scriptFunction.Body = ParseBlockStatement(scriptFunction, !isAnonymous);
            }
            finally
            {
                _expressionLevel = previousExpressionLevel;
            }

            return(Close(scriptFunction));
        }