<div dir="ltr"><div>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:</div><div><br></div><div><font face="monospace, monospace">    data AExpr = Var String | Pair AExpr AExpr deriving (Show)</font></div><div><br></div><div>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:</div><div><br></div><div><font face="monospace, monospace">    aOperators :: [[Operator Parser AExpr]]</font></div><div><font face="monospace, monospace">    aOperators =</font></div><div><font face="monospace, monospace">      [ [ InfixN # symbol "#" *> pure (Pair) ]</font></div><div><font face="monospace, monospace">      , [ InfixN # symbol "##" *> pure (Pair) ]</font></div><div><font face="monospace, monospace">      ]</font></div><div><br></div><div>The # operator works in isolation:</div><div><br></div><div><font face="monospace, monospace">    > parseMaybe aExpr "a # b"</font></div><div><font face="monospace, monospace">    Just (Pair (Var "a") (Var "b"))</font></div><div><br></div><div>Parentheses work with the # operator:</div><div><br></div><div><font face="monospace, monospace">    > parseMaybe aExpr "(a # b) # (c # d)"</font></div><div><font face="monospace, monospace">    Just (Pair (Pair (Var "a") (Var "b")) -- whitespace added by hand</font></div><div><font face="monospace, monospace">               (Pair (Var "c") (Var "d")))</font></div><div><br></div><div>And the # and ## operators work together as intended:</div><div><br></div><div><font face="monospace, monospace">    > parseMaybe aExpr "a # b ## c # d"</font></div><div><font face="monospace, monospace">    Just (Pair (Pair (Var "a") (Var "b")) -- whitespace added by hand</font></div><div><font face="monospace, monospace">               (Pair (Var "c") (Var "d")))</font></div><div><br></div><div>But the ## operator in isolation does not parse!</div><div><br></div><div><font face="monospace, monospace">    > parseMaybe aExpr "a ## b"</font></div><div><font face="monospace, monospace">    Nothing</font></div><div><br></div><div>[1] <a href="https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/master/howto/megaparsec/experim.hs">https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/master/howto/megaparsec/experim.hs</a></div><div><br></div><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div>Jeff Brown | Jeffrey Benjamin Brown</div><div dir="ltr"><a href="https://msu.edu/~brown202/" style="font-size:12.8px" target="_blank">Website</a>   |   <a href="https://www.facebook.com/mejeff.younotjeff" style="font-size:12.8px" target="_blank">Facebook</a>   |   <a href="https://www.linkedin.com/in/jeffreybenjaminbrown" style="font-size:12.8px" target="_blank">LinkedIn</a><span style="font-size:12.8px">(I often miss messages here)   |   </span><a href="https://github.com/jeffreybenjaminbrown" style="font-size:12.8px" target="_blank">Github</a></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>
</div>