9

I'm going through the Write yourself a scheme in 48 hours tutorial.

 symbol :: Parser Char
 symbol = oneOf "!#$%&|*+-/:<=>?@^_~"

This is great for symbols, but what if I have a list of keywords? (i.e. struct, int)

can oneOf be adapted to lists? This is ideally what I want, depicted below.

keywords :: Parser String 
keywords = oneOf ["struct","int",..etc]

Or should I import Text.Parsec.Char and try to mapM string over the list of keywords?

I'm attempting to tokenize and just wanted to know what best practices were from others who have gone down this road.

The docs say to use something like this:

 divOrMod    =   string "div" 
              <|> string "mod"

http://hackage.haskell.org/packages/archive/parsec/3.0.0/doc/html/Text-Parsec-Char.html

The Internet
  • 7,959
  • 10
  • 54
  • 89

1 Answers1

11

The general form of this is the choice combinator, which has the following type:

choice :: Stream s m t => [ParsecT s u m a] -> ParsecT s u m a

Basically, you give it a list of parsers, and it tries them in order until one succeeds. choice is implemented using (<|>), so it's the same as that approach.

In your case, to match a list of keywords but no other parsers, you can just map string over a list of Strings and then use choice on that.

On the other hand, mapM string would do something entirely different--it would expect all of the parsers to succeed in order.

C. A. McCann
  • 76,893
  • 19
  • 209
  • 302
  • 1
    keys = ["class", "constructor"...] keywords = choice $ map string keys. Am I using a newer version of Parsec? No instance for (Text.Parsec.Prim.Stream s0 m0 Char) arising from a use of `string' – The Internet Feb 22 '13 at 14:39
  • 1
    @Dave: Try giving it an explicit type signature. – C. A. McCann Feb 22 '13 at 14:40
  • 2
    @Dave: That's the "Dreaded Monomorphism Restriction" in action. If you prefer, put `{-# LANGUAGE NoMonomorphismRestriction #-}` at the top of your file. This can save some hassle while writing a parser. – C. A. McCann Feb 22 '13 at 15:06