[Haskell-cafe] Recursive attoparsec
Leonard Wörteler
leo at woerteler.de
Wed Oct 5 17:05:47 UTC 2016
Am 05.10.2016 um 14:32 schrieb Lian Hung Hon:
> Given
>
> data Expression = ExpToken String | ExpAnd Expression Expression
>
> How to write an attoparsec parser that parses this example:
>
> "a" and "b" and "c"
>
> into
>
> ExpAnd (ExpToken "a") (ExpAnd (ExpToken "b") (ExpToken "c"))?
You can re-implement `chainr1` from Parsec as follows:
chainr1 :: Parser a -> Parser (a -> a -> a) -> Parser a
chainr1 p op = scan
where
scan = p >>= rest
rest x = op <*> pure x <*> scan <|> return x
Then you just plug in your parsers for variables and the `and` operator.
Working example attached.
-- Leo
-------------- next part --------------
{-# LANGUAGE OverloadedStrings #-}
import Data.Attoparsec.ByteString.Char8
(
Parser, parseOnly,
char8, string, anyChar, skipSpace,
manyTill, endOfInput
)
import Control.Applicative ((<|>))
data Expression
= ExpToken String
| ExpAnd Expression Expression
deriving (Eq, Show)
main :: IO ()
main = print $ parseOnly expression "\"a\" and \"b\" and \"c\""
expression :: Parser Expression
expression = chainr1 varP andP <* skipSpace <* endOfInput
chainr1 :: Parser a -> Parser (a -> a -> a) -> Parser a
chainr1 p op = scan
where
scan = p >>= rest
rest x = op <*> pure x <*> scan <|> return x
varP :: Parser Expression
varP = ExpToken <$> (skipSpace *> char8 '"' *> manyTill anyChar (char8 '"'))
andP :: Parser (Expression -> Expression -> Expression)
andP = skipSpace *> string "and" *> pure ExpAnd
More information about the Haskell-Cafe
mailing list