tree-sitter / tree-sitter-ruby

Ruby grammar for tree-sitter
MIT License
182 stars 58 forks source link

Parse error in block argument with space after & #218

Open aibaars opened 2 years ago

aibaars commented 2 years ago

Originally reported by @grajagandev at https://github.com/github/codeql/issues/9313

Description of the issue

I am seeing parser errors on Ruby lambdas. Here is a test case:

$ cat ruby-parser-errors.rb 
def foo
    puts "hi from foo"
end

foo() { boo( & lambda {}) }
foo() { boo( & ->{}) }
$ 
$ ruby -v
ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-linux-gnu]
$
$ ruby ruby-parser-errors.rb
hi from foo
hi from foo
$ 
$ ruby -c ruby-parser-errors.rb
Syntax OK
$ 
$ codeql database create test-db --language=ruby --overwrite
...
[2022-05-24 20:40:17] [build-stdout] ERROR ruby-parser-errors.rb:5: parse error
[2022-05-24 20:40:17] [build-stdout] ERROR ruby-parser-errors.rb:6: parse error: expecting 'identifier'
[2022-05-24 20:40:17] [build-stdout] ERROR ruby-parser-errors.rb:6: missing value for field: binary::left
Finalizing database at .../test-db.
Successfully created database at .../test-db.

Please let me know if you need further information - Thank you

The cause of the problem is that the scanner does not allow a space after a "block ampersand". I can make the examples work by removing the space after the &. The following parse fine:

foo() { boo( &lambda {}) }
foo() { boo( &->{}) }

Removing the scan check in the scanner, however, causes other problems as it is intended to disambiguate between "bitwise-and" and "block argument" expressions. For example:

foo & bar      # a bitwise and of `foo` and `bar`
foo &bar       # a call to `foo` with block argument `bar`
aibaars commented 2 years ago

I suppose we can fix this by changing the scanner to allow a space after a "block_ampersand" in cases where bitwise-and operators are not expected. Something like !(valid_symbols[BITWISE_AND] && iswspace(lexer->lookahead)) could perhaps work.