diff options
| author | Takashi Kokubun <takashikkbn@gmail.com> | 2026-03-16 11:55:53 -0700 |
|---|---|---|
| committer | Takashi Kokubun <takashikkbn@gmail.com> | 2026-03-16 11:55:53 -0700 |
| commit | 1d3581e18a689f0d392686283e340058ac468ffd (patch) | |
| tree | 25f8f785a329cec271543dccef31dfbf8ced3e72 | |
| parent | 0d845e4a071f67de40e1151cafb419c7aba87050 (diff) | |
merge revision(s) 55694ad7efc3f8dc6d5c7aefa60ded4c303ed6cf: [Backport #21945]
[Bug #21945] Correctly handle `and?` and similar
| -rw-r--r-- | parse.y | 3 | ||||
| -rw-r--r-- | test/ripper/test_lexer.rb | 52 |
2 files changed, 55 insertions, 0 deletions
@@ -7010,6 +7010,9 @@ peek_word_at(struct parser_params *p, const char *str, size_t len, int at) if (lex_eol_ptr_n_p(p, ptr, len-1)) return false; if (memcmp(ptr, str, len)) return false; if (lex_eol_ptr_n_p(p, ptr, len)) return true; + switch (ptr[len]) { + case '!': case '?': return false; + } return !is_identchar(p, ptr+len, p->lex.pend, p->enc); } diff --git a/test/ripper/test_lexer.rb b/test/ripper/test_lexer.rb index 7a2c22ff2d..4bc6fd7ced 100644 --- a/test/ripper/test_lexer.rb +++ b/test/ripper/test_lexer.rb @@ -586,6 +586,58 @@ world" assert_lexer(expected, code) end + def test_fluent_and + code = "foo\n" "and" + expected = [ + [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)], + [[1, 3], :on_ignored_nl, "\n", state(:EXPR_CMDARG)], + [[2, 0], :on_kw, "and", state(:EXPR_BEG)], + ] + assert_lexer(expected, code) + + code = "foo\n" "and?" + expected = [ + [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)], + [[1, 3], :on_nl, "\n", state(:EXPR_BEG)], + [[2, 0], :on_ident, "and?", state(:EXPR_CMDARG)], + ] + assert_lexer(expected, code) + + code = "foo\n" "and!" + expected = [ + [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)], + [[1, 3], :on_nl, "\n", state(:EXPR_BEG)], + [[2, 0], :on_ident, "and!", state(:EXPR_CMDARG)], + ] + assert_lexer(expected, code) + end + + def test_fluent_or + code = "foo\n" "or" + expected = [ + [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)], + [[1, 3], :on_ignored_nl, "\n", state(:EXPR_CMDARG)], + [[2, 0], :on_kw, "or", state(:EXPR_BEG)], + ] + assert_lexer(expected, code) + + code = "foo\n" "or?" + expected = [ + [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)], + [[1, 3], :on_nl, "\n", state(:EXPR_BEG)], + [[2, 0], :on_ident, "or?", state(:EXPR_CMDARG)], + ] + assert_lexer(expected, code) + + code = "foo\n" "or!" + expected = [ + [[1, 0], :on_ident, "foo", state(:EXPR_CMDARG)], + [[1, 3], :on_nl, "\n", state(:EXPR_BEG)], + [[2, 0], :on_ident, "or!", state(:EXPR_CMDARG)], + ] + assert_lexer(expected, code) + end + def assert_lexer(expected, code) assert_equal(code, Ripper.tokenize(code).join("")) assert_equal(expected, result = Ripper.lex(code), |
