[Haskell-cafe] Two questions regarding Alex/Parsec

Niels Aan de Brugh nielsadb at gmail.com
Tue Jun 24 17:04:42 EDT 2008

Hello Haskellers,

As an experiment I'm writing a parser for MediaWiki language. I'm using
the Alex lexer and Parsec. I have novice two questions.

(I've tried using Happy but I was unable to get a grammar file to
compile, which must be because I have no real experience using Yacc and
the like. I've also attempted to write an ad-hoc recursive descent
parser, but that become too complex to be fun very quickly.)

== SourcePos and AlexPosn ==

My first question is about Parsec's SourcePos. I have a definition like:

  type LexToken = (AlexPosn, Token)

  type MWP a = GenParser LexToken () a

  toSourcePos :: AlexPosn -> SourcePos
  toSourcePos (AlexPn _ line col) = undefined

  mwtok :: (Token -> Maybe a) -> MWP a
  mwtok test = token showToken posToken posTest
               showToken = show . snd
               posToken = toSourcePos . fst
               posTest = test . snd

The definition of toSourcePos isn't 100% satisfactory. The constructor
SourcePos is hidden, so I cannot simply use (SourcePos line col). Is
there a way to convert an AlexPosn value to a SourcePos?

== Data Constructors as Parameters and Tags ==

Secondly, I frequently encounter the pattern where I try to match a
token, return Just some result if it matches, and Nothing otherwise. So
I tried to fix this pattern in a nice reusable function.

  onTok0 :: Token -> a -> MWP a
  onTok0 t x = mwtok (\tok -> if tok `isTok` t then Just x else Nothing)

This seems to work, but I'd also like a definition for data constructors
taking one parameter:

  onTok1 :: (a -> Token) -> (a -> b) -> MWP b
  onTok1 t f = mwtok (\tok -> case tok of
                                   (t n) = Just $ f n
                                   _ = Nothing)

This doesn't work, the pattern match (t n) fails, which is
understandable: n is used as a parameter to t and a matched result,
which looks like a paradox. t is a function (constructor) but also a
tag. Is it possible to pass a tag as an argument? Or is there another
way to extract this pattern?


More information about the Haskell-Cafe mailing list