
I used Text.Megaparsec.Expr to write a minimal (56 lines) 2-operator recursive parser. It's on github[1]. It outputs a binary tree of the following form: data AExpr = Var String | Pair AExpr AExpr deriving (Show) The operator table supplied to makeExprParser defines two operators, # and ##. ## binds after #, but both of them refer to the same function, the Pair constructor of the AExpr data type: aOperators :: [[Operator Parser AExpr]] aOperators = [ [ InfixN # symbol "#" *> pure (Pair) ] , [ InfixN # symbol "##" *> pure (Pair) ] ] The # operator works in isolation: > parseMaybe aExpr "a # b" Just (Pair (Var "a") (Var "b")) Parentheses work with the # operator: > parseMaybe aExpr "(a # b) # (c # d)" Just (Pair (Pair (Var "a") (Var "b")) -- whitespace added by hand (Pair (Var "c") (Var "d"))) And the # and ## operators work together as intended: > parseMaybe aExpr "a # b ## c # d" Just (Pair (Pair (Var "a") (Var "b")) -- whitespace added by hand (Pair (Var "c") (Var "d"))) But the ## operator in isolation does not parse! > parseMaybe aExpr "a ## b" Nothing [1] https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/master/howto... -- Jeff Brown | Jeffrey Benjamin Brown Website https://msu.edu/~brown202/ | Facebook https://www.facebook.com/mejeff.younotjeff | LinkedIn https://www.linkedin.com/in/jeffreybenjaminbrown(I often miss messages here) | Github https://github.com/jeffreybenjaminbrown