2012-04-28 5 views
1

Я пишу приложение CLI в python с использованием довольно сложного языка командной строки. Идея очень похожа на находку (1), которая, возможно, имеет такое же свойство.Python: команда синтаксического анализа

В настоящее время синтаксический анализатор полностью рукописный, используя ручной язык описания EBNF. Проблема в том, что этот язык очень неудобен для использования, потому что я должен писать все как структуры python. Я также чувствую, что моя программа все еще слишком раздута из-за разбора.

Есть ли lib, который отличается простотой использования и истинным языком описания (ввод как строка/документ) для синтаксического анализа командной строки? Из дерева синтаксиса я хотел бы непосредственно сопоставить каждый элемент с экземпляром класса. Естественно, я не хочу токенизатор, или, по крайней мере, токенизатор должен отображаться прямо из аргументов командной строки в токены.

Спасибо за все предложения!

UPDATE: Весь смысл моей программы для создания объектов и передавать их через любое количество фильтров (возможно, недостаточные чистоту/effectful действий), которые могут включать или не выводить объекты снова, или даже может выводить объекты других тип. Общая идея, очевидно, почерпнута из find (1). Пример командной строки:

~/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' 
+2

Может ли [argparse] (http://docs.python.org/library/argparse.html#module-argparse) (python 2.7+) удовлетворить ваши потребности? – Aufwind

+0

В дополнение к комментарию @Aufwind - вам не нужно * иметь python 2.7 или новее для пользователя argparse. Он отлично работает со старыми версиями python - вам просто нужно установить, если вы сами (в отличие от того, чтобы быть включенным в стандартную библиотеку). – mgilson

+0

Я думаю, что если бы вы описали свою командную строку (или, по крайней мере, дали пример или два), мы могли бы увидеть, является ли это кандидатом для argparse/optparse ... – mgilson

ответ

3

Это очень сложная проблема ... Вы можете «привязать» действия к аргументам командной строки, используя argparse довольно легко (например, создать класс, работать с ранее созданным классом ...). Вот глупый пример этого ... (аргумент --foo создает объект, аргумент --bar модифицирует объект, созданный --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) 

Однако, это немного отличается от вашего, что -argument не представляется возможным с argparse, только -a или --argument. Это, возможно, уже было для вас нарушением сделки, я не уверен ...

Следующая трудность связана с скобками ... [ и ]. Если вы можете рассматривать их как аргументы для другой опции командной строки, возможно, все в порядке ... Возможно, вы сможете настроить второй парсер для анализа внутренних частей, но я никогда не пробовал ничего подобного раньше. . (Если у кого-то еще есть идеи о том, как иметь дело с скобками, мне было бы очень интересно их услышать).

Что касается optparse и getopt, я уверен, что все, что вы можете с ними сделать, вы можете сделать с помощью argparse, поэтому я оставил их вне обсуждения.

+0

Большое спасибо за ваши усилия. Это означает, что, вероятно, я останусь с моим решением ручной работы. –

1

Существует, по крайней мере, три модуля, которые вы могли бы попробовать; argparse, optparse (устарел в 2.7) и getopt. См. Главу 15 руководства по стандартной библиотеке Python.

Смежные вопросы