-
Notifications
You must be signed in to change notification settings - Fork 21
Improve default error #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve default error #57
Conversation
It's really unfortunate that With that type, and you can recover the same error as this library with: or write a That aside, this PR would already be a breaking change because of switching from |
To clarify, how would it be a breaking change? AFAICT, the only thing changing is the runtime code, which isn't supposed to be touched by people anyway. I didn't add a |
I would prefer the parsing approach. I did it this way because it ensures this code isn't breaking. It might be worth it to make a release with this change as is, and then a breaking changes release that switches completely to the parsing approach. That way, people can still benefit from other work done here (e.g. the |
I'm sorry, you're correct. It's not a breaking change; any pattern-matching will continue working. |
That can still be released separately, as it's already merged. I think it's also fine to release the newtype change before any breaking changes. I might not want to release a |
Should I submit a different PR that just does the newtype change? I included it here because it was something I noticed when working on this one. |
Yea, perhaps do that so that this PR can focus only on the error type discussion. I'm happy to merge the newtype change. |
I've updated this PR to remove the newtype change commit |
While I would like to hear what others say, I would argue that we make this breaking change now rather than later for two reasons. First, most people expect |
I think changing ParseError to include a position as well as a message sounds sensible. That sounds like the kind of breaking change which would be worth doing, especially since we are about to have a round of breaking changes anyway for the upcoming 0.14 release (I’d suggest waiting until then to release this change). |
Three in favor is pretty good. Let's go ahead and move to that representation, then, and it can be released as a breaking change along with anything else for 0.14 / anything from #59. |
I've rebased on master, then made |
I was actually thinking we'd make a larger change: update the |
How should that be done when #48 is involved? |
I'm not sure. Perhaps this change could be rolled in to #59? |
I think this change is orthogonal to #48, so the question is probably just "which one would you rather do first?" |
I would say, though, that I'd recommend keeping the scope of #59 narrow, because code points versus code units is a subtle issue which will need a bit of care taken over it. |
If no one is against this, I'll merge this one in before merging #63. |
I thought we had reached a consensus for the approach where the error type is a record containing a message and a position instead? |
It's been so long, I couldn't remember. I'll have to read through the thread again, but most likely. |
This message is a good summary. We're basically doing the same thing from |
How's this? |
|
||
-- | A parser is represented as a function which takes a pair of | ||
-- | continuations for failure and success. | ||
newtype Parser a = Parser (PosString -> Either { pos :: Pos, error :: ParseError } { result :: a, suffix :: PosString }) | ||
newtype Parser a = Parser (PosString -> Either ParseError { result :: a, suffix :: PosString }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could potentially create a type alias for this, too:
newtype Parser a = Parser (PosString -> Either ParseError { result :: a, suffix :: PosString }) | |
type ParseResult a = { result :: a, suffix :: PosString } | |
newtype Parser a = Parser (PosString -> Either ParseError (ParseResult a)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same record is used in several places, so this would just reduce a bit of duplication. It's not necessary, though.
src/Text/Parsing/StringParser.purs
Outdated
|
||
-- | A parser is represented as a function which takes a pair of | ||
-- | continuations for failure and success. | ||
newtype Parser a = Parser (PosString -> Either { pos :: Pos, error :: ParseError } { result :: a, suffix :: PosString }) | ||
newtype Parser a = Parser (PosString -> Either ParseError { result :: a, suffix :: PosString }) | ||
|
||
-- | Run a parser by providing success and failure continuations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These documentation comments seem a bit funky to me; they keep talking about continuations, but that's not what I interpret from this function. Am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking the same thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think this can be removed.
src/Text/Parsing/StringParser.purs
Outdated
runParser :: forall a. Parser a -> String -> Either String a | ||
runParser (Parser p) s = bimap printError _.result (p { str: s, pos: 0 }) | ||
where | ||
printError :: ParseError -> String | ||
printError rec = rec.error <> "; pos = " <> show rec.pos |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about having runParser
be forall a. Parser a -> String -> Either ParseError a
, and then having a separate printError
function? That's a bit more flexible than the current definition (you can recover the current definition with lmap printError
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed in latest commits.
CI now passes. |
src/Text/Parsing/StringParser.purs
Outdated
|
||
-- | A parser is represented as a function which takes a pair of | ||
-- | continuations for failure and success. | ||
newtype Parser a = Parser (PosString -> Either { pos :: Pos, error :: ParseError } { result :: a, suffix :: PosString }) | ||
newtype Parser a = Parser (PosString -> Either ParseError { result :: a, suffix :: PosString }) | ||
|
||
-- | Run a parser by providing success and failure continuations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think this can be removed.
How about the latest changes to the docs I've made? |
What does this pull request do?
Fixes #56
Fixes #34