diff --git a/parser/Builder.cc b/parser/Builder.cc index f7f3f1ae582..426f192e5db 100644 --- a/parser/Builder.cc +++ b/parser/Builder.cc @@ -779,6 +779,20 @@ class Builder::Impl { return make_unique(tokLoc(tok)); } + unique_ptr find_pattern(const token *lbrack_t, sorbet::parser::NodeVec elements, const token *rbrack_t) { + auto loc = collectionLoc(elements); + + if (lbrack_t != nullptr) { + loc = tokLoc(lbrack_t).join(loc); + } + + if (rbrack_t != nullptr) { + loc = loc.join(tokLoc(rbrack_t)); + } + + return make_unique(loc, std::move(elements)); + } + unique_ptr fileLiteral(const token *tok) { return make_unique(tokLoc(tok)); } @@ -1846,6 +1860,11 @@ ForeignPtr false_(SelfPtr builder, const token *tok) { return build->toForeign(build->false_(tok)); } +ForeignPtr find_pattern(SelfPtr builder, const token *lbrack_t, const node_list *elements, const token *rbrack_t) { + auto build = cast_builder(builder); + return build->toForeign(build->find_pattern(lbrack_t, build->convertNodeList(elements), rbrack_t)); +} + ForeignPtr fileLiteral(SelfPtr builder, const token *tok) { auto build = cast_builder(builder); return build->toForeign(build->fileLiteral(tok)); @@ -2387,6 +2406,7 @@ struct ruby_parser::builder Builder::interface = { defSingleton, encodingLiteral, false_, + find_pattern, fileLiteral, float_, floatComplex, diff --git a/parser/tools/generate_ast.cc b/parser/tools/generate_ast.cc index 94d685e4274..1787a3bbc5c 100644 --- a/parser/tools/generate_ast.cc +++ b/parser/tools/generate_ast.cc @@ -268,6 +268,12 @@ NodeDef nodes[] = { "false", vector(), }, + // Find pattern + { + "FindPattern", + "find_pattern", + vector({{"elements", FieldType::NodeVec}}), + }, // __FILE__ { "FileLiteral", diff --git a/third_party/parser/cc/grammars/typedruby.ypp b/third_party/parser/cc/grammars/typedruby.ypp index b27679d3744..78e58811909 100644 --- a/third_party/parser/cc/grammars/typedruby.ypp +++ b/third_party/parser/cc/grammars/typedruby.ypp @@ -239,6 +239,7 @@ using namespace std::string_literals; p_kw p_kw_label p_primitive + p_rest p_top_expr_body p_var_ref p_value @@ -308,6 +309,7 @@ using namespace std::string_literals; p_args_head p_args_post p_args_tail + p_find p_kwarg p_kwargs p_kwnorest @@ -2426,6 +2428,10 @@ opt_block_args_tail: list->concat($3); $$ = driver.build.array_pattern(self, nullptr, list, nullptr); } + | p_find + { + $$ = driver.build.find_pattern(self, nullptr, $1, nullptr); + } | p_args_tail { $$ = driver.build.array_pattern(self, nullptr, $1, nullptr); @@ -2462,6 +2468,12 @@ opt_block_args_tail: auto pattern = driver.build.array_pattern(self, nullptr, $3, nullptr); $$ = driver.build.const_pattern(self, $1, $2, pattern, $4); } + | p_const p_lparen p_find rparen + { + driver.pattern_hash_keys.pop(); + auto pattern = driver.build.find_pattern(self, nullptr, $3, nullptr); + $$ = driver.build.const_pattern(self, $1, $2, pattern, $4); + } | p_const p_lparen p_kwargs rparen { driver.pattern_hash_keys.pop(); @@ -2480,6 +2492,12 @@ opt_block_args_tail: auto pattern = driver.build.array_pattern(self, nullptr, $3, nullptr); $$ = driver.build.const_pattern(self, $1, $2, pattern, $4); } + | p_const p_lbracket p_find rbracket + { + driver.pattern_hash_keys.pop(); + auto pattern = driver.build.find_pattern(self, nullptr, $3, nullptr); + $$ = driver.build.const_pattern(self, $1, $2, pattern, $4); + } | p_const p_lbracket p_kwargs rbracket { driver.pattern_hash_keys.pop(); @@ -2492,14 +2510,13 @@ opt_block_args_tail: auto pattern = driver.build.array_pattern(self, $2, list, nullptr); $$ = driver.build.const_pattern(self, $1, $2, pattern, $3); } - | tLBRACK + | tLBRACK p_args rbracket { - driver.pattern_hash_keys.push(); + $$ = driver.build.array_pattern(self, $1, $2, $3); } - p_args rbracket + | tLBRACK p_find rbracket { - driver.pattern_hash_keys.pop(); - $$ = driver.build.array_pattern(self, $1, $3, $4); + $$ = driver.build.find_pattern(self, $1, $2, $3); } | tLBRACK rbracket { @@ -2587,27 +2604,28 @@ opt_block_args_tail: $$ = $1; $$->emplace_back(last_item); } - p_args_tail: tSTAR tIDENTIFIER + p_args_tail: p_rest { - auto match_rest = driver.build.match_rest(self, $1, $2); - $$ = driver.alloc.node_list(match_rest); + $$ = driver.alloc.node_list($1); } - | tSTAR tIDENTIFIER tCOMMA p_args_post + | p_rest tCOMMA p_args_post { - auto match_rest = driver.build.match_rest(self, $1, $2); - $$ = driver.alloc.node_list(match_rest); - $$->concat($4); + $$ = driver.alloc.node_list($1); + $$->concat($3); } - | tSTAR + p_find: p_rest tCOMMA p_args_post tCOMMA p_rest { - auto match_rest = driver.build.match_rest(self, $1, nullptr); - $$ = driver.alloc.node_list(match_rest); + $$ = driver.alloc.node_list($1); + $$->concat($3); + $$->emplace_back($5); } - | tSTAR tCOMMA p_args_post + p_rest: tSTAR tIDENTIFIER { - auto match_rest = driver.build.match_rest(self, $1, nullptr); - $$ = driver.alloc.node_list(match_rest); - $$->concat($3); + $$ = driver.build.match_rest(self, $1, $2); + } + | tSTAR + { + $$ = driver.build.match_rest(self, $1, nullptr); } p_args_post: p_arg { diff --git a/third_party/parser/cc/lexer.rl b/third_party/parser/cc/lexer.rl index 43052f11b1d..a0cadb49b5b 100644 --- a/third_party/parser/cc/lexer.rl +++ b/third_party/parser/cc/lexer.rl @@ -2683,7 +2683,7 @@ void lexer::set_state_expr_value() { '*' | '=>' => { emit_table(PUNCTUATION); - fgoto expr_value; + fnext expr_value; fbreak; }; # When '|', '~', '!', '=>' are used as operators diff --git a/third_party/parser/include/ruby_parser/builder.hh b/third_party/parser/include/ruby_parser/builder.hh index 5fc79b0f48f..45e4ee7151a 100644 --- a/third_party/parser/include/ruby_parser/builder.hh +++ b/third_party/parser/include/ruby_parser/builder.hh @@ -56,6 +56,7 @@ struct builder { ForeignPtr(*defSingleton)(SelfPtr builder, ForeignPtr defHead, ForeignPtr args, ForeignPtr body, const token* end); ForeignPtr(*encodingLiteral)(SelfPtr builder, const token* tok); ForeignPtr(*false_)(SelfPtr builder, const token* tok); + ForeignPtr(*find_pattern)(SelfPtr builder, const token* lbrack_t, const node_list* elements, const token* rbrack_t); ForeignPtr(*fileLiteral)(SelfPtr builder, const token* tok); ForeignPtr(*float_)(SelfPtr builder, const token* tok); ForeignPtr(*floatComplex)(SelfPtr builder, const token* tok);