{-# 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