diff --git a/parse.y b/parse.y index 4f0aa6a6ce..7ffd2b5833 100644 --- a/parse.y +++ b/parse.y @@ -768,6 +768,7 @@ struct rb_strterm_heredoc_struct { uint8_t quote; uint8_t func; #endif + bool shebang; }; STATIC_ASSERT(rb_strterm_heredoc_t, sizeof(rb_strterm_heredoc_t) <= 4 * SIZEOF_VALUE); @@ -1212,6 +1213,7 @@ static int looking_at_eol_p(struct parser_params *p); %token tNTH_REF "numbered reference" %token tBACK_REF "back reference" %token tSTRING_CONTENT "literal content" +%token tSTRING_EXTEND_HEREDOC "Heredoc extension" %token tREGEXP_END %type singleton strings string string1 xstring regexp @@ -4948,7 +4950,19 @@ regexp_contents: /* none */ ; string_content : tSTRING_CONTENT - /*% ripper[brace]: ripper_new_yylval(p, 0, get_value($1), $1) %*/ + { + $$ = $1; + /*% ripper[brace]: ripper_new_yylval(p, 0, get_value($1), $1) %*/ + } + | tSTRING_EXTEND_HEREDOC + { + // TODO: use delimiter token for function call + $$ = NEW_FCALL(rb_intern("heredoc_extension_erb"), + list_append(p, + NEW_LIST(NEW_LIT($1->nd_lit, &@$), &@$), + NEW_FCALL(rb_intern("binding"), NULL, &@$)), + &@$); + } | tSTRING_DVAR { /* need to backup p->lex.strterm so that a string literal `%&foo,#$&,bar&` can be parsed */ @@ -7572,6 +7586,7 @@ heredoc_identifier(struct parser_params *p) int c = nextc(p), term, func = 0, quote = 0; enum yytokentype token = tSTRING_BEG; int indent = 0; + bool shebang = 0; if (c == '-') { c = nextc(p); @@ -7584,6 +7599,13 @@ heredoc_identifier(struct parser_params *p) offset++; indent = INT_MAX; } + + if (c == '!') { + c = nextc(p); + offset++; + shebang = true; + } + switch (c) { case '\'': func |= str_squote; goto quoted; @@ -7638,6 +7660,7 @@ heredoc_identifier(struct parser_params *p) here->length = (int)len; here->quote = quote; here->func = func; + here->shebang = shebang; token_flush(p); p->heredoc_indent = indent; @@ -8048,7 +8071,12 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here) #ifndef RIPPER if (bol) yylval.node->flags |= NODE_FL_NEWLINE; #endif - return tSTRING_CONTENT; + if (here->shebang) { + return tSTRING_EXTEND_HEREDOC; + } + else { + return tSTRING_CONTENT; + } } #include "lex.c"