예제 #1
0
    def testSubscript(self):
        self.assertQueryMatches("d['foo']",
                                ast.Select(ast.Var("d"), ast.Literal("foo")))

        self.assertQueryMatches(
            "d['foo'] + 10",
            ast.Sum(ast.Select(ast.Var("d"), ast.Literal("foo")),
                    ast.Literal(10)))

        self.assertQueryMatches(
            "obj.props[0]",
            ast.Select(ast.Resolve(ast.Var("obj"), ast.Literal("props")),
                       ast.Literal(0)))

        self.assertQueryMatches(
            "obj.props[0].foo",
            ast.Resolve(
                ast.Select(ast.Resolve(ast.Var("obj"), ast.Literal("props")),
                           ast.Literal(0)), ast.Literal("foo")))

        self.assertQueryMatches(
            "obj.props[10 + 10].foo",
            ast.Resolve(
                ast.Select(ast.Resolve(ast.Var("obj"), ast.Literal("props")),
                           ast.Sum(ast.Literal(10), ast.Literal(10))),
                ast.Literal("foo")))

        self.assertQueryMatches(
            "w['x'][y[5] + 5] * 10",
            ast.Product(
                ast.Select(
                    ast.Select(ast.Var("w"), ast.Literal("x")),
                    ast.Sum(ast.Select(ast.Var("y"), ast.Literal(5)),
                            ast.Literal(5))), ast.Literal(10)))
예제 #2
0
    def testLet(self):
        self.assertEqual(
            solve.solve(
                ast.Let(ast.Bind(ast.Pair(ast.Literal("x"), ast.Literal(5))),
                        ast.Sum(ast.Var("x"), ast.Var("x"))), {}).value, [10])

        # Previous binding should be made available to subsequent bindings.
        self.assertEqual(
            solve.solve(
                ast.Let(
                    ast.Bind(
                        ast.Pair(ast.Literal("x"), ast.Literal(5)),
                        ast.Pair(ast.Literal("y"),
                                 ast.Sum(ast.Var("x"), ast.Literal(5)))),
                    ast.Var("y")), {}).value, [10])
예제 #3
0
    def testMixfix(self):
        self.assertQueryParses("'foo'[0  ]",
                               ast.Select(ast.Literal("foo"), ast.Literal(0)))

        self.assertQueryParses(
            # I refer you to my previous statement about making sense.
            " (5 +5) [ 'foo']",
            ast.Select(ast.Sum(ast.Literal(5), ast.Literal(5)),
                       ast.Literal("foo")))

        self.assertQueryParses(
            "5 + 5['foo' + 10]",
            ast.Sum(
                ast.Literal(5),
                ast.Select(ast.Literal(5),
                           ast.Sum(ast.Literal("foo"), ast.Literal(10)))))
예제 #4
0
 def testPrefix(self):
     self.assertQueryParses(
         "-5 + 5 eq - (10)",
         ast.Equivalence(
             ast.Sum(ast.Product(ast.Literal(-1), ast.Literal(5)),
                     ast.Literal(5)),
             ast.Product(ast.Literal(-1), ast.Literal(10))))
예제 #5
0
    def testParens(self):
        # Base case.
        self.assertQueryMatches(
            "x + y * z",
            ast.Sum(ast.Var("x"), ast.Product(ast.Var("y"), ast.Var("z"))))

        # With parens.
        self.assertQueryMatches(
            "(x + y) * z",
            ast.Product(ast.Sum(ast.Var("x"), ast.Var("y")), ast.Var("z")))

        # Missing rparen.
        self.assertQueryRaises("(x + y")

        # Empty expressions make no sense.
        self.assertQueryRaises("()")
예제 #6
0
    def testInfix(self):
        self.assertQueryMatches("x + y", ast.Sum(ast.Var("x"), ast.Var("y")))

        self.assertQueryMatches(
            "w.x.y.z",
            ast.Resolve(
                ast.Resolve(ast.Resolve(ast.Var("w"), ast.Literal("x")),
                            ast.Literal("y")), ast.Literal("z")))

        # Operator precedence should work correctly.
        self.assertQueryMatches(
            "x + y * z",
            ast.Sum(ast.Var("x"), ast.Product(ast.Var("y"), ast.Var("z"))))

        self.assertQueryMatches(
            "x * y + z",
            ast.Sum(ast.Product(ast.Var("x"), ast.Var("y")), ast.Var("z")))
예제 #7
0
    def testCircumfix(self):
        self.assertQueryParses(
            "[1, 2, 3]",
            ast.Tuple(ast.Literal(1), ast.Literal(2), ast.Literal(3)))

        self.assertQueryParses(
            # Lists and selection are non-ambiguous.
            "10 + ['foo', 'bar'][1]",
            ast.Sum(
                ast.Literal(10),
                ast.Select(ast.Tuple(ast.Literal("foo"), ast.Literal("bar")),
                           ast.Literal(1))))
예제 #8
0
    def testLet(self):
        self.assertQueryMatches(
            "let x = 5, y = 10 x + y",
            ast.Let(
                ast.Bind(ast.Pair(ast.Literal("x"), ast.Literal(5)),
                         ast.Pair(ast.Literal("y"), ast.Literal(10))),
                ast.Sum(ast.Var("x"), ast.Var("y"))))

        self.assertQueryMatches(
            "let( (x = 5 - 3,y=(10+(10)) ) )x + y",
            ast.Let(
                ast.Bind(
                    ast.Pair(ast.Literal("x"),
                             ast.Difference(ast.Literal(5), ast.Literal(3))),
                    ast.Pair(ast.Literal("y"),
                             ast.Sum(ast.Literal(10), ast.Literal(10)))),
                ast.Sum(ast.Var("x"), ast.Var("y"))))

        self.assertQueryRaises("let x = 5) x + 5")
        self.assertQueryRaises("let ((x = 5) x + 5")
        self.assertQueryRaises("let (x = 5)) x + 5")
        self.assertQueryRaises("let (x = 5 x + 5")
        self.assertQueryRaises("let (x = 5)")
예제 #9
0
    def testOperatorPrecedence(self):
        # Prefix operator, like the unary minus sign, should respect operator
        # precedence order.
        self.assertQueryMatches(
            "-x + y",
            ast.Sum(ast.Product(ast.Literal(-1), ast.Var("x")), ast.Var("y")))

        self.assertQueryMatches(
            "not x and y",
            ast.Intersection(ast.Complement(ast.Var("x")), ast.Var("y")))

        self.assertQueryMatches(
            "x / -f(y) or not z(a, b)",
            ast.Union(
                ast.Quotient(
                    ast.Var("x"),
                    ast.Product(ast.Literal(-1),
                                ast.Apply(ast.Var("f"), ast.Var("y")))),
                ast.Complement(
                    ast.Apply(ast.Var("z"), ast.Var("a"), ast.Var("b")))))
예제 #10
0
    def testIfElse(self):
        self.assertQueryMatches(
            "if true then 'foo'",
            ast.IfElse(ast.Literal(True), ast.Literal("foo"),
                       ast.Literal(None)))

        self.assertQueryMatches(
            "if true then 'foo' else 'bar'",
            ast.IfElse(ast.Literal(True), ast.Literal("foo"),
                       ast.Literal("bar")))

        self.assertQueryMatches(
            "if true then 'foo' else if 5 + 5 then 'bar' else 'baz'",
            ast.IfElse(ast.Literal(True), ast.Literal("foo"),
                       ast.Sum(ast.Literal(5), ast.Literal(5)),
                       ast.Literal("bar"), ast.Literal("baz")))

        # Missing then blows up:
        self.assertQueryRaises("if (true) bar")

        # Colon blows up:
        self.assertQueryRaises("if true: bar")
예제 #11
0
 def testParens(self):
     self.assertQueryParses(
         "5 + (5 eq 10)",  # It doesn't have to make sense.
         ast.Sum(ast.Literal(5),
                 ast.Equivalence(ast.Literal(5), ast.Literal(10))))
예제 #12
0
 def testInfix(self):
     self.assertQueryParses(
         "5 + 5 eq 10",
         ast.Equivalence(ast.Sum(ast.Literal(5), ast.Literal(5)),
                         ast.Literal(10)))