Feature #14973 ยป hash_expand.patch
| ext/ripper/eventids2.c | ||
|---|---|---|
|
ID ripper_id_words_beg;
|
||
|
ID ripper_id_qwords_beg;
|
||
|
ID ripper_id_qsymbols_beg;
|
||
|
ID ripper_id_hashexpand_beg;
|
||
|
ID ripper_id_symbols_beg;
|
||
|
ID ripper_id_words_sep;
|
||
|
ID ripper_id_rational;
|
||
| ... | ... | |
|
set_id2(words_beg);
|
||
|
set_id2(qwords_beg);
|
||
|
set_id2(qsymbols_beg);
|
||
|
set_id2(hashexpand_beg);
|
||
|
set_id2(symbols_beg);
|
||
|
set_id2(words_sep);
|
||
|
set_id2(rational);
|
||
| ... | ... | |
|
{tPOW, O(op)},
|
||
|
{tQWORDS_BEG, O(qwords_beg)},
|
||
|
{tQSYMBOLS_BEG, O(qsymbols_beg)},
|
||
|
{tHASHEXPAND_BEG, O(hashexpand_beg)},
|
||
|
{tSYMBOLS_BEG, O(symbols_beg)},
|
||
|
{tRATIONAL, O(rational)},
|
||
|
{tREGEXP_BEG, O(regexp_beg)},
|
||
| parse.y | ||
|---|---|---|
|
%type <node> singleton strings string string1 xstring regexp
|
||
|
%type <node> string_contents xstring_contents regexp_contents string_content
|
||
|
%type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word
|
||
|
%type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word hashexpand hashexpand_list
|
||
|
%type <node> literal numeric simple_numeric dsym cpath
|
||
|
%type <node> top_compstmt top_stmts top_stmt begin_block
|
||
|
%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
|
||
| ... | ... | |
|
%token tDSTAR "**arg"
|
||
|
%token tAMPER "&"
|
||
|
%token tLAMBDA "->"
|
||
|
%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG tSYMBOLS_BEG tQSYMBOLS_BEG
|
||
|
%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG tSYMBOLS_BEG tQSYMBOLS_BEG tHASHEXPAND_BEG
|
||
|
%token tSTRING_DBEG tSTRING_DEND tSTRING_DVAR tSTRING_END tLAMBEG tLABEL_END
|
||
|
/*
|
||
| ... | ... | |
|
| qwords
|
||
|
| symbols
|
||
|
| qsymbols
|
||
|
| hashexpand
|
||
|
| var_ref
|
||
|
| backref
|
||
|
| tFID
|
||
| ... | ... | |
|
| qwords
|
||
|
| symbols
|
||
|
| qsymbols
|
||
|
| hashexpand
|
||
|
| keyword_variable
|
||
|
{
|
||
|
/*%%%*/
|
||
| ... | ... | |
|
}
|
||
|
;
|
||
|
hashexpand : tHASHEXPAND_BEG ' ' hashexpand_list tSTRING_END
|
||
|
{
|
||
|
/*%%%*/
|
||
|
$$ = new_hash(p, $3, &@$);
|
||
|
/*% %*/
|
||
|
/*% ripper: hash!($3) %*/
|
||
|
}
|
||
|
;
|
||
|
hashexpand_list : /* none */
|
||
|
{
|
||
|
/*%%%*/
|
||
|
$$ = 0;
|
||
|
/*% %*/
|
||
|
/*% ripper: hashexpand_new! %*/
|
||
|
}
|
||
|
| hashexpand_list string_content ' '
|
||
|
{
|
||
|
/*%%%*/
|
||
|
NODE *key, *val, *estr;
|
||
|
estr = evstr2dstr(p, $2);
|
||
|
estr = $2;
|
||
|
key = NEW_CALL(estr, rb_intern("to_sym"), 0, &@$);
|
||
|
val = NEW_FCALL(rb_intern("eval"), NEW_LIST(estr, &@$), &@$);
|
||
|
$$ = list_append(p, list_append(p, $1, key), val);
|
||
|
/*% %*/
|
||
|
/*% ripper: hashexpand_add!($1, $2) %*/
|
||
|
}
|
||
|
;
|
||
|
string_contents : /* none */
|
||
|
{
|
||
|
/*%%%*/
|
||
| ... | ... | |
|
SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);
|
||
|
return tSYMBEG;
|
||
|
case 'h':
|
||
|
p->lex.strterm = NEW_STRTERM(str_dword, term, paren);
|
||
|
return tHASHEXPAND_BEG;
|
||
|
default:
|
||
|
yyerror0("unknown type of %string");
|
||
|
return 0;
|
||
| test/ripper/dummyparser.rb | ||
|---|---|---|
|
symbols.push Node::Sym.new(symbol)
|
||
|
end
|
||
|
def on_hashexpand_new
|
||
|
# NodeList.new
|
||
|
Node.new('assoc')
|
||
|
end
|
||
|
def on_hashexpand_add(hashexpand, str)
|
||
|
pp hashexpand
|
||
|
# hashexpand.push Node::Sym.new(str)
|
||
|
# hashexpand.push str
|
||
|
end
|
||
|
def on_mlhs_new
|
||
|
NodeList.new
|
||
|
end
|
||
| test/ripper/test_parser_events.rb | ||
|---|---|---|
|
assert_equal '[array([:a])]', tree
|
||
|
end
|
||
|
def test_hashexpand_add
|
||
|
thru_hasexpand_add = false
|
||
|
a = 1
|
||
|
b = 2
|
||
|
tree = parse('%h[a,b]', :on_hashexpand_add) {thru_hasexpand_add = true}
|
||
|
pp tree
|
||
|
# assert_equal true, thru_hasexpand_add
|
||
|
# assert_equal '[hash([:a,a,:b,b])]', tree
|
||
|
end
|
||
|
def test_qwords_new
|
||
|
thru_qwords_new = false
|
||
|
parse('%w[]', :on_qwords_new) {thru_qwords_new = true}
|
||
| ... | ... | |
|
assert_equal true, thru_symbols_new
|
||
|
end
|
||
|
def test_hashexpand_new
|
||
|
thru_hashexpand_new = false
|
||
|
parse('%h[]', :on_hashexpand_new) {thru_hashexpand_new = true}
|
||
|
assert_equal true, thru_hashexpand_new
|
||
|
end
|
||
|
def test_redo
|
||
|
thru_redo = false
|
||
|
parse('redo', :on_redo) {thru_redo = true}
|
||
| test/ripper/test_scanner_events.rb | ||
|---|---|---|
|
scan('symbols_beg', "%I(\nw)")
|
||
|
end
|
||
|
def test_hashexpand_beg
|
||
|
assert_equal [],
|
||
|
scan('hashexpand_beg', '')
|
||
|
assert_equal ['%h('],
|
||
|
scan('hashexpand_beg', '%h()')
|
||
|
assert_equal ['%h('],
|
||
|
scan('hashexpand_beg', '%h(w w w)')
|
||
|
assert_equal ['%h('],
|
||
|
scan('hashexpand_beg', '%h( w w w )')
|
||
|
assert_equal ['%h('],
|
||
|
scan('hashexpand_beg', "%h(\nw)")
|
||
|
end
|
||
|
def test_words_sep
|
||
|
assert_equal [],
|
||
|
scan('words_sep', '')
|
||
| test/ruby/test_parse.rb | ||
|---|---|---|
|
assert_valid_syntax('let () { m(a) do; end }')
|
||
|
end
|
||
|
def test_hashexpand_meth
|
||
|
"test_hashexpand_meth"
|
||
|
end
|
||
|
def test_hashexpand
|
||
|
hoge = 1
|
||
|
foo = "str"
|
||
|
bar = nil
|
||
|
@test_hashexpand_value = { a: 1 }
|
||
|
@@test_hashexpand_value = [1, 2]
|
||
|
hash = %h(hoge foo bar @test_hashexpand_value @@test_hashexpand_value test_hashexpand_meth)
|
||
|
assert_equal(
|
||
|
hash,
|
||
|
{ hoge: 1, foo: "str", bar: nil, "@test_hashexpand_value": { a: 1}, "@@test_hashexpand_value": [1, 2], test_hashexpand_meth: "test_hashexpand_meth" }
|
||
|
)
|
||
|
assert_equal(
|
||
|
hash.keys,
|
||
|
%i(hoge foo bar @test_hashexpand_value @@test_hashexpand_value test_hashexpand_meth)
|
||
|
)
|
||
|
str = 42
|
||
|
pp %h(#{foo})
|
||
|
assert_equal(%h(#{foo}), { str: 42 })
|
||
|
assert_operator(Hash, :===, hash)
|
||
|
proc { |value|
|
||
|
hoge = -1
|
||
|
assert_equal(%h(hoge foo value), { hoge: -1, foo: "str", value: 42 })
|
||
|
}.call 42
|
||
|
assert_equal(%h(hoge foo hoge), { hoge: hoge, foo: foo })
|
||
|
assert_equal(%h(hoge foo hoge).keys, %i(hoge foo))
|
||
|
assert_raise(NameError) do
|
||
|
%h(not_found)
|
||
|
end
|
||
|
end
|
||
|
=begin
|
||
|
def test_past_scope_variable
|
||
|
assert_warning(/past scope/) {catch {|tag| eval("BEGIN{throw tag}; tap {a = 1}; a")}}
|
||