optparse-applicative Backtracking

假如想象 提交于 2019-12-01 23:28:02

问题


I'm trying to use the optparse-applicative library in an program which should perform a different action depending on the number of arguments.

For example, the argument parsing for a program which calculates perimeters:

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)

Only the first argument to <|> will ever successfully parse. I think some kind of argument backtracking is required, similar to Parsec's try combinator.

Any ideas on how to parse alternative sets of arguments, when the first alternative may consume some arguments of the next alternative?


回答1:


Please note: this answer was written by the optparse-applicative author, Paolo Capriotti.

You can't do this with optparse-applicative directly. The main feature of optparse-applicative is that options can be parsed in any order. If you want to work mainly with arguments (which are positional), you are better off having two levels of parsers: use many argument in optparse-applicative, then pass the resulting array to a normal parser (say using Parsec). If you only have positional arguments, then optparse-applicative won't buy you very much, and you could just parse the arguments manually with Parsec.



来源:https://stackoverflow.com/questions/25956558/optparse-applicative-backtracking

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!