optparse-applicative

Я пытаюсь использовать библиотеку optparse-applicative в программе, которая должен выполнять разные действия в зависимости от количества аргументов.

Например, разбор аргумента для программы, вычисляющей периметры:

module TestOpts where

import Options.Applicative

type Length = Double

data PerimeterCommand
    = GeneralQuadranglePerimeter Length Length Length Length
    | RectanglePerimeter Length Length

parsePerimeterCommand :: Parser PerimeterCommand
parsePerimeterCommand = parseQuadPerimeter <|> parseRectPerimeter

parseQuadPerimeter = GeneralQuadranglePerimeter <$>
                     parseLength "SIDE1" <*>
                     parseLength "SIDE2" <*>
                     parseLength "SIDE3" <*>
                     parseLength "SIDE4"

parseRectPerimeter = RectanglePerimeter <$>
                     parseLength "WIDTH" <*> parseLength "HEIGHT"

parseLength name = argument auto (metavar name)

Только первый аргумент <|> будет успешно проанализирован. Я думаю, что требуется какой-то возврат аргумента, подобный комбинатору Parsec try.

Любые идеи о том, как анализировать альтернативные наборы аргументов, когда первая альтернатива может использовать некоторые аргументы следующей альтернативы?


person rvl    schedule 21.09.2014    source источник
comment
Глядя на реализацию runParser, можно предположить, что она не может вернуться назад, но я не уверен на 100%. Можете ли вы изменить аргументы вашей программы, используя вспомогательные парсеры команд?   -  person Christian Conkle    schedule 22.09.2014
comment
Спасибо за идею. Это может работать для программы расчета периметра формы. Но в моем реальном приложении отдельные подпарсеры команд не подходят.   -  person rvl    schedule 29.09.2014


Ответы (1)


Обратите внимание: этот ответ был написан автором приложения optparse Паоло Каприотти.

Вы не можете сделать это напрямую с помощью optparse-applicative. Основная особенность optparse-applicative заключается в том, что параметры можно анализировать в любом порядке. Если вы хотите работать в основном с аргументами (которые являются позиционными), вам лучше иметь два уровня парсеров: используйте many argument в optparse-applicative, затем передайте полученный массив обычному парсеру (скажем, используя Parsec). Если у вас есть только позиционные аргументы, то optparse-applicative не сильно вам поможет, и вы можете просто проанализировать аргументы вручную с помощью Parsec.

person rvl    schedule 12.08.2015