summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authoryui-knk <spiketeika@gmail.com>2022-10-01 17:19:34 +0900
committerYuichiro Kaneko <spiketeika@gmail.com>2022-10-08 17:59:11 +0900
commit4f24f3ea94e43d1021fdd8548480f130f5112b99 (patch)
tree8cfe7d2e7dd0dcdabc31aa7a781858b9364a1291 /parse.y
parent342d4c16d963408905fd08118d1908fe197f2364 (diff)
downloadruby-4f24f3ea94e43d1021fdd8548480f130f5112b99.tar.gz
Treat "end" as reserved word with consideration of indent
"end" after "." or "::" is treated as local variable or method, see `EXPR_DOT_bit` for detail. However this "changes" where `bar` method is defined. In the example below it is not module Z but class Foo. ``` module Z class Foo foo. end def bar end end ``` [Feature #19013]
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y37
1 files changed, 36 insertions, 1 deletions
diff --git a/parse.y b/parse.y
index a1b1e2ee46..c0959a5e81 100644
--- a/parse.y
+++ b/parse.y
@@ -438,6 +438,13 @@ pop_end_expect_token_localtions(struct parser_params *p)
rb_ary_pop(p->end_expect_token_localtions);
debug_end_expect_token_localtions(p, "pop_end_expect_token_localtions");
}
+
+static VALUE
+peek_end_expect_token_localtions(struct parser_params *p)
+{
+ if(NIL_P(p->end_expect_token_localtions)) return Qnil;
+ return rb_ary_last(0, 0, p->end_expect_token_localtions);
+}
#endif
RBIMPL_ATTR_NONNULL((1, 2, 3))
@@ -9285,6 +9292,7 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
int mb = ENC_CODERANGE_7BIT;
const enum lex_state_e last_state = p->lex.state;
ID ident;
+ int enforce_keyword_end = 0;
do {
if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
@@ -9314,7 +9322,34 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
return tLABEL;
}
}
- if (mb == ENC_CODERANGE_7BIT && !IS_lex_state(EXPR_DOT)) {
+
+#ifndef RIPPER
+ if (!NIL_P(peek_end_expect_token_localtions(p))) {
+ VALUE end_loc;
+ int lineno, column;
+ int beg_pos = (int)(p->lex.ptok - p->lex.pbeg);
+
+ end_loc = peek_end_expect_token_localtions(p);
+ lineno = NUM2INT(rb_ary_entry(end_loc, 0));
+ column = NUM2INT(rb_ary_entry(end_loc, 1));
+
+ if (p->debug) {
+ rb_parser_printf(p, "enforce_keyword_end check. current: (%d, %d), peek: (%d, %d)\n",
+ p->ruby_sourceline, beg_pos, lineno, column);
+ }
+
+ if ((p->ruby_sourceline > lineno) && (beg_pos <= column)) {
+ const struct kwtable *kw;
+
+ if ((IS_lex_state(EXPR_DOT)) && (kw = rb_reserved_word(tok(p), toklen(p))) && (kw && kw->id[0] == keyword_end)) {
+ if (p->debug) rb_parser_printf(p, "enforce_keyword_end is enabled\n");
+ enforce_keyword_end = 1;
+ }
+ }
+ }
+#endif
+
+ if (mb == ENC_CODERANGE_7BIT && (!IS_lex_state(EXPR_DOT) || enforce_keyword_end)) {
const struct kwtable *kw;
/* See if it is a reserved word. */