* parse.y: added symbols and qsymbols productions for %i and %I
support. %i{ .. } returns a list of symbols without interpolation, %I{ .. } returns a list of symbols with interpolation. Thanks to Josh Susser for inspiration of this feature. [Feature #4985] * ext/ripper/eventids2.c: added ripper events for %i and %I. * test/ripper/test_parser_events.rb: ripper tests * test/ripper/test_scanner_events.rb: ditto * test/ruby/test_array.rb: test for %i and %I behavior git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36524 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1a5773a868
commit
91bd6e711d
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
|||||||
|
Wed Jul 25 03:05:06 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
||||||
|
|
||||||
|
* parse.y: added symbols and qsymbols productions for %i and %I
|
||||||
|
support. %i{ .. } returns a list of symbols without interpolation,
|
||||||
|
%I{ .. } returns a list of symbols with interpolation. Thanks to
|
||||||
|
Josh Susser for inspiration of this feature. [Feature #4985]
|
||||||
|
|
||||||
|
* ext/ripper/eventids2.c: added ripper events for %i and %I.
|
||||||
|
|
||||||
|
* test/ripper/test_parser_events.rb: ripper tests
|
||||||
|
|
||||||
|
* test/ripper/test_scanner_events.rb: ditto
|
||||||
|
|
||||||
|
* test/ruby/test_array.rb: test for %i and %I behavior
|
||||||
|
|
||||||
Tue Jul 24 23:34:43 2012 Hiroshi Shirosaki <h.shirosaki@gmail.com>
|
Tue Jul 24 23:34:43 2012 Hiroshi Shirosaki <h.shirosaki@gmail.com>
|
||||||
|
|
||||||
* include/ruby/win32.h (rb_w32_pow): add new function.
|
* include/ruby/win32.h (rb_w32_pow): add new function.
|
||||||
|
3
NEWS
3
NEWS
@ -169,6 +169,9 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
long.
|
long.
|
||||||
|
|
||||||
=== Language changes
|
=== Language changes
|
||||||
|
|
||||||
|
* Added %i and %I for symbol list creation (similar to %w and %W).
|
||||||
|
|
||||||
=== Compatibility issues (excluding feature bug fixes)
|
=== Compatibility issues (excluding feature bug fixes)
|
||||||
|
|
||||||
* Signal.trap
|
* Signal.trap
|
||||||
|
@ -38,6 +38,8 @@ static ID ripper_id_tstring_content;
|
|||||||
static ID ripper_id_tstring_end;
|
static ID ripper_id_tstring_end;
|
||||||
static ID ripper_id_words_beg;
|
static ID ripper_id_words_beg;
|
||||||
static ID ripper_id_qwords_beg;
|
static ID ripper_id_qwords_beg;
|
||||||
|
static ID ripper_id_qsymbols_beg;
|
||||||
|
static ID ripper_id_symbols_beg;
|
||||||
static ID ripper_id_words_sep;
|
static ID ripper_id_words_sep;
|
||||||
static ID ripper_id_regexp_beg;
|
static ID ripper_id_regexp_beg;
|
||||||
static ID ripper_id_regexp_end;
|
static ID ripper_id_regexp_end;
|
||||||
@ -91,6 +93,8 @@ ripper_init_eventids2(void)
|
|||||||
ripper_id_tstring_end = rb_intern_const("on_tstring_end");
|
ripper_id_tstring_end = rb_intern_const("on_tstring_end");
|
||||||
ripper_id_words_beg = rb_intern_const("on_words_beg");
|
ripper_id_words_beg = rb_intern_const("on_words_beg");
|
||||||
ripper_id_qwords_beg = rb_intern_const("on_qwords_beg");
|
ripper_id_qwords_beg = rb_intern_const("on_qwords_beg");
|
||||||
|
ripper_id_qsymbols_beg = rb_intern_const("on_qsymbols_beg");
|
||||||
|
ripper_id_symbols_beg = rb_intern_const("on_symbols_beg");
|
||||||
ripper_id_words_sep = rb_intern_const("on_words_sep");
|
ripper_id_words_sep = rb_intern_const("on_words_sep");
|
||||||
ripper_id_regexp_beg = rb_intern_const("on_regexp_beg");
|
ripper_id_regexp_beg = rb_intern_const("on_regexp_beg");
|
||||||
ripper_id_regexp_end = rb_intern_const("on_regexp_end");
|
ripper_id_regexp_end = rb_intern_const("on_regexp_end");
|
||||||
@ -228,6 +232,8 @@ static const struct token_assoc {
|
|||||||
{tOROP, &ripper_id_op},
|
{tOROP, &ripper_id_op},
|
||||||
{tPOW, &ripper_id_op},
|
{tPOW, &ripper_id_op},
|
||||||
{tQWORDS_BEG, &ripper_id_qwords_beg},
|
{tQWORDS_BEG, &ripper_id_qwords_beg},
|
||||||
|
{tQSYMBOLS_BEG, &ripper_id_qsymbols_beg},
|
||||||
|
{tSYMBOLS_BEG, &ripper_id_symbols_beg},
|
||||||
{tREGEXP_BEG, &ripper_id_regexp_beg},
|
{tREGEXP_BEG, &ripper_id_regexp_beg},
|
||||||
{tREGEXP_END, &ripper_id_regexp_end},
|
{tREGEXP_END, &ripper_id_regexp_end},
|
||||||
{tRPAREN, &ripper_id_rparen},
|
{tRPAREN, &ripper_id_rparen},
|
||||||
|
98
parse.y
98
parse.y
@ -715,7 +715,7 @@ static void token_info_pop(struct parser_params*, const char *token);
|
|||||||
|
|
||||||
%type <node> singleton strings string string1 xstring regexp
|
%type <node> singleton strings string string1 xstring regexp
|
||||||
%type <node> string_contents xstring_contents regexp_contents string_content
|
%type <node> string_contents xstring_contents regexp_contents string_content
|
||||||
%type <node> words qwords word_list qword_list word
|
%type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word
|
||||||
%type <node> literal numeric dsym cpath
|
%type <node> literal numeric dsym cpath
|
||||||
%type <node> top_compstmt top_stmts top_stmt
|
%type <node> top_compstmt top_stmts top_stmt
|
||||||
%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
|
%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
|
||||||
@ -769,7 +769,7 @@ static void token_info_pop(struct parser_params*, const char *token);
|
|||||||
%token tDSTAR /* ** */
|
%token tDSTAR /* ** */
|
||||||
%token tAMPER /* & */
|
%token tAMPER /* & */
|
||||||
%token tLAMBDA /* -> */
|
%token tLAMBDA /* -> */
|
||||||
%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
|
%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG tSYMBOLS_BEG tQSYMBOLS_BEG
|
||||||
%token tSTRING_DBEG tSTRING_DEND tSTRING_DVAR tSTRING_END tLAMBEG
|
%token tSTRING_DBEG tSTRING_DEND tSTRING_DVAR tSTRING_END tLAMBEG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2672,6 +2672,8 @@ primary : literal
|
|||||||
| regexp
|
| regexp
|
||||||
| words
|
| words
|
||||||
| qwords
|
| qwords
|
||||||
|
| symbols
|
||||||
|
| qsymbols
|
||||||
| var_ref
|
| var_ref
|
||||||
| backref
|
| backref
|
||||||
| tFID
|
| tFID
|
||||||
@ -4105,6 +4107,45 @@ word : string_content
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
symbols : tSYMBOLS_BEG ' ' tSTRING_END
|
||||||
|
{
|
||||||
|
/*%%%*/
|
||||||
|
$$ = NEW_ZARRAY();
|
||||||
|
/*%
|
||||||
|
$$ = dispatch0(symbols_new);
|
||||||
|
$$ = dispatch1(array, $$);
|
||||||
|
%*/
|
||||||
|
}
|
||||||
|
| tSYMBOLS_BEG symbol_list tSTRING_END
|
||||||
|
{
|
||||||
|
/*%%%*/
|
||||||
|
$$ = $2;
|
||||||
|
/*%
|
||||||
|
$$ = dispatch1(array, $2);
|
||||||
|
%*/
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
symbol_list : /* none */
|
||||||
|
{
|
||||||
|
/*%%%*/
|
||||||
|
$$ = 0;
|
||||||
|
/*%
|
||||||
|
$$ = dispatch0(symbols_new);
|
||||||
|
%*/
|
||||||
|
}
|
||||||
|
| symbol_list word ' '
|
||||||
|
{
|
||||||
|
/*%%%*/
|
||||||
|
$2 = evstr2dstr($2);
|
||||||
|
nd_set_type($2, NODE_DSYM);
|
||||||
|
$$ = list_append($1, $2);
|
||||||
|
/*%
|
||||||
|
$$ = dispatch2(symbols_add, $1, $2);
|
||||||
|
%*/
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
qwords : tQWORDS_BEG ' ' tSTRING_END
|
qwords : tQWORDS_BEG ' ' tSTRING_END
|
||||||
{
|
{
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
@ -4124,6 +4165,25 @@ qwords : tQWORDS_BEG ' ' tSTRING_END
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
qsymbols : tQSYMBOLS_BEG ' ' tSTRING_END
|
||||||
|
{
|
||||||
|
/*%%%*/
|
||||||
|
$$ = NEW_ZARRAY();
|
||||||
|
/*%
|
||||||
|
$$ = dispatch0(qsymbols_new);
|
||||||
|
$$ = dispatch1(array, $$);
|
||||||
|
%*/
|
||||||
|
}
|
||||||
|
| tQSYMBOLS_BEG qsym_list tSTRING_END
|
||||||
|
{
|
||||||
|
/*%%%*/
|
||||||
|
$$ = $2;
|
||||||
|
/*%
|
||||||
|
$$ = dispatch1(array, $2);
|
||||||
|
%*/
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
qword_list : /* none */
|
qword_list : /* none */
|
||||||
{
|
{
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
@ -4142,6 +4202,28 @@ qword_list : /* none */
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
qsym_list : /* none */
|
||||||
|
{
|
||||||
|
/*%%%*/
|
||||||
|
$$ = 0;
|
||||||
|
/*%
|
||||||
|
$$ = dispatch0(qsymbols_new);
|
||||||
|
%*/
|
||||||
|
}
|
||||||
|
| qsym_list tSTRING_CONTENT ' '
|
||||||
|
{
|
||||||
|
/*%%%*/
|
||||||
|
VALUE lit;
|
||||||
|
lit = $2->nd_lit;
|
||||||
|
$2->nd_lit = ID2SYM(rb_intern_str(lit));
|
||||||
|
nd_set_type($2, NODE_LIT);
|
||||||
|
$$ = list_append($1, $2);
|
||||||
|
/*%
|
||||||
|
$$ = dispatch2(qsymbols_add, $1, $2);
|
||||||
|
%*/
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
string_contents : /* none */
|
string_contents : /* none */
|
||||||
{
|
{
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
@ -7796,6 +7878,18 @@ parser_yylex(struct parser_params *parser)
|
|||||||
pushback(c);
|
pushback(c);
|
||||||
return tQWORDS_BEG;
|
return tQWORDS_BEG;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
lex_strterm = NEW_STRTERM(str_dword, term, paren);
|
||||||
|
do {c = nextc();} while (ISSPACE(c));
|
||||||
|
pushback(c);
|
||||||
|
return tSYMBOLS_BEG;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
lex_strterm = NEW_STRTERM(str_sword, term, paren);
|
||||||
|
do {c = nextc();} while (ISSPACE(c));
|
||||||
|
pushback(c);
|
||||||
|
return tQSYMBOLS_BEG;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
lex_strterm = NEW_STRTERM(str_xquote, term, paren);
|
lex_strterm = NEW_STRTERM(str_xquote, term, paren);
|
||||||
return tXSTRING_BEG;
|
return tXSTRING_BEG;
|
||||||
|
@ -755,12 +755,36 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
|
|||||||
assert_equal true, thru_qwords_add
|
assert_equal true, thru_qwords_add
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_qsymbols_add
|
||||||
|
thru_qsymbols_add = false
|
||||||
|
parse('%i[a]', :on_qsymbols_add) {thru_qsymbols_add = true}
|
||||||
|
assert_equal true, thru_qsymbols_add
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_symbols_add
|
||||||
|
thru_symbols_add = false
|
||||||
|
parse('%I[a]', :on_symbols_add) {thru_symbols_add = true}
|
||||||
|
assert_equal true, thru_symbols_add
|
||||||
|
end
|
||||||
|
|
||||||
def test_qwords_new
|
def test_qwords_new
|
||||||
thru_qwords_new = false
|
thru_qwords_new = false
|
||||||
parse('%w[]', :on_qwords_new) {thru_qwords_new = true}
|
parse('%w[]', :on_qwords_new) {thru_qwords_new = true}
|
||||||
assert_equal true, thru_qwords_new
|
assert_equal true, thru_qwords_new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_qsymbols_new
|
||||||
|
thru_qsymbols_new = false
|
||||||
|
parse('%i[]', :on_qsymbols_new) {thru_qsymbols_new = true}
|
||||||
|
assert_equal true, thru_qsymbols_new
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_symbols_new
|
||||||
|
thru_symbols_new = false
|
||||||
|
parse('%I[]', :on_symbols_new) {thru_symbols_new = true}
|
||||||
|
assert_equal true, thru_symbols_new
|
||||||
|
end
|
||||||
|
|
||||||
def test_redo
|
def test_redo
|
||||||
thru_redo = false
|
thru_redo = false
|
||||||
parse('redo', :on_redo) {thru_redo = true}
|
parse('redo', :on_redo) {thru_redo = true}
|
||||||
|
@ -608,6 +608,28 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
|
|||||||
scan('qwords_beg', '%w( w w w )')
|
scan('qwords_beg', '%w( w w w )')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_qsymbols_beg
|
||||||
|
assert_equal [],
|
||||||
|
scan('qsymbols_beg', '')
|
||||||
|
assert_equal ['%i('],
|
||||||
|
scan('qsymbols_beg', '%i()')
|
||||||
|
assert_equal ['%i('],
|
||||||
|
scan('qsymbols_beg', '%i(w w w)')
|
||||||
|
assert_equal ['%i( '],
|
||||||
|
scan('qsymbols_beg', '%i( w w w )')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_symbols_beg
|
||||||
|
assert_equal [],
|
||||||
|
scan('symbols_beg', '')
|
||||||
|
assert_equal ['%I('],
|
||||||
|
scan('symbols_beg', '%I()')
|
||||||
|
assert_equal ['%I('],
|
||||||
|
scan('symbols_beg', '%I(w w w)')
|
||||||
|
assert_equal ['%I( '],
|
||||||
|
scan('symbols_beg', '%I( w w w )')
|
||||||
|
end
|
||||||
|
|
||||||
# FIXME: Close paren must not present (`words_end' scanner event?).
|
# FIXME: Close paren must not present (`words_end' scanner event?).
|
||||||
def test_words_sep
|
def test_words_sep
|
||||||
assert_equal [],
|
assert_equal [],
|
||||||
|
@ -12,6 +12,17 @@ class TestArray < Test::Unit::TestCase
|
|||||||
$VERBOSE = @verbose
|
$VERBOSE = @verbose
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_percent_i
|
||||||
|
assert_equal([:foo, :bar], %i[foo bar])
|
||||||
|
assert_equal([:"\"foo"], %i["foo])
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_percent_I
|
||||||
|
x = 10
|
||||||
|
assert_equal([:foo, :b10], %I[foo b#{x}])
|
||||||
|
assert_equal([:"\"foo10"], %I["foo#{x}])
|
||||||
|
end
|
||||||
|
|
||||||
def test_0_literal
|
def test_0_literal
|
||||||
assert_equal([1, 2, 3, 4], [1, 2] + [3, 4])
|
assert_equal([1, 2, 3, 4], [1, 2] + [3, 4])
|
||||||
assert_equal([1, 2, 1, 2], [1, 2] * 2)
|
assert_equal([1, 2, 1, 2], [1, 2] * 2)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user