Пример #1
0
        /// <summary>
        /// Parses an anonymous function definition in the format "(a) => body" or "(a) { body }"
        /// </summary>
        public static ExpressionBase ParseAnonymous(PositionalTokenizer tokenizer)
        {
            var name     = CreateAnonymousFunctionName(tokenizer.Line, tokenizer.Column);
            var function = new AnonymousUserFunctionDefinitionExpression(name);

            function.Location = new TextRange(tokenizer.Line, tokenizer.Column, 0, 0);
            return(function.Parse(tokenizer));
        }
Пример #2
0
        /// <summary>
        /// Parses an anonymous function definition in the format "a => body" where <paramref name="parameter"/>
        /// is "a" and <paramref name="tokenizer"/> is pointing at "body".
        /// </summary>
        public static ExpressionBase ParseAnonymous(PositionalTokenizer tokenizer, ExpressionBase parameter)
        {
            var variable = parameter as VariableExpression;

            if (variable == null)
            {
                return(new ParseErrorExpression("Cannot create anonymous function from " + parameter.Type));
            }

            var name     = CreateAnonymousFunctionName(parameter.Location.Start.Line, parameter.Location.Start.Column);
            var function = new AnonymousUserFunctionDefinitionExpression(name);

            function.Location = parameter.Location;
            function.Parameters.Add(new VariableDefinitionExpression(variable.Name, variable.Location.Start.Line, variable.Location.Start.Column));
            return(function.ParseShorthandBody(tokenizer));
        }
Пример #3
0
        private static ExpressionBase ParseClauseCore(PositionalTokenizer tokenizer)
        {
            ExpressionBase clause;

            switch (tokenizer.NextChar)
            {
            case '!':
                tokenizer.Advance();
                clause = ParseClause(tokenizer);
                if (clause.Type == ExpressionType.ParseError)
                {
                    return(clause);
                }

                return(new ConditionalExpression(null, ConditionalOperation.Not, clause));

            case '(':
                if (AnonymousUserFunctionDefinitionExpression.IsAnonymousParameterList(tokenizer))
                {
                    return(AnonymousUserFunctionDefinitionExpression.ParseAnonymous(tokenizer));
                }

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

                if (tokenizer.NextChar != ')')
                {
                    if (tokenizer.NextChar == '\0')
                    {
                        return(ParseError(tokenizer, "No closing parenthesis found"));
                    }

                    return(ParseError(tokenizer, "Expected closing parenthesis, found: " + tokenizer.NextChar));
                }

                clause.IsLogicalUnit = true;
                tokenizer.Advance();

                return(clause);

            case '"':
                try
                {
                    var stringValue = tokenizer.ReadQuotedString().ToString();
                    return(new StringConstantExpression(stringValue));
                }
                catch (InvalidOperationException ex)
                {
                    return(ParseError(tokenizer, ex.Message));
                }

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                return(ParseNumber(tokenizer, true));

            case '-':
                var tokenStart = tokenizer.Location;
                tokenizer.Advance();
                if (tokenizer.NextChar >= '0' && tokenizer.NextChar <= '9')
                {
                    var result   = ParseNumber(tokenizer, false);
                    var tokenEnd = result.Location.End;
                    switch (result.Type)
                    {
                    case ExpressionType.IntegerConstant:
                        result = new IntegerConstantExpression(-((IntegerConstantExpression)result).Value);
                        break;

                    case ExpressionType.FloatConstant:
                        result = new FloatConstantExpression(-((FloatConstantExpression)result).Value);
                        break;

                    default:
                        return(result);
                    }

                    result.Location = new TextRange(tokenStart, tokenEnd);
                    return(result);
                }
                return(ParseError(tokenizer, "Minus without value", tokenStart.Line, tokenStart.Column));

            case '{':
                tokenizer.Advance();
                return(DictionaryExpression.Parse(tokenizer));

            case '[':
                tokenizer.Advance();
                return(ParseArray(tokenizer));

            default:
                var line       = tokenizer.Line;
                var column     = tokenizer.Column;
                var identifier = tokenizer.ReadIdentifier();
                if (identifier.IsEmpty)
                {
                    var error = ParseError(tokenizer, "Unexpected character: " + tokenizer.NextChar);
                    tokenizer.Advance();
                    return(error);
                }

                SkipWhitespace(tokenizer);

                if (identifier == "return")
                {
                    clause = ExpressionBase.Parse(tokenizer);
                    if (clause.Type == ExpressionType.ParseError)
                    {
                        return(clause);
                    }

                    return(new ReturnExpression(new KeywordExpression(identifier.ToString(), line, column), clause));
                }

                if (identifier == "function")
                {
                    return(UserFunctionDefinitionExpression.Parse(tokenizer, line, column));
                }
                if (identifier == "for")
                {
                    return(ForExpression.Parse(tokenizer, line, column));
                }
                if (identifier == "if")
                {
                    return(IfExpression.Parse(tokenizer, line, column));
                }

                if (identifier == "true")
                {
                    return(new BooleanConstantExpression(true, line, column));
                }
                if (identifier == "false")
                {
                    return(new BooleanConstantExpression(false, line, column));
                }

                if (tokenizer.NextChar == '(')
                {
                    tokenizer.Advance();

                    var parameters = new List <ExpressionBase>();
                    ParseParameters(tokenizer, parameters);

                    var functionCall = new FunctionCallExpression(new FunctionNameExpression(identifier.ToString(), line, column), parameters);
                    functionCall.Location = new TextRange(line, column, tokenizer.Line, tokenizer.Column - 1);
                    return(functionCall);
                }

                if (tokenizer.NextChar == '[')
                {
                    IndexedVariableExpression parent = null;

                    do
                    {
                        tokenizer.Advance();

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

                        SkipWhitespace(tokenizer);
                        if (tokenizer.NextChar != ']')
                        {
                            return(ParseError(tokenizer, "Expecting closing bracket after index"));
                        }
                        tokenizer.Advance();
                        SkipWhitespace(tokenizer);

                        if (parent != null)
                        {
                            parent = new IndexedVariableExpression(parent, index);
                        }
                        else
                        {
                            parent = new IndexedVariableExpression(new VariableExpression(identifier.ToString(), line, column), index);
                        }
                    } while (tokenizer.NextChar == '[');

                    return(parent);
                }

                return(new VariableExpression(identifier.ToString(), line, column));
            }
        }
Пример #4
0
        private static ExpressionBase ParseClauseExtension(ExpressionBase clause, PositionalTokenizer tokenizer, OperationPriority priority)
        {
            do
            {
                var clauseEndLine   = tokenizer.Line;
                var clauseEndColumn = tokenizer.Column;

                SkipWhitespace(tokenizer);

                var joinerLine   = tokenizer.Line;
                var joinerColumn = tokenizer.Column;

                switch (tokenizer.NextChar)
                {
                case '+':
                    if (priority == OperationPriority.AddSubtract && clause.Type == ExpressionType.StringConstant)
                    {
                        priority = OperationPriority.AppendString;
                    }

                    if (priority >= OperationPriority.AddSubtract)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    clause = ParseMathematic(tokenizer, clause, MathematicOperation.Add, joinerLine, joinerColumn);
                    break;

                case '-':
                    if (priority >= OperationPriority.AddSubtract)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    clause = ParseMathematic(tokenizer, clause, MathematicOperation.Subtract, joinerLine, joinerColumn);
                    break;

                case '*':
                    if (priority >= OperationPriority.MulDivMod)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    clause = ParseMathematic(tokenizer, clause, MathematicOperation.Multiply, joinerLine, joinerColumn);
                    break;

                case '/':
                    if (priority >= OperationPriority.MulDivMod)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    clause = ParseMathematic(tokenizer, clause, MathematicOperation.Divide, joinerLine, joinerColumn);
                    break;

                case '%':
                    if (priority >= OperationPriority.MulDivMod)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    clause = ParseMathematic(tokenizer, clause, MathematicOperation.Modulus, joinerLine, joinerColumn);
                    break;

                case '=':
                    if (tokenizer.MatchSubstring("==") == 2)
                    {
                        if (priority >= OperationPriority.Compare)
                        {
                            return(clause);
                        }

                        tokenizer.Advance(2);
                        clause = ParseComparison(tokenizer, clause, ComparisonOperation.Equal, joinerLine, joinerColumn);
                    }
                    else
                    {
                        if (priority > OperationPriority.Assign)
                        {
                            return(clause);
                        }

                        tokenizer.Advance();
                        if (tokenizer.NextChar == '>')
                        {
                            tokenizer.Advance();
                            clause = AnonymousUserFunctionDefinitionExpression.ParseAnonymous(tokenizer, clause);
                        }
                        else
                        {
                            clause = ParseAssignment(tokenizer, clause, joinerLine, joinerColumn);
                        }
                    }
                    break;

                case '!':
                    if (priority >= OperationPriority.Compare)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    if (tokenizer.NextChar != '=')
                    {
                        ParseError(tokenizer, "= expected following !", joinerLine, joinerColumn);
                    }
                    else
                    {
                        tokenizer.Advance();
                        clause = ParseComparison(tokenizer, clause, ComparisonOperation.NotEqual, joinerLine, joinerColumn);
                    }
                    break;

                case '<':
                    if (priority >= OperationPriority.Compare)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    if (tokenizer.NextChar == '=')
                    {
                        tokenizer.Advance();
                        clause = ParseComparison(tokenizer, clause, ComparisonOperation.LessThanOrEqual, joinerLine, joinerColumn);
                    }
                    else
                    {
                        clause = ParseComparison(tokenizer, clause, ComparisonOperation.LessThan, joinerLine, joinerColumn);
                    }
                    break;

                case '>':
                    if (priority >= OperationPriority.Compare)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    if (tokenizer.NextChar == '=')
                    {
                        tokenizer.Advance();
                        clause = ParseComparison(tokenizer, clause, ComparisonOperation.GreaterThanOrEqual, joinerLine, joinerColumn);
                    }
                    else
                    {
                        clause = ParseComparison(tokenizer, clause, ComparisonOperation.GreaterThan, joinerLine, joinerColumn);
                    }
                    break;

                case '&':
                    if (tokenizer.MatchSubstring("&&") == 2)
                    {
                        if (priority >= OperationPriority.And)
                        {
                            return(clause);
                        }

                        tokenizer.Advance(2);
                        clause = ParseConditional(tokenizer, clause, ConditionalOperation.And, joinerLine, joinerColumn);
                    }
                    else
                    {
                        if (priority >= OperationPriority.BitwiseAnd)
                        {
                            return(clause);
                        }

                        tokenizer.Advance();
                        clause = ParseMathematic(tokenizer, clause, MathematicOperation.BitwiseAnd, joinerLine, joinerColumn);
                    }
                    break;

                case '|':
                    if (priority >= OperationPriority.Or)
                    {
                        return(clause);
                    }

                    tokenizer.Advance();
                    if (tokenizer.NextChar != '|')
                    {
                        ParseError(tokenizer, "| expected following |", joinerLine, joinerColumn);
                    }
                    else
                    {
                        tokenizer.Advance();
                        clause = ParseConditional(tokenizer, clause, ConditionalOperation.Or, joinerLine, joinerColumn);
                    }
                    break;

                default:
                    if (clause.Location.End.Column == 0)
                    {
                        clause.Location = new TextRange(clause.Location.Start, new TextLocation(clauseEndLine, clauseEndColumn));
                    }

                    return(clause);
                }

                if (clause.Type == ExpressionType.ParseError)
                {
                    return(clause);
                }
            } while (true);
        }