-
Notifications
You must be signed in to change notification settings - Fork 832
Bugfix: Standalone dotlambda just before EOF #16240
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
Conversation
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.
@T-Gro I see two problems with the existing rules:
-
Why do the rules use different rules for expression, i.e.
atomicExprvsappExpr?
atomicExprcovers the cases with high-precedence applications, so_.M()is already covered.
appExprallows_.M ()to be parsed but adds an additional error.I think it's wrong because dotLambda is an atomic expression, according to the grammar, but it currently captures arbitrary non-atomic app expressions after it, breaking many assumptions about what atomic expressions are. It also makes
f _.P 123inconsistent with other nested applications likef g 123. On top of that it may limit possible future changes in the language and parser recovery. -
Why does the second rule have
recoverat all?
It doesn't look like there something is missing in it where we expect the recovery to kick in. This extrarecover(i.e. not replacing something that is missing) is the source of the issue withEOFindeed.
It seems that simply removing the second rule can fix it (it looks too wrong and interferes with the first rule), while adding this third one only buries the problem deeper.
That will allow _.P 123 to be parsed as:
appExpr
dotLambdaExpr
_
.
namedExpr
P
constExpr
123
and f _.P 123 to be parsed as:
appExpr
appExpr
namedExpr
f
dotLambdaExpr
_
.
namedExpr
P
constExpr
123
Currently f _.P 123 is parsed as this:
appExpr
namedExpr
f
dotLambdaExpr
_
.
appExpr
namedExpr
P
constExpr
123
Side question: if the second rule is removed, do we need having a special precedence at all? Having less of them always makes things easier down the road.
The second rule only exists in order to give a meaningful error message instead of a generic one, while keeping some parser recovery working. |
Could you please show an example of the generic error message when this rule is removed? I think it's very important to fix the atomic expressions being non-atomic here, and the only way I see is to remove this rule. |
...service/data/SyntaxTree/DotLambda/UnderscoreToFunctionNallWithSpaceAndUnitApplication.fs.bsl
Show resolved
Hide resolved
tests/service/data/SyntaxTree/DotLambda/WithNonTupledFunctionCall.fs.bsl
Show resolved
Hide resolved
It is now visible in the diff + I added commented explanations.
The second one looks best to me, WDYT? |
|
@T-Gro Thanks, all the examples are good. Looking at these, I think the first option is probably the best as things stand now. A simple check in the type checker could be checking that dot lambdas aren't allowed as function expressions in application expressions: It would make this allowed, because And this would not be allowed, because Can the special precedence also be removed if non-atomic expressions are no longer allowed there?
That would still mean we're parsing 'top-level' non-atomic expression inside an atomic one. I think we should avoid it, it makes the whole grammar less sound. |
auduchinok
left a comment
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.
It looks good to me now, it's good to have the underlying problem fixed!
|
Agree. I also wanted to remove the %prec, tried that, but I started to get test failures which did not repro locally. => I will keep that outside of this PR, so that it can get it as it is. == this is ready for reviews and merging it |
This addresses #16220 .
If my hypothesis is correct, the difference was caused by an end-of-file marker.
In a bigger statement (e.g. with a "let" binding), rules higher up cover for an EOF.
In a standalone parsing of just the dotlambda construct, this is not covered.
Why did matter? Because EOF is one possibility for "recover", which was meant for error handling when this feature was being implemented. But EOF does not always mean an error.
@auduchinok , @DedSec256 :
I did not like the fact of special casing EOF, because most other constructs do not need it either, it is dealt with higher up.
I would more than welcome any suggestion of yours, both for the EOF as well deduplicating the rules here.