converting a string to a function parameter

andrew cooke andrew at acooke.org
Sat Mar 28 12:37:51 CET 2009


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
>
>





More information about the Python-list mailing list