[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