Recursive attoparsec

Dear cafe, 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"))? Regards, Hon

On 2016-10-05 08:32 AM, Lian Hung Hon wrote:
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"))?
Consider using sepBy1 to obtain ["a", "b", "c"] first. Then you're just a foldr away.

On 2016-10-05 08:32 AM, Lian Hung Hon wrote:
Dear cafe,
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 use recursion at Haskell level: expParser = do left <- ExpToken <$> stringLiteral (string "|" *> (ExpAnd left <$> expParser) <|> pure left)

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

Dear guys,
Thanks! chainr and chainl are exactly what I was looking for. I did
something along the lines of
andParser = ExpAnd <$> ((stringParser <|> andParser) <* "and") <*>
(stringParser <|> andParser)
I can see now, why that wouldn't work!
Regards,
Hon
On 6 October 2016 at 01:05, Leonard Wörteler
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
participants (4)
-
Albert Y. C. Lai
-
Leonard Wörteler
-
Lian Hung Hon
-
Mario Blažević