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

ruby: treat % like /: no space after method call = infix #1563

Merged
merged 1 commit into from
Sep 8, 2020

Conversation

jneen
Copy link
Member

@jneen jneen commented Jul 18, 2020

This is consistent with what I've tested locally with ruby -e ...

Fixes #1562

Thanks @0x7ffc for the report!

This is consistent with what I've tested locally with `ruby -e ...`
@jneen
Copy link
Member Author

jneen commented Jul 18, 2020

Here's how the new bits of the visual spec look with this branch:

image

@jneen
Copy link
Member Author

jneen commented Jul 18, 2020

This is unfortunately another one of those bizarre cases where ruby's parsing behaviour inexplicably depends on what variables happen to be in scope...?

[0: jneen@cinnamon rouge ] -> bugfix.ruby-modulo-spacing $
; ruby -e 'def x(arr); arr; end; puts (x %w]reverse])'
reverse

[0: jneen@cinnamon rouge ] -> bugfix.ruby-modulo-spacing $
; ruby -e 'x=1; w=2; puts (x %w]reverse])'
-e:1: syntax error, unexpected ']', expecting ')'
x=1; w=2; puts (x %w]reverse])

@jneen
Copy link
Member Author

jneen commented Jul 18, 2020

Those examples cleaned up a bit:

def x(arr)
  arr
end

puts (x %w]reverse])
# => prints "reverse"

and

x = 1
w = 2
puts (x %w]reverse])
# => syntax error

@jneen
Copy link
Member Author

jneen commented Jul 20, 2020

A really good read re: the zaniness of ruby's parser: https://whitequark.org/blog/2013/04/01/ruby-hacking-guide-ch-11-finite-state-lexer/

@pyrmont
Copy link
Contributor

pyrmont commented Jul 20, 2020

/me buckles up

@pyrmont pyrmont self-requested a review July 20, 2020 16:41
@pyrmont pyrmont added the needs-review The PR needs to be reviewed label Jul 20, 2020
@pyrmont pyrmont self-assigned this Jul 20, 2020
@jneen
Copy link
Member Author

jneen commented Jul 20, 2020

I FOUND IT BY GOD I FOUND IT

https://github.com/ruby/ruby/blob/master/parse.y#L8966

This is the line where Ruby checks what variables are in scope and changes its parsing behaviour. Found by running ruby -yce on two very similar examples:

x=1; puts (x %w]reverse])

# vs

w=1; puts (x %w]reverse])

and diffing the output.

@jneen
Copy link
Member Author

jneen commented Jul 20, 2020

Anyways, the moral of the story is:

  • Ruby lexing will never be perfect. It just won't. We can't afford to keep track of every nuance of block scoping enough to decide whether a variable is in scope without sacrificing performance.
  • This patch improves the lexer's behaviour in some important real-world cases, so it helps.

@pyrmont pyrmont merged commit 2d4976c into master Sep 8, 2020
@pyrmont
Copy link
Contributor

pyrmont commented Sep 8, 2020

@0x7ffc Echoing @jneen's thanks for submitting the bug report. This will be part of v3.23.0 of Rouge. That's actually scheduled for release later today (or early tomorrow depending on your time zone) 🎉

@pyrmont pyrmont removed the needs-review The PR needs to be reviewed label Sep 8, 2020
mattt pushed a commit to NSHipster/rouge that referenced this pull request May 19, 2021
The Ruby lexer only treats `%` consistently as the modulo operator if it
is followed by whitespace. This is not consistent with Ruby itself which
treats this use of `%` as the modulo operator:

    if board[i/w][i%s] == 'O'
      region << i
    end

This is a difficult problem to solve because Ruby's parser categorises
`%` based on the variables which are in scope (which is not something
Rouge can do). This commit improves the handling of `%` by treating it
in a similar way to `/`.
@tancnle tancnle deleted the bugfix.ruby-modulo-spacing branch September 22, 2021 12:25
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.

Ruby wrong highlighting when handling [i%w]
2 participants