Implement YIELD NODE locations

The following Location information has been added This is the information required for parse.y to be a universal parser:

```
❯ ruby --parser=prism --dump=parsetree -e 'def foo; yield end'
@ ProgramNode (location: (1,0)-(1,18))
+-- locals: []
+-- statements:
    @ StatementsNode (location: (1,0)-(1,18))
    +-- body: (length: 1)
        +-- @ DefNode (location: (1,0)-(1,18))
            +-- name: :foo
            +-- name_loc: (1,4)-(1,7) = "foo"
            +-- receiver: nil
            +-- parameters: nil
            +-- body:
            |   @ StatementsNode (location: (1,9)-(1,14))
            |   +-- body: (length: 1)
            |       +-- @ YieldNode (location: (1,9)-(1,14))
            |           +-- keyword_loc: (1,9)-(1,14) = "yield"
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            |           +-- lparen_loc: nil
                        ^^^^^^^^^^^^^^^^^^^
            |           +-- arguments: nil
            |           +-- rparen_loc: nil
                        ^^^^^^^^^^^^^^^^^^^
            +-- locals: []
            +-- def_keyword_loc: (1,0)-(1,3) = "def"
            +-- operator_loc: nil
            +-- lparen_loc: nil
            +-- rparen_loc: nil
            +-- equal_loc: nil
            +-- end_keyword_loc: (1,15)-(1,18) = "end"
```
This commit is contained in:
ydah 2024-11-06 12:14:01 +09:00 committed by Yudai Takada
parent 4c19201142
commit 607b1b3d76
5 changed files with 40 additions and 11 deletions

6
ast.c
View File

@ -886,6 +886,12 @@ node_locations(VALUE ast_value, const NODE *node)
location_new(nd_code_loc(node)),
location_new(&RNODE_UNTIL(node)->keyword_loc),
location_new(&RNODE_UNTIL(node)->closing_loc));
case NODE_YIELD:
return rb_ary_new_from_args(4,
location_new(nd_code_loc(node)),
location_new(&RNODE_YIELD(node)->keyword_loc),
location_new(&RNODE_YIELD(node)->lparen_loc),
location_new(&RNODE_YIELD(node)->rparen_loc));
case NODE_ARGS_AUX:
case NODE_LAST:
break;

View File

@ -697,8 +697,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("yield invocation");
ANN("format: yield [nd_head]");
ANN("example: yield 1");
LAST_NODE;
F_NODE(nd_head, RNODE_YIELD, "arguments");
F_LOC(keyword_loc, RNODE_YIELD);
F_LOC(lparen_loc, RNODE_YIELD);
LAST_NODE;
F_LOC(rparen_loc, RNODE_YIELD);
return;
case NODE_LVAR:

23
parse.y
View File

@ -1101,7 +1101,7 @@ static rb_node_list_t *rb_node_list_new2(struct parser_params *p, NODE *nd_head,
static rb_node_zlist_t *rb_node_zlist_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_hash_t *rb_node_hash_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
static rb_node_return_t *rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
static rb_node_yield_t *rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
static rb_node_yield_t *rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc);
static rb_node_lvar_t *rb_node_lvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
static rb_node_dvar_t *rb_node_dvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
static rb_node_gvar_t *rb_node_gvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
@ -1209,7 +1209,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_ZLIST(loc) (NODE *)rb_node_zlist_new(p,loc)
#define NEW_HASH(a,loc) (NODE *)rb_node_hash_new(p,a,loc)
#define NEW_RETURN(s,loc,k_loc) (NODE *)rb_node_return_new(p,s,loc,k_loc)
#define NEW_YIELD(a,loc) (NODE *)rb_node_yield_new(p,a,loc)
#define NEW_YIELD(a,loc,k_loc,l_loc,r_loc) (NODE *)rb_node_yield_new(p,a,loc,k_loc,l_loc,r_loc)
#define NEW_LVAR(v,loc) (NODE *)rb_node_lvar_new(p,v,loc)
#define NEW_DVAR(v,loc) (NODE *)rb_node_dvar_new(p,v,loc)
#define NEW_GVAR(v,loc) (NODE *)rb_node_gvar_new(p,v,loc)
@ -1438,7 +1438,7 @@ static rb_node_args_t *args_with_numbered(struct parser_params*,rb_node_args_t*,
static NODE* negate_lit(struct parser_params*, NODE*);
static NODE *ret_args(struct parser_params*,NODE*);
static NODE *arg_blk_pass(NODE*,rb_node_block_pass_t*);
static NODE *new_yield(struct parser_params*,NODE*,const YYLTYPE*);
static NODE *new_yield(struct parser_params*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*);
static NODE *dsym_node(struct parser_params*,NODE*,const YYLTYPE*);
static NODE *gettable(struct parser_params*,ID,const YYLTYPE*);
@ -3515,7 +3515,7 @@ command : fcall command_args %prec tLOWEST
}
| k_yield command_args
{
$$ = new_yield(p, $2, &@$);
$$ = new_yield(p, $2, &@$, &@1, &NULL_LOC, &NULL_LOC);
fixpos($$, $2);
/*% ripper: yield!($:2) %*/
}
@ -4429,17 +4429,17 @@ primary : inline_primary
}
| k_yield '(' call_args rparen
{
$$ = new_yield(p, $3, &@$);
$$ = new_yield(p, $3, &@$, &@1, &@2, &@4);
/*% ripper: yield!(paren!($:3)) %*/
}
| k_yield '(' rparen
{
$$ = NEW_YIELD(0, &@$);
$$ = NEW_YIELD(0, &@$, &@1, &@2, &@3);
/*% ripper: yield!(paren!(args_new!)) %*/
}
| k_yield
{
$$ = NEW_YIELD(0, &@$);
$$ = NEW_YIELD(0, &@$, &@1, &NULL_LOC, &NULL_LOC);
/*% ripper: yield0! %*/
}
| keyword_defined '\n'? '(' begin_defined expr rparen
@ -11499,10 +11499,13 @@ rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, c
}
static rb_node_yield_t *
rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc)
{
rb_node_yield_t *n = NODE_NEWNODE(NODE_YIELD, rb_node_yield_t, loc);
n->nd_head = nd_head;
n->keyword_loc = *keyword_loc;
n->lparen_loc = *lparen_loc;
n->rparen_loc = *rparen_loc;
return n;
}
@ -14389,11 +14392,11 @@ ret_args(struct parser_params *p, NODE *node)
}
static NODE *
new_yield(struct parser_params *p, NODE *node, const YYLTYPE *loc)
new_yield(struct parser_params *p, NODE *node, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc)
{
if (node) no_blockarg(p, node);
return NEW_YIELD(node, loc);
return NEW_YIELD(node, loc, keyword_loc, lparen_loc, rparen_loc);
}
static NODE*

View File

@ -593,6 +593,9 @@ typedef struct RNode_YIELD {
NODE node;
struct RNode *nd_head;
rb_code_location_t keyword_loc;
rb_code_location_t lparen_loc;
rb_code_location_t rparen_loc;
} rb_node_yield_t;
typedef struct RNode_LVAR {

View File

@ -1517,6 +1517,20 @@ dummy
assert_locations(node.children[-1].locations, [[1, 0, 1, 9], [1, 2, 1, 7], nil])
end
def test_yield_locations
node = ast_parse("def foo; yield end")
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 9, 1, 14], [1, 9, 1, 14], nil, nil])
node = ast_parse("def foo; yield() end")
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 9, 1, 16], [1, 9, 1, 14], [1, 14, 1, 15], [1, 15, 1, 16]])
node = ast_parse("def foo; yield 1, 2 end")
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 9, 1, 19], [1, 9, 1, 14], nil, nil])
node = ast_parse("def foo; yield(1, 2) end")
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 9, 1, 20], [1, 9, 1, 14], [1, 14, 1, 15], [1, 19, 1, 20]])
end
private
def ast_parse(src, **options)
begin