This was Parsec's legacy that we should eliminate now. ‘Message’ does
not constitute enumeration, ‘toEnum’ was never properly defined for
it. The idea to use ‘fromEnum’ to determine type of ‘Message’ is also
ugly, for this purpose new functions ‘isUnexpected’, ‘isExpected’, and
‘isMessage’ are defined in ‘Text.Megaparsec.Error’.
This also enables the respective warnings flags in dev mode
to help megaparsec remain forward compatible.
The dependencies on `semigroup` and `fail` are conditional on
`impl(ghc >= 8)` and avoid CPP and conditionally defined instances
(which would result in an conditional API).
Close#81.
This solution is mostly OK as it passes tests and almost all benchmarks
show that there is no performance degradation.
The only function that bothers me is ‘pPlus’ (or ‘mplus’, or
‘<|>’). Benchmarks ‘choice/match’, ‘choice/nomatch’, and ‘manyTill’ show
about 44 % worse performance with current implementation of the feature
— this is not acceptable. All these functions are defined via ‘mplus’,
so it's necessary to find a way to improve that function.
Also, ‘mplus’ is tricky in that it combines different branches of
parsing. Previously, all logic describing how to combine failing
branches into one ‘ParseError’ were in ‘mergeError’ function. Now we
have to have ‘longestMatch’ function to choose right state as well,
because it's natural to expect that state on failure would correspond to
‘ParseError’. This should be done elegantly.
In particular, if input has no newline at the end, we need to treat it
specially, because otherwise we will get confusing “incorrect
indentation” message.
Close#75.
Now accumulated hints are not used with ‘ParseError’ records that have
only custom messages in them (created with ‘Message’ constructor, as
opposed to ‘Unexpected’ or ‘Expected’). This strips “expected” line from
custom error messages where it's unlikely to be relevant anyway.