Пример #1
0
        private ScriptBlockStatement ParseBlockStatement(ScriptStatement parentStatement, bool parseEndOfStatementAfterEnd = true)
        {
            Debug.Assert(!(parentStatement is ScriptBlockStatement));

            Blocks.Push(parentStatement);

            _blockLevel++;
            EnterExpression();

            var blockStatement = Open <ScriptBlockStatement>();

            ScriptStatement statement;
            bool            hasEnd;

            while (TryParseStatement(parentStatement, parseEndOfStatementAfterEnd, out statement, out hasEnd))
            {
                // statement may be null if we have parsed an else continuation of a previous block
                if (statement != null)
                {
                    blockStatement.Statements.Add(statement);
                }
                if (hasEnd)
                {
                    break;
                }
            }

            // Don't emit an EOS for an end statement that doesn't expect it
            if (!parseEndOfStatementAfterEnd && statement is ScriptEndStatement endStatement)
            {
                endStatement.ExpectEos = false;
            }

            if (!hasEnd)
            {
                // If there are any end block not matching, we have an error
                if (_blockLevel > 1)
                {
                    if (_isLiquid)
                    {
                        var syntax = ScriptSyntaxAttribute.Get(parentStatement);
                        LogError(parentStatement, parentStatement?.Span ?? CurrentSpan, $"The `end{syntax.TypeName}` was not found");
                    }
                    else
                    {
                        // unit test: 201-if-else-error2.txt
                        LogError(parentStatement, GetSpanForToken(Previous), $"The <end> statement was not found");
                    }
                }
            }

            LeaveExpression();
            _blockLevel--;

            Blocks.Pop();
            return(Close(blockStatement));
        }
Пример #2
0
        private void LogError(ScriptNode node, SourceSpan span, string message, bool isFatal = false)
        {
            var    syntax    = ScriptSyntaxAttribute.Get(node);
            string inMessage = " in";

            if (message.EndsWith("after"))
            {
                inMessage = string.Empty;
            }
            LogError(span, $"Error while parsing {syntax.TypeName}: {message}{inMessage}: {syntax.Example}", isFatal);
        }
Пример #3
0
        private ScriptBlockStatement ParseBlockStatement(ScriptStatement parentStatement)
        {
#if DEBUG
            Debug.Assert(!(parentStatement is ScriptBlockStatement));
#endif
            Blocks.Push(parentStatement);

            _blockLevel++;
            EnterExpression();

            ScriptBlockStatement blockStatement = Open <ScriptBlockStatement>();

            ScriptStatement statement;
            bool            hasEnd;
            while (TryParseStatement(parentStatement, out statement, out hasEnd))
            {
                // statement may be null if we have parsed an else continuation of a previous block
                if (statement != null)
                {
                    blockStatement.Statements.Add(statement);
                }

                if (hasEnd)
                {
                    break;
                }
            }

            if (!hasEnd)
            {
                // If there are any end block not matching, we have an error
                if (_blockLevel > 1)
                {
                    if (_isLiquid)
                    {
                        ScriptSyntaxAttribute syntax = ScriptSyntaxAttribute.Get(parentStatement);
                        LogError(parentStatement, parentStatement?.Span ?? CurrentSpan, string.Format(RS.EndLiquidStatementNotFound, syntax.Name));
                    }
                    else
                    {
                        // unit test: 201-if-else-error2.txt
                        LogError(parentStatement, GetSpanForToken(Previous), RS.EndStatementNotFound);
                    }
                }
            }

            LeaveExpression();
            _blockLevel--;

            Blocks.Pop();
            return(Close(blockStatement));
        }
Пример #4
0
        private void LogError(ScriptNode node, SourceSpan span, string message, bool isFatal = false)
        {
            ScriptSyntaxAttribute syntax = ScriptSyntaxAttribute.Get(node);
            // #todo
            string inSeparator = " >>> ";

            if (message.EndsWith("after"))
            {
                inSeparator = string.Empty;
            }

            LogError(span, string.Format(RS.ParseError, syntax.Name, message, inSeparator, syntax.Example), isFatal);
        }
Пример #5
0
        public override void Evaluate(TemplateContext context)
        {
            // Check that the Target is actually a function
            var functionCall = Target as ScriptFunctionCall;

            if (functionCall == null)
            {
                var parameterLessFunction = context.Evaluate(Target, true);
                if (!(parameterLessFunction is IScriptCustomFunction))
                {
                    var targetPrettyname = ScriptSyntaxAttribute.Get(Target);
                    throw new ScriptRuntimeException(Target.Span, $"Expecting a direct function instead of the expression [{Target}/{targetPrettyname.Name}]");
                }

                context.BlockDelegates.Push(Body);
                context.Result = ScriptFunctionCall.Call(context, this, parameterLessFunction);
            }
            else
            {
                context.BlockDelegates.Push(Body);
                context.Result = context.Evaluate(functionCall);
            }
        }
Пример #6
0
        private ScriptExpression ParseObjectInitializer()
        {
            var scriptObject = Open <ScriptObjectInitializerExpression>();

            // Should happen before the NextToken to consume any EOL after
            _allowNewLineLevel++;
            NextToken(); // Skip {

            // unit test: 140-object-initializer-accessor.txt
            bool expectingEndOfInitializer = false;

            while (true)
            {
                if (Current.Type == TokenType.CloseBrace)
                {
                    break;
                }

                if (!expectingEndOfInitializer && (Current.Type == TokenType.Identifier || Current.Type == TokenType.String))
                {
                    var positionBefore    = Current;
                    var variableOrLiteral = ParseExpression(scriptObject);
                    var variable          = variableOrLiteral as ScriptVariable;
                    var literal           = variableOrLiteral as ScriptLiteral;

                    if (variable == null && literal == null)
                    {
                        LogError(positionBefore, $"Unexpected member type `{variableOrLiteral}/{ScriptSyntaxAttribute.Get(variableOrLiteral).Name}` found for object initializer member name");
                        break;
                    }

                    if (literal != null && !(literal.Value is string))
                    {
                        LogError(positionBefore,
                                 $"Invalid literal member `{literal.Value}/{literal.Value?.GetType()}` found for object initializer member name. Only literal string or identifier name are allowed");
                        break;
                    }

                    if (variable != null)
                    {
                        if (variable.Scope != ScriptVariableScope.Global)
                        {
                            // unit test: 140-object-initializer-error3.txt
                            LogError("Expecting a simple identifier for member names");
                            break;
                        }
                    }

                    if (Current.Type != TokenType.Colon)
                    {
                        // unit test: 140-object-initializer-error4.txt
                        LogError($"Unexpected token `{Current.Type}` Expecting a colon : after identifier `{variable.Name}` for object initializer member name");
                        break;
                    }

                    // TODO: record as trivia
                    NextToken(); // Skip :

                    if (!StartAsExpression())
                    {
                        // unit test: 140-object-initializer-error5.txt
                        LogError($"Unexpected token `{Current.Type}`. Expecting an expression for the value of the member instead of `{GetAsText(Current)}`");
                        break;
                    }

                    var expression = ParseExpression(scriptObject);

                    // Erase any previous declaration of this member
                    scriptObject.Members[variableOrLiteral] = expression;

                    if (Current.Type == TokenType.Comma)
                    {
                        // Record trailing Commas
                        if (_isKeepTrivia)
                        {
                            expression.AddTrivia(new ScriptTrivia(CurrentSpan, ScriptTriviaType.Comma, _lexer.Text), false);
                        }
                        NextToken();

                        if (_isKeepTrivia && _trivias.Count > 0)
                        {
                            expression.AddTrivias(_trivias, false);
                            _trivias.Clear();
                        }
                    }
                    else
                    {
                        expectingEndOfInitializer = true;
                    }
                }
                else
                {
                    // unit test: 140-object-initializer-error1.txt
                    LogError($"Unexpected token `{Current.Type}` while parsing object initializer. Expecting a simple identifier for the member name instead of `{GetAsText(Current)}`");
                    break;
                }
            }

            // Should happen before NextToken() to stop on the next EOF
            _allowNewLineLevel--;
            NextToken(); // Skip }

            return(Close(scriptObject));
        }
Пример #7
0
        private ScriptExpression ParseObjectInitializer()
        {
            var scriptObject = Open <ScriptObjectInitializerExpression>();

            // Should happen before the NextToken to consume any EOL after
            allowNewLineLevel++;
            NextToken(); // Skip {

            // unit test: 140-object-initializer-accessor.txt
            bool expectingEndOfInitializer = false;

            while (true)
            {
                if (Current.Type == TokenType.CloseBrace)
                {
                    break;
                }

                if (!expectingEndOfInitializer && (Current.Type == TokenType.Identifier || Current.Type == TokenType.String))
                {
                    var positionBefore    = Current;
                    var variableOrLiteral = ParseExpression(scriptObject);
                    var variable          = variableOrLiteral as ScriptVariable;
                    var literal           = variableOrLiteral as ScriptLiteral;

                    if (variable == null && literal == null)
                    {
                        LogError(positionBefore, $"Unexpected member type [{variableOrLiteral}/{ScriptSyntaxAttribute.Get(variableOrLiteral).Name}] found for object initializer member name");
                        break;
                    }

                    if (literal != null && !(literal.Value is string))
                    {
                        LogError(positionBefore, $"Invalid literal member [{literal.Value}/{literal.Value?.GetType()}] found for object initializer member name. Only literal string or identifier name are allowed");
                        break;
                    }

                    if (variable != null)
                    {
                        if (IsKeyword(variable.Name))
                        {
                            // unit test: 140-object-initializer-error2.txt
                            LogError(positionBefore,
                                     $"Invalid Keyword [{variable}] found for object initializer member name");
                            break;
                        }

                        if (variable.Scope != ScriptVariableScope.Global)
                        {
                            // unit test: 140-object-initializer-error3.txt
                            LogError("Expecting a simple identifier for member names");
                            break;
                        }
                    }

                    if (Current.Type != TokenType.Colon)
                    {
                        // unit test: 140-object-initializer-error4.txt
                        LogError($"Unexpected token [{Current.Type}] Expecting a colon : after identifier [{variable.Name}] for object initializer member name");
                        break;
                    }

                    NextToken(); // Skip :

                    if (!StartAsExpression())
                    {
                        // unit test: 140-object-initializer-error5.txt
                        LogError($"Unexpected token [{Current.Type}]. Expecting an expression for the value of the member instead of [{GetAsText(Current)}]");
                        break;
                    }

                    var expression = ParseExpression(scriptObject);

                    // Erase any previous declaration of this member
                    scriptObject.Members[variableOrLiteral] = expression;

                    if (Current.Type == TokenType.Comma)
                    {
                        NextToken();
                    }
                    else
                    {
                        expectingEndOfInitializer = true;
                    }
                }
                else
                {
                    // unit test: 140-object-initializer-error1.txt
                    LogError($"Unexpected token [{Current.Type}] while parsing object initializer. Expecting a simple identifier for the member name instead of [{GetAsText(Current)}]");
                    break;
                }
            }

            // Should happen before NextToken() to stop on the next EOF
            allowNewLineLevel--;
            NextToken(); // Skip }

            return(Close(scriptObject));
        }
Пример #8
0
        private ScriptExpression ParseObjectInitializer()
        {
            ScriptObjectInitializerExpression scriptObject = Open <ScriptObjectInitializerExpression>();

            // Should happen before the NextToken to consume any EOL after
            _allowNewLineLevel++;
            NextToken(); // Skip {

            // unit test: 140-object-initializer-accessor.txt
            bool expectingEndOfInitializer = false;

            while (true)
            {
                if (Current.Type == TokenType.CloseBrace)
                {
                    break;
                }

                if (!expectingEndOfInitializer && (Current.Type == TokenType.Identifier || Current.Type == TokenType.String))
                {
                    Token            positionBefore    = Current;
                    ScriptExpression variableOrLiteral = ParseExpression(scriptObject);
                    var variable = variableOrLiteral as ScriptVariable;
                    var literal  = variableOrLiteral as ScriptLiteral;

                    if (variable == null && literal == null)
                    {
                        LogError(positionBefore, string.Format(RS.InvalidObjectInitMemberNameType, variableOrLiteral, ScriptSyntaxAttribute.Get(variableOrLiteral).Name));
                        break;
                    }

                    if (literal != null && !(literal.Value is string))
                    {
                        LogError(positionBefore, string.Format(RS.InvalidObjectInitMemberName, literal.Value, literal.Value?.GetType()));
                        break;
                    }

                    if (variable != null)
                    {
                        if (variable.Scope != ScriptVariableScope.Global)
                        {
                            // unit test: 140-object-initializer-error3.txt
                            LogError(RS.InvalidMemberName);
                            break;
                        }
                    }

                    if (Current.Type != TokenType.Colon)
                    {
                        // unit test: 140-object-initializer-error4.txt
                        LogError(string.Format(RS.UnexpectedTokenInObjectMemberName, Current.Type, variable.Name));
                        break;
                    }

                    // TODO: record as trivia
                    NextToken(); // Skip :

                    if (!StartAsExpression())
                    {
                        // unit test: 140-object-initializer-error5.txt
                        LogError(string.Format(RS.InvalidMemberValue, Current.Type, GetAsText(Current)));
                        break;
                    }

                    ScriptExpression expression = ParseExpression(scriptObject);

                    // Erase any previous declaration of this member
                    scriptObject.Members[variableOrLiteral] = expression;

                    if (Current.Type == TokenType.Comma)
                    {
                        // Record trailing Commas
                        if (_isKeepTrivia)
                        {
                            expression.AddTrivia(new ScriptTrivia(CurrentSpan, ScriptTriviaType.Comma, _lexer.Text), false);
                        }

                        NextToken();

                        if (_isKeepTrivia && _trivias.Count > 0)
                        {
                            expression.AddTrivias(_trivias, false);
                            _trivias.Clear();
                        }
                    }
                    else
                    {
                        expectingEndOfInitializer = true;
                    }
                }
                else
                {
                    // unit test: 140-object-initializer-error1.txt
                    LogError(string.Format(RS.UnexpectedTokenInObjectInit, Current.Type, GetAsText(Current)));
                    break;
                }
            }

            // Should happen before NextToken() to stop on the next EOF
            _allowNewLineLevel--;
            NextToken(); // Skip }

            return(Close(scriptObject));
        }