diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:15 +0300 |
commit | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch) | |
tree | da2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /contrib/tools/cython/Cython/Compiler/TreePath.py | |
parent | 778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff) | |
download | ydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/cython/Cython/Compiler/TreePath.py')
-rw-r--r-- | contrib/tools/cython/Cython/Compiler/TreePath.py | 550 |
1 files changed, 275 insertions, 275 deletions
diff --git a/contrib/tools/cython/Cython/Compiler/TreePath.py b/contrib/tools/cython/Cython/Compiler/TreePath.py index 8585905557..2ad4545d0b 100644 --- a/contrib/tools/cython/Cython/Compiler/TreePath.py +++ b/contrib/tools/cython/Cython/Compiler/TreePath.py @@ -1,23 +1,23 @@ -""" -A simple XPath-like language for tree traversal. - -This works by creating a filter chain of generator functions. Each -function selects a part of the expression, e.g. a child node, a -specific descendant or a node that holds an attribute. -""" - -from __future__ import absolute_import - -import re -import operator +""" +A simple XPath-like language for tree traversal. + +This works by creating a filter chain of generator functions. Each +function selects a part of the expression, e.g. a child node, a +specific descendant or a node that holds an attribute. +""" + +from __future__ import absolute_import + +import re +import operator import sys - + if sys.version_info[0] >= 3: _unicode = str else: _unicode = unicode -path_tokenizer = re.compile( +path_tokenizer = re.compile( r"(" r"'[^']*'|\"[^\"]*\"|" r"//?|" @@ -26,271 +26,271 @@ path_tokenizer = re.compile( r"[/.*\[\]()@])|" r"([^/\[\]()@=\s]+)|" r"\s+" - ).findall - -def iterchildren(node, attr_name): - # returns an iterable of all child nodes of that name - child = getattr(node, attr_name) - if child is not None: - if type(child) is list: - return child - else: - return [child] - else: - return () - -def _get_first_or_none(it): - try: - try: - _next = it.next - except AttributeError: - return next(it) - else: - return _next() - except StopIteration: - return None - -def type_name(node): - return node.__class__.__name__.split('.')[-1] - -def parse_func(next, token): - name = token[1] - token = next() - if token[0] != '(': - raise ValueError("Expected '(' after function name '%s'" % name) - predicate = handle_predicate(next, token) - return name, predicate - -def handle_func_not(next, token): - """ - not(...) - """ - name, predicate = parse_func(next, token) - - def select(result): - for node in result: - if _get_first_or_none(predicate([node])) is None: - yield node - return select - -def handle_name(next, token): - """ - /NodeName/ - or - func(...) - """ - name = token[1] - if name in functions: - return functions[name](next, token) - def select(result): - for node in result: - for attr_name in node.child_attrs: - for child in iterchildren(node, attr_name): - if type_name(child) == name: - yield child - return select - -def handle_star(next, token): - """ - /*/ - """ - def select(result): - for node in result: - for name in node.child_attrs: - for child in iterchildren(node, name): - yield child - return select - -def handle_dot(next, token): - """ - /./ - """ - def select(result): - return result - return select - -def handle_descendants(next, token): - """ - //... - """ - token = next() - if token[0] == "*": - def iter_recursive(node): - for name in node.child_attrs: - for child in iterchildren(node, name): - yield child - for c in iter_recursive(child): - yield c - elif not token[0]: - node_name = token[1] - def iter_recursive(node): - for name in node.child_attrs: - for child in iterchildren(node, name): - if type_name(child) == node_name: - yield child - for c in iter_recursive(child): - yield c - else: - raise ValueError("Expected node name after '//'") - - def select(result): - for node in result: - for child in iter_recursive(node): - yield child - - return select - - -def handle_attribute(next, token): - token = next() - if token[0]: - raise ValueError("Expected attribute name") - name = token[1] - value = None - try: - token = next() - except StopIteration: - pass - else: - if token[0] == '=': - value = parse_path_value(next) - readattr = operator.attrgetter(name) - if value is None: - def select(result): - for node in result: - try: - attr_value = readattr(node) - except AttributeError: - continue - if attr_value is not None: - yield attr_value - else: - def select(result): - for node in result: - try: - attr_value = readattr(node) - except AttributeError: - continue - if attr_value == value: - yield attr_value + ).findall + +def iterchildren(node, attr_name): + # returns an iterable of all child nodes of that name + child = getattr(node, attr_name) + if child is not None: + if type(child) is list: + return child + else: + return [child] + else: + return () + +def _get_first_or_none(it): + try: + try: + _next = it.next + except AttributeError: + return next(it) + else: + return _next() + except StopIteration: + return None + +def type_name(node): + return node.__class__.__name__.split('.')[-1] + +def parse_func(next, token): + name = token[1] + token = next() + if token[0] != '(': + raise ValueError("Expected '(' after function name '%s'" % name) + predicate = handle_predicate(next, token) + return name, predicate + +def handle_func_not(next, token): + """ + not(...) + """ + name, predicate = parse_func(next, token) + + def select(result): + for node in result: + if _get_first_or_none(predicate([node])) is None: + yield node + return select + +def handle_name(next, token): + """ + /NodeName/ + or + func(...) + """ + name = token[1] + if name in functions: + return functions[name](next, token) + def select(result): + for node in result: + for attr_name in node.child_attrs: + for child in iterchildren(node, attr_name): + if type_name(child) == name: + yield child + return select + +def handle_star(next, token): + """ + /*/ + """ + def select(result): + for node in result: + for name in node.child_attrs: + for child in iterchildren(node, name): + yield child + return select + +def handle_dot(next, token): + """ + /./ + """ + def select(result): + return result + return select + +def handle_descendants(next, token): + """ + //... + """ + token = next() + if token[0] == "*": + def iter_recursive(node): + for name in node.child_attrs: + for child in iterchildren(node, name): + yield child + for c in iter_recursive(child): + yield c + elif not token[0]: + node_name = token[1] + def iter_recursive(node): + for name in node.child_attrs: + for child in iterchildren(node, name): + if type_name(child) == node_name: + yield child + for c in iter_recursive(child): + yield c + else: + raise ValueError("Expected node name after '//'") + + def select(result): + for node in result: + for child in iter_recursive(node): + yield child + + return select + + +def handle_attribute(next, token): + token = next() + if token[0]: + raise ValueError("Expected attribute name") + name = token[1] + value = None + try: + token = next() + except StopIteration: + pass + else: + if token[0] == '=': + value = parse_path_value(next) + readattr = operator.attrgetter(name) + if value is None: + def select(result): + for node in result: + try: + attr_value = readattr(node) + except AttributeError: + continue + if attr_value is not None: + yield attr_value + else: + def select(result): + for node in result: + try: + attr_value = readattr(node) + except AttributeError: + continue + if attr_value == value: + yield attr_value elif (isinstance(attr_value, bytes) and isinstance(value, _unicode) and attr_value == value.encode()): # allow a bytes-to-string comparison too yield attr_value - return select - - -def parse_path_value(next): - token = next() - value = token[0] - if value: - if value[:1] == "'" or value[:1] == '"': - return value[1:-1] - try: - return int(value) - except ValueError: - pass + return select + + +def parse_path_value(next): + token = next() + value = token[0] + if value: + if value[:1] == "'" or value[:1] == '"': + return value[1:-1] + try: + return int(value) + except ValueError: + pass elif token[1].isdigit(): return int(token[1]) - 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() - selector = [] - while token[0] != ']': - selector.append( operations[token[0]](next, token) ) - try: - token = next() - except StopIteration: - break - else: - 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,)) - for select in selector: - subresult = select(subresult) - predicate_result = _get_first_or_none(subresult) - if predicate_result is not None: - 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, - "*": handle_star, - ".": handle_dot, - "//": handle_descendants, - "[": handle_predicate, - } - -functions = { - 'not' : handle_func_not - } - -def _build_path_iterator(path): - # parse pattern - stream = iter([ (special,text) - for (special,text) in path_tokenizer(path) - if special or text ]) - try: - _next = stream.next - except AttributeError: - # Python 3 - def _next(): - return next(stream) - token = _next() - selector = [] - while 1: - try: - selector.append(operations[token[0]](_next, token)) - except StopIteration: - raise ValueError("invalid path") - try: - token = _next() - if token[0] == "/": - token = _next() - except StopIteration: - break - return selector - -# main module API - -def iterfind(node, path): - selector_chain = _build_path_iterator(path) - result = iter((node,)) - for select in selector_chain: - result = select(result) - return result - -def find_first(node, path): - return _get_first_or_none(iterfind(node, path)) - -def find_all(node, path): - return list(iterfind(node, path)) + 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() + selector = [] + while token[0] != ']': + selector.append( operations[token[0]](next, token) ) + try: + token = next() + except StopIteration: + break + else: + 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,)) + for select in selector: + subresult = select(subresult) + predicate_result = _get_first_or_none(subresult) + if predicate_result is not None: + 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, + "*": handle_star, + ".": handle_dot, + "//": handle_descendants, + "[": handle_predicate, + } + +functions = { + 'not' : handle_func_not + } + +def _build_path_iterator(path): + # parse pattern + stream = iter([ (special,text) + for (special,text) in path_tokenizer(path) + if special or text ]) + try: + _next = stream.next + except AttributeError: + # Python 3 + def _next(): + return next(stream) + token = _next() + selector = [] + while 1: + try: + selector.append(operations[token[0]](_next, token)) + except StopIteration: + raise ValueError("invalid path") + try: + token = _next() + if token[0] == "/": + token = _next() + except StopIteration: + break + return selector + +# main module API + +def iterfind(node, path): + selector_chain = _build_path_iterator(path) + result = iter((node,)) + for select in selector_chain: + result = select(result) + return result + +def find_first(node, path): + return _get_first_or_none(iterfind(node, path)) + +def find_all(node, path): + return list(iterfind(node, path)) |