{"action":"created","issue":{"url":"https://api.github.com/repos/mrkkrp/megaparsec/issues/80","repository_url":"https://api.github.com/repos/mrkkrp/megaparsec","labels_url":"https://api.github.com/repos/mrkkrp/megaparsec/issues/80/labels{/name}","comments_url":"https://api.github.com/repos/mrkkrp/megaparsec/issues/80/comments","events_url":"https://api.github.com/repos/mrkkrp/megaparsec/issues/80/events","html_url":"https://github.com/mrkkrp/megaparsec/issues/80","id":130100619,"number":80,"title":"Support error recovery","user":{"login":"adamwalker","id":35527,"avatar_url":"https://avatars.githubusercontent.com/u/35527?v=3","gravatar_id":"","url":"https://api.github.com/users/adamwalker","html_url":"https://github.com/adamwalker","followers_url":"https://api.github.com/users/adamwalker/followers","following_url":"https://api.github.com/users/adamwalker/following{/other_user}","gists_url":"https://api.github.com/users/adamwalker/gists{/gist_id}","starred_url":"https://api.github.com/users/adamwalker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamwalker/subscriptions","organizations_url":"https://api.github.com/users/adamwalker/orgs","repos_url":"https://api.github.com/users/adamwalker/repos","events_url":"https://api.github.com/users/adamwalker/events{/privacy}","received_events_url":"https://api.github.com/users/adamwalker/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/mrkkrp/megaparsec/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/mrkkrp/megaparsec/labels/feature-request","name":"feature-request","color":"fbca04"}],"state":"open","locked":false,"assignee":{"login":"mrkkrp","id":8165792,"avatar_url":"https://avatars.githubusercontent.com/u/8165792?v=3","gravatar_id":"","url":"https://api.github.com/users/mrkkrp","html_url":"https://github.com/mrkkrp","followers_url":"https://api.github.com/users/mrkkrp/followers","following_url":"https://api.github.com/users/mrkkrp/following{/other_user}","gists_url":"https://api.github.com/users/mrkkrp/gists{/gist_id}","starred_url":"https://api.github.com/users/mrkkrp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrkkrp/subscriptions","organizations_url":"https://api.github.com/users/mrkkrp/orgs","repos_url":"https://api.github.com/users/mrkkrp/repos","events_url":"https://api.github.com/users/mrkkrp/events{/privacy}","received_events_url":"https://api.github.com/users/mrkkrp/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/mrkkrp/megaparsec/milestones/7","html_url":"https://github.com/mrkkrp/megaparsec/milestones/4.4.0","labels_url":"https://api.github.com/repos/mrkkrp/megaparsec/milestones/7/labels","id":1557467,"number":7,"title":"4.4.0","description":null,"creator":{"login":"mrkkrp","id":8165792,"avatar_url":"https://avatars.githubusercontent.com/u/8165792?v=3","gravatar_id":"","url":"https://api.github.com/users/mrkkrp","html_url":"https://github.com/mrkkrp","followers_url":"https://api.github.com/users/mrkkrp/followers","following_url":"https://api.github.com/users/mrkkrp/following{/other_user}","gists_url":"https://api.github.com/users/mrkkrp/gists{/gist_id}","starred_url":"https://api.github.com/users/mrkkrp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrkkrp/subscriptions","organizations_url":"https://api.github.com/users/mrkkrp/orgs","repos_url":"https://api.github.com/users/mrkkrp/repos","events_url":"https://api.github.com/users/mrkkrp/events{/privacy}","received_events_url":"https://api.github.com/users/mrkkrp/received_events","type":"User","site_admin":false},"open_issues":3,"closed_issues":2,"state":"open","created_at":"2016-02-02T06:10:50Z","updated_at":"2016-02-09T08:04:26Z","due_on":null,"closed_at":null},"comments":4,"created_at":"2016-01-31T08:31:48Z","updated_at":"2016-02-09T08:14:26Z","closed_at":null,"body":"I frequently want the parsers I write that accept human input to be able to recover from errors and continue parsing if possible.\r\n\r\nIn this commit: https://github.com/adamwalker/megaparsec/commit/e005dec57c5faf180846fced1cd262f124c18083 I hacked together basic support for error recovery into Megaparsec in two functions: \"recover\" and \"recoverNoBacktrack\" with identical signatures:\r\n\r\n```\r\n recoverNoBacktrack :: ParsecT s m a -> (ParseError -> ParsecT s m a) -> ParsecT s m a \r\n```\r\n\r\nFor example, this allows you to write:\r\n```\r\nrecoverNoBacktrack parseCStatement $ \\err -> manyTill (satisfy (const True)) (symbol \";\")\r\n```\r\n\r\nWhich will, on encountering an error parsing the C statement, skip characters from where the error was encountered until a synchronizing semicolon is reached. \r\n\r\nYou can also save the \"err\" argument, for example using the state monad, and present a list of errors to the user when parsing is done.\r\n\r\nIs this something you consider worthwhile having in Megaparsec? If so, I will clean up my commit and submit a PR."},"comment":{"url":"https://api.github.com/repos/mrkkrp/megaparsec/issues/comments/181754611","html_url":"https://github.com/mrkkrp/megaparsec/issues/80#issuecomment-181754611","issue_url":"https://api.github.com/repos/mrkkrp/megaparsec/issues/80","id":181754611,"user":{"login":"mrkkrp","id":8165792,"avatar_url":"https://avatars.githubusercontent.com/u/8165792?v=3","gravatar_id":"","url":"https://api.github.com/users/mrkkrp","html_url":"https://github.com/mrkkrp","followers_url":"https://api.github.com/users/mrkkrp/followers","following_url":"https://api.github.com/users/mrkkrp/following{/other_user}","gists_url":"https://api.github.com/users/mrkkrp/gists{/gist_id}","starred_url":"https://api.github.com/users/mrkkrp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrkkrp/subscriptions","organizations_url":"https://api.github.com/users/mrkkrp/orgs","repos_url":"https://api.github.com/users/mrkkrp/repos","events_url":"https://api.github.com/users/mrkkrp/events{/privacy}","received_events_url":"https://api.github.com/users/mrkkrp/received_events","type":"User","site_admin":false},"created_at":"2016-02-09T08:14:26Z","updated_at":"2016-02-09T08:14:26Z","body":"Here is the thing: #86. FYI, the recovering parser (which is sort of “plan B” anyway) should not influence error messages in any way or it will lead to very confusing messages in some cases. Another thing that I did differently is handling of failure of recovering parser. Again, it would be quite confusing for end-user to see error message of recovering parser, so in my solution when recovering parser fails, user just gets original error message (which main parser produced) as if no `withRecovery` combinator is used.\r\n"}}