Stop using Array to manage dummy end token locations

Before this commit, Array is used to store token locations
which expect `end` token, e.g. `class` and `module`.
This commit introduces dedicated struct to manage them
so that dependency on Ruby Object is reduced.
This commit is contained in:
yui-knk 2024-01-13 13:54:13 +09:00 committed by Yuichiro Kaneko
parent b92c8934a2
commit ccd45a1399

63
parse.y
View File

@ -527,6 +527,11 @@ typedef struct token_info {
struct token_info *next; struct token_info *next;
} token_info; } token_info;
typedef struct end_expect_token_locations {
const rb_code_position_t *pos;
struct end_expect_token_locations *prev;
} end_expect_token_locations_t;
/* /*
Structure of Lexer Buffer: Structure of Lexer Buffer:
@ -639,8 +644,11 @@ struct parser_params {
VALUE error_buffer; VALUE error_buffer;
VALUE debug_lines; VALUE debug_lines;
const struct rb_iseq_struct *parent_iseq; const struct rb_iseq_struct *parent_iseq;
/* store specific keyword locations to generate dummy end token */ /*
VALUE end_expect_token_locations; * Store specific keyword locations to generate dummy end token.
* Refer to the tail of list element.
*/
end_expect_token_locations_t *end_expect_token_locations;
/* id for terms */ /* id for terms */
int token_id; int token_id;
/* Array for term tokens */ /* Array for term tokens */
@ -703,8 +711,15 @@ static void
debug_end_expect_token_locations(struct parser_params *p, const char *name) debug_end_expect_token_locations(struct parser_params *p, const char *name)
{ {
if(p->debug) { if(p->debug) {
VALUE mesg = rb_sprintf("%s: ", name); VALUE mesg = rb_sprintf("%s: [", name);
rb_str_catf(mesg, " %"PRIsVALUE"\n", p->end_expect_token_locations); int i = 0;
for (end_expect_token_locations_t *loc = p->end_expect_token_locations; loc; loc = loc->prev) {
if (i > 0)
rb_str_cat_cstr(mesg, ", ");
rb_str_catf(mesg, "[%d, %d]", loc->pos->lineno, loc->pos->column);
i++;
}
rb_str_cat_cstr(mesg, "]\n");
flush_debug_buffer(p, p->debug_output, mesg); flush_debug_buffer(p, p->debug_output, mesg);
} }
} }
@ -712,24 +727,33 @@ debug_end_expect_token_locations(struct parser_params *p, const char *name)
static void static void
push_end_expect_token_locations(struct parser_params *p, const rb_code_position_t *pos) push_end_expect_token_locations(struct parser_params *p, const rb_code_position_t *pos)
{ {
if(NIL_P(p->end_expect_token_locations)) return; if(!p->error_tolerant) return;
rb_ary_push(p->end_expect_token_locations, rb_ary_new_from_args(2, INT2NUM(pos->lineno), INT2NUM(pos->column)));
end_expect_token_locations_t *locations;
locations = ALLOC(end_expect_token_locations_t);
locations->pos = pos;
locations->prev = p->end_expect_token_locations;
p->end_expect_token_locations = locations;
debug_end_expect_token_locations(p, "push_end_expect_token_locations"); debug_end_expect_token_locations(p, "push_end_expect_token_locations");
} }
static void static void
pop_end_expect_token_locations(struct parser_params *p) pop_end_expect_token_locations(struct parser_params *p)
{ {
if(NIL_P(p->end_expect_token_locations)) return; if(!p->end_expect_token_locations) return;
rb_ary_pop(p->end_expect_token_locations);
end_expect_token_locations_t *locations = p->end_expect_token_locations->prev;
ruby_sized_xfree(p->end_expect_token_locations, sizeof(end_expect_token_locations_t));
p->end_expect_token_locations = locations;
debug_end_expect_token_locations(p, "pop_end_expect_token_locations"); debug_end_expect_token_locations(p, "pop_end_expect_token_locations");
} }
static VALUE static end_expect_token_locations_t *
peek_end_expect_token_locations(struct parser_params *p) peek_end_expect_token_locations(struct parser_params *p)
{ {
if(NIL_P(p->end_expect_token_locations)) return Qnil; return p->end_expect_token_locations;
return rb_ary_last(0, 0, p->end_expect_token_locations);
} }
static ID static ID
@ -10560,14 +10584,14 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
} }
#ifndef RIPPER #ifndef RIPPER
if (!NIL_P(peek_end_expect_token_locations(p))) { if (peek_end_expect_token_locations(p)) {
VALUE end_loc; const rb_code_position_t *end_pos;
int lineno, column; int lineno, column;
int beg_pos = (int)(p->lex.ptok - p->lex.pbeg); int beg_pos = (int)(p->lex.ptok - p->lex.pbeg);
end_loc = peek_end_expect_token_locations(p); end_pos = peek_end_expect_token_locations(p)->pos;
lineno = NUM2INT(rb_ary_entry(end_loc, 0)); lineno = end_pos->lineno;
column = NUM2INT(rb_ary_entry(end_loc, 1)); column = end_pos->column;
if (p->debug) { if (p->debug) {
rb_parser_printf(p, "enforce_keyword_end check. current: (%d, %d), peek: (%d, %d)\n", rb_parser_printf(p, "enforce_keyword_end check. current: (%d, %d), peek: (%d, %d)\n",
@ -10692,7 +10716,7 @@ parser_yylex(struct parser_params *p)
case -1: /* end of script. */ case -1: /* end of script. */
p->eofp = 1; p->eofp = 1;
#ifndef RIPPER #ifndef RIPPER
if (!NIL_P(p->end_expect_token_locations) && RARRAY_LEN(p->end_expect_token_locations) > 0) { if (p->end_expect_token_locations) {
pop_end_expect_token_locations(p); pop_end_expect_token_locations(p);
RUBY_SET_YYLLOC_OF_DUMMY_END(*p->yylloc); RUBY_SET_YYLLOC_OF_DUMMY_END(*p->yylloc);
return tDUMNY_END; return tDUMNY_END;
@ -15856,7 +15880,7 @@ parser_initialize(struct parser_params *p)
p->parsing_thread = Qnil; p->parsing_thread = Qnil;
#else #else
p->error_buffer = Qfalse; p->error_buffer = Qfalse;
p->end_expect_token_locations = Qnil; p->end_expect_token_locations = NULL;
p->token_id = 0; p->token_id = 0;
p->tokens = Qnil; p->tokens = Qnil;
#endif #endif
@ -15887,7 +15911,6 @@ rb_ruby_parser_mark(void *ptr)
#ifndef RIPPER #ifndef RIPPER
rb_gc_mark(p->debug_lines); rb_gc_mark(p->debug_lines);
rb_gc_mark(p->error_buffer); rb_gc_mark(p->error_buffer);
rb_gc_mark(p->end_expect_token_locations);
rb_gc_mark(p->tokens); rb_gc_mark(p->tokens);
#else #else
rb_gc_mark(p->value); rb_gc_mark(p->value);
@ -16012,8 +16035,6 @@ void
rb_ruby_parser_error_tolerant(rb_parser_t *p) rb_ruby_parser_error_tolerant(rb_parser_t *p)
{ {
p->error_tolerant = 1; p->error_tolerant = 1;
// TODO
p->end_expect_token_locations = rb_ary_new();
} }
void void