[Haskell-beginners] parsec question

Michael Mossey mpm at alumni.caltech.edu
Mon Jul 19 03:41:01 EDT 2010


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

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