From b7c56ce3965a69d176f73f8b893d9d2ea1f35e6a Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sun, 4 Oct 2009 21:11:22 +0200 Subject: [PATCH] support 'and' operator and boolean attribute values in TreePath predicates --- Cython/Compiler/Tests/TestTreePath.py | 7 ++++++ Cython/Compiler/TreePath.py | 35 ++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Cython/Compiler/Tests/TestTreePath.py b/Cython/Compiler/Tests/TestTreePath.py index 1ae0d374..fb70bdc3 100644 --- a/Cython/Compiler/Tests/TestTreePath.py +++ b/Cython/Compiler/Tests/TestTreePath.py @@ -68,6 +68,13 @@ class TestTreePath(TransformTest): self.assertEquals(0, len(find_all(t, "//NameNode[not(@name)]"))) self.assertEquals(2, len(find_all(t, "//NameNode[not(@honking)]"))) + def test_node_path_and(self): + t = self._build_tree() + self.assertEquals(1, len(find_all(t, "//DefNode[.//ReturnStatNode and .//NameNode]"))) + self.assertEquals(0, len(find_all(t, "//NameNode[@honking and @name]"))) + self.assertEquals(0, len(find_all(t, "//NameNode[@name and @honking]"))) + self.assertEquals(2, len(find_all(t, "//DefNode[.//NameNode[@name] and @name]"))) + def test_node_path_attribute_string_predicate(self): t = self._build_tree() self.assertEquals(1, len(find_all(t, "//NameNode[@name = 'decorator']"))) diff --git a/Cython/Compiler/TreePath.py b/Cython/Compiler/TreePath.py index 432c8652..527fa6f0 100644 --- a/Cython/Compiler/TreePath.py +++ b/Cython/Compiler/TreePath.py @@ -167,14 +167,20 @@ def handle_attribute(next, token): def parse_path_value(next): token = next() value = token[0] - if value[:1] == "'" or value[:1] == '"': - value = value[1:-1] - else: + if value: + if value[:1] == "'" or value[:1] == '"': + return value[1:-1] try: - value = int(value) + return int(value) except ValueError: - raise ValueError("Invalid attribute predicate: '%s'" % value) - return value + pass + else: + name = token[1].lower() + if name == 'true': + return True + elif name == 'false': + return False + raise ValueError("Invalid attribute predicate: '%s'" % value) def handle_predicate(next, token): token = next() @@ -189,6 +195,9 @@ def handle_predicate(next, token): if token[0] == "/": token = next() + if not token[0] and token[1] == 'and': + return logical_and(selector, handle_predicate(next, token)) + def select(result): for node in result: subresult = iter((node,)) @@ -199,6 +208,20 @@ def handle_predicate(next, token): yield node return select +def logical_and(lhs_selects, rhs_select): + def select(result): + for node in result: + subresult = iter((node,)) + for select in lhs_selects: + subresult = select(subresult) + predicate_result = _get_first_or_none(subresult) + subresult = iter((node,)) + if predicate_result is not None: + for result_node in rhs_select(subresult): + yield node + return select + + operations = { "@": handle_attribute, "": handle_name, -- 2.26.2