summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorydah <t.yudai92@gmail.com>2024-11-04 23:32:00 +0900
committerYudai Takada <t.yudai92@gmail.com>2025-01-04 07:34:25 +0900
commit4c192011422dc04902ddf930ff22be223325a35d (patch)
tree040fced96644259bd80af515e6ca1adc145cd3df
parent34ee062d74ebfcbd04a0f2be2cdfda9cd8d20716 (diff)
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) = "\"" ```
-rw-r--r--ast.c5
-rw-r--r--node_dump.c4
-rw-r--r--parse.y18
-rw-r--r--rubyparser.h2
-rw-r--r--test/ruby/test_ast.rb8
5 files changed, 28 insertions, 9 deletions
diff --git a/ast.c b/ast.c
index 3544aa3b69..fc524d7c46 100644
--- a/ast.c
+++ b/ast.c
@@ -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)),
diff --git a/node_dump.c b/node_dump.c
index ec9a516453..0153296806 100644
--- a/node_dump.c
+++ b/node_dump.c
@@ -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:
diff --git a/parse.y b/parse.y
index d103dd028a..f215c62437 100644
--- a/parse.y
+++ b/parse.y
@@ -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 *
diff --git a/rubyparser.h b/rubyparser.h
index fa2e2af264..e3c7eae05a 100644
--- a/rubyparser.h
+++ b/rubyparser.h
@@ -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 */
diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb
index 58d22149b7..4e449410f1 100644
--- a/test/ruby/test_ast.rb
+++ b/test/ruby/test_ast.rb
@@ -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]])