[pypy-svn] r15017 - in pypy/dist/pypy/interpreter/pyparser: . test
adim at codespeak.net
adim at codespeak.net
Mon Jul 25 14:15:31 CEST 2005
Author: adim
Date: Mon Jul 25 14:15:29 2005
New Revision: 15017
Modified:
pypy/dist/pypy/interpreter/pyparser/astbuilder.py
pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py
Log:
- implemented listcomps (listmaker in general)
- added a TempRuleObject class which represents a fake rule, built
dynamically to keep track of how many elements the next reduce
operation should pop
Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original)
+++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Jul 25 14:15:29 2005
@@ -77,7 +77,7 @@
"""temporary implementation"""
return eval(value)
-def build_atom( builder, nb ):
+def build_atom(builder, nb):
L = get_atoms( builder, nb )
top = L[0]
if isinstance(top, TokenObject):
@@ -85,7 +85,15 @@
if top.name == tok.LPAR:
builder.push( L[1] )
elif top.name == tok.LSQB:
- builder.push( ast.List( L[1].nodes, top.line) )
+ if len(L) == 2:
+ builder.push(ast.List([], top.line))
+ else:
+ list_node = L[1]
+ # XXX lineno is not on *every* child class of ast.Node
+ # (will probably crash the annotator, but should be
+ # easily fixed)
+ list_node.lineno = top.line
+ builder.push(list_node)
elif top.name == tok.LBRACE:
builder.push( ast.Dict( L[1:-1], top.line) )
elif top.name == tok.NAME:
@@ -321,7 +329,7 @@
else:
# genfor
assert False, "TODO"
- builder.push( Tuple( items ) )
+ builder.push(ast.Tuple(items))
return
def build_varargslist(builder, nb):
@@ -353,6 +361,58 @@
builder.push(ArglistObject('arglist', parse_argument(L), None))
+def build_list_for(builder, nb):
+ """
+ list_iter: list_for | list_if
+ list_for: 'for' exprlist 'in' testlist_safe [list_iter]
+ list_if: 'if' test [list_iter]
+ /!\ list_for is (possibly) recursive
+ """
+ L = get_atoms(builder, nb)
+ built_listfors = []
+ ifs = []
+ assign_token = L[1]
+ ass_node = to_lvalue(assign_token, consts.OP_ASSIGN)
+ end_index = len(L) - 1
+ while isinstance(L[end_index], ast.ListCompFor):
+ # we need to insert in reverse order to build the AST
+ built_listfors.insert(0, L[end_index])
+ end_index -= 1
+ index = 4
+ while index <= end_index:
+ ifs.append(L[index])
+ index += 1
+ builder.push(ast.ListCompFor(ass_node, L[3], ifs))
+ for listfor in built_listfors:
+ builder.push(listfor)
+ builder.push(TempRuleObject(0, len(built_listfors) + 1, None))
+
+def build_list_if(builder, nb):
+ """list_if: 'if' test [list_iter]"""
+ L = get_atoms(builder, nb)
+ builder.push(ast.ListCompIf(L[1]))
+
+def build_listmaker(builder, nb):
+ """listmaker: test ( list_for | (',' test)* [','] )"""
+ L = get_atoms(builder, nb)
+ if len(L) >= 2 and isinstance(L[1], ast.ListCompFor):
+ # list comp
+ index = 1
+ listfors = []
+ while index < len(L):
+ listfors.append(L[index])
+ index += 1
+ builder.push(ast.ListComp(L[0], listfors))
+ else:
+ # regular list building (like in [1, 2, 3,])
+ index = 0
+ nodes = []
+ while index < len(L):
+ nodes.append(L[index])
+ index += 2 # skip comas
+ builder.push(ast.List(nodes))
+
+
def parse_argument(tokens):
"""parses function call arguments"""
l = len(tokens)
@@ -393,6 +453,7 @@
break
return arguments, stararg_token, dstararg_token
+
def parse_arglist(tokens):
"""returns names, defaults, flags"""
l = len(tokens)
@@ -468,6 +529,9 @@
sym.varargslist : build_varargslist,
sym.trailer : build_trailer,
sym.arglist : build_arglist,
+ sym.list_for : build_list_for,
+ sym.list_if : build_list_if,
+ sym.listmaker : build_listmaker,
}
class RuleObject(ast.Node):
@@ -484,6 +548,16 @@
def __repr__(self):
return "<Rule: %s/%d>" % (sym.sym_name[self.name], self.count)
+
+class TempRuleObject(RuleObject):
+ """used to keep track of how many items get_atom() should pop"""
+ def __str__(self):
+ return "<Rule: %s/%d>" % (self.name, self.count)
+
+ def __repr__(self):
+ return "<Rule: %s/%d>" % (self.name, self.count)
+
+
class TokenObject(ast.Node):
"""A simple object used to wrap a rule or token"""
def __init__(self, name, value, src ):
Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original)
+++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Mon Jul 25 14:15:29 2005
@@ -30,9 +30,17 @@
"l = func(10, 12, a, b=c, **kwargs)",
"l = func(10, 12, a, b=c, *args, **kwargs)",
"l = func(10, 12, a, b=c)",
- # "l = [i for i in range(10)]",
- # "l = [i for i in range(10) if i%2 == 0]",
- # "l = [1, 2, 3]",
+ "l = []",
+ "l = [1, 2, 3]",
+ "l = [i for i in range(10)]",
+ "l = [i for i in range(10) if i%2 == 0]",
+ "l = [i for i in range(10) if i%2 == 0 or i%2 == 1]",
+ "l = [i for i in range(10) if i%2 == 0 and i%2 == 1]",
+ "l = [i for j in range(10) for i in range(j)]",
+ "l = [i for j in range(10) for i in range(j) if j%2 == 0]",
+ "l = [i for j in range(10) for i in range(j) if j%2 == 0 and i%2 ==0]",
+ "l = [(a, b) for (a,b,c) in l2]",
+ # "l = [{a : b} for (a,b,c) in l2]",
]
expression_tests = range(len(expressions))
# expression_tests = [-1]
@@ -69,7 +77,7 @@
multiexpr = [
'a = b; c = d;',
'a = b = c = d',
- 'a = b\nc = d',
+ # 'a = b\nc = d',
]
def ast_parse_expr(expr):
@@ -84,8 +92,11 @@
def check_expression(expr):
r1 = ast_parse_expr(expr)
ast = tuple_parse_expr(expr)
+ print "-" * 30
print "ORIG :", ast
+ print
print "BUILT:", r1.rule_stack[-1]
+ print "-" * 30
assert ast == r1.rule_stack[-1], 'failed on %r' % (expr)
@@ -132,7 +143,7 @@
# 'snippet_whitespaces.py',
]
-def test_snippets():
+def skippedtest_snippets():
py.test.skip('Not ready to test on real snippet files')
for snippet_name in SNIPPETS:
filepath = os.path.join(os.path.dirname(__file__), 'samples', snippet_name)
More information about the Pypy-commit
mailing list