示例#1
0
        internal static StringSegment ParseArguments(this StringSegment literal, out List <JsToken> arguments, char termination)
        {
            arguments = new List <JsToken>();

            while (!literal.IsNullOrEmpty())
            {
                JsToken listValue;

                literal = literal.AdvancePastWhitespace();
                if (literal.GetChar(0) == termination)
                {
                    literal = literal.Advance(1);
                    break;
                }

                if (literal.StartsWith("..."))
                {
                    literal = literal.Advance(3);
                    literal = literal.ParseJsExpression(out listValue);
                    if (!(listValue is JsIdentifier) && !(listValue is JsArrayExpression))
                    {
                        throw new SyntaxErrorException($"Spread operator expected array but instead found {listValue.DebugToken()}");
                    }

                    listValue = new JsSpreadElement(listValue);
                }
                else
                {
                    literal = literal.ParseJsExpression(out listValue);
                }

                arguments.Add(listValue);

                literal = literal.AdvancePastWhitespace();
                if (literal.IsNullOrEmpty())
                {
                    break;
                }

                if (literal.GetChar(0) == termination)
                {
                    literal = literal.Advance(1);
                    break;
                }

                literal = literal.AdvancePastWhitespace();
                var c = literal.SafeGetChar(0);
                if (c.IsEnd() || c == termination)
                {
                    literal = literal.Advance(1);
                    break;
                }

                if (c != ',')
                {
                    throw new SyntaxErrorException($"Unterminated arguments expression near: {literal.DebugLiteral()}");
                }

                literal = literal.Advance(1);
                literal = literal.AdvancePastWhitespace();
            }

            literal = literal.AdvancePastWhitespace();

            return(literal);
        }
示例#2
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);
        }
示例#3
0
        internal static StringSegment ParseWhitespaceArgument(this StringSegment literal, out JsToken argument)
        {
            // replace everything after ':' up till new line and rewrite as single string to method
            var endStringPos    = literal.IndexOf("\n");
            var endStatementPos = literal.IndexOf("}}");

            if (endStringPos == -1 || (endStatementPos != -1 && endStatementPos < endStringPos))
            {
                endStringPos = endStatementPos;
            }

            if (endStringPos == -1)
            {
                throw new SyntaxErrorException($"Whitespace sensitive syntax did not find a '\\n' new line to mark the end of the statement, near {literal.DebugLiteral()}");
            }

            var originalArg   = literal.Subsegment(0, endStringPos).Trim().ToString();
            var rewrittenArgs = originalArg.Replace("{", "{{").Replace("}", "}}");
            var strArg        = new JsLiteral(rewrittenArgs);

            argument = strArg;
            return(literal.Subsegment(endStringPos));
        }