Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(405)

Unified Diff: third_party/cython/src/Cython/Compiler/TreePath.py

Issue 385073004: Adding cython v0.20.2 in third-party. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Reference cython dev list thread. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/cython/src/Cython/Compiler/TreePath.py
diff --git a/third_party/cython/src/Cython/Compiler/TreePath.py b/third_party/cython/src/Cython/Compiler/TreePath.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee996e821bb0a3fbe2568ab730ef89b4ba349058
--- /dev/null
+++ b/third_party/cython/src/Cython/Compiler/TreePath.py
@@ -0,0 +1,288 @@
+"""
+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.
+"""
+
+import re
+import sys
+
+path_tokenizer = re.compile(
+ "("
+ "'[^']*'|\"[^\"]*\"|"
+ "//?|"
+ "\(\)|"
+ "==?|"
+ "[/.*\[\]\(\)@])|"
+ "([^/\[\]\(\)@=\s]+)|"
+ "\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)
+ if sys.version_info >= (2,6) or (sys.version_info >= (2,4) and '.' not in name):
+ import operator
+ readattr = operator.attrgetter(name)
+ else:
+ name_path = name.split('.')
+ def readattr(node):
+ attr_value = node
+ for attr in name_path:
+ attr_value = getattr(attr_value, attr)
+ return attr_value
+ 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
+ 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
+ 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))
« no previous file with comments | « third_party/cython/src/Cython/Compiler/TreeFragment.py ('k') | third_party/cython/src/Cython/Compiler/TypeInference.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698