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(nd_code_loc(node)),
|
||||||
location_new(&RNODE_CASE3(node)->case_keyword_loc),
|
location_new(&RNODE_CASE3(node)->case_keyword_loc),
|
||||||
location_new(&RNODE_CASE3(node)->end_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:
|
case NODE_NEXT:
|
||||||
return rb_ary_new_from_args(2,
|
return rb_ary_new_from_args(2,
|
||||||
location_new(nd_code_loc(node)),
|
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");
|
ANN("example: if x == 1 then foo else bar end");
|
||||||
F_NODE(nd_cond, RNODE_IF, "condition expr");
|
F_NODE(nd_cond, RNODE_IF, "condition expr");
|
||||||
F_NODE(nd_body, RNODE_IF, "then clause");
|
F_NODE(nd_body, RNODE_IF, "then clause");
|
||||||
LAST_NODE;
|
|
||||||
F_NODE(nd_else, RNODE_IF, "else clause");
|
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;
|
return;
|
||||||
|
|
||||||
case NODE_UNLESS:
|
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_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_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_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_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_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);
|
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_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_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_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_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_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)
|
#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);
|
static NODE* method_cond(struct parser_params *p, NODE *node, const YYLTYPE *loc);
|
||||||
#define new_nil(loc) NEW_NIL(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_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 *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*);
|
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
|
| 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);
|
fixpos($$, $3);
|
||||||
/*% ripper: if_mod!($:3, $:1) %*/
|
/*% ripper: if_mod!($:3, $:1) %*/
|
||||||
}
|
}
|
||||||
@ -4044,7 +4044,7 @@ arg : lhs '=' lex_ctxt arg_rhs
|
|||||||
| arg '?' arg '\n'? ':' arg
|
| arg '?' arg '\n'? ':' arg
|
||||||
{
|
{
|
||||||
value_expr($1);
|
value_expr($1);
|
||||||
$$ = new_if(p, $1, $3, $6, &@$);
|
$$ = new_if(p, $1, $3, $6, &@$, &NULL_LOC, &@5, &NULL_LOC);
|
||||||
fixpos($$, $1);
|
fixpos($$, $1);
|
||||||
/*% ripper: ifop!($:1, $:3, $:6) %*/
|
/*% ripper: ifop!($:1, $:3, $:6) %*/
|
||||||
}
|
}
|
||||||
@ -4488,7 +4488,10 @@ primary : inline_primary
|
|||||||
if_tail
|
if_tail
|
||||||
k_end
|
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);
|
fixpos($$, $2);
|
||||||
/*% ripper: if!($:2, $:4, $:5) %*/
|
/*% ripper: if!($:2, $:4, $:5) %*/
|
||||||
}
|
}
|
||||||
@ -4900,7 +4903,7 @@ if_tail : opt_else
|
|||||||
compstmt
|
compstmt
|
||||||
if_tail
|
if_tail
|
||||||
{
|
{
|
||||||
$$ = new_if(p, $2, $4, $5, &@$);
|
$$ = new_if(p, $2, $4, $5, &@$, &@1, &@3, &NULL_LOC);
|
||||||
fixpos($$, $2);
|
fixpos($$, $2);
|
||||||
/*% ripper: elsif!($:2, $:4, $:5) %*/
|
/*% ripper: elsif!($:2, $:4, $:5) %*/
|
||||||
}
|
}
|
||||||
@ -5465,7 +5468,7 @@ p_cases : opt_else
|
|||||||
p_top_expr : p_top_expr_body
|
p_top_expr : p_top_expr_body
|
||||||
| p_top_expr_body modifier_if expr_value
|
| 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);
|
fixpos($$, $3);
|
||||||
/*% ripper: if_mod!($:3, $:1) %*/
|
/*% 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 *
|
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);
|
rb_node_if_t *n = NODE_NEWNODE(NODE_IF, rb_node_if_t, loc);
|
||||||
n->nd_cond = nd_cond;
|
n->nd_cond = nd_cond;
|
||||||
n->nd_body = nd_body;
|
n->nd_body = nd_body;
|
||||||
n->nd_else = nd_else;
|
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;
|
return n;
|
||||||
}
|
}
|
||||||
@ -14322,11 +14328,11 @@ new_nil_at(struct parser_params *p, const rb_code_position_t *pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NODE*
|
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;
|
if (!cc) return right;
|
||||||
cc = cond0(p, cc, COND_IN_COND, loc, true);
|
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*
|
static NODE*
|
||||||
|
@ -265,6 +265,9 @@ typedef struct RNode_IF {
|
|||||||
struct RNode *nd_cond;
|
struct RNode *nd_cond;
|
||||||
struct RNode *nd_body;
|
struct RNode *nd_body;
|
||||||
struct RNode *nd_else;
|
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;
|
} rb_node_if_t;
|
||||||
|
|
||||||
typedef struct RNode_UNLESS {
|
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]])
|
assert_locations(node.children[-1].locations, [[1, 0, 1, 17], [1, 0, 1, 4], [1, 14, 1, 17]])
|
||||||
end
|
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
|
def test_next_locations
|
||||||
node = ast_parse("loop { next 1 }")
|
node = ast_parse("loop { next 1 }")
|
||||||
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 13], [1, 7, 1, 11]])
|
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