Skip to content

Commit f627870

Browse files
committed
Make Call with arguments work
1 parent 133ce36 commit f627870

File tree

5 files changed

+94
-5
lines changed

5 files changed

+94
-5
lines changed

ast/ast.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ type UnaryOp struct {
429429

430430
type Lambda struct {
431431
ExprBase
432-
Args Arguments
432+
Args *Arguments
433433
Body Expr
434434
}
435435

ast/dump.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ func dumpItem(v interface{}) string {
1919
return fmt.Sprintf("b'%s'", string(x))
2020
case Identifier:
2121
return fmt.Sprintf("'%s'", string(x))
22+
case *Keyword:
23+
return dump(x, "keyword")
2224
case ModBase:
2325
case StmtBase:
2426
case ExprBase:
@@ -43,7 +45,7 @@ func dump(ast interface{}, name string) string {
4345
fieldType := astType.Field(i)
4446
fieldValue := astValue.Field(i)
4547
fname := strings.ToLower(fieldType.Name)
46-
if fname == "stmtbase" || fname == "exprbase" || fname == "modbase" || fname == "slicebase" {
48+
if fname == "stmtbase" || fname == "exprbase" || fname == "modbase" || fname == "slicebase" || fname == "pos" {
4749
continue
4850
}
4951
if fieldValue.Kind() == reflect.Slice && fieldValue.Type().Elem().Kind() != reflect.Uint8 {

parser/grammar.y

+70-3
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,21 @@ func applyTrailers(expr ast.Expr, trailers []ast.Expr) ast.Expr {
5959
comprehensions []ast.Comprehension
6060
isExpr bool
6161
slice ast.Slicer
62+
call *ast.Call
6263
}
6364

6465
%type <obj> strings
6566
%type <mod> inputs file_input single_input eval_input
6667
%type <stmts> simple_stmt stmt nl_or_stmt small_stmts stmts
6768
%type <stmt> 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
6869
%type <op> augassign
69-
%type <expr> 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
70+
%type <expr> 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
7071
%type <exprs> exprlist testlistraw comp_if comp_iter expr_or_star_exprs test_or_star_exprs tests test_colon_tests trailers
7172
%type <cmpop> comp_op
7273
%type <comma> optional_comma
7374
%type <comprehensions> comp_for
7475
%type <slice> subscript subscriptlist subscripts
76+
%type <call> argument arguments optional_arguments arguments2
7577

7678
%token NEWLINE
7779
%token ENDMARKER
@@ -1142,8 +1144,7 @@ trailer:
11421144
}
11431145
| '(' arglist ')'
11441146
{
1145-
// FIXME
1146-
$$ = nil
1147+
$$ = $2
11471148
}
11481149
| '[' subscriptlist ']'
11491150
{
@@ -1329,26 +1330,92 @@ classdef:
13291330

13301331
arguments:
13311332
argument
1333+
{
1334+
$$ = $1
1335+
}
13321336
| arguments ',' argument
1337+
{
1338+
$$.Args = append($$.Args, $3.Args...)
1339+
$$.Keywords = append($$.Keywords, $3.Keywords...)
1340+
}
13331341

13341342
optional_arguments:
1343+
{
1344+
$$ = &ast.Call{}
1345+
}
13351346
| arguments ','
1347+
{
1348+
$$ = $1
1349+
}
13361350

13371351
arguments2:
1352+
{
1353+
$$ = &ast.Call{}
1354+
}
13381355
| arguments2 ',' argument
1356+
{
1357+
$$.Args = append($$.Args, $3.Args...)
1358+
$$.Keywords = append($$.Keywords, $3.Keywords...)
1359+
}
13391360

13401361
arglist:
13411362
arguments optional_comma
1363+
{
1364+
$$ = $1
1365+
}
13421366
| optional_arguments '*' test arguments2
1367+
{
1368+
call := $1
1369+
call.Starargs = $3
1370+
if len($4.Args) != 0 {
1371+
yylex.Error("SyntaxError: only named arguments may follow *expression")
1372+
}
1373+
call.Keywords = append(call.Keywords, $4.Keywords...)
1374+
$$ = call
1375+
}
13431376
| optional_arguments '*' test arguments2 ',' STARSTAR test
1377+
{
1378+
call := $1
1379+
call.Starargs = $3
1380+
call.Kwargs = $7
1381+
if len($4.Args) != 0 {
1382+
yylex.Error("SyntaxError: only named arguments may follow *expression")
1383+
}
1384+
call.Keywords = append(call.Keywords, $4.Keywords...)
1385+
$$ = call
1386+
}
13441387
| optional_arguments STARSTAR test
1388+
{
1389+
call := $1
1390+
call.Kwargs = $3
1391+
$$ = call
1392+
}
13451393

13461394
// The reason that keywords are test nodes instead of NAME is that using NAME
13471395
// results in an ambiguity. ast.c makes sure it's a NAME.
13481396
argument:
13491397
test
1398+
{
1399+
$$ = &ast.Call{}
1400+
$$.Args = []ast.Expr{$1}
1401+
}
13501402
| test comp_for
1403+
{
1404+
$$ = &ast.Call{}
1405+
$$.Args = []ast.Expr{
1406+
&ast.GeneratorExp{ExprBase: ast.ExprBase{$<pos>$}, Elt: $1, Generators: $2},
1407+
}
1408+
}
13511409
| test '=' test // Really [keyword '='] test
1410+
{
1411+
$$ = &ast.Call{}
1412+
test := $1
1413+
if name, ok := test.(*ast.Name); ok {
1414+
$$.Keywords = []*ast.Keyword{&ast.Keyword{Pos: name.Pos, Arg: name.Id, Value: $3}}
1415+
} else {
1416+
yylex.Error("SyntaxError: keyword can't be an expression")
1417+
}
1418+
}
13521419

13531420
comp_iter:
13541421
comp_for

parser/grammar_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ func TestGrammar(t *testing.T) {
131131
{"a==(b<c)", "eval", "Expression(body=Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Compare(left=Name(id='b', ctx=Load()), ops=[Lt()], comparators=[Name(id='c', ctx=Load())])]))"},
132132
{"(a==b)<(c>d)>e", "eval", "Expression(body=Compare(left=Compare(left=Name(id='a', ctx=Load()), ops=[Eq()], comparators=[Name(id='b', ctx=Load())]), ops=[Lt(), Gt()], comparators=[Compare(left=Name(id='c', ctx=Load()), ops=[Gt()], comparators=[Name(id='d', ctx=Load())]), Name(id='e', ctx=Load())]))"},
133133
{"a()", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None))"},
134+
{"a(b)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='b', ctx=Load())], keywords=[], starargs=None, kwargs=None))"},
135+
{"a(b,)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='b', ctx=Load())], keywords=[], starargs=None, kwargs=None))"},
136+
{"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))"},
137+
{"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))"},
138+
{"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())))"},
139+
{"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())))"},
140+
{"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))"},
141+
{"a(a,a=b,*args,**kwargs)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='a', ctx=Load())], keywords=[keyword(arg='a', value=Name(id='b', ctx=Load()))], starargs=Name(id='args', ctx=Load()), kwargs=Name(id='kwargs', ctx=Load())))"},
142+
{"a(a,a=b,*args,e=f,**kwargs)", "eval", "Expression(body=Call(func=Name(id='a', ctx=Load()), args=[Name(id='a', ctx=Load())], keywords=[keyword(arg='a', value=Name(id='b', ctx=Load())), keyword(arg='e', value=Name(id='f', ctx=Load()))], starargs=Name(id='args', ctx=Load()), kwargs=Name(id='kwargs', ctx=Load())))"},
134143
{"a.b", "eval", "Expression(body=Attribute(value=Name(id='a', ctx=Load()), attr='b', ctx=Load()))"},
135144
{"a.b.c.d", "eval", "Expression(body=Attribute(value=Attribute(value=Attribute(value=Name(id='a', ctx=Load()), attr='b', ctx=Load()), attr='c', ctx=Load()), attr='d', ctx=Load()))"},
136145
{"a.b().c.d()()", "eval", "Expression(body=Call(func=Call(func=Attribute(value=Attribute(value=Call(func=Attribute(value=Name(id='a', ctx=Load()), attr='b', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None), attr='c', ctx=Load()), attr='d', ctx=Load()), args=[], keywords=[], starargs=None, kwargs=None), args=[], keywords=[], starargs=None, kwargs=None))"},

parser/make_grammar_test.py

+11
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@
134134

135135
# trailers
136136
("a()", "eval"),
137+
("a(b)", "eval"),
138+
("a(b,)", "eval"),
139+
("a(b,c)", "eval"),
140+
("a(b,*c)", "eval"),
141+
("a(*b)", "eval"),
142+
#("a(*b,c)", "eval"), -test error
143+
("a(b,*c,**d)", "eval"),
144+
("a(b,**c)", "eval"),
145+
("a(a=b)", "eval"),
146+
("a(a,a=b,*args,**kwargs)", "eval"),
147+
("a(a,a=b,*args,e=f,**kwargs)", "eval"),
137148
("a.b", "eval"),
138149
("a.b.c.d", "eval"),
139150
("a.b().c.d()()", "eval"),

0 commit comments

Comments
 (0)