I'm a bit late to the party, but LEPL 2.2, just released, can now handle this too. I suspect email may mangle this, so you can also read it at http://www.acooke.org/lepl/examples.html#parsing-a-python-argument-list
from lepl import * comma = Drop(',') none = Literal('None') >> (lambda x: None) bool = (Literal('True') | Literal('False')) >> (lambda x: x == 'True') ident = Word(Letter() | '_', Letter() | '_' | Digit()) float_ = Float() >> float int_ = Integer() >> int str_ = String() | String("'") item = str_ | int_ | float_ | none | bool | ident with Separator(~Regexp(r'\s*')): value = Delayed() list_ = Drop('[') & value[:, comma] & Drop(']') > list tuple_ = Drop('(') & value[:, comma] & Drop(')') > tuple value += list_ | tuple_ | item arg = value >> 'arg' karg = (ident & Drop('=') & value > tuple) >> 'karg' expr = (karg | arg)[:, comma] & Drop(Eos()) > Node parser = expr.string_parser() ast = parser('True, type=rect, sizes=[3, 4], coords = ([1,2],[3,4])') print(ast[0]) which gives: Node +- arg True +- karg (u'type', u'rect') +- karg (u'sizes', [3, 4]) `- karg (u'coords', ([1, 2], [3, 4])) you can then access those values: >>> ast[0].arg [True] >>> ast[0].karg [('type', 'rect'), ('sizes', [3, 4]), ('coords', ([1, 2], [3, 4]))] alternatively, you could avoid using a Node altogether and just put them in a list or whatever.... andrew Paul McGuire wrote: > from pyparsing import * > > LPAR,RPAR,LBRACK,RBRACK,EQ,COMMA = map(Suppress,"()[]=,") > > noneLiteral = Literal("None") > boolLiteral = oneOf("True False") > integer = Combine(Optional(oneOf("+ -")) + Word(nums)).setName > ("integer") > real = Combine(Optional(oneOf("+ -")) + Word(nums) + "." + > Optional(Word(nums))).setName("real") > > ident = Word(alphas+"_",alphanums+"_") > > listStr = Forward().setName("list") > tupleStr = Forward().setName("tuple") > listItem = real | integer | noneLiteral | boolLiteral | \ > quotedString.setParseAction(removeQuotes) | Group(listStr) | > tupleStr | ident > listStr << ( LBRACK + Optional(delimitedList(listItem)) + Optional > (COMMA) + RBRACK ) > tupleStr << (LPAR + Optional(delimitedList(listItem)) + Optional > (COMMA) + RPAR) > > # parse actions perform parse-time conversions > noneLiteral.setParseAction(lambda: None) > boolLiteral.setParseAction(lambda toks: toks[0]=="True") > integer .setParseAction(lambda toks: int(toks[0])) > real .setParseAction(lambda toks: float(toks[0])) > listStr .setParseAction(lambda toks: toks.asList()) > tupleStr .setParseAction(lambda toks: tuple(toks.asList())) > > arg = Group(ident("varname") + EQ + listItem("varvalue")) | listItem > > > argstring = 'True, type=rect, sizes=[3, 4,], coords = ([1,2],[3,4])' > > parsedArgs = delimitedList(arg).parseString(argstring) > args = [] > kwargs = {} > for a in parsedArgs: > if isinstance(a,ParseResults): > if isinstance(a.varvalue,ParseResults): > val = a.varvalue.asList() > else: > val = a.varvalue > kwargs[a.varname] = val > else: > args.append(a) > > print "Args:", args > print "Kwargs:", kwargs > > > Prints: > > Args: [True] > Kwargs: {'coords': ([1, 2], [3, 4]), 'type': 'rect', 'sizes': [3, 4]} > > -- > http://mail.python.org/mailman/listinfo/python-list > > -- http://mail.python.org/mailman/listinfo/python-list