Implement IF 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 -y -e "if a; elsif b; else end" @ ProgramNode (location: (1,0)-(1,23)) +-- locals: [] +-- statements: @ StatementsNode (location: (1,0)-(1,23)) +-- body: (length: 1) +-- @ IfNode (location: (1,0)-(1,23)) +-- if_keyword_loc: (1,0)-(1,2) = "if" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +-- predicate: | @ CallNode (location: (1,3)-(1,4)) | +-- CallNodeFlags: variable_call, ignore_visibility | +-- receiver: nil | +-- call_operator_loc: nil | +-- name: :a | +-- message_loc: (1,3)-(1,4) = "a" | +-- opening_loc: nil | +-- arguments: nil | +-- closing_loc: nil | +-- block: nil +-- then_keyword_loc: nil ^^^^^^^^^^^^^^^^^^^^^^^^^ +-- statements: nil +-- subsequent: | @ IfNode (location: (1,6)-(1,23)) | +-- if_keyword_loc: (1,6)-(1,11) = "elsif" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | +-- predicate: | | @ CallNode (location: (1,12)-(1,13)) | | +-- CallNodeFlags: variable_call, ignore_visibility | | +-- receiver: nil | | +-- call_operator_loc: nil | | +-- name: :b | | +-- message_loc: (1,12)-(1,13) = "b" | | +-- opening_loc: nil | | +-- arguments: nil | | +-- closing_loc: nil | | +-- block: nil | +-- then_keyword_loc: nil ^^^^^^^^^^^^^^^^^^^^^^^^^ | +-- statements: nil | +-- subsequent: | | @ ElseNode (location: (1,15)-(1,23)) | | +-- else_keyword_loc: (1,15)-(1,19) = "else" | | +-- statements: nil | | +-- end_keyword_loc: (1,20)-(1,23) = "end" | +-- end_keyword_loc: (1,20)-(1,23) = "end" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +-- end_keyword_loc: (1,20)-(1,23) = "end" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ```
This commit is contained in:
parent
23018c2fb4
commit
0643f08187
6
ast.c
6
ast.c
@ -807,6 +807,12 @@ node_locations(VALUE ast_value, const NODE *node)
|
||||
location_new(nd_code_loc(node)),
|
||||
location_new(&RNODE_CASE3(node)->case_keyword_loc),
|
||||
location_new(&RNODE_CASE3(node)->end_keyword_loc));
|
||||
case NODE_IF:
|
||||
return rb_ary_new_from_args(4,
|
||||
location_new(nd_code_loc(node)),
|
||||
location_new(&RNODE_IF(node)->if_keyword_loc),
|
||||
location_new(&RNODE_IF(node)->then_keyword_loc),
|
||||
location_new(&RNODE_IF(node)->end_keyword_loc));
|
||||
case NODE_NEXT:
|
||||
return rb_ary_new_from_args(2,
|
||||
location_new(nd_code_loc(node)),
|
||||
|
@ -239,8 +239,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
|
||||
ANN("example: if x == 1 then foo else bar end");
|
||||
F_NODE(nd_cond, RNODE_IF, "condition expr");
|
||||
F_NODE(nd_body, RNODE_IF, "then clause");
|
||||
LAST_NODE;
|
||||
F_NODE(nd_else, RNODE_IF, "else clause");
|
||||
F_LOC(if_keyword_loc, RNODE_IF);
|
||||
F_LOC(then_keyword_loc, RNODE_IF);
|
||||
LAST_NODE;
|
||||
F_LOC(end_keyword_loc, RNODE_IF);
|
||||
return;
|
||||
|
||||
case NODE_UNLESS:
|
||||
|
28
parse.y
28
parse.y
@ -1058,7 +1058,7 @@ rb_discard_node(struct parser_params *p, NODE *n)
|
||||
static rb_node_scope_t *rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc);
|
||||
static rb_node_scope_t *rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc);
|
||||
static rb_node_block_t *rb_node_block_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
|
||||
static rb_node_if_t *rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc);
|
||||
static rb_node_if_t *rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc);
|
||||
static rb_node_unless_t *rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *end_keyword_loc);
|
||||
static rb_node_case_t *rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc);
|
||||
static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc);
|
||||
@ -1166,7 +1166,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
|
||||
#define NEW_SCOPE(a,b,loc) (NODE *)rb_node_scope_new(p,a,b,loc)
|
||||
#define NEW_SCOPE2(t,a,b,loc) (NODE *)rb_node_scope_new2(p,t,a,b,loc)
|
||||
#define NEW_BLOCK(a,loc) (NODE *)rb_node_block_new(p,a,loc)
|
||||
#define NEW_IF(c,t,e,loc) (NODE *)rb_node_if_new(p,c,t,e,loc)
|
||||
#define NEW_IF(c,t,e,loc,ik_loc,tk_loc,ek_loc) (NODE *)rb_node_if_new(p,c,t,e,loc,ik_loc,tk_loc,ek_loc)
|
||||
#define NEW_UNLESS(c,t,e,loc,k_loc,t_loc,e_loc) (NODE *)rb_node_unless_new(p,c,t,e,loc,k_loc,t_loc,e_loc)
|
||||
#define NEW_CASE(h,b,loc,ck_loc,ek_loc) (NODE *)rb_node_case_new(p,h,b,loc,ck_loc,ek_loc)
|
||||
#define NEW_CASE2(b,loc,ck_loc,ek_loc) (NODE *)rb_node_case2_new(p,b,loc,ck_loc,ek_loc)
|
||||
@ -1387,7 +1387,7 @@ static NODE* cond(struct parser_params *p, NODE *node, const YYLTYPE *loc);
|
||||
static NODE* method_cond(struct parser_params *p, NODE *node, const YYLTYPE *loc);
|
||||
#define new_nil(loc) NEW_NIL(loc)
|
||||
static NODE *new_nil_at(struct parser_params *p, const rb_code_position_t *pos);
|
||||
static NODE *new_if(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*);
|
||||
static NODE *new_if(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*);
|
||||
static NODE *new_unless(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*);
|
||||
static NODE *logop(struct parser_params*,ID,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*);
|
||||
|
||||
@ -3159,7 +3159,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
|
||||
}
|
||||
| stmt modifier_if expr_value
|
||||
{
|
||||
$$ = new_if(p, $3, remove_begin($1), 0, &@$);
|
||||
$$ = new_if(p, $3, remove_begin($1), 0, &@$, &@2, &NULL_LOC, &NULL_LOC);
|
||||
fixpos($$, $3);
|
||||
/*% ripper: if_mod!($:3, $:1) %*/
|
||||
}
|
||||
@ -4044,7 +4044,7 @@ arg : lhs '=' lex_ctxt arg_rhs
|
||||
| arg '?' arg '\n'? ':' arg
|
||||
{
|
||||
value_expr($1);
|
||||
$$ = new_if(p, $1, $3, $6, &@$);
|
||||
$$ = new_if(p, $1, $3, $6, &@$, &NULL_LOC, &@5, &NULL_LOC);
|
||||
fixpos($$, $1);
|
||||
/*% ripper: ifop!($:1, $:3, $:6) %*/
|
||||
}
|
||||
@ -4488,7 +4488,10 @@ primary : inline_primary
|
||||
if_tail
|
||||
k_end
|
||||
{
|
||||
$$ = new_if(p, $2, $4, $5, &@$);
|
||||
if ($5 && nd_type_p($5, NODE_IF))
|
||||
RNODE_IF($5)->end_keyword_loc = @6;
|
||||
|
||||
$$ = new_if(p, $2, $4, $5, &@$, &@1, &@3, &@6);
|
||||
fixpos($$, $2);
|
||||
/*% ripper: if!($:2, $:4, $:5) %*/
|
||||
}
|
||||
@ -4900,7 +4903,7 @@ if_tail : opt_else
|
||||
compstmt
|
||||
if_tail
|
||||
{
|
||||
$$ = new_if(p, $2, $4, $5, &@$);
|
||||
$$ = new_if(p, $2, $4, $5, &@$, &@1, &@3, &NULL_LOC);
|
||||
fixpos($$, $2);
|
||||
/*% ripper: elsif!($:2, $:4, $:5) %*/
|
||||
}
|
||||
@ -5465,7 +5468,7 @@ p_cases : opt_else
|
||||
p_top_expr : p_top_expr_body
|
||||
| p_top_expr_body modifier_if expr_value
|
||||
{
|
||||
$$ = new_if(p, $3, $1, 0, &@$);
|
||||
$$ = new_if(p, $3, $1, 0, &@$, &@2, &NULL_LOC, &NULL_LOC);
|
||||
fixpos($$, $3);
|
||||
/*% ripper: if_mod!($:3, $:1) %*/
|
||||
}
|
||||
@ -11512,12 +11515,15 @@ rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
|
||||
}
|
||||
|
||||
static rb_node_if_t *
|
||||
rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc)
|
||||
rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc)
|
||||
{
|
||||
rb_node_if_t *n = NODE_NEWNODE(NODE_IF, rb_node_if_t, loc);
|
||||
n->nd_cond = nd_cond;
|
||||
n->nd_body = nd_body;
|
||||
n->nd_else = nd_else;
|
||||
n->if_keyword_loc = *if_keyword_loc;
|
||||
n->then_keyword_loc = *then_keyword_loc;
|
||||
n->end_keyword_loc = *end_keyword_loc;
|
||||
|
||||
return n;
|
||||
}
|
||||
@ -14322,11 +14328,11 @@ new_nil_at(struct parser_params *p, const rb_code_position_t *pos)
|
||||
}
|
||||
|
||||
static NODE*
|
||||
new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc)
|
||||
new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc)
|
||||
{
|
||||
if (!cc) return right;
|
||||
cc = cond0(p, cc, COND_IN_COND, loc, true);
|
||||
return newline_node(NEW_IF(cc, left, right, loc));
|
||||
return newline_node(NEW_IF(cc, left, right, loc, if_keyword_loc, then_keyword_loc, end_keyword_loc));
|
||||
}
|
||||
|
||||
static NODE*
|
||||
|
@ -265,6 +265,9 @@ typedef struct RNode_IF {
|
||||
struct RNode *nd_cond;
|
||||
struct RNode *nd_body;
|
||||
struct RNode *nd_else;
|
||||
rb_code_location_t if_keyword_loc;
|
||||
rb_code_location_t then_keyword_loc;
|
||||
rb_code_location_t end_keyword_loc;
|
||||
} rb_node_if_t;
|
||||
|
||||
typedef struct RNode_UNLESS {
|
||||
|
@ -1376,6 +1376,24 @@ dummy
|
||||
assert_locations(node.children[-1].locations, [[1, 0, 1, 17], [1, 0, 1, 4], [1, 14, 1, 17]])
|
||||
end
|
||||
|
||||
def test_if_locations
|
||||
node = ast_parse("if cond then 1 else 2 end")
|
||||
assert_locations(node.children[-1].locations, [[1, 0, 1, 25], [1, 0, 1, 2], [1, 8, 1, 12], [1, 22, 1, 25]])
|
||||
|
||||
node = ast_parse("1 if 2")
|
||||
assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 2, 1, 4], nil, nil])
|
||||
|
||||
node = ast_parse("if 1; elsif 2; else end")
|
||||
assert_locations(node.children[-1].locations, [[1, 0, 1, 23], [1, 0, 1, 2], [1, 4, 1, 5], [1, 20, 1, 23]])
|
||||
assert_locations(node.children[-1].children[-1].locations, [[1, 6, 1, 19], [1, 6, 1, 11], [1, 13, 1, 14], [1, 20, 1, 23]])
|
||||
|
||||
node = ast_parse("true ? 1 : 2")
|
||||
assert_locations(node.children[-1].locations, [[1, 0, 1, 12], nil, [1, 9, 1, 10], nil])
|
||||
|
||||
node = ast_parse("case a; in b if c; end")
|
||||
assert_locations(node.children[-1].children[1].children[0].locations, [[1, 11, 1, 17], [1, 13, 1, 15], nil, nil])
|
||||
end
|
||||
|
||||
def test_next_locations
|
||||
node = ast_parse("loop { next 1 }")
|
||||
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 13], [1, 7, 1, 11]])
|
||||
|
Loading…
x
Reference in New Issue
Block a user