
Hi all, I'm rather new to Haskell and I'm diving right into the deep end writing a parser using Parsec. In particular I'm using Text.ParserCombinators.Parsec.Language to do some of the heavy lifting and have this: import qualified Text.ParserCombinators.Parsec.Language as L import qualified Text.ParserCombinators.Parsec.Token as T lexer = T.makeTokenParser L.emptyDef { L.identStart = letter <|> char '_', L.identLetter = alphaNum <|> char '_', .... identifier :: CharParser st String identifier = T.identifier lexer and now I need to parse things "this.that.the.other". I'd like to have a function with the following signature: qualifiedIdentifier :: CharParser st [ String ] which should return [ "this", "that", "the", "other" ] and write it in terms of identifier and thats where I'm stuck. Anyone care to whack me with the cluestick? Cheers, Erik -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- "If you don't have freedom as a principle, you can never see a reason not to make an exception." -- Richard Stallman.

Erik de Castro Lopo wrote:
qualifiedIdentifier :: CharParser st [ String ]
Ahh, figured it out myself: qualifiedIdentifier :: CharParser st [ String ] qualifiedIdentifier = do i <- identifier r <- dotIdentifier return (i : r) where dotIdentifier = do char '.' i <- identifier r <- dotIdentifier return (i : r) <|> return [] Does that look sane to people who know Haskell and Parsec better than me? Erik -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- The Earth is around 70% water. Fish rule the seas. Humans are over 90% water. It's only a matter of time.

Erik de Castro Lopo schrieb:
Erik de Castro Lopo wrote:
qualifiedIdentifier :: CharParser st [ String ]
Ahh, figured it out myself:
qualifiedIdentifier :: CharParser st [ String ] qualifiedIdentifier = do i <- identifier r <- dotIdentifier return (i : r) where dotIdentifier = do char '.' i <- identifier r <- dotIdentifier return (i : r) <|> return []
Does that look sane to people who know Haskell and Parsec better than me? Hi Erik, have a look at the module Text.ParserCombinators.Parsec.Combinator. Those functions should help you to build up parsers from smaller building blocks.
Using sepBy1, the above parser can be written as dot = T.dot lexer qualifiedIdentifier = sepBy1 identifier dot benedikt

Benedikt Huber wrote:
have a look at the module Text.ParserCombinators.Parsec.Combinator. Those functions should help you to build up parsers from smaller building blocks.
Using sepBy1, the above parser can be written as
dot = T.dot lexer qualifiedIdentifier = sepBy1 identifier dot
WOW!!!! That is really impressive! Thanks, Erik -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- "One serious obstacle to the adoption of good programming languages is the notion that everything has to be sacrificed for speed. In computer languages as in life, speed kills." -- Mike Vanier

Benedikt Huber wrote:
Using sepBy1, the above parser can be written as
dot = T.dot lexer qualifiedIdentifier = sepBy1 identifier dot
My next problem is matching things like: identifier ('.' identifier)* ('.' '*')? I've had a look at lookAhead from Text.ParserCombinators.Parsec.Combinator but I can't get it to work. Clues? Erik -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- "That being done, all you have to do next is call free() slightly less often than malloc(). You may want to examine the Solaris system libraries for a particularly ambitious implementation of this technique." -- Eric O'Dell (comp.lang.dylan)

On Wed, Dec 24, 2008 at 9:22 AM, Erik de Castro Lopo
My next problem is matching things like:
identifier ('.' identifier)* ('.' '*')?
I've had a look at lookAhead from Text.ParserCombinators.Parsec.Combinator but I can't get it to work.
* is analogous to the 'many' combinator, and ? can be implemented with the 'option' combinator. Parsec is all about composing bigger parsers out of smaller ones using combinators like these. One of the tricks I found early on is to understand where to use 'try' (since by default input is consumed even if a parser fails) but apart from that just read Daan's page, even though it's out of date, and look at how all these cool combinators work. http://legacy.cs.uu.nl/daan/download/parsec/parsec.html

Toby Hutton wrote:
One of the tricks I found early on is to understand where to use 'try' (since by default input is consumed even if a parser fails) but apart from that just read Daan's page, even though it's out of date, and look at how all these cool combinators work.
Ah yes, reading that document and using 'try' is a good tip. This is what I cam up with: qualifiedIdentStar :: CharParser st [ String ] qualifiedIdentStar = do try identDotStar <|> qualifiedIdentifier where identDotStar = do s <- sepEndBy1 identifier dot char '*' return (s ++ [ "*" ]) Cheers, Erik -- ----------------------------------------------------------------- Erik de Castro Lopo ----------------------------------------------------------------- "It has been discovered that C++ provides a remarkable facility for concealing the trival details of a program -- such as where its bugs are." -- David Keppel
participants (3)
-
Benedikt Huber
-
Erik de Castro Lopo
-
Toby Hutton