Skip to content

Commit

Permalink
75% grammar coverage.
Browse files Browse the repository at this point in the history
whitequark committed May 5, 2015
1 parent f3d451d commit a4ede46
Showing 3 changed files with 364 additions and 56 deletions.
15 changes: 9 additions & 6 deletions pyparser/ast.py
Original file line number Diff line number Diff line change
@@ -450,9 +450,10 @@ class ClassDef(keywordloc, stmt, ast.ClassDef):
:ivar name_loc: location of name
:ivar lparen_loc: location of ``(``, if any
:ivar rparen_loc: location of ``)``, if any
:ivar colon_loc: location of ``:``
:ivar at_locs: locations of decorator ``@``
"""
_locs = keywordloc._locs + ('name_loc', 'lparen_loc', 'rparen_loc', 'at_loc')
_locs = keywordloc._locs + ('name_loc', 'lparen_loc', 'rparen_loc', 'colon_loc', 'at_locs')
class Continue(keywordloc, stmt, ast.Continue):
"""The ``continue`` statement."""
class Delete(keywordloc, stmt, ast.Delete):
@@ -478,7 +479,7 @@ class Expr(stmt, ast.Expr):
:ivar value: (:class:`expr`) value
"""
class For(keywordloc, stmt, ast.While):
class For(keywordloc, stmt, ast.For):
"""
The ``for x in y:· z·else:· t`` statement.
@@ -506,13 +507,15 @@ class FunctionDef(keywordloc, stmt, ast.FunctionDef):
:ivar colon_loc: location of ``:``, if any
:ivar at_locs: locations of decorator ``@``
"""
_locs = keywordloc._locs + ('keyword_loc' 'name_loc', 'colon_loc', 'at_loc')
_locs = keywordloc._locs + ('name_loc', 'colon_loc', 'at_loc')
class Global(keywordloc, stmt, ast.Global):
"""
The ``global x, y`` statement.
:ivar names: (list of :class:`Name`) names
:ivar names: (list of string) names
:ivar name_locs: locations of names
"""
_locs = keywordloc._locs + ('name_locs',)
class If(keywordloc, stmt, ast.If):
"""
The ``if x:· y·else:· z`` or ``if x:· y·elif: z· t`` statement.
@@ -603,7 +606,7 @@ class While(keywordloc, stmt, ast.While):
:ivar else_loc: location of ``else``, if any
:ivar else_colon_loc: location of colon after ``else``, if any
"""
_locs = keywordloc._locs + ('while_loc', 'while_colon_loc', 'else_loc', 'else_colon_loc')
_locs = keywordloc._locs + ('while_colon_loc', 'else_loc', 'else_colon_loc')
class With(keywordloc, stmt, ast.With):
"""
The ``with x as y:· z`` statement.
@@ -615,7 +618,7 @@ class With(keywordloc, stmt, ast.With):
:ivar as_loc: location of ``as``, if any
:ivar colon_loc: location of ``:``
"""
_locs = keywordloc._locs + ('colon_loc',)
_locs = keywordloc._locs + ('as_loc', 'colon_loc')

class unaryop(commonloc):
"""Base class for unary numeric and boolean operators."""
136 changes: 87 additions & 49 deletions pyparser/parser.py
Original file line number Diff line number Diff line change
@@ -228,15 +228,15 @@ def rule(parser):
while True:
result = separator_rule(parser)
if result is unmatched:
results.trailing_comma = False
results.trailing_comma = None
return results

result = inner_rule(parser)
if result is unmatched:
results.trailing_comma = True
result_1 = inner_rule(parser)
if result_1 is unmatched:
results.trailing_comma = result
return results
else:
results.append(result)
results.append(result_1)
return rule

# Python AST specific parser combinators
@@ -365,7 +365,7 @@ def decorated(self, decorators, classfuncdef):
return classfuncdef

@action(Seq(Loc('def'), Tok('ident'), Rule('parameters'), Loc(':'), Rule('suite')))
def funcdef(def_loc, ident_tok, args, colon_loc, suite):
def funcdef(self, def_loc, ident_tok, args, colon_loc, suite):
"""funcdef: 'def' NAME parameters ':' suite"""
return ast.FunctionDef(name=ident_tok.value, args=args, body=suite, decorator_list=[],
keyword_loc=def_loc, name_loc=ident_tok.value, colon_loc=colon_loc)
@@ -457,13 +457,17 @@ def expr_stmt(self, lhs, rhs):

@action(List(Rule('test'), ',', trailing=True))
def print_stmt_1(self, values):
return ast.Print(dest=None, values=values, nl=values.trailing,
dest_loc=None)
loc = values.trailing_comma.loc if values.trailing_comma else values[-1].loc
nl = True if values.trailing_comma else False
return ast.Print(dest=None, values=values, nl=nl,
dest_loc=None, loc=loc)

@action(Seq(Loc('>>'), Rule('test'), Tok(','), List(Rule('test'), ',', trailing=True)))
def print_stmt_2(self, dest_loc, dest, comma_tok, values):
return ast.Print(dest=dest, values=values, nl=values.trailing,
dest_loc=dest_loc)
loc = values.trailing_comma.loc if values.trailing_comma else values[-1].loc
nl = True if values.trailing_comma else False
return ast.Print(dest=dest, values=values, nl=nl,
dest_loc=dest_loc, loc=loc)

@action(Seq(Loc('print'), Alt(print_stmt_1, print_stmt_2)))
def print_stmt(self, print_loc, stmt):
@@ -473,12 +477,13 @@ def print_stmt(self, print_loc, stmt):
'>>' test [ (',' test)+ [','] ] )
"""
stmt.keyword_loc = print_loc
stmt.loc = print_loc.join(stmt.loc)
return stmt

@action(Seq(Loc('del'), Rule('exprlist')))
def del_stmt(self, stmt_loc, exprs):
"""del_stmt: 'del' exprlist"""
return ast.Delete(targets=list(map(self._assignable, exprs)),
return ast.Delete(targets=self._assignable(exprs),
loc=stmt_loc.join(exprs.loc), keyword_loc=stmt_loc)

@action(Loc('pass'))
@@ -503,23 +508,34 @@ def continue_stmt(self, stmt_loc):
@action(Seq(Loc('return'), Opt(Rule('testlist'))))
def return_stmt(self, stmt_loc, values):
"""return_stmt: 'return' [testlist]"""
return ast.Return(loc=stmt_loc.join(values.loc), keyword_loc=stmt_loc)
loc = stmt_loc
if values:
loc = loc.join(values.loc)
return ast.Return(value=values,
loc=loc, keyword_loc=stmt_loc)

yield_stmt = Rule('yield_expr')
"""yield_stmt: yield_expr"""
@action(Rule('yield_expr'))
def yield_stmt(self, expr):
"""yield_stmt: yield_expr"""
return ast.Expr(value=expr, loc=expr.loc)

@action(Seq(Loc('raise'), Opt(Seq(Rule('test'),
Opt(Seq(Tok(','), Rule('test'),
Opt(SeqN(1, Tok(','), Rule('test')))))))))
def raise_stmt(self, raise_loc, type_opt):
"""raise_stmt: 'raise' [test [',' test [',' test]]]"""
type_ = inst = tback = None
loc = raise_loc
if type_opt:
_, type_, inst_opt = type_opt
type_, inst_opt = type_opt
loc = loc.join(type_.loc)
if inst_opt:
inst, tback = inst_opt
_, inst, tback = inst_opt
loc = loc.join(inst.loc)
if tback:
loc = loc.join(tback.loc)
return ast.Raise(type=type_, inst=inst, tback=tback,
raise_loc=raise_loc)
keyword_loc=raise_loc, loc=loc)

import_stmt = Alt(Rule('import_name'), Rule('import_from'))
"""import_stmt: import_name | import_from"""
@@ -593,27 +609,36 @@ def dotted_name(self, idents):
'.'.join(list(map(lambda x: x.value, idents)))

@action(Seq(Loc('global'), List(Tok('ident'), ',', trailing=False)))
def global_stmt(self, keyword_loc, names):
def global_stmt(self, global_loc, names):
"""global_stmt: 'global' NAME (',' NAME)*"""
return ast.Global(names=list(map(ast.Name, names)),
keyword_loc=keyword_loc)
return ast.Global(names=list(map(lambda x: x.value, names)),
name_locs=list(map(lambda x: x.loc, names)),
keyword_loc=global_loc, loc=global_loc.join(names[-1].loc))

@action(Seq(Loc('exec'), Rule('expr'),
Opt(Seq(Loc('in'), Rule('test'),
Opt(SeqN(1, Loc(','), Rule('test')))))))
def exec_stmt(self, keyword_loc, body, in_opt):
def exec_stmt(self, exec_loc, body, in_opt):
"""exec_stmt: 'exec' expr ['in' test [',' test]]"""
in_loc, locals, globals_opt = None, None, None
in_loc, locals, globals = None, None, None
loc = exec_loc.join(body.loc)
if in_opt:
in_loc, locals, globals_opt = in_opt
in_loc, locals, globals = in_opt
if globals:
loc = loc.join(globals.loc)
else:
loc = loc.join(locals.loc)
return ast.Exec(body=body, locals=locals, globals=globals,
keyword_loc=keyword_loc, in_loc=in_loc)
loc=loc, keyword_loc=exec_loc, in_loc=in_loc)

@action(Seq(Loc('assert'), Rule('test'), Opt(SeqN(1, Tok(','), Rule('test')))))
def assert_stmt(self, keyword_loc, test, msg):
def assert_stmt(self, assert_loc, test, msg):
"""assert_stmt: 'assert' test [',' test]"""
loc = assert_loc.join(test.loc)
if msg:
loc = loc.join(msg.loc)
return ast.Assert(test=test, msg=msg,
keyword_loc=keyword_loc)
loc=loc, keyword_loc=assert_loc)

@action(Alt(Rule('if_stmt'), Rule('while_stmt'), Rule('for_stmt'),
Rule('try_stmt'), Rule('with_stmt'), Rule('funcdef'),
@@ -637,38 +662,42 @@ def if_stmt(self, if_loc, test, if_colon_loc, body, elifs, else_opt):
for elif_ in elifs:
stmt.keyword_loc, stmt.test, stmt.if_colon_loc, stmt.body = elif_
stmt.loc = stmt.keyword_loc.join(stmt.body[-1].loc)
if stmt.orelse: stmt.loc = stmt.loc.join(stmt.orelse[-1])
if stmt.orelse: stmt.loc = stmt.loc.join(stmt.orelse[-1].loc)
stmt = ast.If(orelse=[stmt],
else_loc=None, else_colon_loc=None)

stmt.keyword_loc, stmt.test, stmt.if_colon_loc, stmt.body = \
if_loc, test, if_colon_loc, body
stmt.loc = stmt.keyword_loc.join(stmt.body[-1].loc)
if stmt.orelse: stmt.loc = stmt.loc.join(stmt.orelse[-1])
if stmt.orelse: stmt.loc = stmt.loc.join(stmt.orelse[-1].loc)
return stmt

@action(Seq(Loc('while'), Rule('test'), Loc(':'), Rule('suite'),
Opt(Seq(Loc('else'), Loc(':'), Rule('suite')))))
def while_stmt(while_loc, test, while_colon_loc, body, else_opt):
def while_stmt(self, while_loc, test, while_colon_loc, body, else_opt):
"""while_stmt: 'while' test ':' suite ['else' ':' suite]"""
stmt = ast.While(test=test, body=body, orelse=[],
while_loc=while_loc, while_colon_loc=while_colon_loc,
else_loc=None, else_colon_loc=None)
keyword_loc=while_loc, while_colon_loc=while_colon_loc,
else_loc=None, else_colon_loc=None,
loc=while_loc.join(body[-1].loc))
if else_opt:
stmt.else_loc, stmt.else_colon_loc, orelse = else_opt
stmt.else_loc, stmt.else_colon_loc, stmt.orelse = else_opt
stmt.loc = stmt.loc.join(stmt.orelse[-1].loc)

return stmt

@action(Seq(Loc('for'), Rule('exprlist'), Loc('in'), Rule('testlist'),
Loc(':'), Rule('suite'),
Opt(Seq(Loc('else'), Loc(':'), Rule('suite')))))
def for_stmt(for_loc, target, in_loc, iter, for_colon_loc, body, else_opt):
def for_stmt(self, for_loc, target, in_loc, iter, for_colon_loc, body, else_opt):
"""for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]"""
stmt = ast.For(target=self._assignable(target), iter=iter, body=body, orelse=[],
for_loc=for_loc, in_loc=in_loc, for_colon_loc=for_colon_loc,
else_loc=None, else_colon_loc=None)
keyword_loc=for_loc, in_loc=in_loc, for_colon_loc=for_colon_loc,
else_loc=None, else_colon_loc=None,
loc=for_loc.join(body[-1].loc))
if else_opt:
stmt.else_loc, stmt.else_colon_loc, orelse = else_opt
stmt.else_loc, stmt.else_colon_loc, stmt.orelse = else_opt
stmt.loc = stmt.loc.join(stmt.orelse[-1].loc)

return stmt

@@ -716,19 +745,22 @@ def try_stmt(self, try_loc, try_colon_loc, body, stmt):
return stmt

@action(Seq(Loc('with'), Rule('test'), Opt(Rule('with_var')), Loc(':'), Rule('suite')))
def with_stmt(with_loc, context, with_var, colon_loc, body):
def with_stmt(self, with_loc, context, with_var, colon_loc, body):
"""with_stmt: 'with' test [ with_var ] ':' suite"""
as_loc, optional_vars = with_var
return ast.With(context=context, optional_vars=optional_vars, body=body,
keyword_loc=with_loc, as_loc=as_loc, colon_loc=colon_loc)
as_loc = optional_vars = None
if with_var:
as_loc, optional_vars = with_var
return ast.With(context_expr=context, optional_vars=optional_vars, body=body,
keyword_loc=with_loc, as_loc=as_loc, colon_loc=colon_loc,
loc=with_loc.join(body[-1].loc))

with_var = Seq(Loc('as'), Rule('expr'))
"""with_var: 'as' expr"""

@action(Seq(Loc('except'),
Opt(Seq(Rule('test'),
Opt(Seq(Alt(Loc('as'), Loc(',')), Rule('test')))))))
def except_clause(except_loc, exc_opt):
def except_clause(self, except_loc, exc_opt):
"""except_clause: 'except' [test [('as' | ',') test]]"""
type_ = name = as_loc = None
if exc_opt:
@@ -738,8 +770,12 @@ def except_clause(except_loc, exc_opt):
return ast.ExceptHandler(type=type_, name=name,
except_loc=except_loc, as_loc=as_loc)

@action(Plus(Rule('stmt')))
def suite_1(self, stmts):
return reduce(list.__add__, stmts, [])

suite = Alt(Rule('simple_stmt'),
SeqN(2, Tok('newline'), Tok('indent'), Plus(Rule('stmt')), Tok('dedent')))
SeqN(2, Tok('newline'), Tok('indent'), suite_1, Tok('dedent')))
"""suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT"""

# 2.x-only backwards compatibility start
@@ -1031,17 +1067,19 @@ def dictmaker(self, elts):
loc=None)

@action(Seq(Loc('class'), Tok('ident'),
Opt(BeginEnd('(', Rule('testlist'), ')')),
Opt(Seq(Loc('('), List(Rule('test'), ',', trailing=True), Loc(')'))),
Loc(':'), Rule('suite')))
def classdef(class_loc, name_tok, bases_opt, colon_loc, body):
def classdef(self, class_loc, name_tok, bases_opt, colon_loc, body):
"""classdef: 'class' NAME ['(' [testlist] ')'] ':' suite"""
bases = lparen_loc = rparen_loc = None
bases, lparen_loc, rparen_loc = [], None, None
if bases_opt:
lparen_loc, bases, rparen_loc = \
bases_opt.begin_loc, bases_opt.elts, bases_opt.end_loc
lparen_loc, bases, rparen_loc = bases_opt

return ast.ClassDef(name=name_tok.value, bases=bases, body=body, decorator_list=[],
keyword_loc=class_loc, lparen_loc=lparen_loc, rparen_loc=rparen_loc)
return ast.ClassDef(name=name_tok.value, bases=bases, body=body,
decorator_list=[], at_locs=[],
keyword_loc=class_loc, lparen_loc=lparen_loc, rparen_loc=rparen_loc,
name_loc=name_tok.loc, colon_loc=colon_loc,
loc=class_loc.join(body[-1].loc))

@action(Seq(Loc('*'), Rule('test'), Star(SeqN(1, Tok(','), Rule('argument'))),
Opt(Seq(Tok(','), Loc('**'), Rule('test')))))
269 changes: 268 additions & 1 deletion pyparser/test/test_parser.py
Original file line number Diff line number Diff line change
@@ -136,6 +136,10 @@ def assertDiagnosesUnexpected(self, code, err_token, loc):
ast_2 = {'ty': 'Num', 'n': 2}
ast_3 = {'ty': 'Num', 'n': 3}

ast_expr_1 = {'ty': 'Expr', 'value': {'ty': 'Num', 'n': 1}}
ast_expr_2 = {'ty': 'Expr', 'value': {'ty': 'Num', 'n': 2}}
ast_expr_3 = {'ty': 'Expr', 'value': {'ty': 'Num', 'n': 3}}

ast_x = {'ty': 'Name', 'id': 'x', 'ctx': None}
ast_y = {'ty': 'Name', 'id': 'y', 'ctx': None}
ast_z = {'ty': 'Name', 'id': 'z', 'ctx': None}
@@ -649,6 +653,13 @@ def test_subscript(self):
" ~~~~~ slice.loc"
"~~~~~~~~ loc")

self.assertParsesExpr(
{'ty': 'Subscript', 'value': self.ast_x, 'ctx': None,
'slice': {'ty': 'Ellipsis'}},
"x[...]",
" ~~~ slice.loc"
"~~~~~~ loc")

def test_attribute(self):
self.assertParsesExpr(
{'ty': 'Attribute', 'value': self.ast_x, 'attr': 'zz', 'ctx': None},
@@ -658,7 +669,7 @@ def test_attribute(self):
"~~~~ loc")

#
# STATEMENTS
# SIMPLE STATEMENTS
#

def test_assign(self):
@@ -675,6 +686,12 @@ def test_assign(self):
" ^ 0.op_locs.0"
" ^ 0.op_locs.1")

self.assertParsesSuite(
[{'ty': 'Assign', 'targets': [self.ast_x], 'value':
{'ty': 'Yield', 'value': self.ast_y}}],
"x = yield y",
"~~~~~~~~~~~ 0.loc")

def test_augassign(self):
self.assertParsesSuite(
[{'ty': 'AugAssign', 'op': {'ty': 'Add'}, 'target': self.ast_x, 'value': self.ast_1}],
@@ -748,6 +765,256 @@ def test_augassign(self):
"~~~~~~ 0.loc"
" ~~ 0.op.loc")

self.assertParsesSuite(
[{'ty': 'AugAssign', 'op': {'ty': 'Add'}, 'target': self.ast_x, 'value':
{'ty': 'Yield', 'value': self.ast_y}}],
"x += yield y",
"~~~~~~~~~~~~ 0.loc")

def test_print(self):
self.assertParsesSuite(
[{'ty': 'Print', 'dest': None, 'values': [self.ast_1], 'nl': False}],
"print 1",
"~~~~~ 0.keyword_loc"
"~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Print', 'dest': None, 'values': [self.ast_1], 'nl': True}],
"print 1,",
"~~~~~ 0.keyword_loc"
"~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Print', 'dest': self.ast_2, 'values': [self.ast_1], 'nl': False}],
"print >>2, 1",
"~~~~~ 0.keyword_loc"
" ~~ 0.dest_loc"
"~~~~~~~~~~~~ 0.loc")

def test_del(self):
self.assertParsesSuite(
[{'ty': 'Delete', 'targets': self.ast_x}],
"del x",
"~~~ 0.keyword_loc"
"~~~~~ 0.loc")

def test_pass(self):
self.assertParsesSuite(
[{'ty': 'Pass'}],
"pass",
"~~~~ 0.keyword_loc"
"~~~~ 0.loc")

def test_break(self):
self.assertParsesSuite(
[{'ty': 'Break'}],
"break",
"~~~~~ 0.keyword_loc"
"~~~~~ 0.loc")

def test_continue(self):
self.assertParsesSuite(
[{'ty': 'Continue'}],
"continue",
"~~~~~~~~ 0.keyword_loc"
"~~~~~~~~ 0.loc")

def test_return(self):
self.assertParsesSuite(
[{'ty': 'Return', 'value': None}],
"return",
"~~~~~~ 0.keyword_loc"
"~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Return', 'value': self.ast_x}],
"return x",
"~~~~~~ 0.keyword_loc"
"~~~~~~~~ 0.loc")

def test_yield(self):
self.assertParsesSuite(
[{'ty': 'Expr', 'value': {'ty': 'Yield', 'value': self.ast_x}}],
"yield x",
"~~~~~ 0.value.keyword_loc"
"~~~~~~~ 0.value.loc"
"~~~~~~~ 0.loc")

def test_raise(self):
self.assertParsesSuite(
[{'ty': 'Raise', 'type': None, 'inst': None, 'tback': None}],
"raise",
"~~~~~ 0.keyword_loc"
"~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Raise', 'type': self.ast_x, 'inst': None, 'tback': None}],
"raise x",
"~~~~~ 0.keyword_loc"
"~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Raise', 'type': self.ast_x, 'inst': self.ast_y, 'tback': None}],
"raise x, y",
"~~~~~ 0.keyword_loc"
"~~~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Raise', 'type': self.ast_x, 'inst': self.ast_y, 'tback': self.ast_z}],
"raise x, y, z",
"~~~~~ 0.keyword_loc"
"~~~~~~~~~~~~~ 0.loc")

def test_global(self):
self.assertParsesSuite(
[{'ty': 'Global', 'names': ['x', 'y']}],
"global x, y",
"~~~~~~ 0.keyword_loc"
" ^ 0.name_locs.0"
" ^ 0.name_locs.1"
"~~~~~~~~~~~ 0.loc")

def test_exec(self):
self.assertParsesSuite(
[{'ty': 'Exec', 'body': self.ast_1, 'locals': None, 'globals': None}],
"exec 1",
"~~~~ 0.keyword_loc"
"~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Exec', 'body': self.ast_1, 'locals': self.ast_2, 'globals': None}],
"exec 1 in 2",
"~~~~ 0.keyword_loc"
" ~~ 0.in_loc"
"~~~~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Exec', 'body': self.ast_1, 'locals': self.ast_2, 'globals': self.ast_3}],
"exec 1 in 2, 3",
"~~~~ 0.keyword_loc"
" ~~ 0.in_loc"
"~~~~~~~~~~~~~~ 0.loc")

def test_assert(self):
self.assertParsesSuite(
[{'ty': 'Assert', 'test': self.ast_1, 'msg': None}],
"assert 1",
"~~~~~~ 0.keyword_loc"
"~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'Assert', 'test': self.ast_1, 'msg': self.ast_2}],
"assert 1, 2",
"~~~~~~ 0.keyword_loc"
"~~~~~~~~~~~ 0.loc")

#
# COMPOUND STATEMENTS
#

def test_if(self):
self.assertParsesSuite(
[{'ty': 'If', 'test': self.ast_x, 'body': [self.ast_expr_1], 'orelse': []}],
"if x:· 1",
"^^ 0.keyword_loc"
" ^ 0.if_colon_loc"
"~~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'If', 'test': self.ast_x,
'body': [self.ast_expr_1], 'orelse': [self.ast_expr_2] }],
"if x:· 1·else:· 2",
"^^ 0.keyword_loc"
" ^ 0.if_colon_loc"
" ^^^^ 0.else_loc"
" ^ 0.else_colon_loc"
"~~~~~~~~~~~~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'If', 'test': self.ast_x, 'body': [self.ast_expr_1], 'orelse': [
{'ty': 'If', 'test': self.ast_y, 'body': [self.ast_expr_2],
'orelse': [self.ast_expr_3]}
]}],
"if x:· 1·elif y:· 2·else:· 3",
"^^ 0.keyword_loc"
" ^ 0.if_colon_loc"
" ~~~~ 0.orelse.0.keyword_loc"
" ^ 0.orelse.0.if_colon_loc"
" ~~~~ 0.orelse.0.else_loc"
" ^ 0.orelse.0.else_colon_loc"
" ~~~~~~~~~~~~~~~~~~~~~ 0.orelse.0.loc"
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0.loc")

def test_while(self):
self.assertParsesSuite(
[{'ty': 'While', 'test': self.ast_x, 'body': [self.ast_expr_1], 'orelse': []}],
"while x:· 1",
"~~~~~ 0.keyword_loc"
" ^ 0.while_colon_loc"
"~~~~~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'While', 'test': self.ast_x, 'body': [self.ast_expr_1],
'orelse': [self.ast_expr_2]}],
"while x:· 1·else:· 2",
"~~~~~ 0.keyword_loc"
" ^ 0.while_colon_loc"
" ~~~~ 0.else_loc"
" ^ 0.else_colon_loc"
"~~~~~~~~~~~~~~~~~~~~~~ 0.loc")

def test_for(self):
self.assertParsesSuite(
[{'ty': 'For', 'target': self.ast_x, 'iter': self.ast_y,
'body': [self.ast_expr_1], 'orelse': []}],
"for x in y:· 1",
"~~~ 0.keyword_loc"
" ~~ 0.in_loc"
" ^ 0.for_colon_loc"
"~~~~~~~~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'For', 'target': self.ast_x, 'iter': self.ast_y,
'body': [self.ast_expr_1], 'orelse': [self.ast_expr_2]}],
"for x in y:· 1·else:· 2",
" ~~~~ 0.else_loc"
" ^ 0.else_colon_loc"
"~~~~~~~~~~~~~~~~~~~~~~~~~ 0.loc")

def test_with(self):
self.assertParsesSuite(
[{'ty': 'With', 'context_expr': self.ast_x, 'optional_vars': None,
'body': [self.ast_expr_1]}],
"with x:· 1",
"~~~~ 0.keyword_loc"
" ^ 0.colon_loc"
"~~~~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'With', 'context_expr': self.ast_x, 'optional_vars': self.ast_y,
'body': [self.ast_expr_1]}],
"with x as y:· 1",
" ~~ 0.as_loc"
"~~~~~~~~~~~~~~~~ 0.loc")

def test_class(self):
self.assertParsesSuite(
[{'ty': 'ClassDef', 'name': 'x', 'bases': [],
'body': [{'ty': 'Pass'}], 'decorator_list': []}],
"class x:· pass",
"~~~~~ 0.keyword_loc"
" ^ 0.name_loc"
" ^ 0.colon_loc"
"~~~~~~~~~~~~~~~ 0.loc")

self.assertParsesSuite(
[{'ty': 'ClassDef', 'name': 'x', 'bases': [self.ast_y, self.ast_z],
'body': [{'ty': 'Pass'}], 'decorator_list': []}],
"class x(y, z):· pass",
" ^ 0.lparen_loc"
" ^ 0.rparen_loc"
"~~~~~~~~~~~~~~~~~~~~~ 0.loc")

#
# PARSING MODES
#

0 comments on commit a4ede46

Please sign in to comment.