Author: Amaury Forgeot d'Arc <[email protected]>
Branch:
Changeset: r93615:28aa6e61df25
Date: 2017-12-28 22:49 +0100
http://bitbucket.org/pypy/pypy/changeset/28aa6e61df25/
Log: First stab at parser.tuple2st()
diff --git a/pypy/module/parser/__init__.py b/pypy/module/parser/__init__.py
--- a/pypy/module/parser/__init__.py
+++ b/pypy/module/parser/__init__.py
@@ -24,5 +24,7 @@
'ASTType' : 'pyparser.W_STType',
'compilest' : 'pyparser.compilest',
'compileast' : 'pyparser.compilest',
- 'ParserError' : 'space.new_exception_class("parser.ParserError")',
+ 'tuple2st' : 'pyparser.tuple2st',
+ 'sequence2st' : 'pyparser.tuple2st',
+ 'ParserError' : 'pyparser.get_error(space)',
}
diff --git a/pypy/module/parser/pyparser.py b/pypy/module/parser/pyparser.py
--- a/pypy/module/parser/pyparser.py
+++ b/pypy/module/parser/pyparser.py
@@ -8,6 +8,14 @@
from rpython.rlib.objectmodel import specialize
+class Cache:
+ def __init__(self, space):
+ self.error = space.new_exception_class("parser.ParserError")
+
+def get_error(space):
+ return space.fromcache(Cache).error
+
+
class W_STType(W_Root):
def __init__(self, tree, mode):
self.tree = tree
@@ -114,3 +122,59 @@
@unwrap_spec(w_st=W_STType)
def compilest(space, w_st, __args__):
return space.call_args(space.getattr(w_st, space.newtext("compile")),
__args__)
+
+
+def raise_parser_error(space, w_tuple, message):
+ raise OperationError(get_error(space), space.newtuple(
+ [w_tuple, space.newtext("Illegal component tuple.")]))
+
+
+def get_node_type(space, w_tuple):
+ try:
+ w_type = space.getitem(w_tuple, space.newint(0))
+ return space.int_w(w_type)
+ except OperationError:
+ raise_parser_error(space, w_tuple, "Illegal component tuple.")
+
+class NodeState:
+ def __init__(self):
+ self.lineno = 0
+
+def build_node_tree(space, w_tuple):
+ type = get_node_type(space, w_tuple)
+ node_state = NodeState()
+ if 0 <= type < 256:
+ # The tuple is simple, but it doesn't start with a start symbol.
+ # Raise an exception now and be done with it.
+ raise_parser_error(space, w_tuple,
+ "Illegal syntax-tree; cannot start with terminal
symbol.")
+ node = pyparse.parser.Nonterminal(type, [])
+ build_node_children(space, w_tuple, node, node_state)
+ return node
+
+def build_node_children(space, w_tuple, node, node_state):
+ for w_elem in space.unpackiterable(w_tuple)[1:]:
+ type = get_node_type(space, w_elem)
+ if type < 256: # Terminal node
+ length = space.len_w(w_elem)
+ if length == 2:
+ _, w_obj = space.unpackiterable(w_elem, 2)
+ elif length == 3:
+ _, w_obj, w_lineno = space.unpackiterable(w_elem, 3)
+ else:
+ raise_error(space, "terminal nodes must have 2 or 3 entries")
+ strn = space.text_w(w_obj)
+ child = pyparse.parser.Terminal(type, strn, node_state.lineno, 0)
+ else:
+ child = pyparse.parser.Nonterminal(type, [])
+ node.append_child(child)
+ if type >= 256: # Nonterminal node
+ build_node_children(space, w_elem, child, node_state)
+ elif type == pyparse.pygram.tokens.NEWLINE:
+ node_state.lineno += 1
+
+
+def tuple2st(space, w_sequence):
+ # Convert the tree to the internal form before checking it
+ tree = build_node_tree(space, w_sequence)
+ return W_STType(tree, 'eval')
diff --git a/pypy/module/parser/test/test_parser.py
b/pypy/module/parser/test/test_parser.py
--- a/pypy/module/parser/test/test_parser.py
+++ b/pypy/module/parser/test/test_parser.py
@@ -56,3 +56,18 @@
def test_error(self):
assert repr(self.m.ParserError) == "<class 'parser.ParserError'>"
+
+ def test_roundtrip(self):
+ def roundtrip(f, s):
+ st1 = f(s)
+ t = st1.totuple()
+ st2 = self.m.sequence2st(t)
+ assert t == st2.totuple()
+
+ def check_expr(s):
+ roundtrip(self.m.expr, s)
+ def check_suite(s):
+ roundtrip(self.m.suite, s)
+
+ check_expr("foo(1)")
+ check_suite("def f(): yield 1")
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit