Skip to content
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

Merged
merged 6 commits into from Nov 11, 2021
Merged

Add tutorial to readme #299

merged 6 commits into from Nov 11, 2021

Conversation

DenisNovac
Copy link
Contributor

Fixed version of #298

@zsluedem
Copy link
Contributor

zsluedem commented Nov 8, 2021

Just want to say . This pr is great.

Copy link
Collaborator

@johnynek johnynek left a 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 Show resolved Hide resolved
import cats.parse.Parser


val p: Parser[String] = (sp.?.with1 *> alpha.rep <* sp.?).rep.map { words =>
Copy link
Collaborator

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 Show resolved Hide resolved
// 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!).
Copy link
Collaborator

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).

Copy link
Collaborator

@regadas regadas left a 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.

@DenisNovac
Copy link
Contributor Author

@johnynek i've made some changes for every suggestion you give. Please resolve conversations which are not relevant anymore.

Copy link
Collaborator

@johnynek johnynek left a 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:

```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 Show resolved Hide resolved
@@ -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**).
Copy link
Collaborator

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.

### 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:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arresting

@@ -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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arresting.


So the `backtrack` helps us where the *left side* throws an error.
So the `backtrack` helps us where the *left side* throws halting error.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arresting


### 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:
Copy link
Collaborator

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.

@@ -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:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returns an epsilon

@DenisNovac
Copy link
Contributor Author

Fixed the terminology. I'll check mdoc later today.

@DenisNovac
Copy link
Contributor Author

Added the mdoc and checked it compiles

@codecov-commenter
Copy link

Codecov Report

Merging #299 (af73caf) into main (714a9df) will decrease coverage by 0.09%.
The diff coverage is n/a.

Impacted file tree graph

@@            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     
Impacted Files Coverage Δ
core/shared/src/main/scala/cats/parse/Parser.scala 96.20% <0.00%> (-0.12%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 714a9df...af73caf. Read the comment docs.

@DenisNovac
Copy link
Contributor Author

Fixed the warning (through web-version, didn't compile it for other warnings)

@johnynek johnynek merged commit a0ec067 into typelevel:main Nov 11, 2021
@johnynek
Copy link
Collaborator

Thank you so much!

@filosganga
Copy link

It is just what I was looking for, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants