[pypy-svn] r45067 - in pypy/dist/pypy/interpreter/pyparser: . data test
justas at codespeak.net
justas at codespeak.net
Sat Jul 14 12:51:04 CEST 2007
Author: justas
Date: Sat Jul 14 12:51:04 2007
New Revision: 45067
Modified:
pypy/dist/pypy/interpreter/pyparser/astbuilder.py
pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a
pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder_future.py
Log:
(Arlo, Justas)
The future_import_builder supports with statements.
The AstBuilder supports rules which doesn't consume attoms:
if the builder function returns True it assumes that the rule
didn't consume any atoms and leaves the stack unmodified.
Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original)
+++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Sat Jul 14 12:51:04 2007
@@ -765,6 +765,7 @@
else_ = atoms[6]
builder.push(ast.While(test, body, else_, atoms[0].lineno))
+
def build_with_stmt(builder, nb):
"""with_stmt: 'with' test [ NAME expr ] ':' suite"""
@@ -783,6 +784,7 @@
body = atoms[5]
builder.push(ast.With(test, body, var, atoms[0].lineno))
+
def build_import_name(builder, nb):
"""import_name: 'import' dotted_as_names
@@ -837,6 +839,7 @@
import_as_name: NAME [NAME NAME]
"""
atoms = get_atoms(builder, nb)
+
index = 1
incr, from_name = parse_dotted_names(atoms[index:], builder)
index += (incr + 1) # skip 'import'
@@ -887,20 +890,33 @@
Enables python language future imports. Called once per feature imported,
no matter how you got to this one particular feature.
"""
+
atoms = peek_atoms(builder, nb)
+
feature_name = atoms[0].get_value()
assert type(feature_name) is str
space = builder.space
- w_feature_code = space.appexec([space.wrap(feature_name)],
+ feature_code = space.unwrap(space.appexec([space.wrap(feature_name)],
"""(feature):
import __future__ as f
feature = getattr(f, feature, None)
return feature and feature.compiler_flag or 0
- """)
+ """))
# We will call a method on the parser (the method exists only in unit
# tests).
- builder.parser.add_production(space.unwrap(w_feature_code))
+ if feature_code == consts.CO_FUTURE_WITH_STATEMENT:
+ rules = """
+ compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt |
+ funcdef | classdef | with_stmt)
+ with_stmt: 'with' test [ 'as' expr ] ':' suite
+ """
+ builder.insert_grammar_rule(rules, {
+ 'with_stmt': build_with_stmt})
+
+ # We need to keep the rule on the stack so we can share atoms
+ # with a later rule
+ return True
def build_yield_stmt(builder, nb):
@@ -1074,7 +1090,6 @@
'exprlist' : build_exprlist,
'decorator' : build_decorator,
'eval_input' : build_eval_input,
- 'with_stmt' : build_with_stmt,
}
@@ -1143,9 +1158,7 @@
self.push(astnode)
else:
builder_func = self.build_rules.get(rulename, None)
- if builder_func:
- builder_func(self, 1)
- else:
+ if not builder_func or builder_func(self, 1):
self.push_rule(rule.codename, 1, source)
else:
self.push_rule(rule.codename, 1, source)
@@ -1165,9 +1178,7 @@
self.push(astnode)
else:
builder_func = self.build_rules.get(rulename, None)
- if builder_func:
- builder_func(self, elts_number)
- else:
+ if not builder_func or builder_func(self, elts_number):
self.push_rule(rule.codename, elts_number, source)
else:
self.push_rule(rule.codename, elts_number, source)
@@ -1218,6 +1229,13 @@
else:
return None
+ def insert_grammar_rule(self, rule, buildfuncs):
+ """Inserts new grammar rules for the builder
+ This allows to change the rules during the parsing
+ """
+ self.parser.insert_rule(rule)
+ self.build_rules.update(buildfuncs)
+
def show_stack(before, after):
"""debugging helper function"""
Modified: pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a (original)
+++ pypy/dist/pypy/interpreter/pyparser/data/Grammar2.5a Sat Jul 14 12:51:04 2007
@@ -69,15 +69,12 @@
exec_stmt: 'exec' expr ['in' test [',' test]]
assert_stmt: 'assert' test [',' test]
-# TODO: with_stmt should be added dynamically to compund_stmt if
-# imported from __future__
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break
['else' ':' suite] | 'try' ':' suite 'finally' ':' suite)
-with_stmt: 'with' test [ 'as' expr ] ':' suite
# NB compile.c makes sure that the default except clause is last
except_clause: 'except' [test [',' test]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder_future.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder_future.py (original)
+++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder_future.py Sat Jul 14 12:51:04 2007
@@ -28,9 +28,10 @@
return val
return self.tokens[ tok ]
- def add_production(self, rule):
+ def insert_rule(self, rule):
self.trace.append(rule)
+
class RuleStub:
def __init__(self, name, root=False):
self.codename = name
@@ -49,6 +50,11 @@
feature_name = posargs_w[0]
return self.feature_code_lookup.get(feature_name, 0)
+def assert_stripped_lines(text1, text2):
+ lines1 = [line.strip() for line in text1.strip().split('\n')]
+ lines2 = [line.strip() for line in text2.strip().split('\n')]
+ assert lines1 == lines2
+
class TestBuilderFuture:
def setup_class(self):
@@ -71,8 +77,24 @@
for val in token_values:
self.builder.push(TokenForTest(val, self.parser))
- astbuilder.build_future_import_feature(self.builder, len(token_values))
+ assert 'with_stmt' not in self.builder.build_rules
+
+ result = astbuilder.build_future_import_feature(
+ self.builder, len(token_values))
+ assert result
+
assert ([rule.value for rule in self.builder.rule_stack] ==
token_values)
- assert self.parser.trace == [32768]
+ assert_stripped_lines(self.parser.trace[0],
+ """
+ compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt |
+ funcdef | classdef | with_stmt)
+ with_stmt: 'with' test [ 'as' expr ] ':' suite
+ """)
+ assert len(self.parser.trace) == 1
+
+ assert (self.builder.build_rules['with_stmt'] ==
+ astbuilder.build_with_stmt)
+
+
More information about the Pypy-commit
mailing list