Python: parse commandline
Question: I'm writing a CLI application in python with is used by means of a rather
elaborate commandline language. The idea is very similar to find(1) which
arguably has the same property.

Currently, the parser is completely handwritten using a handmade EBNF
description language. The problem is that this language is very awkward to use
because I have to write everything as python structures. I also feel that my
program is still way too bloated because of the parsing.

Is there any lib that features ease of use, and a true description language
(input as string/document) for commandline parsing? From the syntax tree, I
would like to directly map each item to a class instance. Naturally, I don't
want a tokenizer, or at least the tokenizer must map straight from commandline
arguments to tokens.

Thanks for all suggestions!

_UPDATE_ : The whole point of my program is to generate objects and pass them
through any number of filters (possibly unpure/effectful actions) that might
or might not output the objects again, or might even output objects of another
type. The general idea is obviously gleaned from find(1). An example
commandline would be:

    
    
    ~/picdb.py -sqlselect 'select * from pics where dirname like "testdir%"' -tagged JoSo  -updateFromFile [ -resx +300 -or -resX +200 -resY +500 ] -printfXml '<jpegfile><src>%fp</src><DateTimeOriginal>%ed</DateTimeOriginal><Manufacturer>%eM</Manufacturer><Model>%em</Model></jpegfile>%NL'
    


Answer: This is a very tricky problem...You can "bind" actions to commandline
arguments using argparse quite easily (e.g. create a class, operate on a
previously created class ...). Here's a silly example of that...(argument
--foo creates an object, argument --bar modifies the object created by --foo).

    
    
    from argparse import ArgumentParser,Action
    
    class Foo(object):
        def __init__(self,*args):
            self.args=args
        def __str__(self):
            return str(self.args)
    
    class FooAction(Action):
        def __call__(self,parser,namespace,values,option_string=None):
            setattr(namespace,self.dest,Foo(*values))  #Add Foo to the options...
    class BarAction(Action):
        def __call__(self,parser,namespace,values,option_string=None):
            FooObj=getattr(namespace,'foo')  #raises an error if foo isn't in namespace...
                                             #In this way, BarAction is like a filter on the
                                             #object created by foo.
            FooObj.args=tuple(list(FooObj.args)+list(values)) #append to the list of args.
    
    parser=ArgumentParser()
    parser.add_argument('--foo',nargs='*',action=FooAction,help="Foo!")
    parser.add_argument('--bar',nargs='*',action=BarAction,help="Bar! : Must be used after --foo")
    
    namespace=parser.parse_args("--foo Hello World --bar Nice Day".split())
    print (namespace)
    print (namespace.foo)
    

However, this is a little different from yours in that `-argument` is not
really possible with argparse, only `-a` or `--argument`. That may already be
a deal breaker for you, I'm not sure...

The next difficulty is dealing with the brackets... `[` and `]`. If you can
treat those as arguments to a different commandline option, you might be
OK...You might be able to set up a second parser to parse out the inside
portions -- but I've never tried anything like that before... (If anyone else
has any ideas about how to deal with the brackets, I'd be very interested to
hear them).

As far as `optparse` and `getopt` are concerned, I'm pretty sure that anything
you can do with them, you can do with argparse, which is why I've left them
out of the discussion.

