[Haskell-beginners] Re: parsec question
Christian Maeder
Christian.Maeder at dfki.de
Mon Jul 19 05:44:41 EDT 2010
Michael Mossey schrieb:
> Here's what I eventually came up with. I decided to make a function
> parseArg that can parse either "v" args or "c" args, and use
>
> sepBy parseArg space
You may want to reject duplicate v or c args rather than to discard them
silently.
You can do so by checking the list before returning "Play singleV
singleC" and use the "fail" or "unexpected" parser for non-proper lists.
C.
>
> to parse all the args on the command line. I created the algebraic type
> Arg to express both kinds of args, which I call Verts and Chans, so that
> parseArg can have the signature
>
> parseArg :: Parser Arg
>
> and parsing the whole command line:
>
> parseArgs :: Parser [Arg]
>
> Then I grab the first Verts and first Chans from the resulting list, and
> ignore the other ones (if any others are present). I use fromMaybe to
> supply a default value.
>
>
>
>
> data Command = Forward Int
> | Backward Int
> | Jump Int
> | Play Int [Int]
> | Quit
> deriving (Show)
>
> data Arg = Verts Int
> | Chans [Int]
> deriving (Show)
>
> integer :: Parser Int
> integer = do ds <- many1 digit
> return (read ds)
>
> digitList :: Parser [Int]
> digitList = do d <- digit
> remainder <- digitList
> return $ read [d] : remainder
> <|>
> return []
>
> -- Parse an argument for the p command.
> -- Note that so-called "v" args are now just bare integers.
> -- "c" args are still prefaced with a "c"
> parseArg :: Parser Arg
> parseArg = do fmap Verts integer
> <|>
> do char 'c'
> fmap Chans digitList
>
> parseArgs :: Parser [Arg]
> parseArgs = sepBy parseArg space
>
> parseP :: Parser Command
> parseP = (do many space
> -- Zero or more arguments may be present.
> -- We will consider at most one "v" argument
> -- and at most one "c" argument. There are
> -- default values for the "V" and "C" arguments
> -- when none are present.
> args <- parseArgs
> let vArgs = [i | Verts i <- args]
> cArgs = [c | Chans c <- args]
> singleV = fromMaybe 1 (listToMaybe vArgs)
> singleC = fromMaybe [] (listToMaybe cArgs)
> return $ Play singleV singleC)
> <|>
> (return $ Play 1 [])
>
>
> parseCommand :: Parser Command
> parseCommand = do char 'j'
> fmap Jump integer
> <|>
> do char 'f'
> fmap Forward (option 1 integer)
> <|>
> do char 'b'
> fmap Backward (option 1 integer)
> <|>
> do char 'p'
> parseP
> <|>
> do char 'q'
> return Quit
>
>
> runParse :: String -> Either String Command
> runParse s = case parse parseCommand "" s of
> Left err -> Left $ show err
> Right x -> Right x
>
More information about the Beginners
mailing list