Skip to content

Correctly parse ado without any statements in it #46

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

Merged
merged 4 commits into from
Mar 5, 2023

Conversation

MonoidMusician
Copy link
Contributor

Fixes natefaubion/purescript-tidy#108

The issue was that the parser wasn't backtracking enough to abort valueParser and fall back to pure [], so instead I parse the layout tokens up front so we can commit to the right path early. Perhaps it could be more elegant.

Tested on the examples in the issue and on our work codebase. Do you want me to add a test to test/Main.purs?

where
values = (go =<< valueParser) <|> pure []
Copy link
Owner

Choose a reason for hiding this comment

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

This seems like it should be equivalent to optional? If we had an empty layout, then valueParser should immediately fail if given a TokLayoutEnd, shouldn't it? It's not obvious to me what "backtracking far enough" means then, and that there isn't some other internal bug. Do we know where backtracking is halting?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I was a little hasty in ascribing it to backtracking. Putting try in there does not help.

What's really messing it up is the indentation-based parser recovery when we call it in parseAdo (this is the only usage of layout). An an example change, this manages to parse the empty ado in:

--- a/src/PureScript/CST/Parser.purs
+++ b/src/PureScript/CST/Parser.purs
@@ -673,7 +673,7 @@ parseDo = do
 parseAdo :: Parser (Recovered Expr)
 parseAdo = do
   keyword <- tokQualifiedKeyword "ado"
-  statements <- layout (recoverDoStatement parseDoStatement)
+  statements <- layout parseDoStatement
   in_ <- tokKeyword "in"
   result <- parseExpr
   pure $ ExprAdo { keyword, statements, in: in_, result }

Copy link
Owner

@natefaubion natefaubion Feb 23, 2023

Choose a reason for hiding this comment

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

It makes sense to me that there is something odd with recovery, but I'm not sure what. In the case of ado in, I would expect recoverIndent to immediately hit a TokLayoutEnd where col == indent, resulting in empty tokens, yielding Nothing, which would propagate the error.

let
Tuple tokens newStream = recoverTokensWhile
( \tok indent -> case tok.value of
TokLayoutEnd col -> col > indent
TokLayoutSep col -> col > indent
_ -> true
)
stream
if Array.null tokens then
Nothing

case k error state1.stream of
Nothing ->
runFn2 resume (state2 { consumed = state1.consumed }) error

Maybe something is wrong with the state threading in recover. The logic of the original code seems OK to me, which makes me think this is an internal bug and not related to the specific formulation of this parser.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I'll push a test for this case and dig deeper.

@natefaubion
Copy link
Owner

I think that this should have a regression test, yes. We test against publicly available code, but this was triggered by an edge case that doesn't exist in any public code.

@natefaubion natefaubion merged commit a7ca658 into natefaubion:main Mar 5, 2023
@natefaubion
Copy link
Owner

Thanks!

@MonoidMusician MonoidMusician deleted the muchadoaboutnothing branch March 5, 2023 18:14
natefaubion added a commit that referenced this pull request May 26, 2025
With the fixes to indentation recovery in #63, the workaround for empty
ado parsing is no longer necessary. This effectively reverts #46.
@natefaubion natefaubion mentioned this pull request May 26, 2025
natefaubion added a commit that referenced this pull request May 26, 2025
With the fixes to indentation recovery in #63, the workaround for empty
ado parsing is no longer necessary. This effectively reverts #46.
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.

Cannot parse ado in without any statements
2 participants