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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 3 additions & 1 deletion
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

Lines changed: 70 additions & 3 deletions
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

Lines changed: 9 additions & 0 deletions
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

Lines changed: 11 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy