Implement EVSTR 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 '"#{foo}"'
@ ProgramNode (location: (1,0)-(1,8))
+-- locals: []
+-- statements:
    @ StatementsNode (location: (1,0)-(1,8))
    +-- body: (length: 1)
        +-- @ InterpolatedStringNode (location: (1,0)-(1,8))
            +-- InterpolatedStringNodeFlags: nil
            +-- opening_loc: (1,0)-(1,1) = "\""
            +-- parts: (length: 1)
            |   +-- @ EmbeddedStatementsNode (location: (1,1)-(1,7))
            |       +-- opening_loc: (1,1)-(1,3) = "\#{"
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            |       +-- statements:
            |       |   @ StatementsNode (location: (1,3)-(1,6))
            |       |   +-- body: (length: 1)
            |       |       +-- @ CallNode (location: (1,3)-(1,6))
            |       |           +-- CallNodeFlags: variable_call, ignore_visibility
            |       |           +-- receiver: nil
            |       |           +-- call_operator_loc: nil
            |       |           +-- name: :foo
            |       |           +-- message_loc: (1,3)-(1,6) = "foo"
            |       |           +-- opening_loc: nil
            |       |           +-- arguments: nil
            |       |           +-- closing_loc: nil
            |       |           +-- block: nil
            |       +-- closing_loc: (1,6)-(1,7) = "}"
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            +-- closing_loc: (1,7)-(1,8) = "\""
```
This commit is contained in:
ydah 2024-11-04 23:32:00 +09:00 committed by Yudai Takada
parent 34ee062d74
commit 4c19201142
5 changed files with 28 additions and 9 deletions

5
ast.c
View File

@ -807,6 +807,11 @@ 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_EVSTR:
return rb_ary_new_from_args(3,
location_new(nd_code_loc(node)),
location_new(&RNODE_EVSTR(node)->opening_loc),
location_new(&RNODE_EVSTR(node)->closing_loc));
case NODE_IF:
return rb_ary_new_from_args(4,
location_new(nd_code_loc(node)),

View File

@ -882,8 +882,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("interpolation expression");
ANN("format: \"..#{ [nd_body] }..\"");
ANN("example: \"foo#{ bar }baz\"");
LAST_NODE;
F_NODE(nd_body, RNODE_EVSTR, "body");
F_LOC(opening_loc, RNODE_EVSTR);
LAST_NODE;
F_LOC(closing_loc, RNODE_EVSTR);
return;
case NODE_ARGSCAT:

18
parse.y
View File

@ -1121,7 +1121,7 @@ static rb_node_dstr_t *rb_node_dstr_new0(struct parser_params *p, rb_parser_stri
static rb_node_dstr_t *rb_node_dstr_new(struct parser_params *p, rb_parser_string_t *string, const YYLTYPE *loc);
static rb_node_xstr_t *rb_node_xstr_new(struct parser_params *p, rb_parser_string_t *string, const YYLTYPE *loc);
static rb_node_dxstr_t *rb_node_dxstr_new(struct parser_params *p, rb_parser_string_t *string, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
static rb_node_evstr_t *rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
static rb_node_evstr_t *rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc);
static rb_node_regx_t *rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc);
static rb_node_once_t *rb_node_once_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
static rb_node_args_t *rb_node_args_new(struct parser_params *p, const YYLTYPE *loc);
@ -1229,7 +1229,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_DSTR(s,loc) (NODE *)rb_node_dstr_new(p,s,loc)
#define NEW_XSTR(s,loc) (NODE *)rb_node_xstr_new(p,s,loc)
#define NEW_DXSTR(s,l,n,loc) (NODE *)rb_node_dxstr_new(p,s,l,n,loc)
#define NEW_EVSTR(n,loc) (NODE *)rb_node_evstr_new(p,n,loc)
#define NEW_EVSTR(n,loc,o_loc,c_loc) (NODE *)rb_node_evstr_new(p,n,loc,o_loc,c_loc)
#define NEW_REGX(str,opts,loc) (NODE *)rb_node_regx_new(p,str,opts,loc)
#define NEW_ONCE(b,loc) (NODE *)rb_node_once_new(p,b,loc)
#define NEW_ARGS(loc) rb_node_args_new(p,loc)
@ -1409,7 +1409,7 @@ static NODE *arg_append(struct parser_params*,NODE*,NODE*,const YYLTYPE*);
static NODE *last_arg_append(struct parser_params *p, NODE *args, NODE *last_arg, const YYLTYPE *loc);
static NODE *rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTYPE *loc);
static NODE *literal_concat(struct parser_params*,NODE*,NODE*,const YYLTYPE*);
static NODE *new_evstr(struct parser_params*,NODE*,const YYLTYPE*);
static NODE *new_evstr(struct parser_params*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*);
static NODE *new_dstr(struct parser_params*,NODE*,const YYLTYPE*);
static NODE *str2dstr(struct parser_params*,NODE*);
static NODE *evstr2dstr(struct parser_params*,NODE*);
@ -6167,7 +6167,7 @@ string_content : tSTRING_CONTENT
string_dvar
{
p->lex.strterm = $2;
$$ = NEW_EVSTR($3, &@$);
$$ = NEW_EVSTR($3, &@$, &@1, &NULL_LOC);
nd_set_line($$, @3.end_pos.lineno);
/*% ripper: string_dvar!($:3) %*/
}
@ -6198,7 +6198,7 @@ string_content : tSTRING_CONTENT
p->heredoc_indent = $indent;
p->heredoc_line_indent = -1;
if ($compstmt) nd_unset_fl_newline($compstmt);
$$ = new_evstr(p, $compstmt, &@$);
$$ = new_evstr(p, $compstmt, &@$, &@state, &@string_dend);
/*% ripper: string_embexpr!($:compstmt) %*/
}
;
@ -12135,10 +12135,12 @@ rb_node_dsym_new(struct parser_params *p, rb_parser_string_t *string, long nd_al
}
static rb_node_evstr_t *
rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
{
rb_node_evstr_t *n = NODE_NEWNODE(NODE_EVSTR, rb_node_evstr_t, loc);
n->nd_body = nd_body;
n->opening_loc = *opening_loc;
n->closing_loc = *closing_loc;
return n;
}
@ -12824,7 +12826,7 @@ evstr2dstr(struct parser_params *p, NODE *node)
}
static NODE *
new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
{
NODE *head = node;
@ -12838,7 +12840,7 @@ new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
return node;
}
}
return NEW_EVSTR(head, loc);
return NEW_EVSTR(head, loc, opening_loc, closing_loc);
}
static NODE *

View File

@ -725,6 +725,8 @@ typedef struct RNode_EVSTR {
NODE node;
struct RNode *nd_body;
rb_code_location_t opening_loc;
rb_code_location_t closing_loc;
} rb_node_evstr_t;
typedef struct RNode_REGX { /* also RNode_MATCH */

View File

@ -1376,6 +1376,14 @@ dummy
assert_locations(node.children[-1].locations, [[1, 0, 1, 17], [1, 0, 1, 4], [1, 14, 1, 17]])
end
def test_evstr_locations
node = ast_parse('"#{foo}"')
assert_locations(node.children[-1].children[1].locations, [[1, 0, 1, 8], [1, 1, 1, 3], [1, 6, 1, 7]])
node = ast_parse('"#$1"')
assert_locations(node.children[-1].children[1].locations, [[1, 0, 1, 5], [1, 1, 1, 2], nil])
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]])