Author: Amaury Forgeot d'Arc <amaur...@gmail.com> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit