Hi,

At Thu, 13 Jan 2011 10:17:23 +0900,
Tyler Benster wrote in [ruby-core:34453]:
> Current syntactic sugar allows this:
> hash = {Alabama: "AL"}
> 
> This feature request is to also allow symbols delimited by quotes (and thus able to contain a whitespace) to use an equivalent syntactic sugar:
> hash2 = {"Rhode Island": "RI"}

I've forgotten to post the patch.


diff --git i/parse.y w/parse.y index 06f96ce..0cacdd5 100644 --- i/parse.y +++ w/parse.y @@ -380,6 +380,8 @@ static NODE *ret_args_gen(struct parser_params*,NODE*); static NODE *arg_blk_pass(NODE*,NODE*); static NODE *new_yield_gen(struct parser_params*,NODE*); #define new_yield(node) new_yield_gen(parser, (node)) +static NODE *dsym_node_gen(struct parser_params*,NODE*); +#define dsym_node(node) dsym_node_gen(parser, (node)) static NODE *gettable_gen(struct parser_params*,ID); #define gettable(id) gettable_gen(parser,(id)) @@ -678,12 +680,12 @@ static void token_info_pop(struct parser_params*, const char *token); keyword__FILE__ keyword__ENCODING__ -%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL +%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL tLABEL_END %token <node> tINTEGER tFLOAT tSTRING_CONTENT tCHAR %token <node> tNTH_REF tBACK_REF %token <num> tREGEXP_END -%type <node> singleton strings string string1 xstring regexp +%type <node> singleton strings string string1 xstring regexp string_body %type <node> string_contents xstring_contents regexp_contents string_content %type <node> words qwords word_list qword_list word %type <node> literal numeric dsym cpath @@ -3841,12 +3843,18 @@ string : tCHAR } ; -string1 : tSTRING_BEG string_contents tSTRING_END +string_body : tSTRING_BEG string_contents { - /*%%%*/ $$ = $2; + } + ; + +string1 : string_body tSTRING_END + { + /*%%%*/ + $$ = $1; /*% - $$ = dispatch1(string_literal, $2); + $$ = dispatch1(string_literal, $1); %*/ } ; @@ -4199,26 +4207,7 @@ dsym : tSYMBEG xstring_contents tSTRING_END { lex_state = EXPR_END; /*%%%*/ - if (!($$ = $2)) { - $$ = NEW_LIT(ID2SYM(rb_intern(""))); - } - else { - VALUE lit; - - switch (nd_type($$)) { - case NODE_DSTR: - nd_set_type($$, NODE_DSYM); - break; - case NODE_STR: - lit = $$->nd_lit; - $$->nd_lit = ID2SYM(rb_intern_str(lit)); - nd_set_type($$, NODE_LIT); - break; - default: - $$ = NEW_NODE(NODE_DSYM, Qnil, 1, NEW_LIST($$)); - break; - } - } + $$ = dsym_node($2); /*% $$ = dispatch1(dyna_symbol, $2); %*/ @@ -4761,6 +4750,15 @@ assoc : arg_value tASSOC arg_value $$ = dispatch2(assoc_new, $1, $2); %*/ } + | string_body tLABEL_END arg_value + { + /*%%%*/ + $$ = list_append(NEW_LIST(dsym_node($1)), $3); + /*% + $$ = dispatch1(dyna_symbol, $1); + $$ = dispatch2(assoc_new, $$, $3); + %*/ + } ; operation : tIDENTIFIER @@ -5334,6 +5332,7 @@ rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int st #define STR_FUNC_QWORDS 0x08 #define STR_FUNC_SYMBOL 0x10 #define STR_FUNC_INDENT 0x20 +#define STR_FUNC_LABEL 0x40 enum string_type { str_squote = (0), @@ -5925,6 +5924,8 @@ parser_tokadd_string(struct parser_params *parser, #define NEW_STRTERM(func, term, paren) \ rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0) +#define IS_LABEL_SUFFIX(n) (peek_n(':',(n)) && !peek_n(':', (n)+1)) +#define MAYBE_LABEL() (IS_LABEL_POSSIBLE() ? STR_FUNC_LABEL : 0) static int parser_parse_string(struct parser_params *parser, NODE *quote) @@ -5946,6 +5947,10 @@ parser_parse_string(struct parser_params *parser, NODE *quote) quote->nd_func = -1; return ' '; } + if ((func & STR_FUNC_LABEL) && IS_LABEL_SUFFIX(0)) { + lex_state = EXPR_BEG; + return tLABEL_END; + } if (!(func & STR_FUNC_REGEXP)) return tSTRING_END; set_yylval_num(regx_options()); return tREGEXP_END; @@ -6533,7 +6538,6 @@ parser_prepare(struct parser_params *parser) #define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || lex_state == EXPR_VALUE || lex_state == EXPR_CLASS) #define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c)) #define IS_LABEL_POSSIBLE() ((lex_state == EXPR_BEG && !cmd_state) || IS_ARG()) -#define IS_LABEL_SUFFIX(n) (peek_n(':',(n)) && !peek_n(':', (n)+1)) #ifndef RIPPER #define ambiguous_operator(op, syn) ( \ @@ -6849,7 +6853,7 @@ parser_yylex(struct parser_params *parser) return '>'; case '"': - lex_strterm = NEW_STRTERM(str_dquote, '"', 0); + lex_strterm = NEW_STRTERM(str_dquote | MAYBE_LABEL(), '"', 0); return tSTRING_BEG; case '`': @@ -6868,7 +6872,7 @@ parser_yylex(struct parser_params *parser) return tXSTRING_BEG; case '\'': - lex_strterm = NEW_STRTERM(str_squote, '\'', 0); + lex_strterm = NEW_STRTERM(str_squote | MAYBE_LABEL(), '\'', 0); return tSTRING_BEG; case '?': @@ -8987,6 +8991,32 @@ new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b ruby_sourceline = saved_line; return node; } + +static NODE* +dsym_node_gen(struct parser_params *parser, NODE *node) +{ + if (!node) { + node = NEW_LIT(ID2SYM(rb_intern(""))); + } + else { + VALUE lit; + + switch (nd_type(node)) { + case NODE_DSTR: + nd_set_type(node, NODE_DSYM); + break; + case NODE_STR: + lit = node->nd_lit; + node->nd_lit = ID2SYM(rb_intern_str(lit)); + nd_set_type(node, NODE_LIT); + break; + default: + node = NEW_NODE(NODE_DSYM, Qnil, 1, NEW_LIST(node)); + break; + } + } + return node; +} #endif /* !RIPPER */ static void
-- Nobu Nakada