[Haskell-cafe] Why is Megaparsec treating these two operators differently?

Jeffrey Brown jeffbrown.the at gmail.com
Sun May 14 06:53:19 UTC 2017


The problem's not solved! Check out this weirdness. |+| and |-| are
supposed to be identical, mapping to the same function, the Pair
constructor.

    > mapM_ putStrLn exprs
    a |+| b
    a |-| b
    a |+| b |-| c
    a |-| b |+| c
    a |+| b   |-|  c |+| d
    > mapM_ putStrLn $ map (show . parseMaybe aExpr) exprs
    Just (Pair (Var "a") (Var "b"))
    Nothing
    Just (Pair (Pair (Var "a") (Var "b")) (Var "c"))
    Nothing
    Just (Pair (Pair (Var "a") (Var "b")) (Pair (Var "c") (Var "d")))

Why the two failures?

If I change them from InfixN to InfixR or InfixL, then only the first of
those five expressions parses.

Here are two relevant definitions:

    data AExpr = Var String | Pair AExpr AExpr deriving (Show)

    aOperators :: [[Operator Parser AExpr]]
    aOperators =
      [ [ InfixN $ symbol "|+|" *> pure (Pair) ]
      , [ InfixN $ symbol "|-|" *> pure (Pair) ] -- binds last, I think
      ]

And here is the code in full[1].

Thanks,
Jeff


[1]
https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/master/howto/megaparsec/minimal.hs


On Sun, Oct 23, 2016 at 2:50 PM, Brandon Allbery <allbery.b at gmail.com>
wrote:

> Aha. I had forgotten some details.
>
> If you want to have an operator that is a prefix of another operator in
>> the table, use the following (or similar) wrapper instead of plain symbol
>> :
>> op n = (lexeme . try) (string n <* notFollowedBy punctuationChar)
>
> http://hackage.haskell.org/package/megaparsec-5.1.1/docs/
> Text-Megaparsec-Expr.html#v:makeExprParser
>
> So you actually need to be a little clever for those two operators to
> work; it's not as simple as I had recalled it (which would have been
> correct for a basic manual combinator setup). I am going to guess that
> something in there is not using `try` and silently consuming the extra "#",
> but I'd have to study the `makeExprParser` code in Megaparsec to be certain.
>
> On Sun, Oct 23, 2016 at 5:38 PM, Jeffrey Brown <jeffbrown.the at gmail.com>
> wrote:
>
>> Thanks, Brandon! How did you know that?
>>
>> I changed them to "#1" and "#2" and now it works[1].
>>
>> But before making that change, why would "a # b ## c # d" evaluate, even
>> though "a ## b" would not?
>>
>>
>> [1] https://github.com/JeffreyBenjaminBrown/digraphs-with-text/
>> tree/master/howto/megaparsec
>> The corrected file is called "experim.hs"; the old one, uncorrected, is
>> called "experim.buggy.hs".
>>
>> On Sun, Oct 23, 2016 at 2:03 PM, Brandon Allbery <allbery.b at gmail.com>
>> wrote:
>>
>>>
>>> On Sun, Oct 23, 2016 at 4:15 PM, Jeffrey Brown <jeffbrown.the at gmail.com>
>>> wrote:
>>>
>>>>       [ [ InfixN # symbol "#" *> pure (Pair) ]
>>>>       , [ InfixN # symbol "##" *> pure (Pair) ]
>>>>       ]
>>>>
>>>
>>> Combinator parsers can't rearrange themselves to do longest token
>>> matching. So the ## operator will take the first case, match against
>>> `symbol "#"` and aOperator will succeed; the the next token match will hit
>>> the unconsumed "#" and fail. If you place "##" first then it will match
>>> "##" but not "#", which would the match the second rule.
>>>
>>> --
>>> brandon s allbery kf8nh                               sine nomine
>>> associates
>>> allbery.b at gmail.com
>>> ballbery at sinenomine.net
>>> unix, openafs, kerberos, infrastructure, xmonad
>>> http://sinenomine.net
>>>
>>
>>
>>
>> --
>> 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>
>>
>
>
>
> --
> brandon s allbery kf8nh                               sine nomine
> associates
> allbery.b at gmail.com
> ballbery at sinenomine.net
> unix, openafs, kerberos, infrastructure, xmonad
> http://sinenomine.net
>



-- 
Jeff Brown | Jeffrey Benjamin Brown
Website <https://msu.edu/~brown202/>   |   Facebook
<https://www.facebook.com/mejeff.younotjeff>   |   LinkedIn
<https://www.linkedin.com/in/jeffreybenjaminbrown>(spammy, so I often miss
messages here)   |   Github <https://github.com/jeffreybenjaminbrown>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20170513/40975f98/attachment.html>


More information about the Haskell-Cafe mailing list