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
Add tutorial to readme #299
Conversation
Just want to say . This pr is great. |
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.
This is really great and I want to merge it!
I did have a few suggestions, mostly around calling out the two kinds of conceptual errors: halting and epsilon, and making the distinction early to help understand orElse, backtrack and soft.
docs/src/index.md
Outdated
import cats.parse.Parser | ||
|
||
|
||
val p: Parser[String] = (sp.?.with1 *> alpha.rep <* sp.?).rep.map { words => |
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.
should we mention the convenience method .between
or .surroundedBy
(sp.?.with1 *> alpha.rep <* sp.?) == alpha.rep.surroundedBy(sp.?)
docs/src/index.md
Outdated
// res3 = Right((,(None,The Wind Has Risen))) | ||
``` | ||
|
||
So when the *right side* throws an error the `soft` method allows us to rewind parsed input and try to proceed it's parsing with next parsers (without changing the parser itself!). |
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.
when the right side throws a non-halting error (which is to say epsilon error, or the right side did not consume any input).
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.
This looks great! 👏
Besides @johnynek comments can we make the code blocks mdoc
blocks? It will make sure the examples compile and eval result will always be accurate.
@johnynek i've made some changes for every suggestion you give. Please resolve conversations which are not relevant anymore. |
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 agree with @regadas we should use scala mdoc
so we compile these docs to make sure the examples compile.
See for instance here:
Line 39 in 714a9df
```scala mdoc |
I am looking forward to publishing the next version of this library, but I'd love to merge this first so new users will see this tutorial if they see the announcement of a new version.
docs/src/index.md
Outdated
@@ -181,9 +239,31 @@ If we have multiple `Parser0` parsers before the `Parser` - we'd need to use par | |||
|
|||
## Error handling | |||
|
|||
Parser might be interrupted by parsing error. There are two kinds of errors: | |||
- an error that has consumed 0 characters (**epsilon failure**); | |||
- an error that has consumer 1 or more characters (**halting failure**). |
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.
sorry for misleading you, let's stick to arresting
used in the docs.
docs/src/index.md
Outdated
### Backtrack | ||
|
||
Parser job might be interrupted by parsing error. This happens when input can't be parsed with this parser: | ||
Backtrack allows us to convert a *halting failure* to *epsilon failure*. It also rewinds the input to the offset to that used before parsing began. The resulting parser might still be combined with others. Let's look at the example: |
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.
arresting
docs/src/index.md
Outdated
@@ -234,13 +316,13 @@ val p3 = digit | |||
// res2 = Right((,1)) | |||
``` | |||
|
|||
The first parsing is interrupted by error since it *started* the parsing (one first space was correct on parser `p1`) so it won't work without `backtrack`. The second parsing works fine with `orElse` alone since it does not start in `p1` or `p2`. | |||
The first parser combination is interrupted by *halting error* and the second parsing combination will only suffer from *epsilon errors*. The second parser works because `orElse` and `|` operators actually allows recovering from epsilon errors, but not from halting errors. |
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.
arresting.
docs/src/index.md
Outdated
|
||
So the `backtrack` helps us where the *left side* throws an error. | ||
So the `backtrack` helps us where the *left side* throws halting error. |
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.
arresting
docs/src/index.md
Outdated
|
||
### Soft | ||
|
||
This method might look similar to `backtrack`, but it allows us to *proceed* the parsing when the *right side* is failed. It is really useful for ambiguous parsers when we can't really tell what exactly we are parsing before the end. Let's say we want to parse some input to the search engine which contains fields. This might look like "field:search_query". Let's try to write a parser for this: | ||
This method might look similar to `backtrack`, but it allows us to *proceed* the parsing when the *right side* is throwing an epsilon error. It is really useful for ambiguous parsers when we can't really tell what exactly we are parsing before the end. Let's say we want to parse some input to the search engine which contains fields. This might look like "field:search_query". Let's try to write a parser for this: |
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.
maybe returning
than throwing
which sounds like a jvm exception being thrown, which is not how it happens.
docs/src/index.md
Outdated
@@ -273,7 +355,7 @@ val p3 = (searchWord ~ sp.?).rep.string | |||
// res1 = Right((,The Wind Has Risen)) | |||
``` | |||
|
|||
But this problem might be resolved with `soft` method: | |||
But this problem might be resolved with `soft` method inside the first parser since the right side of it actually throws an epsilon failure itself: |
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.
returns an epsilon
Fixed the terminology. I'll check mdoc later today. |
Added the mdoc and checked it compiles |
Codecov Report
@@ Coverage Diff @@
## main #299 +/- ##
==========================================
- Coverage 96.43% 96.34% -0.10%
==========================================
Files 8 8
Lines 1011 1011
Branches 81 81
==========================================
- Hits 975 974 -1
- Misses 36 37 +1
Continue to review full report at Codecov.
|
Fixed the warning (through web-version, didn't compile it for other warnings) |
Thank you so much! |
It is just what I was looking for, thank you! |
Fixed version of #298