lib/parser/ruby18.y
class Parser::Ruby18
token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kRETURN kYIELD kSUPER
kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
k__FILE__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tNTH_REF
tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT tUPLUS
tUMINUS tUNARY_NUM tPOW tCMP tEQ tEQQ tNEQ tGEQ tLEQ tANDOP
tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF tASET tLSHFT tRSHFT
tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN tLPAREN2 tRPAREN tLPAREN_ARG
tLBRACK tLBRACK2 tRBRACK tLBRACE tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2
tTILDE tPERCENT tDIVIDE tPLUS tMINUS tLT tGT tPIPE tBANG tCARET
tLCURLY tRCURLY tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END tSTRING
tSYMBOL tREGEXP_OPT tNL tEH tCOLON tCOMMA tSPACE tSEMI
prechigh
right tBANG tTILDE tUPLUS
right tPOW
right tUNARY_NUM tUMINUS
left tSTAR2 tDIVIDE tPERCENT
left tPLUS tMINUS
left tLSHFT tRSHFT
left tAMPER2
left tPIPE tCARET
left tGT tGEQ tLT tLEQ
nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
left tANDOP
left tOROP
nonassoc tDOT2 tDOT3
right tEH tCOLON
left kRESCUE_MOD
right tEQL tOP_ASGN
nonassoc kDEFINED
right kNOT
left kOR kAND
nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
nonassoc tLBRACE_ARG
nonassoc tLOWEST
preclow
rule
program: compstmt
{
result = val[0]
}
bodystmt: compstmt opt_rescue opt_else opt_ensure
{
rescue_bodies = val[1]
else_t, else_ = val[2]
ensure_t, ensure_ = val[3]
if rescue_bodies.empty? && !else_t.nil?
diagnostic :warning, :useless_else, nil, else_t
end
result = @builder.begin_body(val[0],
rescue_bodies,
else_t, else_,
ensure_t, ensure_)
}
compstmt: stmts opt_terms
{
result = @builder.compstmt(val[0])
}
stmts: # nothing
{
result = []
}
| stmt
{
result = [ val[0] ]
}
| error stmt
{
result = [ val[1] ]
}
| stmts terms stmt
{
result = val[0] << val[2]
}
stmt: kALIAS fitem
{
@lexer.state = :expr_fname
}
fitem
{
result = @builder.alias(val[0], val[1], val[3])
}
| kALIAS tGVAR tGVAR
{
result = @builder.alias(val[0],
@builder.gvar(val[1]),
@builder.gvar(val[2]))
}
| kALIAS tGVAR tBACK_REF
{
result = @builder.alias(val[0],
@builder.gvar(val[1]),
@builder.back_ref(val[2]))
}
| kALIAS tGVAR tNTH_REF
{
diagnostic :error, :nth_ref_alias, nil, val[2]
}
| kUNDEF undef_list
{
result = @builder.undef_method(val[0], val[1])
}
| stmt kIF_MOD expr_value
{
result = @builder.condition_mod(val[0], nil,
val[1], val[2])
}
| stmt kUNLESS_MOD expr_value
{
result = @builder.condition_mod(nil, val[0],
val[1], val[2])
}
| stmt kWHILE_MOD expr_value
{
result = @builder.loop_mod(:while, val[0], val[1], val[2])
}
| stmt kUNTIL_MOD expr_value
{
result = @builder.loop_mod(:until, val[0], val[1], val[2])
}
| stmt kRESCUE_MOD stmt
{
rescue_body = @builder.rescue_body(val[1],
nil, nil, nil,
nil, val[2])
result = @builder.begin_body(val[0], [ rescue_body ])
}
| klBEGIN tLCURLY compstmt tRCURLY
{
if @context.in_def
diagnostic :error, :begin_in_method, nil, val[0]
end
result = @builder.preexe(val[0], val[1], val[2], val[3])
}
| klEND tLCURLY compstmt tRCURLY
{
result = @builder.postexe(val[0], val[1], val[2], val[3])
}
| lhs tEQL command_call
{
result = @builder.assign(val[0], val[1], val[2])
}
| mlhs tEQL command_call
{
result = @builder.multi_assign(val[0], val[1], val[2])
}
| var_lhs tOP_ASGN command_call
{
result = @builder.op_assign(val[0], val[1], val[2])
}
| primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN command_call
{
result = @builder.op_assign(
@builder.index(
val[0], val[1], val[2], val[3]),
val[4], val[5])
}
| primary_value tDOT tIDENTIFIER tOP_ASGN command_call
{
result = @builder.op_assign(
@builder.call_method(
val[0], val[1], val[2]),
val[3], val[4])
}
| primary_value tDOT tCONSTANT tOP_ASGN command_call
{
result = @builder.op_assign(
@builder.call_method(
val[0], val[1], val[2]),
val[3], val[4])
}
| primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
{
result = @builder.op_assign(
@builder.call_method(
val[0], val[1], val[2]),
val[3], val[4])
}
| backref tOP_ASGN command_call
{
@builder.op_assign(val[0], val[1], val[2])
}
| lhs tEQL mrhs
{
result = @builder.assign(val[0], val[1],
@builder.array(nil, val[2], nil))
}
| mlhs tEQL arg_value
{
result = @builder.multi_assign(val[0], val[1], val[2])
}
| mlhs tEQL mrhs
{
result = @builder.multi_assign(val[0], val[1],
@builder.array(nil, val[2], nil))
}
| expr
expr: command_call
| expr kAND expr
{
result = @builder.logical_op(:and, val[0], val[1], val[2])
}
| expr kOR expr
{
result = @builder.logical_op(:or, val[0], val[1], val[2])
}
| kNOT expr
{
result = @builder.not_op(val[0], nil, val[1], nil)
}
| tBANG command_call
{
result = @builder.not_op(val[0], nil, val[1], nil)
}
| arg
expr_value: expr
command_call: command
| block_command
| kRETURN call_args
{
result = @builder.keyword_cmd(:return, val[0],
nil, val[1], nil)
}
| kBREAK call_args
{
result = @builder.keyword_cmd(:break, val[0],
nil, val[1], nil)
}
| kNEXT call_args
{
result = @builder.keyword_cmd(:next, val[0],
nil, val[1], nil)
}
block_command: block_call
| block_call tDOT operation2 command_args
{
lparen_t, args, rparen_t = val[3]
result = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
}
| block_call tCOLON2 operation2 command_args
{
lparen_t, args, rparen_t = val[3]
result = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
}
cmd_brace_block: tLBRACE_ARG
{
@static_env.extend_dynamic
result = @context.dup
@context.in_block = true
}
opt_block_var compstmt tRCURLY
{
result = [ val[0], val[2], val[3], val[4] ]
@static_env.unextend
@context.in_block = val[1].in_block
}
command: operation command_args =tLOWEST
{
lparen_t, args, rparen_t = val[1]
result = @builder.call_method(nil, nil, val[0],
lparen_t, args, rparen_t)
}
| operation command_args cmd_brace_block
{
lparen_t, args, rparen_t = val[1]
method_call = @builder.call_method(nil, nil, val[0],
lparen_t, args, rparen_t)
begin_t, block_args, body, end_t = val[2]
result = @builder.block(method_call,
begin_t, block_args, body, end_t)
}
| primary_value tDOT operation2 command_args =tLOWEST
{
lparen_t, args, rparen_t = val[3]
result = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
}
| primary_value tDOT operation2 command_args cmd_brace_block
{
lparen_t, args, rparen_t = val[3]
method_call = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
begin_t, block_args, body, end_t = val[4]
result = @builder.block(method_call,
begin_t, block_args, body, end_t)
}
| primary_value tCOLON2 operation2 command_args =tLOWEST
{
lparen_t, args, rparen_t = val[3]
result = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
}
| primary_value tCOLON2 operation2 command_args cmd_brace_block
{
lparen_t, args, rparen_t = val[3]
method_call = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
begin_t, block_args, body, end_t = val[4]
result = @builder.block(method_call,
begin_t, block_args, body, end_t)
}
| kSUPER command_args
{
lparen_t, args, rparen_t = val[1]
result = @builder.keyword_cmd(:super, val[0],
lparen_t, args, rparen_t)
}
| kYIELD command_args
{
lparen_t, args, rparen_t = val[1]
result = @builder.keyword_cmd(:yield, val[0],
lparen_t, args, rparen_t)
}
mlhs: mlhs_basic
{
result = @builder.multi_lhs(nil, val[0], nil)
}
| tLPAREN mlhs_entry tRPAREN
{
result = @builder.begin(val[0], val[1], val[2])
}
mlhs_entry: mlhs_basic
{
result = @builder.multi_lhs(nil, val[0], nil)
}
| tLPAREN mlhs_entry tRPAREN
{
result = @builder.multi_lhs(val[0], val[1], val[2])
}
mlhs_basic: mlhs_head
{
result = val[0]
}
| mlhs_head mlhs_item
{
result = val[0] << val[1]
}
| mlhs_head tSTAR mlhs_node
{
result = val[0] << @builder.splat(val[1], val[2])
}
| mlhs_head tSTAR
{
result = val[0] << @builder.splat(val[1])
}
| tSTAR mlhs_node
{
result = [ @builder.splat(val[0], val[1]) ]
}
| tSTAR
{
result = [ @builder.splat(val[0]) ]
}
mlhs_item: mlhs_node
| tLPAREN mlhs_entry tRPAREN
{
result = @builder.begin(val[0], val[1], val[2])
}
mlhs_head: mlhs_item tCOMMA
{
result = [ val[0] ]
}
| mlhs_head mlhs_item tCOMMA
{
result = val[0] << val[1]
}
mlhs_node: variable
{
result = @builder.assignable(val[0])
}
| primary_value tLBRACK2 aref_args tRBRACK
{
result = @builder.index_asgn(val[0], val[1], val[2], val[3])
}
| primary_value tDOT tIDENTIFIER
{
result = @builder.attr_asgn(val[0], val[1], val[2])
}
| primary_value tCOLON2 tIDENTIFIER
{
result = @builder.attr_asgn(val[0], val[1], val[2])
}
| primary_value tDOT tCONSTANT
{
result = @builder.attr_asgn(val[0], val[1], val[2])
}
| primary_value tCOLON2 tCONSTANT
{
result = @builder.assignable(
@builder.const_fetch(val[0], val[1], val[2]))
}
| tCOLON3 tCONSTANT
{
result = @builder.assignable(
@builder.const_global(val[0], val[1]))
}
| backref
{
result = @builder.assignable(val[0])
}
lhs: variable
{
result = @builder.assignable(val[0])
}
| primary_value tLBRACK2 aref_args tRBRACK
{
result = @builder.index_asgn(val[0], val[1], val[2], val[3])
}
| primary_value tDOT tIDENTIFIER
{
result = @builder.attr_asgn(val[0], val[1], val[2])
}
| primary_value tCOLON2 tIDENTIFIER
{
result = @builder.attr_asgn(val[0], val[1], val[2])
}
| primary_value tDOT tCONSTANT
{
result = @builder.attr_asgn(val[0], val[1], val[2])
}
| primary_value tCOLON2 tCONSTANT
{
result = @builder.assignable(
@builder.const_fetch(val[0], val[1], val[2]))
}
| tCOLON3 tCONSTANT
{
result = @builder.assignable(
@builder.const_global(val[0], val[1]))
}
| backref
{
result = @builder.assignable(val[0])
}
cname: tIDENTIFIER
{
diagnostic :error, :module_name_const, nil, val[0]
}
| tCONSTANT
cpath: tCOLON3 cname
{
result = @builder.const_global(val[0], val[1])
}
| cname
{
result = @builder.const(val[0])
}
| primary_value tCOLON2 cname
{
result = @builder.const_fetch(val[0], val[1], val[2])
}
fname: tIDENTIFIER | tCONSTANT | tFID
| op
| reswords
fsym: fname
{
result = @builder.symbol_internal(val[0])
}
| symbol
fitem: fsym
| dsym
undef_list: fitem
{
result = [ val[0] ]
}
| undef_list tCOMMA
{
@lexer.state = :expr_fname
}
fitem
{
result = val[0] << val[3]
}
op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
| tMATCH | tGT | tGEQ | tLT | tLEQ | tLSHFT
| tRSHFT | tPLUS | tMINUS | tSTAR2 | tSTAR | tDIVIDE
| tPERCENT | tPOW | tTILDE | tUPLUS | tUMINUS | tAREF
| tASET | tBACK_REF2
reswords: k__LINE__ | k__FILE__ | klBEGIN | klEND | kALIAS | kAND
| kBEGIN | kBREAK | kCASE | kCLASS | kDEF | kDEFINED
| kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
| kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
| kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF
| kSUPER | kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
| kIF | kUNLESS | kWHILE | kUNTIL
arg: lhs tEQL arg
{
result = @builder.assign(val[0], val[1], val[2])
}
| lhs tEQL arg kRESCUE_MOD arg
{
rescue_body = @builder.rescue_body(val[3],
nil, nil, nil,
nil, val[4])
rescue_ = @builder.begin_body(val[2], [ rescue_body ])
result = @builder.assign(val[0], val[1], rescue_)
}
| var_lhs tOP_ASGN arg
{
result = @builder.op_assign(val[0], val[1], val[2])
}
| primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN arg
{
result = @builder.op_assign(
@builder.index(
val[0], val[1], val[2], val[3]),
val[4], val[5])
}
| primary_value tDOT tIDENTIFIER tOP_ASGN arg
{
result = @builder.op_assign(
@builder.call_method(
val[0], val[1], val[2]),
val[3], val[4])
}
| primary_value tDOT tCONSTANT tOP_ASGN arg
{
result = @builder.op_assign(
@builder.call_method(
val[0], val[1], val[2]),
val[3], val[4])
}
| primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
{
result = @builder.op_assign(
@builder.call_method(
val[0], val[1], val[2]),
val[3], val[4])
}
| primary_value tCOLON2 tCONSTANT tOP_ASGN arg
{
diagnostic :error, :dynamic_const, nil, val[2], [ val[3] ]
}
| tCOLON3 tCONSTANT tOP_ASGN arg
{
diagnostic :error, :dynamic_const, nil, val[1], [ val[2] ]
}
| backref tOP_ASGN arg
{
result = @builder.op_assign(val[0], val[1], val[2])
}
| arg tDOT2 arg
{
result = @builder.range_inclusive(val[0], val[1], val[2])
}
| arg tDOT3 arg
{
result = @builder.range_exclusive(val[0], val[1], val[2])
}
| arg tPLUS arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tMINUS arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tSTAR2 arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tDIVIDE arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tPERCENT arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tPOW arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| tUNARY_NUM tINTEGER tPOW arg
{
result = @builder.unary_op(val[0],
@builder.binary_op(
@builder.integer(val[1]),
val[2], val[3]))
}
| tUNARY_NUM tFLOAT tPOW arg
{
result = @builder.unary_op(val[0],
@builder.binary_op(
@builder.float(val[1]),
val[2], val[3]))
}
| tUPLUS arg
{
result = @builder.unary_op(val[0], val[1])
}
| tUMINUS arg
{
result = @builder.unary_op(val[0], val[1])
}
| arg tPIPE arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tCARET arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tAMPER2 arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tCMP arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tGT arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tGEQ arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tLT arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tLEQ arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tEQ arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tEQQ arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tNEQ arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tMATCH arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tNMATCH arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| tBANG arg
{
result = @builder.not_op(val[0], nil, val[1], nil)
}
| tTILDE arg
{
result = @builder.unary_op(val[0], val[1])
}
| arg tLSHFT arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tRSHFT arg
{
result = @builder.binary_op(val[0], val[1], val[2])
}
| arg tANDOP arg
{
result = @builder.logical_op(:and, val[0], val[1], val[2])
}
| arg tOROP arg
{
result = @builder.logical_op(:or, val[0], val[1], val[2])
}
| kDEFINED opt_nl arg
{
result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
}
| arg tEH arg tCOLON arg
{
result = @builder.ternary(val[0], val[1],
val[2], val[3], val[4])
}
| primary
arg_value: arg
aref_args: none
{
result = []
}
| command opt_nl
{
result = [ val[0] ]
}
| args trailer
{
result = val[0]
}
| args tCOMMA tSTAR arg opt_nl
{
result = val[0] << @builder.splat(val[2], val[3])
}
| assocs trailer
{
result = [ @builder.associate(nil, val[0], nil) ]
}
| tSTAR arg opt_nl
{
result = [ @builder.splat(val[0], val[1]) ]
}
paren_args: tLPAREN2 none tRPAREN
{
result = [ val[0], [], val[2] ]
}
| tLPAREN2 call_args opt_nl tRPAREN
{
result = [ val[0], val[1], val[3] ]
}
| tLPAREN2 block_call opt_nl tRPAREN
{
result = [ val[0], [ val[1] ], val[3] ]
}
| tLPAREN2 args tCOMMA block_call opt_nl tRPAREN
{
result = [ val[0], val[1] << val[3], val[5] ]
}
opt_paren_args: # nothing
{
result = [ nil, [], nil ]
}
| paren_args
call_args: command
{
result = [ val[0] ]
}
| args opt_block_arg
{
result = val[0].concat(val[1])
}
| args tCOMMA tSTAR arg_value opt_block_arg
{
result = val[0].concat(
[ @builder.splat(val[2], val[3]),
*val[4] ])
}
| assocs opt_block_arg
{
result = [ @builder.associate(nil, val[0], nil),
*val[1] ]
}
| assocs tCOMMA tSTAR arg_value opt_block_arg
{
result = [ @builder.associate(nil, val[0], nil),
@builder.splat(val[2], val[3]),
*val[4] ]
}
| args tCOMMA assocs opt_block_arg
{
result = val[0].concat(
[ @builder.associate(nil, val[2], nil),
*val[3] ])
}
| args tCOMMA assocs tCOMMA tSTAR arg opt_block_arg
{
result = val[0].concat(
[ @builder.associate(nil, val[2], nil),
@builder.splat(val[4], val[5]),
*val[6] ])
}
| tSTAR arg_value opt_block_arg
{
result = [ @builder.splat(val[0], val[1]),
*val[2] ]
}
| block_arg
{
result = [ val[0] ]
}
call_args2: arg_value tCOMMA args opt_block_arg
{
result = [ val[0], *val[2].concat(val[3]) ]
}
| arg_value tCOMMA block_arg
{
result = [ val[0], val[2] ]
}
| arg_value tCOMMA tSTAR arg_value opt_block_arg
{
result = [ val[0],
@builder.splat(val[2], val[3]),
*val[4] ]
}
| arg_value tCOMMA args tCOMMA tSTAR arg_value opt_block_arg
{
result = [ val[0],
*val[2].
push(@builder.splat(val[4], val[5])).
concat(val[6]) ]
}
| assocs opt_block_arg
{
result = [ @builder.associate(nil, val[0], nil),
*val[1] ]
}
| assocs tCOMMA tSTAR arg_value opt_block_arg
{
result = [ @builder.associate(nil, val[0], nil),
@builder.splat(val[2], val[3]),
*val[4] ]
}
| arg_value tCOMMA assocs opt_block_arg
{
result = [ val[0],
@builder.associate(nil, val[2], nil),
*val[3] ]
}
| arg_value tCOMMA args tCOMMA assocs opt_block_arg
{
result = [ val[0],
*val[2].
push(@builder.associate(nil, val[4], nil)).
concat(val[5]) ]
}
| arg_value tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
{
result = [ val[0],
@builder.associate(nil, val[2], nil),
@builder.splat(val[4], val[5]),
*val[6] ]
}
| arg_value tCOMMA args tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
{
result = [ val[0],
*val[2].
push(@builder.associate(nil, val[4], nil)).
push(@builder.splat(val[6], val[7])).
concat(val[8]) ]
}
| tSTAR arg_value opt_block_arg
{
result = [ @builder.splat(val[0], val[1]),
*val[2] ]
}
| block_arg
{
result = [ val[0] ]
}
command_args: {
result = @lexer.cmdarg.dup
@lexer.cmdarg.push(true)
}
open_args
{
@lexer.cmdarg = val[0]
result = val[1]
}
open_args: call_args
{
result = [ nil, val[0], nil ]
}
| tLPAREN_ARG
{
@lexer.state = :expr_endarg
}
tRPAREN
{
result = [ val[0], [], val[2] ]
}
| tLPAREN_ARG call_args2
{
@lexer.state = :expr_endarg
}
tRPAREN
{
result = [ val[0], val[1], val[3] ]
}
block_arg: tAMPER arg_value
{
result = @builder.block_pass(val[0], val[1])
}
opt_block_arg: tCOMMA block_arg
{
result = [ val[1] ]
}
| # nothing
{
result = []
}
args: arg_value
{
result = [ val[0] ]
}
| args tCOMMA arg_value
{
result = val[0] << val[2]
}
mrhs: args tCOMMA arg_value
{
result = val[0] << val[2]
}
| args tCOMMA tSTAR arg_value
{
result = val[0] << @builder.splat(val[2], val[3])
}
| tSTAR arg_value
{
result = [ @builder.splat(val[0], val[1]) ]
}
primary: literal
| strings
| xstring
| regexp
| words
| qwords
| var_ref
| backref
| tFID
{
result = @builder.call_method(nil, nil, val[0])
}
| kBEGIN bodystmt kEND
{
result = @builder.begin_keyword(val[0], val[1], val[2])
}
| tLPAREN_ARG expr
{
@lexer.state = :expr_endarg
}
opt_nl tRPAREN
{
result = @builder.begin(val[0], val[1], val[4])
}
| tLPAREN compstmt tRPAREN
{
result = @builder.begin(val[0], val[1], val[2])
}
| primary_value tCOLON2 tCONSTANT
{
result = @builder.const_fetch(val[0], val[1], val[2])
}
| tCOLON3 tCONSTANT
{
result = @builder.const_global(val[0], val[1])
}
| primary_value tLBRACK2 aref_args tRBRACK
{
result = @builder.index(val[0], val[1], val[2], val[3])
}
| tLBRACK aref_args tRBRACK
{
result = @builder.array(val[0], val[1], val[2])
}
| tLBRACE assoc_list tRCURLY
{
result = @builder.associate(val[0], val[1], val[2])
}
| kRETURN
{
result = @builder.keyword_cmd(:return, val[0])
}
| kYIELD tLPAREN2 call_args tRPAREN
{
result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
}
| kYIELD tLPAREN2 tRPAREN
{
result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
}
| kYIELD
{
result = @builder.keyword_cmd(:yield, val[0])
}
| kDEFINED opt_nl tLPAREN2 expr tRPAREN
{
result = @builder.keyword_cmd(:defined?, val[0],
val[2], [ val[3] ], val[4])
}
| operation brace_block
{
method_call = @builder.call_method(nil, nil, val[0])
begin_t, args, body, end_t = val[1]
result = @builder.block(method_call,
begin_t, args, body, end_t)
}
| method_call
| method_call brace_block
{
begin_t, args, body, end_t = val[1]
result = @builder.block(val[0],
begin_t, args, body, end_t)
}
| kIF expr_value then compstmt if_tail kEND
{
else_t, else_ = val[4]
result = @builder.condition(val[0], val[1], val[2],
val[3], else_t,
else_, val[5])
}
| kUNLESS expr_value then compstmt opt_else kEND
{
else_t, else_ = val[4]
result = @builder.condition(val[0], val[1], val[2],
else_, else_t,
val[3], val[5])
}
| kWHILE
{
@lexer.cond.push(true)
}
expr_value do
{
@lexer.cond.pop
}
compstmt kEND
{
result = @builder.loop(:while, val[0], val[2], val[3],
val[5], val[6])
}
| kUNTIL
{
@lexer.cond.push(true)
}
expr_value do
{
@lexer.cond.pop
}
compstmt kEND
{
result = @builder.loop(:until, val[0], val[2], val[3],
val[5], val[6])
}
| kCASE expr_value opt_terms case_body kEND
{
when_bodies = val[3][0..-2]
else_t, else_body = val[3][-1]
result = @builder.case(val[0], val[1],
when_bodies, else_t, else_body,
val[4])
}
| kCASE opt_terms case_body kEND
{
when_bodies = val[2][0..-2]
else_t, else_body = val[2][-1]
result = @builder.case(val[0], nil,
when_bodies, else_t, else_body,
val[3])
}
| kCASE opt_terms kELSE compstmt kEND
{
result = @builder.case(val[0], nil,
[], val[2], val[3],
val[4])
}
| kFOR for_var kIN
{
@lexer.cond.push(true)
}
expr_value do
{
@lexer.cond.pop
}
compstmt kEND
{
result = @builder.for(val[0], val[1],
val[2], val[4],
val[5], val[7], val[8])
}
| k_class cpath superclass
{
local_push
@context.in_class = true
}
bodystmt kEND
{
k_class, ctx = val[0]
if @context.in_def
diagnostic :error, :class_in_def, nil, k_class
end
lt_t, superclass = val[2]
result = @builder.def_class(k_class, val[1],
lt_t, superclass,
val[4], val[5])
local_pop
@context.in_class = ctx.in_class
}
| k_class tLSHFT expr term
{
@context.in_def = false
@context.in_class = false
local_push
}
bodystmt kEND
{
k_class, ctx = val[0]
result = @builder.def_sclass(k_class, val[1], val[2],
val[5], val[6])
local_pop
@context.in_def = ctx.in_def
@context.in_class = ctx.in_class
}
| k_module cpath
{
@context.in_class = true
local_push
}
bodystmt kEND
{
k_mod, ctx = val[0]
if @context.in_def
diagnostic :error, :module_in_def, nil, k_mod
end
result = @builder.def_module(k_mod, val[1],
val[3], val[4])
local_pop
@context.in_class = ctx.in_class
}
| kDEF fname
{
local_push
result = context.dup
@context.in_def = true
}
f_arglist bodystmt kEND
{
result = @builder.def_method(val[0], val[1],
val[3], val[4], val[5])
local_pop
@context.in_def = val[2].in_def
}
| kDEF singleton dot_or_colon
{
@lexer.state = :expr_fname
}
fname
{
local_push
result = context.dup
@context.in_def = true
}
f_arglist bodystmt kEND
{
result = @builder.def_singleton(val[0], val[1], val[2],
val[4], val[6], val[7], val[8])
local_pop
@context.in_def = val[5].in_def
}
| kBREAK
{
result = @builder.keyword_cmd(:break, val[0])
}
| kNEXT
{
result = @builder.keyword_cmd(:next, val[0])
}
| kREDO
{
result = @builder.keyword_cmd(:redo, val[0])
}
| kRETRY
{
result = @builder.keyword_cmd(:retry, val[0])
}
primary_value: primary
k_class: kCLASS
{
result = [ val[0], @context.dup ]
}
k_module: kMODULE
{
result = [ val[0], @context.dup ]
}
then: term
| tCOLON
| kTHEN
| term kTHEN
{
result = val[1]
}
do: term
| tCOLON
| kDO_COND
if_tail: opt_else
| kELSIF expr_value then compstmt if_tail
{
else_t, else_ = val[4]
result = [ val[0],
@builder.condition(val[0], val[1], val[2],
val[3], else_t,
else_, nil),
]
}
opt_else: none
| kELSE compstmt
{
result = val
}
for_var: lhs
| mlhs
block_par: mlhs_item
{
result = [ @builder.arg_expr(val[0]) ]
}
| block_par tCOMMA mlhs_item
{
result = val[0] << @builder.arg_expr(val[2])
}
block_var: block_par
| block_par tCOMMA
| block_par tCOMMA tAMPER lhs
{
result = val[0].
push(@builder.blockarg_expr(val[2], val[3]))
}
| block_par tCOMMA tSTAR lhs tCOMMA tAMPER lhs
{
result = val[0].
push(@builder.restarg_expr(val[2], val[3])).
push(@builder.blockarg_expr(val[5], val[6]))
}
| block_par tCOMMA tSTAR tCOMMA tAMPER lhs
{
result = val[0].
push(@builder.restarg_expr(val[2])).
push(@builder.blockarg_expr(val[4], val[5]))
}
| block_par tCOMMA tSTAR lhs
{
result = val[0].
push(@builder.restarg_expr(val[2], val[3]))
}
| block_par tCOMMA tSTAR
{
result = val[0].
push(@builder.restarg_expr(val[2]))
}
| tSTAR lhs tCOMMA tAMPER lhs
{
result = [ @builder.restarg_expr(val[0], val[1]),
@builder.blockarg_expr(val[3], val[4]) ]
}
| tSTAR tCOMMA tAMPER lhs
{
result = [ @builder.restarg_expr(val[0]),
@builder.blockarg_expr(val[2], val[3]) ]
}
| tSTAR lhs
{
result = [ @builder.restarg_expr(val[0], val[1]) ]
}
| tSTAR
{
result = [ @builder.restarg_expr(val[0]) ]
}
| tAMPER lhs
{
result = [ @builder.blockarg_expr(val[0], val[1]) ]
}
;
opt_block_var: # nothing
{
result = @builder.args(nil, [], nil)
}
| tPIPE tPIPE
{
result = @builder.args(val[0], [], val[1])
}
| tOROP
{
result = @builder.args(val[0], [], val[0])
}
| tPIPE block_var tPIPE
{
result = @builder.args(val[0], val[1], val[2], false)
}
do_block: kDO_BLOCK
{
@static_env.extend_dynamic
result = @context.dup
@context.in_block = true
}
opt_block_var compstmt kEND
{
result = [ val[0], val[2], val[3], val[4] ]
@static_env.unextend
@context.in_block = val[1].in_block
}
block_call: command do_block
{
begin_t, block_args, body, end_t = val[1]
result = @builder.block(val[0],
begin_t, block_args, body, end_t)
}
| block_call tDOT operation2 opt_paren_args
{
lparen_t, args, rparen_t = val[3]
result = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
}
| block_call tCOLON2 operation2 opt_paren_args
{
lparen_t, args, rparen_t = val[3]
result = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
}
method_call: operation paren_args
{
lparen_t, args, rparen_t = val[1]
result = @builder.call_method(nil, nil, val[0],
lparen_t, args, rparen_t)
}
| primary_value tDOT operation2 opt_paren_args
{
lparen_t, args, rparen_t = val[3]
result = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
}
| primary_value tCOLON2 operation2 paren_args
{
lparen_t, args, rparen_t = val[3]
result = @builder.call_method(val[0], val[1], val[2],
lparen_t, args, rparen_t)
}
| primary_value tCOLON2 operation3
{
result = @builder.call_method(val[0], val[1], val[2])
}
| kSUPER paren_args
{
lparen_t, args, rparen_t = val[1]
result = @builder.keyword_cmd(:super, val[0],
lparen_t, args, rparen_t)
}
| kSUPER
{
result = @builder.keyword_cmd(:zsuper, val[0])
}
brace_block: tLCURLY
{
@static_env.extend_dynamic
result = @context.dup
@context.in_block = true
}
opt_block_var compstmt tRCURLY
{
result = [ val[0], val[2], val[3], val[4] ]
@static_env.unextend
@context.in_block = val[1].in_block
}
| kDO
{
@static_env.extend_dynamic
result = @context.dup
@context.in_block = true
}
opt_block_var compstmt kEND
{
result = [ val[0], val[2], val[3], val[4] ]
@static_env.unextend
@context.in_block = val[1].in_block
}
case_body: kWHEN when_args then compstmt cases
{
result = [ @builder.when(val[0], val[1], val[2], val[3]),
*val[4] ]
}
when_args: args
| args tCOMMA tSTAR arg_value
{
result = val[0] << @builder.splat(val[2], val[3])
}
| tSTAR arg_value
{
result = [ @builder.splat(val[0], val[1]) ]
}
cases: opt_else
{
result = [ val[0] ]
}
| case_body
opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
{
assoc_t, exc_var = val[2]
if val[1]
exc_list = @builder.array(nil, val[1], nil)
end
result = [ @builder.rescue_body(val[0],
exc_list, assoc_t, exc_var,
val[3], val[4]),
*val[5] ]
}
| # nothing
{
result = []
}
exc_list: arg_value
{
result = [ val[0] ]
}
| mrhs
| none
exc_var: tASSOC lhs
{
result = [ val[0], val[1] ]
}
| none
opt_ensure: kENSURE compstmt
{
result = [ val[0], val[1] ]
}
| none
literal: numeric
| symbol
| dsym
strings: string
{
result = @builder.string_compose(nil, val[0], nil)
}
string: string1
{
result = [ val[0] ]
}
| string string1
{
result = val[0] << val[1]
}
string1: tSTRING_BEG string_contents tSTRING_END
{
result = @builder.string_compose(val[0], val[1], val[2])
}
| tSTRING
{
result = @builder.string(val[0])
}
xstring: tXSTRING_BEG xstring_contents tSTRING_END
{
result = @builder.xstring_compose(val[0], val[1], val[2])
}
regexp: tREGEXP_BEG xstring_contents tSTRING_END tREGEXP_OPT
{
opts = @builder.regexp_options(val[3])
result = @builder.regexp_compose(val[0], val[1], val[2], opts)
}
words: tWORDS_BEG word_list tSTRING_END
{
result = @builder.words_compose(val[0], val[1], val[2])
}
word_list: # nothing
{
result = []
}
| word_list word tSPACE
{
result = val[0] << @builder.word(val[1])
}
word: string_content
{
result = [ val[0] ]
}
| word string_content
{
result = val[0] << val[1]
}
qwords: tQWORDS_BEG qword_list tSTRING_END
{
result = @builder.words_compose(val[0], val[1], val[2])
}
qword_list: # nothing
{
result = []
}
| qword_list tSTRING_CONTENT tSPACE
{
result = val[0] << @builder.string_internal(val[1])
}
string_contents: # nothing
{
result = []
}
| string_contents string_content
{
result = val[0] << val[1]
}
xstring_contents: # nothing
{
result = []
}
| xstring_contents string_content
{
result = val[0] << val[1]
}
string_content: tSTRING_CONTENT
{
result = @builder.string_internal(val[0])
}
| tSTRING_DVAR string_dvar
{
result = val[1]
}
| tSTRING_DBEG
{
@lexer.cond.push(false)
@lexer.cmdarg.push(false)
}
compstmt tRCURLY
{
@lexer.cond.lexpop
@lexer.cmdarg.lexpop
result = @builder.begin(val[0], val[2], val[3])
}
string_dvar: tGVAR
{
result = @builder.gvar(val[0])
}
| tIVAR
{
result = @builder.ivar(val[0])
}
| tCVAR
{
result = @builder.cvar(val[0])
}
| backref
symbol: tSYMBOL
{
result = @builder.symbol(val[0])
}
dsym: tSYMBEG xstring_contents tSTRING_END
{
result = @builder.symbol_compose(val[0], val[1], val[2])
}
numeric: tINTEGER
{
result = @builder.integer(val[0])
}
| tFLOAT
{
result = @builder.float(val[0])
}
| tUNARY_NUM tINTEGER =tLOWEST
{
num = @builder.integer(val[1])
if @builder.respond_to? :negate
# AST builder interface compatibility
result = @builder.negate(val[0], num)
else
result = @builder.unary_num(val[0], num)
end
}
| tUNARY_NUM tFLOAT =tLOWEST
{
num = @builder.float(val[1])
if @builder.respond_to? :negate
# AST builder interface compatibility
result = @builder.negate(val[0], num)
else
result = @builder.unary_num(val[0], num)
end
}
variable: tIDENTIFIER
{
result = @builder.ident(val[0])
}
| tIVAR
{
result = @builder.ivar(val[0])
}
| tGVAR
{
result = @builder.gvar(val[0])
}
| tCVAR
{
result = @builder.cvar(val[0])
}
| tCONSTANT
{
result = @builder.const(val[0])
}
| kNIL
{
result = @builder.nil(val[0])
}
| kSELF
{
result = @builder.self(val[0])
}
| kTRUE
{
result = @builder.true(val[0])
}
| kFALSE
{
result = @builder.false(val[0])
}
| k__FILE__
{
result = @builder.__FILE__(val[0])
}
| k__LINE__
{
result = @builder.__LINE__(val[0])
}
var_ref: variable
{
result = @builder.accessible(val[0])
}
var_lhs: variable
{
result = @builder.assignable(val[0])
}
backref: tNTH_REF
{
result = @builder.nth_ref(val[0])
}
| tBACK_REF
{
result = @builder.back_ref(val[0])
}
superclass: term
{
result = nil
}
| tLT expr_value term
{
result = [ val[0], val[1] ]
}
| error term
{
yyerrok
result = nil
}
f_arglist: tLPAREN2 f_args opt_nl tRPAREN
{
result = @builder.args(val[0], val[1], val[3])
@lexer.state = :expr_beg
}
| f_args term
{
result = @builder.args(nil, val[0], nil)
}
f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_f_block_arg
{
result = val[0].
concat(val[2]).
concat(val[4]).
concat(val[5])
}
| f_arg tCOMMA f_optarg opt_f_block_arg
{
result = val[0].
concat(val[2]).
concat(val[3])
}
| f_arg tCOMMA f_rest_arg opt_f_block_arg
{
result = val[0].
concat(val[2]).
concat(val[3])
}
| f_arg opt_f_block_arg
{
result = val[0].
concat(val[1])
}
| f_optarg tCOMMA f_rest_arg opt_f_block_arg
{
result = val[0].
concat(val[2]).
concat(val[3])
}
| f_optarg opt_f_block_arg
{
result = val[0].
concat(val[1])
}
| f_rest_arg opt_f_block_arg
{
result = val[0].
concat(val[1])
}
| f_block_arg
{
result = [ val[0] ]
}
| # nothing
{
result = []
}
f_norm_arg: tCONSTANT
{
diagnostic :error, :argument_const, nil, val[0]
}
| tIVAR
{
diagnostic :error, :argument_ivar, nil, val[0]
}
| tGVAR
{
diagnostic :error, :argument_gvar, nil, val[0]
}
| tCVAR
{
diagnostic :error, :argument_cvar, nil, val[0]
}
| tIDENTIFIER
{
@static_env.declare val[0][0]
result = @builder.arg(val[0])
}
f_arg: f_norm_arg
{
result = [ val[0] ]
}
| f_arg tCOMMA f_norm_arg
{
result = val[0] << val[2]
}
f_opt: tIDENTIFIER tEQL arg_value
{
@static_env.declare val[0][0]
result = @builder.optarg(val[0], val[1], val[2])
}
f_optarg: f_opt
{
result = [ val[0] ]
}
| f_optarg tCOMMA f_opt
{
result = val[0] << val[2]
}
restarg_mark: tSTAR2 | tSTAR
f_rest_arg: restarg_mark tIDENTIFIER
{
@static_env.declare val[1][0]
result = [ @builder.restarg(val[0], val[1]) ]
}
| restarg_mark
{
result = [ @builder.restarg(val[0]) ]
}
blkarg_mark: tAMPER2 | tAMPER
f_block_arg: blkarg_mark tIDENTIFIER
{
@static_env.declare val[1][0]
result = @builder.blockarg(val[0], val[1])
}
opt_f_block_arg: tCOMMA f_block_arg
{
result = [ val[1] ]
}
| # nothing
{
result = []
}
singleton: var_ref
| tLPAREN2 expr opt_nl tRPAREN
{
result = val[1]
}
assoc_list: # nothing
{
result = []
}
| assocs trailer
{
result = val[0]
}
| args trailer
{
result = @builder.pair_list_18(val[0])
}
assocs: assoc
{
result = [ val[0] ]
}
| assocs tCOMMA assoc
{
result = val[0] << val[2]
}
assoc: arg_value tASSOC arg_value
{
result = @builder.pair(val[0], val[1], val[2])
}
operation: tIDENTIFIER | tCONSTANT | tFID
operation2: tIDENTIFIER | tCONSTANT | tFID | op
operation3: tIDENTIFIER | tFID | op
dot_or_colon: tDOT | tCOLON2
opt_terms: | terms
opt_nl: | tNL
trailer: | tNL | tCOMMA
term: tSEMI
{
yyerrok
}
| tNL
terms: term
| terms tSEMI
none: # nothing
{
result = nil
}
end
---- header
require_relative '../parser'
---- inner
def version
18
end
def default_encoding
Encoding::BINARY
end
def local_push
@static_env.extend_static
@lexer.cmdarg.push(false)
@lexer.cond.push(false)
end
def local_pop
@static_env.unextend
@lexer.cmdarg.pop
@lexer.cond.pop
end