From b685896ce6c3d44229a188ed341749ea6b021e40 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 27 Nov 2014 21:40:09 +0000 Subject: [PATCH] Simple statements --- ast/ast.go | 6 +- ast/dump.go | 7 ++ parser/grammar.y | 132 +++++++++++++++++++++--------------- parser/grammar_test.go | 39 ++++++++++- parser/make_grammar_test.py | 41 ++++++++++- 5 files changed, 163 insertions(+), 62 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index d0acb240..63726fc6 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -363,13 +363,13 @@ type Assert struct { type Import struct { StmtBase - Names []Alias + Names []*Alias } type ImportFrom struct { StmtBase Module Identifier - Names []Alias + Names []*Alias Level int } @@ -673,7 +673,7 @@ type Keyword struct { type Alias struct { Pos Name Identifier - Asname Identifier + AsName *Identifier } type WithItem struct { diff --git a/ast/dump.go b/ast/dump.go index 53fd20b5..e3287628 100644 --- a/ast/dump.go +++ b/ast/dump.go @@ -19,6 +19,11 @@ func dumpItem(v interface{}) string { return fmt.Sprintf("b'%s'", string(x)) case Identifier: return fmt.Sprintf("'%s'", string(x)) + case *Identifier: + if x == nil { + return "None" + } + return fmt.Sprintf("'%s'", string(*x)) case *Keyword: return dump(x, "keyword") case ModBase: @@ -26,6 +31,8 @@ func dumpItem(v interface{}) string { case ExprBase: case SliceBase: case Pos: + case *Alias: + return dump(v, "alias") case Ast: return Dump(x) case py.I__str__: diff --git a/parser/grammar.y b/parser/grammar.y index 4c5f8927..26c12a7c 100644 --- a/parser/grammar.y +++ b/parser/grammar.y @@ -60,12 +60,16 @@ func applyTrailers(expr ast.Expr, trailers []ast.Expr) ast.Expr { isExpr bool slice ast.Slicer call *ast.Call + level int + alias *ast.Alias + aliases []*ast.Alias + identifiers []ast.Identifier } %type strings %type inputs file_input single_input eval_input %type simple_stmt stmt nl_or_stmt small_stmts stmts -%type compound_stmt small_stmt expr_stmt del_stmt pass_stmt flow_stmt import_stmt global_stmt nonlocal_stmt assert_stmt break_stmt continue_stmt return_stmt raise_stmt yield_stmt +%type compound_stmt small_stmt expr_stmt del_stmt pass_stmt flow_stmt import_stmt global_stmt nonlocal_stmt assert_stmt break_stmt continue_stmt return_stmt raise_stmt yield_stmt import_name import_from %type augassign %type expr_or_star_expr expr star_expr xor_expr and_expr shift_expr arith_expr term factor power trailer atom test_or_star_expr test not_test lambdef test_nocond lambdef_nocond or_test and_test comparison testlist testlist_star_expr yield_expr_or_testlist yield_expr yield_expr_or_testlist_star_expr dictorsetmaker sliceop arglist %type exprlist testlistraw comp_if comp_iter expr_or_star_exprs test_or_star_exprs tests test_colon_tests trailers @@ -74,6 +78,11 @@ func applyTrailers(expr ast.Expr, trailers []ast.Expr) ast.Expr { %type comp_for %type subscript subscriptlist subscripts %type argument arguments optional_arguments arguments2 +%type dot dots +%type dotted_name from_arg +%type names +%type dotted_as_name import_as_name +%type dotted_as_names import_as_names import_from_arg %token NEWLINE %token ENDMARKER @@ -664,6 +673,9 @@ augassign: del_stmt: DEL exprlist { + for i := range $2 { + $2[i].(ast.SetCtxer).SetCtx(ast.Del) + } $$ = &ast.Delete{StmtBase: ast.StmtBase{$$}, Targets: $2} } @@ -698,186 +710,194 @@ flow_stmt: break_stmt: BREAK { - // FIXME + $$ = &ast.Break{StmtBase: ast.StmtBase{$$}} } continue_stmt: CONTINUE { - // FIXME + $$ = &ast.Continue{StmtBase: ast.StmtBase{$$}} } return_stmt: RETURN { - // FIXME + $$ = &ast.Return{StmtBase: ast.StmtBase{$$}} } | RETURN testlist { - // FIXME + $$ = &ast.Return{StmtBase: ast.StmtBase{$$}, Value: $2} } yield_stmt: yield_expr { - // FIXME + $$ = &ast.ExprStmt{StmtBase: ast.StmtBase{$$}, Value: $1} } raise_stmt: RAISE { - // FIXME + $$ = &ast.Raise{StmtBase: ast.StmtBase{$$}} } | RAISE test { - // FIXME + $$ = &ast.Raise{StmtBase: ast.StmtBase{$$}, Exc: $2} } | RAISE test FROM test { - // FIXME + $$ = &ast.Raise{StmtBase: ast.StmtBase{$$}, Exc: $2, Cause: $4} } import_stmt: import_name { - // FIXME + $$ = $1 } | import_from { - // FIXME + $$ = $1 } import_name: IMPORT dotted_as_names { - // FIXME + $$ = &ast.Import{StmtBase: ast.StmtBase{$$}, Names: $2} } // note below: the '.' | ELIPSIS is necessary because '...' is tokenized as ELIPSIS dot: '.' { - // FIXME + $$ = 1 } | ELIPSIS { - // FIXME + $$ = 3 } dots: dot { - // FIXME + $$ = $1 } | dots dot { - // FIXME + $$ += $2 } from_arg: dotted_name { - // FIXME + $$ = 0 + $$ = $1 } | dots dotted_name { - // FIXME + $$ = $1 + $$ = $2 } | dots { - // FIXME + $$ = $1 + $$ = "" } import_from_arg: '*' { - // FIXME + $$ = []*ast.Alias{&ast.Alias{Pos: $$, Name: ast.Identifier("*")}} } -| '(' import_as_names ')' +| '(' import_as_names optional_comma ')' { - // FIXME + $$ = $2 } -| import_as_names +| import_as_names optional_comma { - // FIXME + $$ = $1 } import_from: FROM from_arg IMPORT import_from_arg { - // FIXME + $$ = &ast.ImportFrom{StmtBase: ast.StmtBase{$$}, Module: ast.Identifier($2), Names: $4, Level: $2} } import_as_name: NAME { - // FIXME + $$ = &ast.Alias{Pos: $$, Name: ast.Identifier($1)} } | NAME AS NAME { - // FIXME + as := ast.Identifier($3) + $$ = &ast.Alias{Pos: $$, Name: ast.Identifier($1), AsName: &as} } dotted_as_name: dotted_name { - // FIXME + $$ = &ast.Alias{Pos: $$, Name: ast.Identifier($1)} } | dotted_name AS NAME { - // FIXME + as := ast.Identifier($3) + $$ = &ast.Alias{Pos: $$, Name: ast.Identifier($1), AsName: &as} } import_as_names: - import_as_name optional_comma + import_as_name { - // FIXME + $$ = nil + $$ = append($$, $1) } -| import_as_name ',' import_as_names +| import_as_names ',' import_as_name { - // FIXME + $$ = append($$, $3) } dotted_as_names: dotted_as_name { - // FIXME + $$ = nil + $$ = append($$, $1) } | dotted_as_names ',' dotted_as_name { - // FIXME + $$ = append($$, $3) } dotted_name: NAME { - // FIXME + $$ = $1 } | dotted_name '.' NAME { - // FIXME + $$ += "." + $3 } names: NAME { - // FIXME + $$ = nil + $$ = append($$, ast.Identifier($1)) } | names ',' NAME { - // FIXME + $$ = append($$, ast.Identifier($3)) } global_stmt: GLOBAL names { - // FIXME + $$ = &ast.Global{StmtBase: ast.StmtBase{$$}, Names: $2} } nonlocal_stmt: NONLOCAL names { - // FIXME + $$ = &ast.Nonlocal{StmtBase: ast.StmtBase{$$}, Names: $2} } tests: @@ -894,7 +914,15 @@ tests: assert_stmt: ASSERT tests { - // FIXME + tests := $2 + switch len(tests) { + case 1: + $$ = &ast.Assert{StmtBase: ast.StmtBase{$$}, Test: tests[0]} + case 2: + $$ = &ast.Assert{StmtBase: ast.StmtBase{$$}, Test: tests[0], Msg: tests[1]} + default: + yylex.Error("Invalid syntax") + } } compound_stmt: @@ -1363,9 +1391,7 @@ atom: } | '(' yield_expr ')' { - // FIXME - panic("yield_expr not implemented") - $$ = nil + $$ = $2 } | '(' test_or_star_expr comp_for ')' { @@ -1768,19 +1794,13 @@ comp_if: yield_expr: YIELD { - // FIXME - } -| YIELD yield_arg - { - // FIXME + $$ = &ast.Yield{ExprBase: ast.ExprBase{$$}} } - -yield_arg: - FROM test +| YIELD FROM test { - // FIXME + $$= &ast.YieldFrom{ExprBase: ast.ExprBase{$$}, Value: $3} } -| testlist +| YIELD testlist { - // FIXME + $$= &ast.Yield{ExprBase: ast.ExprBase{$$}, Value: $2} } diff --git a/parser/grammar_test.go b/parser/grammar_test.go index b0916630..ba2eabbc 100644 --- a/parser/grammar_test.go +++ b/parser/grammar_test.go @@ -21,7 +21,6 @@ func TestGrammar(t *testing.T) { // START TESTS // *** Tests auto generated by make_grammar_test.py - do not edit *** {"", "exec", "Module(body=[])"}, - {"pass", "exec", "Module(body=[Pass()])"}, {"()", "eval", "Expression(body=Tuple(elts=[], ctx=Load()))"}, {"()", "exec", "Module(body=[Expr(value=Tuple(elts=[], ctx=Load()))])"}, {"[ ]", "exec", "Module(body=[Expr(value=List(elts=[], ctx=Load()))])"}, @@ -135,6 +134,7 @@ func TestGrammar(t *testing.T) { {"a(b,)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='b', ctx=Load())], keywords=[], starargs=None, kwargs=None))"}, {"a(b,c)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='b', ctx=Load()), Name(id='c', ctx=Load())], keywords=[], starargs=None, kwargs=None))"}, {"a(b,*c)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='b', ctx=Load())], keywords=[], starargs=Name(id='c', ctx=Load()), kwargs=None))"}, + {"a(*b)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[], keywords=[], starargs=Name(id='b', ctx=Load()), kwargs=None))"}, {"a(b,*c,**d)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='b', ctx=Load())], keywords=[], starargs=Name(id='c', ctx=Load()), kwargs=Name(id='d', ctx=Load())))"}, {"a(b,**c)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='b', ctx=Load())], keywords=[], starargs=None, kwargs=Name(id='c', ctx=Load())))"}, {"a(a=b)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[], keywords=[keyword(arg='a', value=Name(id='b', ctx=Load()))], starargs=None, kwargs=None))"}, @@ -159,6 +159,43 @@ func TestGrammar(t *testing.T) { {"x[a, b:c, ::d]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=ExtSlice(dims=[Index(value=Name(id='a', ctx=Load())), Slice(lower=Name(id='b', ctx=Load()), upper=Name(id='c', ctx=Load()), step=None), Slice(lower=None, upper=None, step=Name(id='d', ctx=Load()))]), ctx=Load()))"}, {"x[a, b:c, ::d]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=ExtSlice(dims=[Index(value=Name(id='a', ctx=Load())), Slice(lower=Name(id='b', ctx=Load()), upper=Name(id='c', ctx=Load()), step=None), Slice(lower=None, upper=None, step=Name(id='d', ctx=Load()))]), ctx=Load()))"}, {"x[0, 1:2, ::5, ...]", "eval", "Expression(body=Subscript(value=Name(id='x', ctx=Load()), slice=ExtSlice(dims=[Index(value=Num(n=0)), Slice(lower=Num(n=1), upper=Num(n=2), step=None), Slice(lower=None, upper=None, step=Num(n=5)), Index(value=Ellipsis())]), ctx=Load()))"}, + {"(yield a,b)", "eval", "Expression(body=Yield(value=Tuple(elts=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())], ctx=Load())))"}, + {"(yield from a)", "eval", "Expression(body=YieldFrom(value=Name(id='a', ctx=Load())))"}, + {"del a,b", "exec", "Module(body=[Delete(targets=[Name(id='a', ctx=Del()), Name(id='b', ctx=Del())])])"}, + {"pass", "exec", "Module(body=[Pass()])"}, + {"break", "exec", "Module(body=[Break()])"}, + {"continue", "exec", "Module(body=[Continue()])"}, + {"return", "exec", "Module(body=[Return(value=None)])"}, + {"return a", "exec", "Module(body=[Return(value=Name(id='a', ctx=Load()))])"}, + {"return a,", "exec", "Module(body=[Return(value=Tuple(elts=[Name(id='a', ctx=Load())], ctx=Load()))])"}, + {"return a,b", "exec", "Module(body=[Return(value=Tuple(elts=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())], ctx=Load()))])"}, + {"raise", "exec", "Module(body=[Raise(exc=None, cause=None)])"}, + {"raise a", "exec", "Module(body=[Raise(exc=Name(id='a', ctx=Load()), cause=None)])"}, + {"raise a from b", "exec", "Module(body=[Raise(exc=Name(id='a', ctx=Load()), cause=Name(id='b', ctx=Load()))])"}, + {"yield", "exec", "Module(body=[Expr(value=Yield(value=None))])"}, + {"yield a", "exec", "Module(body=[Expr(value=Yield(value=Name(id='a', ctx=Load())))])"}, + {"yield a, b", "exec", "Module(body=[Expr(value=Yield(value=Tuple(elts=[Name(id='a', ctx=Load()), Name(id='b', ctx=Load())], ctx=Load())))])"}, + {"import a", "exec", "Module(body=[Import(names=[alias(name='a', asname=None)])])"}, + {"import a . b,c .d.e", "exec", "Module(body=[Import(names=[alias(name='a.b', asname=None), alias(name='c.d.e', asname=None)])])"}, + {"from a import b", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None)], level=0)])"}, + {"from a import b, c", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None), alias(name='c', asname=None)], level=0)])"}, + {"from a import (b, c)", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None), alias(name='c', asname=None)], level=0)])"}, + {"from a import *", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='*', asname=None)], level=0)])"}, + {"from .a import (b, c,)", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None), alias(name='c', asname=None)], level=1)])"}, + {"from ..a import b", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None)], level=2)])"}, + {"from ...a import b", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None)], level=3)])"}, + {"from ....a import b", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None)], level=4)])"}, + {"from .....a import b", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None)], level=5)])"}, + {"from ......a import b", "exec", "Module(body=[ImportFrom(module='a', names=[alias(name='b', asname=None)], level=6)])"}, + {"global a", "exec", "Module(body=[Global(names=['a'])])"}, + {"global a, b", "exec", "Module(body=[Global(names=['a', 'b'])])"}, + {"global a, b, c", "exec", "Module(body=[Global(names=['a', 'b', 'c'])])"}, + {"nonlocal a", "exec", "Module(body=[Nonlocal(names=['a'])])"}, + {"nonlocal a, b", "exec", "Module(body=[Nonlocal(names=['a', 'b'])])"}, + {"nonlocal a, b, c", "exec", "Module(body=[Nonlocal(names=['a', 'b', 'c'])])"}, + {"assert True", "exec", "Module(body=[Assert(test=NameConstant(value=True), msg=None)])"}, + {"assert True, 'Bang'", "exec", "Module(body=[Assert(test=NameConstant(value=True), msg=Str(s='Bang'))])"}, + {"assert a == b, 'Bang'", "exec", "Module(body=[Assert(test=Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), msg=Str(s='Bang'))])"}, // END TESTS } { Ast, err := ParseString(test.in, test.mode) diff --git a/parser/make_grammar_test.py b/parser/make_grammar_test.py index 0ec0a44b..6f6301fc 100755 --- a/parser/make_grammar_test.py +++ b/parser/make_grammar_test.py @@ -8,7 +8,6 @@ inp = [ ("", "exec"), - ("pass", "exec"), ("()", "eval"), ("()", "exec"), ("[ ]", "exec"), @@ -165,7 +164,45 @@ ("x[a, b:c, ::d]", "eval"), ("x[0, 1:2, ::5, ...]", "eval"), - # ("del a,b", "exec"), + # yield expressions + ("(yield a,b)", "eval"), + ("(yield from a)", "eval"), + + ("del a,b", "exec"), + ("pass", "exec"), + ("break", "exec"), + ("continue", "exec"), + ("return", "exec"), + ("return a", "exec"), + ("return a,", "exec"), + ("return a,b", "exec"), + ("raise", "exec"), + ("raise a", "exec"), + ("raise a from b", "exec"), + ("yield", "exec"), + ("yield a", "exec"), + ("yield a, b", "exec"), + ("import a", "exec"), + ("import a . b,c .d.e", "exec"), + ("from a import b", "exec"), + ("from a import b, c", "exec"), + ("from a import (b, c)", "exec"), + ("from a import *", "exec"), + ("from .a import (b, c,)", "exec"), + ("from ..a import b", "exec"), + ("from ...a import b", "exec"), + ("from ....a import b", "exec"), + ("from .....a import b", "exec"), + ("from ......a import b", "exec"), + ("global a", "exec"), + ("global a, b", "exec"), + ("global a, b, c", "exec"), + ("nonlocal a", "exec"), + ("nonlocal a, b", "exec"), + ("nonlocal a, b, c", "exec"), + ("assert True", "exec"), + ("assert True, 'Bang'", "exec"), + ("assert a == b, 'Bang'", "exec"), ] def dump(source, mode):