@@ -365,6 +365,8 @@ static NODE *new_evstr_gen(struct parser_params*,NODE*);
365
365
#define new_evstr (n ) new_evstr_gen(parser,(n))
366
366
static NODE *evstr2dstr_gen (struct parser_params *,NODE*);
367
367
#define evstr2dstr (n ) evstr2dstr_gen(parser,(n))
368
+ static NODE *str_suffix_gen (struct parser_params *, NODE*, long );
369
+ #define str_suffix (n,o ) str_suffix_gen(parser,(n),(o))
368
370
static NODE *splat_array (NODE*);
369
371
370
372
static NODE *call_bin_op_gen (struct parser_params *,NODE*,ID,NODE*);
@@ -474,6 +476,8 @@ static int lvar_defined_gen(struct parser_params*, ID);
474
476
#define RE_OPTION_MASK 0xff
475
477
#define RE_OPTION_ARG_ENCODING_NONE 32
476
478
479
+ #define STR_OPTION_FROZEN 1
480
+
477
481
#define NODE_STRTERM NODE_ZARRAY /* nothing to gc */
478
482
#define NODE_HEREDOC NODE_ARRAY /* 1, 3 to gc */
479
483
#define SIGN_EXTEND (x,n ) (((1 <<(n)-1 )^((x)&~(~0 <<(n))))-(1 <<(n)-1 ))
@@ -679,7 +683,7 @@ static void token_info_pop(struct parser_params*, const char *token);
679
683
%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
680
684
%token <node> tINTEGER tFLOAT tSTRING_CONTENT tCHAR
681
685
%token <node> tNTH_REF tBACK_REF
682
- %token <num> tREGEXP_END
686
+ %to
6D40
ken <num> tREGEXP_END tSTRING_SUFFIX
683
687
684
688
%type <node> singleton strings string string1 xstring regexp
685
689
%type <node> string_contents xstring_contents regexp_contents string_content
@@ -703,6 +707,7 @@ static void token_info_pop(struct parser_params*, const char *token);
703
707
%type <node> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner
704
708
%type <id> fsym keyword_variable user_variable sym symbol operation operation2 operation3
705
709
%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
710
+ %type <num> opt_string_sfx
706
711
/* %%%*/
707
712
/* %
708
713
%type <val> program reswords then do dot_or_colon
@@ -3839,7 +3844,7 @@ literal : numeric
3839
3844
| dsym
3840
3845
;
3841
3846
3842
- strings : string
3847
+ strings : string opt_string_sfx
3843
3848
{
3844
3849
/* %%%*/
3845
3850
NODE *node = $1 ;
@@ -3849,6 +3854,7 @@ strings : string
3849
3854
else {
3850
3855
node = evstr2dstr (node);
3851
3856
}
3857
+ node = str_suffix (node, $2 );
3852
3858
$$ = node;
3853
3859
/* %
3854
3860
$$ = $1;
@@ -3878,6 +3884,10 @@ string1 : tSTRING_BEG string_contents tSTRING_END
3878
3884
}
3879
3885
;
3880
3886
3887
+ opt_string_sfx : tSTRING_SUFFIX
3888
+ | /* none */ { $$ = 0 ; }
3889
+ ;
3890
+
3881
3891
xstring : tXSTRING_BEG xstring_contents tSTRING_END
3882
3892
{
3883
3893
/* %%%*/
@@ -4886,6 +4896,7 @@ none : /* none */
4886
4896
# define yylval (*((YYSTYPE*)(parser->parser_yylval)))
4887
4897
4888
4898
static int parser_regx_options (struct parser_params *);
4899
+ static int parser_str_options (struct parser_params *);
4889
4900
static int parser_tokadd_string (struct parser_params *,int ,int ,int ,long *,rb_encoding**);
4890
4901
static void parser_tokaddmbc (struct parser_params *parser, int c, rb_encoding *enc);
4891
4902
static int parser_parse_string (struct parser_params *,NODE*);
@@ -4901,6 +4912,7 @@ static int parser_here_document(struct parser_params*,NODE*);
4901
4912
# define read_escape (flags,e ) parser_read_escape(parser, (flags), (e))
4902
4913
# define tokadd_escape (e ) parser_tokadd_escape(parser, (e))
4903
4914
# define regx_options () parser_regx_options(parser)
4915
+ # define str_options () parser_str_options(parser)
4904
4916
# define tokadd_string (f,t,p,n,e ) parser_tokadd_string(parser,(f),(t),(p),(n),(e))
4905
4917
# define parse_string (n ) parser_parse_string(parser,(n))
4906
4918
# define tokaddmbc (c, enc ) parser_tokaddmbc(parser, (c), (enc))
@@ -5385,10 +5397,11 @@ rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int st
5385
5397
#define STR_FUNC_QWORDS 0x08
5386
5398
#define STR_FUNC_SYMBOL 0x10
5387
5399
#define STR_FUNC_INDENT 0x20
5400
+ #define STR_FUNC_OPTION 0x40
5388
5401
5389
5402
enum string_type {
5390
- str_squote = (0 ),
5391
- str_dquote = (STR_FUNC_EXPAND),
5403
+ str_squote = (STR_FUNC_OPTION ),
5404
+ str_dquote = (STR_FUNC_EXPAND|STR_FUNC_OPTION ),
5392
5405
str_xquote = (STR_FUNC_EXPAND),
5393
5406
str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
5394
5407
str_sword = (STR_FUNC_QWORDS),
@@ -5827,6 +5840,28 @@ parser_regx_options(struct parser_params *parser)
5827
5840
return options | RE_OPTION_ENCODING (kcode);
5828
5841
}
5829
5842
5843
+ static int
5844
+ parser_str_options (struct parser_params *parser)
5845
+ {
5846
+ int c, options = 0 ;
5847
+ const char *save_p = lex_p;
5848
+
5849
+ while (c = nextc (), ISALPHA (c)) {
5850
+ switch (c) {
5851
+ #if STR_OPTION_FROZEN
5852
+ case ' f' :
5853
+ options |= STR_OPTION_FROZEN;
5854
+ break ;
5855
+ #endif
5856
+ default :
5857
+ lex_p = save_p;
5858
+ return 0 ;
5859
+ }
5860
+ }
5861
+ pushback (c);
5862
+ return options;
5863
+ }
5864
+
5830
5865
static void
5831
5866
dispose_string (VALUE str)
5832
5867
{
@@ -5995,6 +6030,10 @@ parser_parse_string(struct parser_params *parser, NODE *quote)
5995
6030
rb_encoding *enc = parser->enc ;
5996
6031
5997
6032
if (func == -1 ) return tSTRING_END;
6033
+ if (func == 0 ) {
6034
+ set_yylval_num (term);
6035
+ return tSTRING_SUFFIX;
6036
+ }
5998
6037
c = nextc ();
5999
6038
if ((func & STR_FUNC_QWORDS) && ISSPACE (c)) {
6000
6039
do {c = nextc ();} while (ISSPACE (c));
@@ -6003,11 +6042,18 @@ parser_parse_string(struct parser_params *parser, NODE *quote)
6003
6042
if (c == term && !quote->nd_nest ) {
6004
6043
if (func & STR_FUNC_QWORDS) {
6005
6044
quote->nd_func = -1 ;
6045
+ quote->u2 .id = 0 ;
6006
6046
return ' ' ;
6007
6047
}
6008
- if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
6009
- set_yylval_num (regx_options ());
6010
- return tREGEXP_END;
6048
+ if (func & STR_FUNC_REGEXP) {
6049
+ set_yylval_num (regx_options ());
6050
+ return tREGEXP_END;
6051
+ }
6052
+ if ((func & STR_FUNC_OPTION) && (func = str_options ()) != 0 ) {
6053
+ quote->nd_func = 0 ;
6054
+ quote->u2 .id = func;
6055
+ }
6056
+ return tSTRING_END;
6011
6057
}
6012
6058
if (space) {
6013
6059
pushback (c);
@@ -6655,7 +6701,8 @@ parser_yylex(struct parser_params *parser)
6655
6701
}
6656
6702
else {
6657
6703
token = parse_string (lex_strterm);
6658
- if (token == tSTRING_END || token == tREGEXP_END) {
6704
+ if ((token == tSTRING_END && lex_strterm->nd_func ) ||
6705
+ token == tSTRING_SUFFIX || token == tREGEXP_END) {
6659
6706
rb_gc_force_recycle ((VALUE)lex_strterm);
6660
6707
lex_strterm = 0 ;
6661
6708
lex_state = EXPR_END;
@@ -8187,6 +8234,27 @@ evstr2dstr_gen(struct parser_params *parser, NODE *node)
8187
8234
return node;
8188
8235
}
8189
8236
8237
+ static NODE *
8238
+ str_suffix_gen (struct parser_params *parser, NODE *node, long opt)
8239
+ {
8240
+ if (nd_type (node) == NODE_STR) {
8241
+ #if STR_OPTION_FROZEN
8242
+ if (opt & STR_OPTION_FROZEN) {
8243
+ OBJ_FREEZE (node->nd_lit );
8244
+ nd_set_type (node, NODE_LIT);
8245
+ }
8246
+ #endif
8247
+ }
8248
+ else {
8249
+ #if STR_OPTION_FROZEN
8250
+ if (opt & STR_OPTION_FROZEN) {
8251
+ node = NEW_CALL (node, rb_intern (" freeze" ), 0 );
8252
+ }
8253
+ #endif
8254
+ }
8255
+ return node;
8256
+ }
8257
+
8190
8258
static NODE *
8191
8259
new_evstr_gen (struct parser_params *parser, NODE *node)
8192
8260
{
0 commit comments