Exemple #1
0
        public static Parser <char, IExpr> CreateExpressionParser()
        {
            Parser <char, IExpr> expr = null;

            var call = Parenthesised(Rec(() => expr).Separated(Tok(",")))
                       .Select <Func <IExpr, IExpr> >(
                args => method => new Call(method, args.ToImmutableArray())
                ).Labelled("function call");

            var term = OneOf(
                Identifier,
                Floating,
                Parenthesised(Rec(() => expr)).Labelled("parenthesised expression")
                );

            expr = ExpressionParser.Build(
                term,
                new[]
            {
                Operator.PostfixChainable(call),
                Operator.InfixL(Powered),
                Operator.Prefix(Neg),
                Operator.InfixL(Div),
                Operator.InfixL(Mul),
                Operator.InfixL(Sub),
                Operator.InfixL(Add)
            }
                ).Labelled("expression");

            return(expr);
        }
Exemple #2
0
        public void TestPrefix()
        {
            Parser <char, bool> parser = null;
            var termParser             =
                String("false").Select(_ => false)
                .Or(String("true").Select(_ => true))
                .Or(Rec(() => parser).Between(Char('('), Char(')')));

            parser = ExpressionParser.Build(
                termParser,
                new[]
            {
                new[]
                {
                    Operator.Prefix(
                        Char('!').Select <Func <bool, bool> >(_ => b => !b)
                        )
                }
            }
                );

            AssertSuccess(parser.Parse("true"), true, true);
            AssertSuccess(parser.Parse("!true"), false, true);
            AssertSuccess(parser.Parse("!(!true)"), true, true);
        }
Exemple #3
0
        private static Parser <char, Expression> BuildExpressionParser()
        {
            Parser <char, Expression> expr = null;

            var term = OneOf(
                Identifier,
                IntegerLiteral,
                Parenthesised(Rec(() => expr)).Labelled("parenthesised expression")
                );

            var call = Parenthesised(Rec(() => expr).Separated(Token(",")))
                       .Select <Func <Expression, Expression> >(args => method => new Call(method, args.ToImmutableArray()))
                       .Labelled("function call");

            expr = ExpressionParser.Build(
                term,
                new[]
            {
                Operator.PostfixChainable(call),
                Operator.Prefix(Negate).And(Operator.Prefix(Complement)),
                Operator.InfixL(Multiply),
                Operator.InfixL(Add)
            }
                ).Labelled("expression");

            return(expr);
        }
Exemple #4
0
        public void Setup()
        {
            _bigExpression = string.Join("+", Enumerable.Range(1, 1000));

            var infixL = Operator.InfixL(Parser.Char('+').Then(Return <Func <int, int, int> >((x, y) => x + y)));

            _leftAssoc = ExpressionParser.Build(
                Parser.Num,
                new[] { new[] { infixL } }
                );
            var infixR = Operator.InfixR(Parser.Char('+').Then(Return <Func <int, int, int> >((x, y) => x + y)));

            _rightAssoc = ExpressionParser.Build(
                Parser.Num,
                new[] { new[] { infixR } }
                );
        }
Exemple #5
0
        public void TestInfixR()
        {
            Parser <char, Expr> parser = null;
            var termParser             = Digit.Select <Expr>(x => new Lit((int)char.GetNumericValue(x)));

            parser = ExpressionParser.Build(
                termParser,
                new[]
            {
                new[]
                {
                    Operator.InfixR(
                        Char('*').Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Times(x, y)))
                        )
                },
                new[]
                {
                    Operator.InfixR(
                        Char('+').Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Plus(x, y)))
                        ),
                    Operator.InfixR(
                        Char('-').Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Minus(x, y)))
                        )
                }
            }
                );

            AssertSuccess(
                parser.Parse("1+2+3+4"),
                new Plus(new Lit(1), new Plus(new Lit(2), new Plus(new Lit(3), new Lit(4)))),
                true
                );
            // yeah it's not mathematically accurate but who cares, it's a test
            AssertSuccess(
                parser.Parse("1+2-3+4"),
                new Plus(new Lit(1), new Minus(new Lit(2), new Plus(new Lit(3), new Lit(4)))),
                true
                );
            AssertSuccess(
                parser.Parse("1*2*3+4*5"),
                new Plus(new Times(new Lit(1), new Times(new Lit(2), new Lit(3))), new Times(new Lit(4), new Lit(5))),
                true
                );
        }
Exemple #6
0
        public void TestPostfix()
        {
            Func <dynamic> f = () => true;

            Parser <char, dynamic> parser = null;
            var termParser = String("f").Select <dynamic>(_ => f);

            parser = ExpressionParser.Build(
                termParser,
                new[]
            {
                new[]
                {
                    Operator.Postfix(String("()").Select <Func <dynamic, dynamic> >(_ => g => g()))
                }
            }
                );

            AssertSuccess(parser.Parse("f"), f, true);
            AssertSuccess(parser.Parse("f()"), f(), true);
        }
Exemple #7
0
        static SyntaxQueryParser()
        {
            var axis = OneOf(
                Try(String("self::").Select(s => SyntaxQueryAxis.Self)),
                Try(OneOf(String("//"), String("descendant::")).Select(s => SyntaxQueryAxis.Descendant)),
                String("/").Select(s => SyntaxQueryAxis.Child),
                Try(String("parent::").Select(s => SyntaxQueryAxis.Parent))
                );
            var target = Letter.Labelled("keyword").AtLeastOnceString().Select(ParseKeyword);

            Parser <char, SyntaxQuery> query = null;
            var literal = AnyCharExcept('\'').ManyString().Between(Char('\''))
                          .Select(value => new SyntaxFilterLiteralExpression(value));
            var expressionLeaf = OneOf(
                Rec(() => query).Cast <ISyntaxFilterExpression>(),
                literal.Cast <ISyntaxFilterExpression>()
                );
            var expression = ExpressionParser.Build(
                expressionLeaf,
                new[] {
                new[] {
                    BinaryOperator("==", SyntaxFilterBinaryOperator.Equals)
                },
                new[] {
                    BinaryOperator("&&", SyntaxFilterBinaryOperator.And)
                },
            }
                );
            var filter = Char('[').Then(expression).Before(Char(']'));

            query = Map(
                (a, t, f) => new SyntaxQuery(a.GetValueOrDefault(SyntaxQueryAxis.Child), t, f.GetValueOrDefault()),
                axis.Optional(),
                target,
                filter.Optional()
                );

            Root = query.Before(End());
        }
Exemple #8
0
        public void TestInfixL()
        {
            Parser <char, Expr> parser = null;
            var termParser             = Digit.Select <Expr>(x => new Lit((int)char.GetNumericValue(x)));

            parser = ExpressionParser.Build(
                termParser,
                new[]
            {
                Operator.InfixL(
                    Char('*').Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Times(x, y)))
                    ),

                Operator.InfixL(
                    Char('+').Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Plus(x, y)))
                    ).And(Operator.InfixL(
                              Char('-').Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Minus(x, y)))
                              ))
            }
                );

            AssertSuccess(
                parser.Parse("1+2+3+4"),
                new Plus(new Plus(new Plus(new Lit(1), new Lit(2)), new Lit(3)), new Lit(4)),
                true
                );
            AssertSuccess(
                parser.Parse("1+2-3+4"),
                new Plus(new Minus(new Plus(new Lit(1), new Lit(2)), new Lit(3)), new Lit(4)),
                true
                );
            AssertSuccess(
                parser.Parse("1*2*3+4*5"),
                new Plus(new Times(new Times(new Lit(1), new Lit(2)), new Lit(3)), new Times(new Lit(4), new Lit(5))),
                true
                );
        }
Exemple #9
0
        private static Tuple <Parser <char, Expr>, Stack <bool>, Stack <bool> > BuildExprParser()
        {
            Parser <char, Expr> exprParser = null;

            var listParser = Rec(() => exprParser).Separated(Comma.Before(SkipWhitespaces));
            var funcHead   = Id.Or(If).Between(SkipWhitespaces).Before(LParen.Between(SkipWhitespaces));
            var funcParser = Try(Lookahead(funcHead)).Then(Map((id, prms) => (Expr) new Function(id, prms), funcHead,
                                                               listParser.Before(RParen))).Labelled("func");
            var termParser = funcParser
                             .Or(Try(Bool.Select <Expr>(x => new BoolLit(x)))
                                 .Or(Num.Select <Expr>(x => new NumLit(x)))
                                 .Or(Str.Select <Expr>(x => new StringLit(x)))
                                 .Or(Chr.Select <Expr>(x => new CharLit(x)))
                                 .Or(Id.Select <Expr>(x => new Identifier(x)))
                                 .Or(Rec(() => listParser)
                                     .Between(LBrace.Then(SkipWhitespaces), SkipWhitespaces.Then(RBrace))
                                     .Select <Expr>(x => new Membership(x)))
                                 .Or(Rec(() => exprParser)
                                     .Between(LParen.Then(SkipWhitespaces), SkipWhitespaces.Then(RParen))
                                     .Select <Expr>(x => new Nested(x)))
                                 ).Labelled("term")
                             .Between(SkipWhitespaces.Or(End()));
            var cTerStack  = new Stack <bool>();
            var pyTerStack = new Stack <bool>();

            exprParser = ExpressionParser.Build(termParser, new[]
            {
                // arithmatic
                new[] {
                    Operator.Prefix(Char('+').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr> >(x => new Positive(x)))),
                    Operator.Prefix(Char('-').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr> >(x => new Negative(x)))),
                },
                new[] {
                    Operator.InfixR(Char('^').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Power(x, y)))),
                },
                new[] {
                    Operator.InfixL(Char('*').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Mult(x, y)))),
                    Operator.InfixL(Char('/').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Div(x, y)))),
                },
                new[] {
                    Operator.InfixL(Char('%').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Mod(x, y)))),
                },
                new[] {
                    Operator.InfixL(Char('+').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Plus(x, y)))),
                    Operator.InfixL(Char('-').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Minus(x, y)))),
                },
                new[] { // VB string cat
                    Operator.InfixL(Try(Lookahead(Not(Char('&').Before(Char('&'))))).Then(Char('&').Between(SkipWhitespaces)).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Cat(x, y)))),
                },
                new[] {
                    Operator.InfixL(Try(Lookahead(String("??"))).Then(String("??").Between(SkipWhitespaces)).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new NullCoalesce(x, y)))),
                },
                // comparision. TODO: check how to separate arithmatic, comparison and logical ops
                new[] {
                    Operator.InfixL(Try(String(">=").Between(SkipWhitespaces)).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Ge(x, y)))),
                    Operator.InfixL(Try(String("<=").Between(SkipWhitespaces)).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Le(x, y)))),
                    Operator.InfixL(Try(String("<>").Between(SkipWhitespaces)).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Ne("<>", x, y)))),
                    Operator.InfixL(String("!=").Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Ne(x, y)))),
                    Operator.InfixL(String(">").Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Gt(x, y)))),
                    Operator.InfixL(String("<").Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Lt(x, y)))),
                    Operator.InfixL(Try(String("==")).Or(String("=")).Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Eq(x, y)))),
                    Operator.InfixL(Try(String("in").Between(SkipWhitespaces).Before(Lookahead(LBrace))).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new In(x, y)))),
                },
                // logical. TODO: check how to separate arithmatic, comparison and logical ops
                new[] {
                    Operator.Prefix(Char('!').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr> >(x => new Not(x)))),
                },
                new[] {
                    Operator.InfixL(String("&&").Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new And(x, y)))),
                },
                new[] {
                    Operator.InfixL(String("||").Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) => new Or(x, y)))),
                },
                new[] {
                    Operator.InfixR(If.Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) =>
                    {
                        if (pyTerStack.Count == 0)
                        {
                            throw new InvalidOperationException("Unbalanced Python-style Ternary Operators, fewer 'else' parts than 'then' parts");
                        }
                        pyTerStack.Pop();
                        return(TerUtils.FormPyTerExpr(x, y));
                    }))),
                    Operator.InfixR(Else.Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) =>
                    {
                        pyTerStack.Push(true);
                        return(new PyTerExprElse(x, y));
                    }))),
                    Operator.InfixR(Try(Lookahead(Not(Char('?').Before(Char('?'))))).Then(Char('?').Between(SkipWhitespaces)).Then(Return <Func <Expr, Expr, Expr> >((x, y) =>
                    {
                        if (cTerStack.Count == 0)
                        {
                            throw new InvalidOperationException("Unbalanced C-style Ternary Operators, fewer 'else' parts than 'then' parts");
                        }
                        cTerStack.Pop();
                        return(TerUtils.FormCTerExpr(x, y));
                    }))),
                    Operator.InfixR(Char(':').Between(SkipWhitespaces).Then(Return <Func <Expr, Expr, Expr> >((x, y) =>
                    {
                        cTerStack.Push(true);
                        return(new CTerElseExpr(x, y));
                    }))),
                },
            });
            return(Tuple.Create(exprParser, cTerStack, pyTerStack));
        }