[Python-checkins] r52901 - sandbox/trunk/2to3/fix_has_key.py sandbox/trunk/2to3/pytree.py
guido.van.rossum
python-checkins at python.org
Sat Dec 2 03:43:48 CET 2006
Author: guido.van.rossum
Date: Sat Dec 2 03:43:47 2006
New Revision: 52901
Modified:
sandbox/trunk/2to3/fix_has_key.py
sandbox/trunk/2to3/pytree.py
Log:
Add a wildcard pattern matcher. Lightly tested.
Modified: sandbox/trunk/2to3/fix_has_key.py
==============================================================================
--- sandbox/trunk/2to3/fix_has_key.py (original)
+++ sandbox/trunk/2to3/fix_has_key.py Sat Dec 2 03:43:47 2006
@@ -59,7 +59,7 @@
pytree.LeafPattern(token.NAME, "has_key")))
p_trailer_args = pytree.NodePattern(syms.trailer,
(pytree.LeafPattern(token.LPAR),
- pytree.NodePattern(name="args"),
+ pytree.WildcardPattern(name="args"),
pytree.LeafPattern(token.RPAR)))
@@ -82,7 +82,10 @@
results = {}
if not p_trailer_args.match(next, results):
return
- argsnode = results["args"]
+ argsnodes = results["args"]
+ if len(argsnodes) != 1:
+ return
+ argsnode = argsnodes[0]
arg = argsnode
if argsnode.type == syms.arglist:
args = argsnode.children
Modified: sandbox/trunk/2to3/pytree.py
==============================================================================
--- sandbox/trunk/2to3/pytree.py (original)
+++ sandbox/trunk/2to3/pytree.py Sat Dec 2 03:43:47 2006
@@ -6,11 +6,13 @@
This is a very concrete parse tree; we need to keep every token and
even the comments and whitespace between tokens.
-There's also a matching pattern implementation here.
+There's also a pattern matching implementation here.
"""
__author__ = "Guido van Rossum <guido at python.org>"
+import sys
+
class Base(object):
@@ -261,6 +263,8 @@
class NodePattern(BasePattern):
+ wildcards = False
+
def __init__(self, type=None, content=None, name=None):
"""Constructor. Takes optional type, content, and name.
@@ -281,6 +285,8 @@
content = tuple(content)
for i, item in enumerate(content):
assert isinstance(item, BasePattern), (i, item)
+ if isinstance(item, WildcardPattern):
+ self.wildcards = True
self.type = type
self.content = content
self.name = name
@@ -297,6 +303,8 @@
When returning False, the results dict may still be updated.
"""
+ if self.wildcards:
+ return _wcmatch(self.content, node.children, results)
if len(self.content) != len(node.children):
return False
for subpattern, child in zip(self.content, node.children):
@@ -305,6 +313,38 @@
return True
+def _wcmatch(patterns, nodes, results):
+ if not patterns:
+ if nodes:
+ return False
+ return True
+ pat = patterns[0]
+ if isinstance(pat, WildcardPattern):
+ for i in xrange(pat.min):
+ if i >= len(nodes) or not pat.match(nodes[i], None):
+ return False
+ for i in xrange(pat.min, pat.max):
+ # Shortest match wins
+ r = {}
+ if _wcmatch(patterns[1:], nodes[i:], r):
+ if pat.name:
+ r[pat.name] = nodes[:i]
+ if results is not None:
+ results.update(r)
+ return True
+ return False
+ else:
+ if not nodes:
+ return False
+ r = {}
+ if pat.match(nodes[0], r):
+ if _wcmatch(patterns[1:], nodes[1:], r):
+ if results is not None:
+ results.update(r)
+ return True
+ return False
+
+
class LeafPattern(BasePattern):
def __init__(self, type, content=None, name=None):
@@ -337,3 +377,18 @@
When returning False, the results dict may still be updated.
"""
return self.content == node.value
+
+
+class WildcardPattern(NodePattern):
+
+ """A wildcard pattern can match zero or more nodes.
+
+ The matching must be done by special-casing in NodePattern._submatch().
+ """
+
+ def __init__(self, type=None, content=None, name=None,
+ min=0, max=sys.maxint):
+ """Constructor."""
+ NodePattern.__init__(self, type=type, content=content, name=name)
+ self.min = min
+ self.max = max
More information about the Python-checkins
mailing list