Skip to content

Commit cd2f7ac

Browse files
author
whitequark
committed
Rewrite the arglist rule to actually match the Python grammar.
Fixes #5.
1 parent f8c8392 commit cd2f7ac

File tree

2 files changed

+30
-23
lines changed

2 files changed

+30
-23
lines changed

pythonparser/parser.py

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,13 +1805,9 @@ def classdef__30(self, class_loc, name_tok, arglist_opt, colon_loc, body):
18051805
name_loc=name_tok.loc, colon_loc=colon_loc,
18061806
loc=class_loc.join(body[-1].loc))
18071807

1808-
@action(Rule("argument"))
1809-
def arglist_1(self, arg):
1810-
return [arg], self._empty_arglist()
1811-
18121808
@action(Seq(Loc("*"), Rule("test"), Star(SeqN(1, Tok(","), Rule("argument"))),
18131809
Opt(Seq(Tok(","), Loc("**"), Rule("test")))))
1814-
def arglist_2(self, star_loc, stararg, postargs, kwarg_opt):
1810+
def arglist_1(self, star_loc, stararg, postargs, kwarg_opt):
18151811
dstar_loc = kwarg = None
18161812
if kwarg_opt:
18171813
_, dstar_loc, kwarg = kwarg_opt
@@ -1828,31 +1824,32 @@ def arglist_2(self, star_loc, stararg, postargs, kwarg_opt):
18281824
star_loc=star_loc, dstar_loc=dstar_loc, loc=None)
18291825

18301826
@action(Seq(Loc("**"), Rule("test")))
1831-
def arglist_3(self, dstar_loc, kwarg):
1827+
def arglist_2(self, dstar_loc, kwarg):
18321828
return [], \
18331829
ast.Call(args=[], keywords=[], starargs=None, kwargs=kwarg,
18341830
star_loc=None, dstar_loc=dstar_loc, loc=None)
18351831

1836-
@action(SeqN(0, Rule("argument"), Tok(",")))
1837-
def arglist_4(self, arg):
1838-
return [], ([arg], self._empty_arglist())
1839-
1840-
@action(Alt(Seq(Star(SeqN(0, Rule("argument"), Tok(","))),
1841-
Alt(arglist_1, arglist_2, arglist_3)),
1842-
arglist_4))
1843-
def arglist(self, pre_args, rest):
1844-
# Python's grammar is very awkwardly formulated here in a way
1845-
# that is not easily amenable to our combinator approach.
1846-
# Thus it is changed to the equivalent:
1847-
#
1848-
# arglist: (argument ',')* ( argument | ... ) | argument ','
1849-
#
1832+
@action(Seq(Rule("argument"),
1833+
Alt(SeqN(1, Tok(","), Alt(Rule("arglist_1"),
1834+
Rule("arglist_2"),
1835+
Rule("arglist_3"),
1836+
Eps())),
1837+
Eps())))
1838+
def arglist_3(self, arg, cont):
1839+
if cont is None:
1840+
return [arg], self._empty_arglist()
1841+
else:
1842+
args, rest = cont
1843+
return [arg] + args, rest
1844+
1845+
@action(Alt(Rule("arglist_1"),
1846+
Rule("arglist_2"),
1847+
Rule("arglist_3")))
1848+
def arglist(self, args, call):
18501849
"""arglist: (argument ',')* (argument [','] |
18511850
'*' test (',' argument)* [',' '**' test] |
18521851
'**' test)"""
1853-
post_args, call = rest
1854-
1855-
for arg in pre_args + post_args:
1852+
for arg in args:
18561853
if isinstance(arg, ast.keyword):
18571854
call.keywords.append(arg)
18581855
elif len(call.keywords) > 0:

pythonparser/test/test_parser.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,16 @@ def test_call(self):
835835
" ^^ dstar_loc"
836836
"~~~~~~ loc")
837837

838+
self.assertParsesExpr(
839+
{"ty": "Call", "func": self.ast_x, "starargs": None, "kwargs": self.ast_z,
840+
"args": [self.ast_1], "keywords": []},
841+
"x(1, **z)")
842+
843+
self.assertParsesExpr(
844+
{"ty": "Call", "func": self.ast_x, "starargs": None, "kwargs": None,
845+
"args": [self.ast_1, self.ast_2], "keywords": []},
846+
"x(1, 2,)")
847+
838848
self.assertParsesExpr(
839849
{"ty": "Call", "func": self.ast_x, "starargs": None, "kwargs": None,
840850
"keywords": [], "args": [

0 commit comments

Comments
 (0)