Exemple #1
0
        static int GetNextBinaryPrecedence(this StringSegment literal)
        {
            if (!literal.IsNullOrEmpty() && !literal.GetChar(0).IsExpressionTerminatorChar())
            {
                literal.ParseJsBinaryOperator(out var binaryOp);
                if (binaryOp != null)
                {
                    return(JsTokenUtils.GetBinaryPrecedence(binaryOp.Token));
                }
            }

            return(0);
        }
        static int GetNextBinaryPrecedence(this ReadOnlySpan <char> literal)
        {
            if (!literal.IsNullOrEmpty() && !literal[0].IsExpressionTerminatorChar())
            {
                literal.ParseJsBinaryOperator(out var binaryOp);
                if (binaryOp != null)
                {
                    return(JsTokenUtils.GetBinaryPrecedence(binaryOp.Token));
                }
            }

            return(0);
        }
        static int GetNextBinaryPrecedence(this StringSegment literal)
        {
            if (!literal.IsNullOrEmpty())
            {
                var c = literal.GetChar(0);
                if (!JsTokenUtils.ExpressionTerminator.Contains(c))
                {
                    literal.ParseJsToken(out var token);

                    if (token is JsBinaryOperator binaryOp)
                    {
                        return(JsTokenUtils.GetBinaryPrecedence(binaryOp.Token));
                    }
                }
            }

            return(0);
        }
Exemple #4
0
        public static StringSegment ParseBinaryExpression(this StringSegment literal, out JsExpression expr, bool filterExpression)
        {
            literal = literal.AdvancePastWhitespace();

            literal = literal.ParseJsToken(out var lhs, filterExpression: filterExpression);

            if (literal.IsNullOrEmpty())
            {
                expr = lhs is JsExpression jsExpr
                    ? jsExpr
                    : throw new SyntaxErrorException($"Expected Expression but was {lhs.DebugToken()}");
            }
            else
            {
                literal = literal.ParseJsBinaryOperator(out var op);

                if (op == null)
                {
                    throw new SyntaxErrorException($"Expected binary operator near: {literal.DebugLiteral()}");
                }

                var prec = JsTokenUtils.GetBinaryPrecedence(op.Token);
                if (prec > 0)
                {
                    literal = literal.ParseJsToken(out JsToken rhs, filterExpression: filterExpression);

                    var stack = new Stack <JsToken>();
                    stack.Push(lhs);
                    stack.Push(op);
                    stack.Push(rhs);

                    var precedences = new List <int> {
                        prec
                    };

                    while (true)
                    {
                        literal = literal.AdvancePastWhitespace();
                        if (filterExpression && literal.Length > 2 && (literal.GetChar(0) == '|' && literal.GetChar(1) != '|'))
                        {
                            break;
                        }

                        prec = literal.GetNextBinaryPrecedence();
                        if (prec == 0)
                        {
                            break;
                        }

                        while ((stack.Count > 2) && prec <= precedences[precedences.Count - 1])
                        {
                            rhs = stack.Pop();
                            var operand = (JsBinaryOperator)stack.Pop();
                            precedences.RemoveAt(precedences.Count - 1);
                            lhs = stack.Pop();
                            stack.Push(CreateJsExpression(lhs, operand, rhs));
                        }

                        literal = literal.ParseJsBinaryOperator(out op);

                        if (literal.IsNullOrEmpty())
                        {
                            throw new SyntaxErrorException($"Expected expression near: '{literal.DebugLiteral()}'");
                        }

                        literal = literal.ParseJsToken(out var token, filterExpression: filterExpression);

                        stack.Push(op);
                        stack.Push(token);
                        precedences.Add(prec);
                    }

                    var i   = stack.Count - 1;
                    var ret = stack.Pop();

                    while (stack.Count > 0)
                    {
                        op  = (JsBinaryOperator)stack.Pop();
                        lhs = stack.Pop();
                        ret = CreateJsExpression(lhs, op, ret);
                    }

                    expr = (JsExpression)ret;
                }
                else
                {
                    expr = lhs is JsExpression jsExpr
                        ? jsExpr
                        : throw new SyntaxErrorException($"Expected Expression but was {lhs.DebugToken()}");
                }
            }

            return(literal);
        }
        public static StringSegment ParseBinaryExpression(this StringSegment literal, out JsExpression expr, bool filterExpression)
        {
            literal = literal.AdvancePastWhitespace();

            literal = literal.ParseJsToken(out JsToken lhs, filterExpression: filterExpression);

            JsExpression CreateSingleExpression(JsToken left)
            {
                if (left is JsExpression jsExpr)
                {
                    return(jsExpr);
                }

                throw new ArgumentException($"Invalid Syntax: Expected Expression but was '{left}'");
            }

            if (literal.IsNullOrEmpty())
            {
                expr = CreateSingleExpression(lhs);
            }
            else
            {
                literal = literal.ParseJsToken(out JsToken token, filterExpression: filterExpression);

                if (token is JsAssignment)
                {
                    token = JsEquals.Operator;
                }

                if (!(token is JsBinaryOperator op))
                {
                    throw new ArgumentException(
                              $"Invalid syntax: Expected binary operand but instead found '{token}' near: {literal.SubstringWithElipsis(0, 50)}");
                }

                var prec = JsTokenUtils.GetBinaryPrecedence(op.Token);

                if (prec > 0)
                {
                    literal = literal.ParseJsToken(out JsToken rhs, filterExpression: filterExpression);

                    var stack = new Stack <JsToken>();
                    stack.Push(lhs);
                    stack.Push(op);
                    stack.Push(rhs);

                    var precedences = new List <int> {
                        prec
                    };

                    while (true)
                    {
                        literal = literal.AdvancePastWhitespace();
                        if (filterExpression && literal.Length > 2 && (literal.GetChar(0) == '|' && literal.GetChar(1) != '|'))
                        {
                            break;
                        }

                        prec = literal.GetNextBinaryPrecedence();
                        if (prec == 0)
                        {
                            break;
                        }

                        while ((stack.Count > 2) && prec <= precedences[precedences.Count - 1])
                        {
                            rhs = stack.Pop();
                            var operand = (JsBinaryOperator)stack.Pop();
                            precedences.RemoveAt(precedences.Count - 1);
                            lhs = stack.Pop();
                            stack.Push(CreateJsExpression(lhs, operand, rhs));
                        }

                        literal = literal.ParseJsToken(out var opToken, filterExpression: filterExpression);

                        if (literal.IsNullOrEmpty())
                        {
                            throw new ArgumentException($"Invalid syntax: Expected expression after '{token}'");
                        }

                        literal = literal.ParseJsToken(out token, filterExpression: filterExpression);

                        stack.Push(opToken);
                        stack.Push(token);
                        precedences.Add(prec);
                    }

                    var i   = stack.Count - 1;
                    var ret = stack.Pop();

                    while (stack.Count > 0)
                    {
                        op  = (JsBinaryOperator)stack.Pop();
                        lhs = stack.Pop();
                        ret = CreateJsExpression(lhs, op, ret);
                    }

                    expr = (JsExpression)ret;
                }
                else
                {
                    expr = CreateSingleExpression(lhs);
                }
            }

            return(literal);
        }