Beispiel #1
0
        protected ExpressionBase ParseShorthandBody(PositionalTokenizer tokenizer)
        {
            ExpressionBase.SkipWhitespace(tokenizer);

            var expression = ExpressionBase.Parse(tokenizer);

            if (expression.Type == ExpressionType.ParseError)
            {
                return(expression);
            }

            switch (expression.Type)
            {
            case ExpressionType.Return:
                return(ParseError(tokenizer, "Return statement is implied by =>", ((ReturnExpression)expression).Keyword));

            case ExpressionType.For:
                return(ParseError(tokenizer, "Shorthand function definition does not support loops.", expression));

            case ExpressionType.If:
                return(ParseError(tokenizer, "Shorthand function definition does not support branches.", expression));
            }

            var returnExpression = new ReturnExpression(expression);

            Expressions.Add(returnExpression);
            Location = new TextRange(Location.Start, expression.Location.End);
            return(MakeReadOnly(this));
        }
Beispiel #2
0
        /// <summary>
        /// Replaces the variables in the expression with values from <paramref name="scope" />.
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="result">[out] The new expression containing the replaced variables.</param>
        /// <returns>
        ///   <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />.
        /// </returns>
        public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result)
        {
            ExpressionBase value;

            if (!Value.ReplaceVariables(scope, out value))
            {
                result = value;
                return(false);
            }

            result = new ReturnExpression(value);
            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// Parses a function definition.
        /// </summary>
        /// <remarks>
        /// Assumes the 'function' keyword has already been consumed.
        /// </remarks>
        internal static ExpressionBase Parse(PositionalTokenizer tokenizer, int line = 0, int column = 0)
        {
            var function = new FunctionDefinitionExpression();

            function._keyword = new KeywordExpression("function", line, column);

            ExpressionBase.SkipWhitespace(tokenizer);

            line   = tokenizer.Line;
            column = tokenizer.Column;

            var functionName = tokenizer.ReadIdentifier();

            function.Name = new VariableDefinitionExpression(functionName.ToString(), line, column);
            if (functionName.IsEmpty)
            {
                ExpressionBase.ParseError(tokenizer, "Invalid function name");
                return(function);
            }

            ExpressionBase.SkipWhitespace(tokenizer);
            if (tokenizer.NextChar != '(')
            {
                ExpressionBase.ParseError(tokenizer, "Expected '(' after function name", function.Name);
                return(function);
            }
            tokenizer.Advance();

            ExpressionBase.SkipWhitespace(tokenizer);
            if (tokenizer.NextChar != ')')
            {
                do
                {
                    line   = tokenizer.Line;
                    column = tokenizer.Column;

                    var parameter = tokenizer.ReadIdentifier();
                    if (parameter.IsEmpty)
                    {
                        ExpressionBase.ParseError(tokenizer, "Invalid parameter name", line, column);
                        return(function);
                    }

                    function.Parameters.Add(new VariableDefinitionExpression(parameter.ToString(), line, column));

                    ExpressionBase.SkipWhitespace(tokenizer);
                    if (tokenizer.NextChar == ')')
                    {
                        break;
                    }

                    if (tokenizer.NextChar != ',')
                    {
                        ExpressionBase.ParseError(tokenizer, "Expected ',' or ')' after parameter name, found: " + tokenizer.NextChar);
                        return(function);
                    }

                    tokenizer.Advance();
                    ExpressionBase.SkipWhitespace(tokenizer);
                } while (true);
            }

            tokenizer.Advance(); // closing parenthesis
            ExpressionBase.SkipWhitespace(tokenizer);

            ExpressionBase expression;

            if (tokenizer.Match("=>"))
            {
                ExpressionBase.SkipWhitespace(tokenizer);

                expression = ExpressionBase.Parse(tokenizer);
                if (expression.Type == ExpressionType.ParseError)
                {
                    return(expression);
                }

                if (expression.Type == ExpressionType.Return)
                {
                    return(new ParseErrorExpression("Return statement is implied by =>", ((ReturnExpression)expression).Keyword));
                }

                var returnExpression = new ReturnExpression(expression);
                function.Expressions.Add(returnExpression);
                return(function);
            }

            if (tokenizer.NextChar != '{')
            {
                ExpressionBase.ParseError(tokenizer, "Expected '{' after function declaration", function.Name);
                return(function);
            }

            line   = tokenizer.Line;
            column = tokenizer.Column;
            tokenizer.Advance();
            ExpressionBase.SkipWhitespace(tokenizer);

            bool seenReturn = false;

            while (tokenizer.NextChar != '}')
            {
                expression = ExpressionBase.Parse(tokenizer);
                if (expression.Type == ExpressionType.ParseError)
                {
                    return(expression);
                }

                if (expression.Type == ExpressionType.Return)
                {
                    seenReturn = true;
                }
                else if (seenReturn)
                {
                    ExpressionBase.ParseError(tokenizer, "Expression after return statement", expression);
                }

                function.Expressions.Add(expression);

                ExpressionBase.SkipWhitespace(tokenizer);
            }

            tokenizer.Advance();
            return(function);
        }