summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authorKazuki Tsujimoto <kazuki@callcc.net>2020-06-14 09:24:36 +0900
committerKazuki Tsujimoto <kazuki@callcc.net>2020-06-14 09:24:36 +0900
commitddded1157a90d21cb54b9f07de35ab9b4cc472e1 (patch)
tree315005f4eead6840846e6ce4bbd4dfa44c3bfce7 /parse.y
parentf7906a7e31e6b1cfa135ecea69deb8827e8c8803 (diff)
Introduce find pattern [Feature #16828]
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y121
1 files changed, 111 insertions, 10 deletions
diff --git a/parse.y b/parse.y
index 38640664d0..2c8b1ab97a 100644
--- a/parse.y
+++ b/parse.y
@@ -496,6 +496,8 @@ static NODE *new_args(struct parser_params*,NODE*,NODE*,ID,NODE*,NODE*,const YYL
static NODE *new_args_tail(struct parser_params*,NODE*,ID,ID,const YYLTYPE*);
static NODE *new_array_pattern(struct parser_params *p, NODE *constant, NODE *pre_arg, NODE *aryptn, const YYLTYPE *loc);
static NODE *new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID rest_arg, NODE *post_args, const YYLTYPE *loc);
+static NODE *new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YYLTYPE *loc);
+static NODE *new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID post_rest_arg, const YYLTYPE *loc);
static NODE *new_hash_pattern(struct parser_params *p, NODE *constant, NODE *hshptn, const YYLTYPE *loc);
static NODE *new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, const YYLTYPE *loc);
static NODE *new_case3(struct parser_params *p, NODE *val, NODE *pat, const YYLTYPE *loc);
@@ -871,6 +873,42 @@ new_array_pattern_tail(struct parser_params *p, VALUE pre_args, VALUE has_rest,
return (VALUE)t;
}
+static VALUE
+new_find_pattern(struct parser_params *p, VALUE constant, VALUE fndptn, const YYLTYPE *loc)
+{
+ NODE *t = (NODE *)fndptn;
+ struct rb_fnd_pattern_info *fpinfo = t->nd_fpinfo;
+ VALUE pre_rest_arg = Qnil, args = Qnil, post_rest_arg = Qnil;
+
+ if (fpinfo) {
+ pre_rest_arg = rb_ary_entry(fpinfo->imemo, 0);
+ args = rb_ary_entry(fpinfo->imemo, 1);
+ post_rest_arg = rb_ary_entry(fpinfo->imemo, 2);
+ }
+
+ return dispatch4(fndptn, constant, pre_rest_arg, args, post_rest_arg);
+}
+
+static VALUE
+new_find_pattern_tail(struct parser_params *p, VALUE pre_rest_arg, VALUE args, VALUE post_rest_arg, const YYLTYPE *loc)
+{
+ NODE *t;
+ struct rb_fnd_pattern_info *fpinfo;
+
+ pre_rest_arg = dispatch1(var_field, pre_rest_arg ? pre_rest_arg : Qnil);
+ post_rest_arg = dispatch1(var_field, post_rest_arg ? post_rest_arg : Qnil);
+
+ VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
+ fpinfo = ZALLOC(struct rb_fnd_pattern_info);
+ rb_imemo_tmpbuf_set_ptr(tmpbuf, fpinfo);
+ fpinfo->imemo = rb_ary_new_from_args(4, pre_rest_arg, args, post_rest_arg, tmpbuf);
+
+ t = rb_node_newnode(NODE_FNDPTN, Qnil, Qnil, (VALUE)fpinfo, &NULL_LOC);
+ RB_OBJ_WRITTEN(p->ast, Qnil, fpinfo->imemo);
+
+ return (VALUE)t;
+}
+
#define new_hash(p,h,l) rb_ary_new_from_args(0)
static VALUE
@@ -1139,14 +1177,14 @@ static int looking_at_eol_p(struct parser_params *p);
%type <node> brace_block cmd_brace_block do_block lhs none fitem
%type <node> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner
%type <node> p_case_body p_cases p_top_expr p_top_expr_body
-%type <node> p_expr p_as p_alt p_expr_basic
+%type <node> p_expr p_as p_alt p_expr_basic p_find
%type <node> p_args p_args_head p_args_tail p_args_post p_arg
%type <node> p_value p_primitive p_variable p_var_ref p_const
%type <node> p_kwargs p_kwarg p_kw
%type <id> keyword_variable user_variable sym operation operation2 operation3
%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
%type <id> f_kwrest f_label f_arg_asgn call_op call_op2 reswords relop dot_or_colon
-%type <id> p_kwrest p_kwnorest p_any_kwrest p_kw_label
+%type <id> p_rest p_kwrest p_kwnorest p_any_kwrest p_kw_label
%type <id> f_no_kwarg f_any_kwrest args_forward excessed_comma
%token END_OF_INPUT 0 "end-of-input"
%token <id> '.'
@@ -3963,6 +4001,10 @@ p_top_expr_body : p_expr
/*%
%*/
}
+ | p_find
+ {
+ $$ = new_find_pattern(p, Qnone, $1, &@$);
+ }
| p_args_tail
{
$$ = new_array_pattern(p, Qnone, Qnone, $1, &@$);
@@ -4011,6 +4053,15 @@ p_expr_basic : p_value
/*%
%*/
}
+ | p_const p_lparen p_find rparen
+ {
+ pop_pktbl(p, $<tbl>2);
+ $$ = new_find_pattern(p, $1, $3, &@$);
+ /*%%%*/
+ nd_set_first_loc($$, @1.beg_pos);
+ /*%
+ %*/
+ }
| p_const p_lparen p_kwargs rparen
{
pop_pktbl(p, $<tbl>2);
@@ -4034,6 +4085,15 @@ p_expr_basic : p_value
/*%
%*/
}
+ | p_const p_lbracket p_find rbracket
+ {
+ pop_pktbl(p, $<tbl>2);
+ $$ = new_find_pattern(p, $1, $3, &@$);
+ /*%%%*/
+ nd_set_first_loc($$, @1.beg_pos);
+ /*%
+ %*/
+ }
| p_const p_lbracket p_kwargs rbracket
{
pop_pktbl(p, $<tbl>2);
@@ -4052,6 +4112,10 @@ p_expr_basic : p_value
{
$$ = new_array_pattern(p, Qnone, Qnone, $2, &@$);
}
+ | tLBRACK p_find rbracket
+ {
+ $$ = new_find_pattern(p, Qnone, $2, &@$);
+ }
| tLBRACK rbracket
{
$$ = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &@$);
@@ -4135,21 +4199,30 @@ p_args_head : p_arg ','
}
;
-p_args_tail : tSTAR tIDENTIFIER
+p_args_tail : p_rest
{
- $$ = new_array_pattern_tail(p, Qnone, 1, $2, Qnone, &@$);
+ $$ = new_array_pattern_tail(p, Qnone, 1, $1, Qnone, &@$);
}
- | tSTAR tIDENTIFIER ',' p_args_post
+ | p_rest ',' p_args_post
{
- $$ = new_array_pattern_tail(p, Qnone, 1, $2, $4, &@$);
+ $$ = new_array_pattern_tail(p, Qnone, 1, $1, $3, &@$);
}
- | tSTAR
+ ;
+
+p_find : p_rest ',' p_args_post ',' p_rest
{
- $$ = new_array_pattern_tail(p, Qnone, 1, 0, Qnone, &@$);
+ $$ = new_find_pattern_tail(p, $1, $3, $5, &@$);
+ }
+ ;
+
+
+p_rest : tSTAR tIDENTIFIER
+ {
+ $$ = $2;
}
- | tSTAR ',' p_args_post
+ | tSTAR
{
- $$ = new_array_pattern_tail(p, Qnone, 1, 0, $3, &@$);
+ $$ = 0;
}
;
@@ -11537,6 +11610,34 @@ new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID
}
static NODE*
+new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YYLTYPE *loc)
+{
+ fndptn->nd_pconst = constant;
+
+ return fndptn;
+}
+
+static NODE*
+new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID post_rest_arg, const YYLTYPE *loc)
+{
+ int saved_line = p->ruby_sourceline;
+ NODE *node;
+ VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
+ struct rb_fnd_pattern_info *fpinfo = ZALLOC(struct rb_fnd_pattern_info);
+ rb_imemo_tmpbuf_set_ptr(tmpbuf, fpinfo);
+ node = NEW_NODE(NODE_FNDPTN, 0, 0, fpinfo, loc);
+ fpinfo->imemo = tmpbuf;
+ RB_OBJ_WRITTEN(p->ast, Qnil, tmpbuf);
+
+ fpinfo->pre_rest_arg = pre_rest_arg ? assignable(p, pre_rest_arg, 0, loc) : NODE_SPECIAL_NO_NAME_REST;
+ fpinfo->args = args;
+ fpinfo->post_rest_arg = post_rest_arg ? assignable(p, post_rest_arg, 0, loc) : NODE_SPECIAL_NO_NAME_REST;
+
+ p->ruby_sourceline = saved_line;
+ return node;
+}
+
+static NODE*
new_hash_pattern(struct parser_params *p, NODE *constant, NODE *hshptn, const YYLTYPE *loc)
{
hshptn->nd_pconst = constant;