Feature #17768 ยป 2021-aprilfool.patch
parse.y | ||
---|---|---|
VALUE prevline;
|
||
VALUE lastline;
|
||
VALUE nextline;
|
||
st_table *new_nodes;
|
||
const char *pbeg;
|
||
const char *pcur;
|
||
const char *pend;
|
||
... | ... | |
static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE, const rb_code_location_t*);
|
||
#define rb_node_newnode(type, a1, a2, a3, loc) node_newnode(p, (type), (a1), (a2), (a3), (loc))
|
||
static NODE *nd_set_loc(NODE *nd, const YYLTYPE *loc);
|
||
static NODE *nd_set_loc(struct parser_params *, NODE *nd, const YYLTYPE *loc);
|
||
static int
|
||
parser_get_node_id(struct parser_params *p)
|
||
... | ... | |
static NODE *new_regexp(struct parser_params *, NODE *, int, const YYLTYPE *);
|
||
#define make_list(list, loc) ((list) ? (nd_set_loc(list, loc), list) : NEW_ZLIST(loc))
|
||
#define make_list(list, loc) ((list) ? (nd_set_loc(p, list, loc), list) : NEW_ZLIST(loc))
|
||
static NODE *new_xstring(struct parser_params *, NODE *, const YYLTYPE *loc);
|
||
... | ... | |
{
|
||
/*%%%*/
|
||
$$ = heredoc_dedent(p, $2);
|
||
if ($$) nd_set_loc($$, &@$);
|
||
if ($$) nd_set_loc(p, $$, &@$);
|
||
/*% %*/
|
||
/*% ripper: string_literal!(heredoc_dedent(p, $2)) %*/
|
||
}
|
||
... | ... | |
}
|
||
#endif
|
||
goto normal_newline;
|
||
case '^': {
|
||
const char *down = RSTRING_PTR(p->lex.lastline);
|
||
if (p->lex.prevline && !p->eofp) p->lex.lastline = p->lex.prevline;
|
||
int i = 0;
|
||
while (1) {
|
||
while (ISSPACE(down[i]) && down[i] != '\n') i++;
|
||
if (down[i] == '\n') break;
|
||
if (down[i] != '^') {
|
||
yyerror0("invalid syntax in down assignment line");
|
||
break;
|
||
}
|
||
int j = i;
|
||
while (down[j] == '^') j++;
|
||
int k = j;
|
||
while (down[k] != '^' && !ISSPACE(down[k]) && down[k] != '\n' && ISASCII(down[k])) k++;
|
||
rb_code_location_t loc = { { p->ruby_sourceline - 1, i }, { p->ruby_sourceline - 1, j } };
|
||
NODE *node;
|
||
if (p->lex.new_nodes && st_lookup(p->lex.new_nodes, (st_data_t)&loc, (st_data_t*)&node)) {
|
||
NODE *n = rb_ast_newnode(p->ast, nd_type(node));
|
||
rb_node_init(n, nd_type(node), node->u1.value, node->u2.value, node->u3.value);
|
||
nd_set_loc(p, n, &node->nd_loc);
|
||
n->node_id = node->node_id;
|
||
ID id = intern_cstr(down + j, k - j, p->enc);
|
||
NODE *tmp = assignable(p, id, n, &loc);
|
||
*node = *tmp;
|
||
node->node_id = -1;
|
||
}
|
||
else {
|
||
yyerror0("cannot identify node");
|
||
break;
|
||
}
|
||
i = k;
|
||
}
|
||
p->lex.pbeg = RSTRING_PTR(p->lex.lastline);
|
||
p->lex.pend = p->lex.pcur = p->lex.pbeg + RSTRING_LEN(p->lex.lastline);
|
||
pushback(p, 1); /* always pushback */
|
||
p->lex.ptok = p->lex.pcur;
|
||
goto normal_newline;
|
||
}
|
||
}
|
||
}
|
||
normal_newline:
|
||
if (p->lex.new_nodes) st_clear(p->lex.new_nodes);
|
||
p->command_start = TRUE;
|
||
SET_LEX_STATE(EXPR_BEG);
|
||
return '\n';
|
||
... | ... | |
#define LVAR_USED ((ID)1 << (sizeof(ID) * CHAR_BIT - 1))
|
||
int
|
||
st_loc_cmp(st_data_t x, st_data_t y)
|
||
{
|
||
const YYLTYPE *loc1 = (const YYLTYPE *)x;
|
||
const YYLTYPE *loc2 = (const YYLTYPE *)y;
|
||
return !(
|
||
loc1->beg_pos.lineno == loc2->beg_pos.lineno &&
|
||
loc1->beg_pos.column == loc2->beg_pos.column &&
|
||
loc1->end_pos.lineno == loc2->end_pos.lineno &&
|
||
loc1->end_pos.column == loc2->end_pos.column
|
||
);
|
||
}
|
||
st_index_t
|
||
st_loc_hash(st_data_t x)
|
||
{
|
||
const YYLTYPE *loc = (const YYLTYPE *)x;
|
||
return loc->beg_pos.lineno ^ loc->beg_pos.column ^ loc->end_pos.lineno ^ loc->end_pos.column;
|
||
}
|
||
static const struct st_hash_type st_hashtype_loc = {
|
||
st_loc_cmp,
|
||
st_loc_hash,
|
||
};
|
||
static NODE*
|
||
node_newnode(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2, const rb_code_location_t *loc)
|
||
{
|
||
... | ... | |
rb_node_init(n, type, a0, a1, a2);
|
||
nd_set_loc(n, loc);
|
||
nd_set_loc(p, n, loc);
|
||
nd_set_node_id(n, parser_get_node_id(p));
|
||
return n;
|
||
}
|
||
static NODE *
|
||
nd_set_loc(NODE *nd, const YYLTYPE *loc)
|
||
nd_set_loc(struct parser_params *p, NODE *nd, const YYLTYPE *loc)
|
||
{
|
||
if (!p->lex.new_nodes) p->lex.new_nodes = st_init_table(&st_hashtype_loc);
|
||
nd->nd_loc = *loc;
|
||
if (!st_lookup(p->lex.new_nodes, (st_data_t)&nd->nd_loc, NULL)) {
|
||
st_insert(p->lex.new_nodes, (st_data_t)&nd->nd_loc, (st_data_t)nd);
|
||
}
|
||
nd_set_line(nd, loc->beg_pos.lineno);
|
||
return nd;
|
||
}
|
||
... | ... | |
{
|
||
VALUE src = node->nd_lit;
|
||
nd_set_type(node, NODE_LIT);
|
||
nd_set_loc(node, loc);
|
||
nd_set_loc(p, node, loc);
|
||
RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit = reg_compile(p, src, options));
|
||
}
|
||
break;
|
||
... | ... | |
/* fall through */
|
||
case NODE_DSTR:
|
||
nd_set_type(node, NODE_DREGX);
|
||
nd_set_loc(node, loc);
|
||
nd_set_loc(p, node, loc);
|
||
node->nd_cflag = options & RE_OPTION_MASK;
|
||
if (!NIL_P(node->nd_lit)) reg_fragment_check(p, node->nd_lit, options);
|
||
for (list = (prev = node)->nd_next; list; list = list->nd_next) {
|
||
... | ... | |
switch (nd_type(node)) {
|
||
case NODE_STR:
|
||
nd_set_type(node, NODE_XSTR);
|
||
nd_set_loc(node, loc);
|
||
nd_set_loc(p, node, loc);
|
||
break;
|
||
case NODE_DSTR:
|
||
nd_set_type(node, NODE_DXSTR);
|
||
nd_set_loc(node, loc);
|
||
nd_set_loc(p, node, loc);
|
||
break;
|
||
default:
|
||
node = NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node, loc), loc);
|
||
... | ... | |
case NODE_MASGN:
|
||
case NODE_CVASGN:
|
||
lhs->nd_value = rhs;
|
||
nd_set_loc(lhs, loc);
|
||
nd_set_loc(p, lhs, loc);
|
||
break;
|
||
case NODE_ATTRASGN:
|
||
lhs->nd_args = arg_append(p, lhs->nd_args, rhs, loc);
|
||
nd_set_loc(lhs, loc);
|
||
nd_set_loc(p, lhs, loc);
|
||
break;
|
||
default:
|
||
... | ... | |
args->ruby2_keywords = rest_arg == idFWD_REST;
|
||
p->ruby_sourceline = saved_line;
|
||
nd_set_loc(tail, loc);
|
||
nd_set_loc(p, tail, loc);
|
||
return tail;
|
||
}
|
||
... | ... | |
if (!args) {
|
||
YYLTYPE loc = RUBY_INIT_YYLLOC();
|
||
args = new_args_tail(p, 0, 0, 0, 0);
|
||
nd_set_loc(args, &loc);
|
||
nd_set_loc(p, args, &loc);
|
||
}
|
||
args->nd_ainfo->pre_args_num = max_numparam;
|
||
}
|
||
... | ... | |
switch (nd_type(node)) {
|
||
case NODE_DSTR:
|
||
nd_set_type(node, NODE_DSYM);
|
||
nd_set_loc(node, loc);
|
||
nd_set_loc(p, node, loc);
|
||
break;
|
||
case NODE_STR:
|
||
lit = node->nd_lit;
|
||
RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit = ID2SYM(rb_intern_str(lit)));
|
||
nd_set_type(node, NODE_LIT);
|
||
nd_set_loc(node, loc);
|
||
nd_set_loc(p, node, loc);
|
||
break;
|
||
default:
|
||
node = NEW_NODE(NODE_DSYM, Qnil, 1, NEW_LIST(node, loc), loc);
|
||
... | ... | |
if (op == tOROP) {
|
||
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
|
||
lhs->nd_value = rhs;
|
||
nd_set_loc(lhs, loc);
|
||
nd_set_loc(p, lhs, loc);
|
||
asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc);
|
||
if (is_notop_id(vid)) {
|
||
switch (id_type(vid)) {
|
||
... | ... | |
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
|
||
}
|
||
lhs->nd_value = rhs;
|
||
nd_set_loc(lhs, loc);
|
||
nd_set_loc(p, lhs, loc);
|
||
asgn = NEW_OP_ASGN_AND(gettable(p, vid, &lhs_loc), lhs, loc);
|
||
}
|
||
else {
|
||
... | ... | |
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
|
||
}
|
||
asgn->nd_value = rhs;
|
||
nd_set_loc(asgn, loc);
|
||
nd_set_loc(p, asgn, loc);
|
||
}
|
||
}
|
||
else {
|