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

Stop parsing incorrect trailing commas and improve error recovery in comma-separated lists. #14534

Closed
wants to merge 1 commit into from

Conversation

adampauls
Copy link
Contributor

@adampauls adampauls commented Feb 22, 2022

Instead of handling trailing commas in the scanner, which leads to buggy behavior where trailing commas are accepted in places they shouldn't, handle trailing commas in the parser. Accomplished by adding a isCommaSeparated field to the InParens region. A redux of scala/scala#8780.

A combination of #14509 and #14517, but with some feedback from @odersky. I put the two together because the need to handle trailing commas outside of the scanner is more apparent with both changes.

@@ -249,8 +249,13 @@ object Parsers {

/** Skip on error to next safe point.
*/
protected def skip(stopAtComma: Boolean): Unit =
protected def skip(): Unit =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Smarter skip, though it is actually a little dumber because it now doesn't handle non-delimited comma-separated lists like for x,y,z <- ...

/** part { `,` part }
* @param delimited If true, this comma-separated list must surrounded by brackets, parens, or braces.
*/
def commaSeparated[T](part: () => T, delimited: Boolean = true, readFirst: Boolean = true): List[T] = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Main change all here.

@adampauls adampauls force-pushed the comma_separated_region_3 branch 3 times, most recently from 08678ab to 58c8da0 Compare February 22, 2022 17:36
Check for trailing commas in parser instead of scanner

Instead of passing down a flag, add a bit to regions to say if we are in a comma-separated region.

delimited instead of expectedToken
@adampauls adampauls force-pushed the comma_separated_region_3 branch from 58c8da0 to fc759ec Compare March 5, 2022 00:01
@adampauls adampauls changed the title WIP Better error recovery in comma-separated lists (version 2) Stop parsing incorrect trailing commas and improve error recovery in comma-separated lists. Mar 5, 2022
@@ -655,13 +655,6 @@ object Scanners {
insert(OUTDENT, offset)
currentRegion = r.outer
case _ =>
lookAhead()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No longer handled in scanner

@@ -1386,14 +1427,7 @@ object Parsers {
else
Function(params, t)
}
def funTypeArgsRest(first: Tree, following: () => Tree) = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was really just a comma-separated list.

@@ -558,19 +563,55 @@ object Parsers {
def inDefScopeBraces[T](body: => T, rewriteWithColon: Boolean = false): T =
inBracesOrIndented(body, rewriteWithColon)

/** part { `separator` part }
*/
def tokenSeparated[T](separator: Int, part: () => T): List[T] = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Inlined since it was only ever used with commas.

@adampauls adampauls marked this pull request as ready for review March 5, 2022 00:06
@adampauls
Copy link
Contributor Author

I have already fixed the broken community build projects -- they both had incorrect trailing commas. I'm not sure how to bump them though.

@dwijnand dwijnand requested a review from odersky March 7, 2022 10:31
@adampauls
Copy link
Contributor Author

@odersky any chance you're going to have a look at this soon? I was hoping to get it in before 3.1.3. Thanks!

@@ -0,0 +1,79 @@

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pulled over from scala/scala#8780.

@som-snytt
Copy link
Contributor

Not an odersky, but I did fetch the branch and look forward to studying it. Today is my birthday, so it won't be today.

@odersky
Copy link
Contributor

odersky commented Mar 16, 2022

I think skip can be simplified to not take a parameter regardless of what else we do. That's more in line with the other recovery code where we specifically do not pass any information about expected symbols into skip. I'e we also stop at a ), ] or } regardless of whether one of these symbols is expected or not.

After looking at the code in depth, I now need to step back from my earlier recommendation to use regions for trailing comma parsing. First the code is not really simpler than in #14517. Second, regions are currently a Scanner only thing. To mix context information from the parser into them would muddle the architecture. So in the end I think I prefer the approach of #14517.

@adampauls
Copy link
Contributor Author

Closing in favor of #14517

@adampauls adampauls closed this Mar 16, 2022
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.

3 participants