[pypy-svn] r15908 - in pypy/dist/pypy/interpreter/pyparser: . test test/samples
adim at codespeak.net
adim at codespeak.net
Wed Aug 10 14:03:10 CEST 2005
Author: adim
Date: Wed Aug 10 14:03:05 2005
New Revision: 15908
Added:
pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_docstring.py
Modified:
pypy/dist/pypy/interpreter/pyparser/astbuilder.py
pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py
Log:
- implemented subscript (indexation and slices)
- fetch docstring
- added lvalue support for attraccess and subscripts
Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original)
+++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Wed Aug 10 14:03:05 2005
@@ -20,6 +20,13 @@
for node in ast_node.getChildren():
nodes.append(ast.AssName(node.name, consts.OP_ASSIGN))
return ast.AssTuple(nodes)
+ elif isinstance(ast_node, ast.Getattr):
+ expr = ast_node.expr
+ attrname = ast_node.attrname
+ return ast.AssAttr(expr, attrname, OP)
+ elif isinstance(ast_node, ast.Subscript):
+ ast_node.flags = OP
+ return ast_node
else:
assert False, "TODO"
@@ -119,8 +126,21 @@
if len(L) == 1:
builder.push( L[0] )
elif len(L) == 2:
- arguments, stararg, dstararg = L[1].value
- builder.push(ast.CallFunc(L[0], arguments, stararg, dstararg))
+ if isinstance(L[1], ArglistObject):
+ arguments, stararg, dstararg = L[1].value
+ builder.push(ast.CallFunc(L[0], arguments, stararg, dstararg))
+ elif isinstance(L[1], SubscriptObject):
+ subs = L[1].value
+ builder.push(ast.Subscript(L[0], consts.OP_APPLY, subs))
+ elif isinstance(L[1], SlicelistObject):
+ if L[1].name == 'slice':
+ start = L[1].value[0]
+ end = L[1].value[1]
+ builder.push(ast.Slice(L[0], consts.OP_APPLY, start, end))
+ else: # sliceobj (with 'step' argument)
+ builder.push(ast.Subscript(L[0], consts.OP_APPLY, [ast.Sliceobj(L[1].value)]))
+ else:
+ assert False, "TODO"
elif len(L) == 3:
if isinstance(L[1], TokenObject) and L[1].name == tok.DOT:
builder.push(ast.Getattr(L[0], L[2].value))
@@ -326,11 +346,6 @@
def build_file_input(builder, nb):
# FIXME: need to handle docstring !
doc = None
- # doc = self.get_docstring(nodelist, symbol.file_input)
- # if doc is not None:
- # i = 1
- # else:
- # i = 0
stmts = []
L = get_atoms(builder, nb)
for node in L:
@@ -343,7 +358,9 @@
continue
else:
stmts.append(node)
- return builder.push(ast.Module(doc, ast.Stmt(stmts)))
+ main_stmt = ast.Stmt(stmts)
+ doc = get_docstring(main_stmt)
+ return builder.push(ast.Module(doc, main_stmt))
def build_single_input( builder, nb ):
L = get_atoms( builder, nb )
@@ -394,6 +411,14 @@
elif len(L) == 3: # '(' Arglist ')'
# push arglist on the stack
builder.push(L[1])
+ elif L[0].name == tok.LSQB:
+ if isinstance(L[1], SlicelistObject):
+ builder.push(L[1])
+ else:
+ subs = []
+ for index in range(1, len(L), 2):
+ subs.append(L[index])
+ builder.push(SubscriptObject('subscript', subs, None))
elif len(L) == 2:
# Attribute access: '.' NAME
# XXX Warning: fails if trailer is used in lvalue
@@ -407,7 +432,46 @@
L = get_atoms(builder, nb)
builder.push(ArglistObject('arglist', parse_argument(L), None))
+def build_subscript(builder, nb):
+ """'.' '.' '.' | [test] ':' [test] [':' [test]] | test"""
+ L = get_atoms(builder, nb)
+ if isinstance(L[0], TokenObject) and L[0].name == tok.DOT:
+ # Ellipsis:
+ builder.push(ast.Ellipsis())
+ elif len(L) == 1:
+ token = L[0]
+ if isinstance(token, TokenObject) and token.name == tok.COLON:
+ builder.push(SlicelistObject('slice', [None, None, None], None))
+ else:
+ # test
+ builder.push(L[0])
+ else: # elif len(L) > 1:
+ items = []
+ sliceinfos = [None, None, None]
+ infosindex = 0
+ subscript_type = 'subscript'
+ for token in L:
+ if isinstance(token, TokenObject):
+ if token.name == tok.COLON:
+ infosindex += 1
+ subscript_type = 'slice'
+ # elif token.name == tok.COMMA:
+ # subscript_type = 'subscript'
+ else:
+ items.append(token)
+ sliceinfos[infosindex] = token
+ else:
+ items.append(token)
+ sliceinfos[infosindex] = token
+ if subscript_type == 'slice':
+ if infosindex == 2:
+ builder.push(SlicelistObject('sliceobj', sliceinfos, None))
+ else:
+ builder.push(SlicelistObject('slice', sliceinfos, None))
+ else:
+ builder.push(SubscriptObject('subscript', items, None))
+
def build_listmaker(builder, nb):
"""listmaker: test ( list_for | (',' test)* [','] )"""
L = get_atoms(builder, nb)
@@ -440,8 +504,9 @@
funcname = L[1].value
arglist = L[2]
code = L[-1]
+ doc = get_docstring(code)
# FIXME: decorators and docstring !
- builder.push(ast.Function(None, funcname, names, default, flags, None, code))
+ builder.push(ast.Function(None, funcname, names, default, flags, doc, code))
def build_classdef(builder, nb):
@@ -461,7 +526,8 @@
for node in base.nodes:
assert isinstance(node, ast.Name)
basenames.append(node)
- builder.push(ast.Class(classname, basenames, None, body))
+ doc = get_docstring(body)
+ builder.push(ast.Class(classname, basenames, doc, body))
def build_suite(builder, nb):
"""suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT"""
@@ -628,8 +694,14 @@
def build_del_stmt(builder, nb):
L = get_atoms(builder, nb)
- assert isinstance(L[1], ast.Name), "build_del_stmt implementation is incomplete !"
- builder.push(ast.AssName(L[1].name, consts.OP_DELETE))
+ builder.push(to_lvalue(L[1], consts.OP_DELETE))
+## if isinstance(L[1], ast.Name):
+## builder.push(ast.AssName(L[1].name, consts.OP_DELETE))
+## elif isinstance(L[1], ast.Getattr):
+## assert "TODO", "build_del_stmt implementation is incomplete !"
+## else:
+## assert "TODO", "build_del_stmt implementation is incomplete !"
+
def build_assert_stmt(builder, nb):
"""assert_stmt: 'assert' test [',' test]"""
@@ -920,6 +992,27 @@
return genexpr_fors
+def get_docstring(stmt):
+ """parses a Stmt node.
+
+ If a docstring if found, the Discard node is **removed**
+ from <stmt> and the docstring is returned.
+
+ If no docstring is found, <stmt> is left unchanged
+ and None is returned
+ """
+ if not isinstance(stmt, ast.Stmt):
+ return None
+ doc = None
+ first_child = stmt.nodes[0]
+ if isinstance(first_child, ast.Discard):
+ expr = first_child.expr
+ if isinstance(expr, ast.Const):
+ # This *is* a docstring, remove it from stmt list
+ del stmt.nodes[0]
+ doc = expr.value
+ return doc
+
ASTRULES = {
# "single_input" : build_single_input,
sym.atom : build_atom,
@@ -946,6 +1039,7 @@
sym.varargslist : build_varargslist,
sym.trailer : build_trailer,
sym.arglist : build_arglist,
+ sym.subscript : build_subscript,
sym.listmaker : build_listmaker,
sym.funcdef : build_funcdef,
sym.classdef : build_classdef,
@@ -1029,6 +1123,39 @@
return "<ArgList: (%s, %s, %s)>" % self.value
+class SubscriptObject(ast.Node):
+ """helper class to build function's arg list"""
+ def __init__(self, name, value, src):
+ self.name = name
+ self.value = value
+ self.count = 0
+ self.line = 0 # src.getline()
+ self.col = 0 # src.getcol()
+
+ def __str__(self):
+ return "<SubscriptList: (%s)>" % self.value
+
+ def __repr__(self):
+ return "<SubscriptList: (%s)>" % self.value
+
+class SlicelistObject(ast.Node):
+ def __init__(self, name, value, src):
+ self.name = name
+ self.value = value
+## self.begin = value[0]
+## self.end = value[1]
+## self.step = value[2]
+ self.count = 0
+ self.line = 0 # src.getline()
+ self.col = 0 # src.getcol()
+
+ def __str__(self):
+ return "<SliceList: (%s)>" % self.value
+
+ def __repr__(self):
+ return "<SliceList: (%s)>" % self.value
+
+
class AstBuilderContext(AbstractContext):
"""specific context management for AstBuidler"""
def __init__(self, rule_stack):
Added: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_docstring.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_docstring.py Wed Aug 10 14:03:05 2005
@@ -0,0 +1,17 @@
+"""module docstring"""
+
+
+"""hello
+
+"""
+
+class A:
+ """class doctring
+
+ on several lines
+ """
+
+def foo(self):
+ """function docstring"""
+
+"""world"""
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 Wed Aug 10 14:03:05 2005
@@ -25,7 +25,10 @@
"x, y, z = 1, 2, 3",
"x = 'a' 'b' 'c'",
"del foo",
- # "del foo[bar]",
+ "del foo[bar]",
+ "del foo.bar",
+ "l[0]",
+ "m[a,b]",
]
funccalls = [
@@ -98,10 +101,18 @@
]
attraccess = [
- # 'a.b = 2', # Module(None, Stmt([Assign([AssAttr(Name('a'), 'b', 'OP_ASSIGN')], Const(2))]))
+ 'a.b = 2',
'x = a.b',
]
+slices = [
+ "l[:]",
+ "l[1:2]",
+ "l[1:]",
+ "l[:2]",
+ "l[0:1:2]",
+ ]
+
imports = [
'import os',
'import sys, os',
@@ -252,6 +263,19 @@
"def f(**kwargs): return 1",
]
+docstrings = [
+ '''def foo():
+ """foo docstring"""
+ return 1
+ ''',
+ '''def foo():
+ """foo docstring"""
+ a = 1
+ """bar"""
+ return a
+ '''
+ ]
+
TESTS = [
expressions,
comparisons,
@@ -262,6 +286,7 @@
dictmakers,
multiexpr,
attraccess,
+ slices,
imports,
asserts,
execs,
@@ -274,6 +299,7 @@
one_stmt_funcdefs,
if_stmts,
tryexcepts,
+ docstrings,
]
TARGET_DICT = {
@@ -324,6 +350,8 @@
'snippet_generator.py',
'snippet_exceptions.py',
'snippet_classes.py',
+ 'snippet_simple_class.py',
+ 'snippet_docstring.py'
# 'snippet_2.py',
# 'snippet_3.py',
# 'snippet_4.py',
@@ -340,7 +368,6 @@
# 'snippet_redirected_prints.py',
# 'snippet_samples.py',
# 'snippet_simple_assignment.py',
-# 'snippet_simple_class.py',
# 'snippet_simple_in_expr.py',
# 'snippet_slice.py',
# 'snippet_whitespaces.py',
More information about the Pypy-commit
mailing list