org.jruby.ext.ripper.RipperParser.y Maven / Gradle / Ivy
%{
/*
***** BEGIN LICENSE BLOCK *****
* Version: EPL 2.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v20.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2013-2017 The JRuby Team ([email protected])
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.ext.ripper;
import org.jruby.RubyArray;
import org.jruby.lexer.LexerSource;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import static org.jruby.lexer.LexingCommon.EXPR_BEG;
import static org.jruby.lexer.LexingCommon.EXPR_FITEM;
import static org.jruby.lexer.LexingCommon.EXPR_FNAME;
import static org.jruby.lexer.LexingCommon.EXPR_ENDFN;
import static org.jruby.lexer.LexingCommon.EXPR_ENDARG;
import static org.jruby.lexer.LexingCommon.EXPR_END;
import static org.jruby.lexer.LexingCommon.EXPR_LABEL;
public class RipperParser extends RipperParserBase {
public RipperParser(ThreadContext context, IRubyObject ripper, LexerSource source) {
super(context, ripper, source);
}
%}
%token keyword_class keyword_module keyword_def keyword_undef
keyword_begin keyword_rescue keyword_ensure keyword_end keyword_if
keyword_unless keyword_then keyword_elsif keyword_else keyword_case
keyword_when keyword_while keyword_until keyword_for keyword_break
keyword_next keyword_redo keyword_retry keyword_in keyword_do keyword_do_cond
keyword_do_block keyword_return keyword_yield keyword_super keyword_self
keyword_nil keyword_true keyword_false keyword_and keyword_or keyword_not
modifier_if modifier_unless modifier_while modifier_until modifier_rescue
keyword_alias keyword_defined keyword_BEGIN keyword_END keyword__LINE__
keyword__FILE__ keyword__ENCODING__ keyword_do_lambda
%token tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
%token tCHAR
%type sym symbol operation operation2 operation3 op fname cname
%type f_norm_arg restarg_mark
%type dot_or_colon blkarg_mark
%token tUPLUS /* unary+ */
%token tUMINUS /* unary- */
%token tUMINUS_NUM /* unary- */
%token tPOW /* ** */
%token tCMP /* <=> */
%token tEQ /* == */
%token tEQQ /* === */
%token tNEQ /* != */
%token tGEQ /* >= */
%token tLEQ /* <= */
%token tANDOP tOROP /* && and || */
%token tMATCH tNMATCH /* =~ and !~ */
%token tDOT /* Is just '.' in ruby and not a token */
%token tDOT2 tDOT3 /* .. and ... */
%token tAREF tASET /* [] and []= */
%token tLSHFT tRSHFT /* << and >> */
%token tANDDOT /* &. */
%token tCOLON2 /* :: */
%token tCOLON3 /* :: at EXPR_BEG */
%token tOP_ASGN /* +=, -= etc. */
%token tASSOC /* => */
%token tLPAREN /* ( */
%token tLPAREN2 /* ( Is just '(' in ruby and not a token */
%token tRPAREN /* ) */
%token tLPAREN_ARG /* ( */
%token tLBRACK /* [ */
%token tRBRACK /* ] */
%token tLBRACE /* { */
%token tLBRACE_ARG /* { */
%token tSTAR /* * */
%token tSTAR2 /* * Is just '*' in ruby and not a token */
%token tAMPER /* & */
%token tAMPER2 /* & Is just '&' in ruby and not a token */
%token tTILDE /* ` is just '`' in ruby and not a token */
%token tPERCENT /* % is just '%' in ruby and not a token */
%token tDIVIDE /* / is just '/' in ruby and not a token */
%token tPLUS /* + is just '+' in ruby and not a token */
%token tMINUS /* - is just '-' in ruby and not a token */
%token tLT /* < is just '<' in ruby and not a token */
%token tGT /* > is just '>' in ruby and not a token */
%token tPIPE /* | is just '|' in ruby and not a token */
%token tBANG /* ! is just '!' in ruby and not a token */
%token tCARET /* ^ is just '^' in ruby and not a token */
%token tLCURLY /* { is just '{' in ruby and not a token */
%token tRCURLY /* } is just '}' in ruby and not a token */
%token tBACK_REF2 /* { is just '`' in ruby and not a token */
%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
%token tSTRING_DBEG tSTRING_DVAR tSTRING_END
%token tLAMBDA tLAMBEG
%token tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tIMAGINARY
%token tFLOAT
%token tRATIONAL
%token tREGEXP_END
/* RIPPER-ONY TOKENS { */
%token tIGNORED_NL, tCOMMENT, tEMBDOC_BEG, tEMBDOC, tEMBDOC_END
%token tSP, tHEREDOC_BEG, tHEREDOC_END
/* } RIPPER-ONY TOKENS */
%type f_rest_arg
%type singleton strings string string1 xstring regexp
%type string_contents xstring_contents method_call
%type string_content
%type regexp_contents
%type words qwords word literal dsym cpath command_asgn command_call
%type numeric simple_numeric
%type mrhs_arg
%type compstmt bodystmt stmts stmt expr arg primary command
%type stmt_or_begin
%type expr_value primary_value opt_else cases if_tail exc_var rel_expr
%type call_args opt_ensure paren_args superclass
%type command_args var_ref opt_paren_args block_call block_command
%type command_rhs arg_rhs
%type f_opt
%type undef_list
%type string_dvar backref
%type f_args f_larglist block_param block_param_def opt_block_param
%type f_arglist
%type mrhs mlhs_item mlhs_node arg_value case_body exc_list aref_args
%type lhs none args
%type qword_list word_list
%type f_arg f_optarg
%type f_marg_list, symbol_list
%type qsym_list, symbols, qsymbols
%type opt_args_tail, opt_block_args_tail, block_args_tail, args_tail
%type f_kw, f_block_kw
%type f_block_kwarg, f_kwarg
%type assoc_list
%type assocs
%type assoc
%type mlhs_head mlhs_post
%type f_block_optarg
%type opt_block_arg block_arg none_block_pass
%type opt_f_block_arg f_block_arg
%type brace_block do_block cmd_brace_block brace_body do_body
%type mlhs mlhs_basic
%type opt_rescue
%type var_lhs
%type fsym
%type fitem
%type f_arg_item
%type bv_decls
%type opt_bv_decl lambda_body
%type lambda
%type mlhs_inner f_block_opt for_var
%type opt_call_args f_marg f_margs
%type bvar
%type reswords f_bad_arg relop
%type rparen rbracket
%type top_compstmt top_stmts top_stmt
%token tSYMBOLS_BEG
%token tQSYMBOLS_BEG
%token tDSTAR
%token tSTRING_DEND
%type kwrest_mark f_kwrest f_label
%type call_op call_op2
%type f_arg_asgn
%type fcall
%token tLABEL_END, tSTRING_DEND
%type do then
%type program
/*
* precedence table
*/
%nonassoc tLOWEST
%nonassoc tLBRACE_ARG
%nonassoc modifier_if modifier_unless modifier_while modifier_until
%left keyword_or keyword_and
%right keyword_not
%nonassoc keyword_defined
%right '=' tOP_ASGN
%left modifier_rescue
%right '?' ':'
%nonassoc tDOT2 tDOT3
%left tOROP
%left tANDOP
%nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
%left tGT tGEQ tLT tLEQ
%left tPIPE tCARET
%left tAMPER2
%left tLSHFT tRSHFT
%left tPLUS tMINUS
%left tSTAR2 tDIVIDE tPERCENT
%right tUMINUS_NUM tUMINUS
%right tPOW
%right tBANG tTILDE tUPLUS
//%token tLAST_TOKEN
%token k__END__
%%
program : {
p.setState(EXPR_BEG);
p.pushLocalScope();
} top_compstmt {
$$ = p.dispatch("on_program", $2);
p.popCurrentScope();
}
top_compstmt : top_stmts opt_terms {
$$ = $1;
}
top_stmts : none {
$$ = p.dispatch("on_stmts_add", p.dispatch("on_stmts_new"), p.dispatch("on_void_stmt"));
}
| top_stmt {
$$ = p.dispatch("on_stmts_add", p.dispatch("on_stmts_new"), $1);
}
| top_stmts terms top_stmt {
$$ = p.dispatch("on_stmts_add", $1, $3);
}
| error top_stmt {
$$ = $2;
}
top_stmt : stmt
| keyword_BEGIN {
if (p.isInDef()) {
p.yyerror("BEGIN in method");
}
} tLCURLY top_compstmt tRCURLY {
$$ = p.dispatch("on_BEGIN", $4);
}
bodystmt : compstmt opt_rescue opt_else opt_ensure {
$$ = p.dispatch("on_bodystmt", $1, $2, $3, $4);
}
compstmt : stmts opt_terms {
$$ = $1;
}
stmts : none {
$$ = p.dispatch("on_stmts_add", p.dispatch("on_stmts_new"), p.dispatch("on_void_stmt"));
}
| stmt_or_begin {
$$ = p.dispatch("on_stmts_add", p.dispatch("on_stmts_new"), $1);
}
| stmts terms stmt_or_begin {
$$ = p.dispatch("on_stmts_add", $1, $3);
}
| error stmt {
$$ = $2;
}
stmt_or_begin : stmt {
$$ = $1;
}
// FIXME: How can this new begin ever work? is yyerror conditional in MRI?
| keyword_begin {
p.yyerror("BEGIN is permitted only at toplevel");
} tLCURLY top_compstmt tRCURLY {
$$ = p.dispatch("on_BEGIN", $4);
}
stmt : keyword_alias fitem {
p.setState(EXPR_FNAME|EXPR_FITEM);
} fitem {
$$ = p.dispatch("on_alias", $2, $4);
}
| keyword_alias tGVAR tGVAR {
$$ = p.dispatch("on_var_alias", $2, $3);
}
| keyword_alias tGVAR tBACK_REF {
$$ = p.dispatch("on_var_alias", $2, $3);
}
| keyword_alias tGVAR tNTH_REF {
$$ = p.dispatch("on_alias_error", p.dispatch("on_var_alias", $2, $3));
p.error();
}
| keyword_undef undef_list {
$$ = p.dispatch("on_undef", $2);
}
| stmt modifier_if expr_value {
$$ = p.dispatch("on_if_mod", $3, $1);
}
| stmt modifier_unless expr_value {
$$ = p.dispatch("on_unless_mod", $3, $1);
}
| stmt modifier_while expr_value {
$$ = p.dispatch("on_while_mod", $3, $1);
}
| stmt modifier_until expr_value {
$$ = p.dispatch("on_until_mod", $3, $1);
}
| stmt modifier_rescue stmt {
$$ = p.dispatch("on_rescue_mod", $1, $3);
}
| keyword_END tLCURLY compstmt tRCURLY {
if (p.isInDef()) {
p.warn("END in method; use at_exit");
}
$$ = p.dispatch("on_END", $3);
}
| command_asgn
| mlhs '=' command_call {
$$ = p.dispatch("on_massign", $1, $3);
}
| lhs '=' mrhs {
$$ = p.dispatch("on_assign", $1, $3);
}
| mlhs '=' mrhs_arg {
$$ = p.dispatch("on_massign", $1, $3);
}
| expr
command_asgn : lhs '=' command_rhs {
$$ = p.dispatch("on_assign", $1, $3);
}
| var_lhs tOP_ASGN command_rhs {
$$ = p.dispatch("on_opassign", $1, $2, $3);
}
| primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs {
$$ = p.dispatch("on_opassign",
p.dispatch("on_aref_field", $1, $3),
$5, $6);
}
| primary_value call_op tIDENTIFIER tOP_ASGN command_rhs {
$$ = p.dispatch("on_opassign",
p.dispatch("on_field", $1, $2, $3),
$4, $5);
}
| primary_value call_op tCONSTANT tOP_ASGN command_rhs {
$$ = p.dispatch("on_opassign",
p.dispatch("on_field",$1, $2, $3),
$4, $5);
}
| primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs {
$$ = p.dispatch("on_opassign",
p.dispatch("on_const_path_field", $1, $3),
$4,
$5);
}
| primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs {
$$ = p.dispatch("on_opassign",
p.dispatch("on_field", $1, p.intern("::"), $3),
$4, $5);
}
| backref tOP_ASGN command_rhs {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_assign",
p.dispatch("on_var_field", $1),
$3));
p.error();
}
command_rhs : command_call %prec tOP_ASGN {
$$ = $1;
}
| command_call modifier_rescue stmt {
$$ = p.dispatch("on_rescue_mod", $1, $3);
}
| command_asgn
// Node:expr *CURRENT* all but arg so far
expr : command_call
| expr keyword_and expr {
$$ = p.dispatch("on_binary", $1, p.intern("and"), $3);
}
| expr keyword_or expr {
$$ = p.dispatch("on_binary", $1, p.intern("or"), $3);
}
| keyword_not opt_nl expr {
$$ = p.dispatch("on_unary", p.intern("not"), $3);
}
| tBANG command_call {
$$ = p.dispatch("on_unary", p.intern("!"), $2);
}
| arg
expr_value : expr {
$$ = $1;
}
// Node:command - call with or with block on end [!null]
command_call : command
| block_command
;
// Node:block_command - A call with a block (foo.bar {...}, foo::bar {...}, bar {...}) [!null]
block_command : block_call
| block_call call_op2 operation2 command_args {
$$ = p.dispatch("on_method_add_arg",
p.dispatch("on_call", $1, $2, $3),
$4);
}
// :brace_block - [!null]
cmd_brace_block : tLBRACE_ARG brace_body tRCURLY {
$$ = $2;
}
fcall : operation
// Node:command - fcall/call/yield/super [!null]
command : fcall command_args %prec tLOWEST {
$$ = p.dispatch("on_command", $1, $2);
}
| fcall command_args cmd_brace_block {
$$ = p.dispatch("on_method_add_block",
p.dispatch("on_command", $1, $2),
$3);
}
| primary_value call_op operation2 command_args %prec tLOWEST {
$$ = p.dispatch("on_command_call", $1, $2, $3, $4);
}
| primary_value call_op operation2 command_args cmd_brace_block {
$$ = p.dispatch("on_method_add_block",
p.dispatch("on_command_call", $1, $2, $3, $4),
$5);
}
| primary_value tCOLON2 operation2 command_args %prec tLOWEST {
$$ = p.dispatch("on_command_call", $1, p.intern("::"), $3, $4);
}
| primary_value tCOLON2 operation2 command_args cmd_brace_block {
$$ = p.dispatch("on_method_add_block",
p.dispatch("on_command_call", $1, p.intern("::"), $3, $4),
$5);
}
| keyword_super command_args {
$$ = p.dispatch("on_super", $2);
}
| keyword_yield command_args {
$$ = p.dispatch("on_yield", $2);
}
| keyword_return call_args {
$$ = p.dispatch("on_return", $2);
}
| keyword_break call_args {
$$ = p.dispatch("on_break", $2);
}
| keyword_next call_args {
$$ = p.dispatch("on_next", $2);
}
// MultipleAssigNode:mlhs - [!null]
mlhs : mlhs_basic
| tLPAREN mlhs_inner rparen {
$$ = p.dispatch("on_mlhs_paren", $2);
}
// MultipleAssignNode:mlhs_entry - mlhs w or w/o parens [!null]
mlhs_inner : mlhs_basic
| tLPAREN mlhs_inner rparen {
$$ = p.dispatch("on_mlhs_paren", $2);
}
// MultipleAssignNode:mlhs_basic - multiple left hand side (basic because used in multiple context) [!null]
mlhs_basic : mlhs_head {
$$ = $1;
}
| mlhs_head mlhs_item {
$$ = p.dispatch("on_mlhs_add", $1, $2);
}
| mlhs_head tSTAR mlhs_node {
$$ = p.dispatch("on_mlhs_add_star", $1, $3);
}
| mlhs_head tSTAR mlhs_node ',' mlhs_post {
$$ = p.dispatch("on_mlhs_add_post",
p.dispatch("on_mlhs_add_star", $1, $3),
$5);
}
| mlhs_head tSTAR {
$$ = p.dispatch("on_mlhs_add_star", $1, null);
}
| mlhs_head tSTAR ',' mlhs_post {
$$ = p.dispatch("on_mlhs_add_post",
p.dispatch("on_mlhs_add_star", $1, null),
$4);
}
| tSTAR mlhs_node {
$$ = p.dispatch("on_mlhs_add_star", p.dispatch("on_mlhs_new"), $2);
}
| tSTAR mlhs_node ',' mlhs_post {
$$ = p.dispatch("on_mlhs_add_post",
p.dispatch("on_mlhs_add_star", p.dispatch("on_mlhs_new"), $2),
$4);
}
| tSTAR {
$$ = p.dispatch("on_mlhs_add_star", p.dispatch("on_mlhs_new"), null);
}
| tSTAR ',' mlhs_post {
$$ = p.dispatch("on_mlhs_add_post",
p.dispatch("on_mlhs_add_star", p.dispatch("on_mlhs_new"), null),
$3);
}
mlhs_item : mlhs_node
| tLPAREN mlhs_inner rparen {
$$ = p.dispatch("on_mlhs_paren", $2);
}
// Set of mlhs terms at front of mlhs (a, *b, d, e = arr # a is head)
mlhs_head : mlhs_item ',' {
$$ = p.dispatch("on_mlhs_add", p.dispatch("on_mlhs_new"), $1);
}
| mlhs_head mlhs_item ',' {
$$ = p.dispatch("on_mlhs_add", $1, $2);
}
// Set of mlhs terms at end of mlhs (a, *b, d, e = arr # d,e is post)
mlhs_post : mlhs_item {
$$ = p.dispatch("on_mlhs_add", p.dispatch("on_mlhs_new"), $1);
}
| mlhs_post ',' mlhs_item {
$$ = p.dispatch("on_mlhs_add", $1, $3);
}
mlhs_node : /*mri:user_variable*/ tIDENTIFIER {
$$ = p.assignableIdentifier(p.dispatch("on_var_field", $1));
}
| tIVAR {
$$ = p.dispatch("on_var_field", $1);
}
| tGVAR {
$$ = p.dispatch("on_var_field", $1);
}
| tCONSTANT {
$$ = p.assignableConstant(p.dispatch("on_var_field", $1));
}
| tCVAR {
$$ = p.dispatch("on_var_field", $1);
} /*mri:user_variable*/
| /*mri:keyword_variable*/ keyword_nil {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword_self {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword_true {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword_false {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword__FILE__ {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword__LINE__ {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword__ENCODING__ {
p.yyerror("Can't assign to __ENCODING__");
} /*mri:keyword_variable*/
| primary_value '[' opt_call_args rbracket {
$$ = p.dispatch("on_aref_field", $1, $3);
}
| primary_value call_op tIDENTIFIER {
$$ = p.dispatch("on_field", $1, $2, $3);
}
| primary_value tCOLON2 tIDENTIFIER {
$$ = p.dispatch("on_const_path_field", $1, $3);
}
| primary_value call_op tCONSTANT {
$$ = p.dispatch("on_field", $1, $2, $3);
}
| primary_value tCOLON2 tCONSTANT {
$$ = p.dispatch("on_const_path_field", $1, $3);
if (p.isInDef()) {
$$ = p.dispatch("on_assign_error", $$);
p.error();
}
}
| tCOLON3 tCONSTANT {
$$ = p.dispatch("on_top_const_field", $2);
if (p.isInDef()) {
$$ = p.dispatch("on_assign_error", $$);
p.error();
}
}
| backref {
$$ = p.dispatch("on_assign_error", p.dispatch("on_var_field", $1));
p.error();
}
lhs : /*mri:user_variable*/ tIDENTIFIER {
$$ = p.dispatch("on_var_field", p.assignableIdentifier($1));
}
| tIVAR {
$$ = p.dispatch("on_var_field", $1);
}
| tGVAR {
$$ = p.dispatch("on_var_field", $1);
}
| tCONSTANT {
$$ = p.assignableConstant(p.dispatch("on_var_field", $1));
}
| tCVAR {
$$ = p.dispatch("on_var_field", $1);
} /*mri:user_variable*/
| /*mri:keyword_variable*/ keyword_nil {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword_self {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword_true {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword_false {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword__FILE__ {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword__LINE__ {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
}
| keyword__ENCODING__ {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
} /*mri:keyword_variable*/
| primary_value '[' opt_call_args rbracket {
$$ = p.dispatch("on_aref_field", $1, $3);
}
| primary_value call_op tIDENTIFIER {
$$ = p.dispatch("on_field", $1, $2, $3);
}
| primary_value tCOLON2 tIDENTIFIER {
$$ = p.dispatch("on_field", $1, p.intern("::"), $3);
}
| primary_value call_op tCONSTANT {
$$ = p.dispatch("on_field", $1, $2, $3);
}
| primary_value tCOLON2 tCONSTANT {
IRubyObject val = p.dispatch("on_const_path_field", $1, $3);
if (p.isInDef()) {
val = p.dispatch("on_assign_error", val);
p.error();
}
$$ = val;
}
| tCOLON3 tCONSTANT {
IRubyObject val = p.dispatch("on_top_const_field", $2);
if (p.isInDef()) {
val = p.dispatch("on_assign_error", val);
p.error();
}
$$ = val;
}
| backref {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_var_field", $1));
p.error();
}
cname : tIDENTIFIER {
$$ = p.dispatch("on_class_name_error", $1);
p.error();
}
| tCONSTANT
cpath : tCOLON3 cname {
$$ = p.dispatch("on_top_const_ref", $2);
}
| cname {
$$ = p.dispatch("on_const_ref", $1);
}
| primary_value tCOLON2 cname {
$$ = p.dispatch("on_const_path_ref", $1, $3);
}
// Token:fname - A function name [!null]
fname : tIDENTIFIER | tCONSTANT | tFID
| op {
p.setState(EXPR_ENDFN);
$$ = $1;
}
| reswords {
p.setState(EXPR_ENDFN);
$$ = $1;
}
// LiteralNode:fsym
fsym : fname {
$$ = $1;
}
| symbol {
$$ = $1;
}
// Node:fitem
fitem : fsym {
$$ = p.dispatch("on_symbol_literal", $1);
}
| dsym {
$$ = $1;
}
undef_list : fitem {
$$ = p.new_array($1);
}
| undef_list ',' {
p.setState(EXPR_FNAME|EXPR_FITEM);
} fitem {
$$ = $1.append($4);
}
// Token:op
op : tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ | tMATCH
| tNMATCH | tGT | tGEQ | tLT | tLEQ | tNEQ | tLSHFT | tRSHFT
| tPLUS | tMINUS | tSTAR2 | tSTAR | tDIVIDE | tPERCENT | tPOW
| tBANG | tTILDE | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
// Token:op
reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_BEGIN | keyword_END
| keyword_alias | keyword_and | keyword_begin | keyword_break | keyword_case | keyword_class | keyword_def
| keyword_defined | keyword_do | keyword_else | keyword_elsif | keyword_end | keyword_ensure | keyword_false
| keyword_for | keyword_in | keyword_module | keyword_next | keyword_nil | keyword_not
| keyword_or | keyword_redo | keyword_rescue | keyword_retry | keyword_return | keyword_self | keyword_super
| keyword_then | keyword_true | keyword_undef | keyword_when | keyword_yield
| keyword_if | keyword_unless | keyword_while | keyword_until
| modifier_if | modifier_unless | modifier_while | modifier_until | modifier_rescue
arg : lhs '=' arg_rhs {
$$ = p.dispatch("on_assign", $1, $3);
}
| var_lhs tOP_ASGN arg_rhs {
$$ = p.dispatch("on_opassign", $1, $2, $3);
}
| primary_value '[' opt_call_args rbracket tOP_ASGN arg {
$$ = p.dispatch("on_opassign",
p.dispatch("on_aref_field", $1, $3),
$5, $6);
}
| primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs {
$$ = p.dispatch("on_opassign",
p.dispatch("on_field", $1, $2, $3),
$4, $5);
}
| primary_value call_op tCONSTANT tOP_ASGN arg_rhs {
$$ = p.dispatch("on_opassign",
p.dispatch("on_field", $1, $2, $3),
$4, $5);
}
| primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs {
$$ = p.dispatch("on_opassign",
p.dispatch("on_field", $1, p.intern("::"), $3),
$4, $5);
}
| primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_opassign",
p.dispatch("on_const_path_field", $1, $3),
$4, $5));
}
| tCOLON3 tCONSTANT tOP_ASGN arg_rhs {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_opassign",
p.dispatch("on_top_const_field", $2),
$3, $4));
}
| backref tOP_ASGN arg_rhs {
$$ = p.dispatch("on_assign_error",
p.dispatch("on_opassign",
p.dispatch("on_var_field", $1),
$2, $3));
p.error();
}
| arg tDOT2 arg {
$$ = p.dispatch("on_dot2", $1, $3);
}
| arg tDOT3 arg {
$$ = p.dispatch("on_dot3", $1, $3);
}
| arg tPLUS arg {
$$ = p.dispatch("on_binary", $1, p.intern("+"), $3);
}
| arg tMINUS arg {
$$ = p.dispatch("on_binary", $1, p.intern("-"), $3);
}
| arg tSTAR2 arg {
$$ = p.dispatch("on_binary", $1, p.intern("*"), $3);
}
| arg tDIVIDE arg {
$$ = p.dispatch("on_binary", $1, p.intern("/"), $3);
}
| arg tPERCENT arg {
$$ = p.dispatch("on_binary", $1, p.intern("%"), $3);
}
| arg tPOW arg {
$$ = p.dispatch("on_binary", $1, p.intern("**"), $3);
}
| tUMINUS_NUM simple_numeric tPOW arg {
$$ = p.dispatch("on_unary",
p.intern("-@"),
p.dispatch("on_binary", $2, p.intern("**"), $4));
}
| tUPLUS arg {
$$ = p.dispatch("on_unary", p.intern("+@"), $2);
}
| tUMINUS arg {
$$ = p.dispatch("on_unary", p.intern("-@"), $2);
}
| arg tPIPE arg {
$$ = p.dispatch("on_binary", $1, p.intern("|"), $3);
}
| arg tCARET arg {
$$ = p.dispatch("on_binary", $1, p.intern("^"), $3);
}
| arg tAMPER2 arg {
$$ = p.dispatch("on_binary", $1, p.intern("&"), $3);
}
| arg tCMP arg {
$$ = p.dispatch("on_binary", $1, p.intern("<=>"), $3);
}
| rel_expr %prec tCMP {
$$ = $1;
}
| arg tEQ arg {
$$ = p.dispatch("on_binary", $1, p.intern("=="), $3);
}
| arg tEQQ arg {
$$ = p.dispatch("on_binary", $1, p.intern("==="), $3);
}
| arg tNEQ arg {
$$ = p.dispatch("on_binary", $1, p.intern("!="), $3);
}
| arg tMATCH arg {
$$ = p.dispatch("on_binary", $1, p.intern("=~"), $3);
}
| arg tNMATCH arg {
$$ = p.dispatch("on_binary", $1, p.intern("!~"), $3);
}
| tBANG arg {
$$ = p.dispatch("on_unary", p.intern("!"), $2);
}
| tTILDE arg {
$$ = p.dispatch("on_unary", p.intern("~"), $2);
}
| arg tLSHFT arg {
$$ = p.dispatch("on_binary", $1, p.intern("<<"), $3);
}
| arg tRSHFT arg {
$$ = p.dispatch("on_binary", $1, p.intern(">>"), $3);
}
| arg tANDOP arg {
$$ = p.dispatch("on_binary", $1, p.intern("&&"), $3);
}
| arg tOROP arg {
$$ = p.dispatch("on_binary", $1, p.intern("||"), $3);
}
| keyword_defined opt_nl arg {
$$ = p.dispatch("on_defined", $3);
}
| arg '?' arg opt_nl ':' arg {
$$ = p.dispatch("on_ifop", $1, $3, $6);
}
| primary {
$$ = $1;
}
relop : tGT {
$$ = $1;
}
| tLT {
$$ = $1;
}
| tGEQ {
$$ = $1;
}
| tLEQ {
$$ = $1;
}
rel_expr : arg relop arg %prec tGT {
$$ = p.dispatch("on_binary", $1, p.intern(">"), $3);
}
| rel_expr relop arg %prec tGT {
p.warning("comparison '" + $2 + "' after comparison");
$$ = p.dispatch("on_binary", $1, p.intern(">"), $3);
}
arg_value : arg {
$$ = $1;
}
aref_args : none
| args trailer {
$$ = $1;
}
| args ',' assocs trailer {
$$ = p.dispatch("on_args_add",
$1,
p.dispatch("on_bare_assoc_hash", $3));
}
| assocs trailer {
$$ = p.dispatch("on_args_add",
p.dispatch("on_args_new"),
p.dispatch("on_bare_assoc_hash", $1));
}
arg_rhs : arg %prec tOP_ASGN {
$$ = $1;
}
| arg modifier_rescue arg {
$$ = p.dispatch("on_rescue_mod", $1, $3);
}
paren_args : tLPAREN2 opt_call_args rparen {
$$ = p.dispatch("on_arg_paren", $2);
}
opt_paren_args : none | paren_args
opt_call_args : none
| call_args
| args ',' {
$$ = $1;
}
| args ',' assocs ',' {
$$ = p.dispatch("on_args_add", $1, p.dispatch("on_bare_assoc_hash", $3));
}
| assocs ',' {
$$ = p.dispatch("on_args_add",
p.dispatch("on_args_new"),
p.dispatch("on_bare_assoc_hash", $1));
}
// [!null]
call_args : command {
$$ = p.dispatch("on_args_add", p.dispatch("on_args_new"), $1);
}
| args opt_block_arg {
$$ = p.arg_add_optblock($1, $2);
}
| assocs opt_block_arg {
$$ = p.arg_add_optblock(p.dispatch("on_args_add",
p.dispatch("on_args_new"),
p.dispatch("on_bare_assoc_hash", $1)),
$2);
}
| args ',' assocs opt_block_arg {
$$ = p.arg_add_optblock(p.dispatch("on_args_add",
$1,
p.dispatch("on_bare_assoc_hash", $3)),
$4);
}
| block_arg {
$$ = p.dispatch("on_args_add_block", p.dispatch("on_args_new"), $1);
}
command_args : /* none */ {
$$ = Long.valueOf(p.getCmdArgumentState().getStack());
p.getCmdArgumentState().begin();
} call_args {
p.getCmdArgumentState().reset($1.longValue());
$$ = $2;
}
block_arg : tAMPER arg_value {
$$ = $2;
}
opt_block_arg : ',' block_arg {
$$ = $2;
}
| none_block_pass
// [!null]
args : arg_value {
$$ = p.dispatch("on_args_add", p.dispatch("on_args_new"), $1);
}
| tSTAR arg_value {
$$ = p.dispatch("on_args_add_star", p.dispatch("on_args_new"), $2);
}
| args ',' arg_value {
$$ = p.dispatch("on_args_add", $1, $3);
}
| args ',' tSTAR arg_value {
$$ = p.dispatch("on_args_add_star", $1, $4);
}
mrhs_arg : mrhs {
$$ = $1;
}
| arg_value {
$$ = $1;
}
mrhs : args ',' arg_value {
$$ = p.dispatch("on_mrhs_add",
p.dispatch("on_mrhs_new_from_args", $1),
$3);
}
| args ',' tSTAR arg_value {
$$ = p.dispatch("on_mrhs_add_star",
p.dispatch("on_mrhs_new_from_args", $1),
$4);
}
| tSTAR arg_value {
$$ = p.dispatch("on_mrhs_add_star", p.dispatch("on_mrhs_new"), $2);
}
primary : literal
| strings
| xstring
| regexp
| words
| qwords
| symbols {
$$ = $1; // FIXME: Why complaining without $$ = $1;
}
| qsymbols {
$$ = $1; // FIXME: Why complaining without $$ = $1;
}
| var_ref
| backref
| tFID {
$$ = p.dispatch("on_method_add_arg", p.dispatch("on_fcall", $1), p.dispatch("on_args_new"));
}
| keyword_begin {
$$ = p.getCmdArgumentState().getStack();
p.getCmdArgumentState().reset();
} bodystmt keyword_end {
p.getCmdArgumentState().reset($2.longValue());
$$ = p.dispatch("on_begin", $3);
}
| tLPAREN_ARG {
p.setState(EXPR_ENDARG);
} rparen {
$$ = p.dispatch("on_paren", null);
}
| tLPAREN_ARG {
$$ = p.getCmdArgumentState().getStack();
p.getCmdArgumentState().reset();
} stmt {
p.setState(EXPR_ENDARG);
} rparen {
p.getCmdArgumentState().reset($2.longValue());
p.warning("(...) interpreted as grouped expression");
$$ = p.dispatch("on_paren", $3);
}
| tLPAREN compstmt tRPAREN {
$$ = p.dispatch("on_paren", $2);
}
| primary_value tCOLON2 tCONSTANT {
$$ = p.dispatch("on_const_path_ref", $1, $3);
}
| tCOLON3 tCONSTANT {
$$ = p.dispatch("on_top_const_ref", $2);
}
| tLBRACK aref_args tRBRACK {
$$ = p.dispatch("on_array", $2);
}
| tLBRACE assoc_list tRCURLY {
$$ = p.dispatch("on_hash", $2);
}
| keyword_return {
$$ = p.dispatch("on_return0");
}
| keyword_yield tLPAREN2 call_args rparen {
$$ = p.dispatch("on_yield", p.dispatch("on_paren", $3));
}
| keyword_yield tLPAREN2 rparen {
$$ = p.dispatch("on_yield", p.dispatch("on_paren", p.dispatch("on_args_new")));
}
| keyword_yield {
$$ = p.dispatch("on_yield0");
}
| keyword_defined opt_nl tLPAREN2 expr rparen {
$$ = p.dispatch("on_defined", $4);
}
| keyword_not tLPAREN2 expr rparen {
$$ = p.dispatch("on_unary", p.intern("not"), $3);
}
| keyword_not tLPAREN2 rparen {
$$ = p.dispatch("on_unary", p.intern("not"), null);
}
| fcall brace_block {
$$ = p.dispatch("on_method_add_block",
p.dispatch("on_method_add_arg",
p.dispatch("on_fcall", $1),
p.dispatch("on_args_new")),
$2);
}
| method_call
| method_call brace_block {
$$ = p.dispatch("on_method_add_block", $1, $2);
}
| tLAMBDA lambda {
$$ = $2;
}
| keyword_if expr_value then compstmt if_tail keyword_end {
$$ = p.dispatch("on_if", $2, $4, $5);
}
| keyword_unless expr_value then compstmt opt_else keyword_end {
$$ = p.dispatch("on_unless", $2, $4, $5);
}
| keyword_while {
p.getConditionState().begin();
} expr_value do {
p.getConditionState().end();
} compstmt keyword_end {
$$ = p.dispatch("on_while", $3, $6);
}
| keyword_until {
p.getConditionState().begin();
} expr_value do {
p.getConditionState().end();
} compstmt keyword_end {
$$ = p.dispatch("on_until", $3, $6);
}
| keyword_case expr_value opt_terms case_body keyword_end {
$$ = p.dispatch("on_case", $2, $4);
}
| keyword_case opt_terms case_body keyword_end {
$$ = p.dispatch("on_case", null, $3);
}
| keyword_for for_var keyword_in {
p.getConditionState().begin();
} expr_value do {
p.getConditionState().end();
} compstmt keyword_end {
$$ = p.dispatch("on_for", $2, $5, $8);
}
| keyword_class cpath superclass {
if (p.isInDef()) {
p.yyerror("class definition in method body");
}
p.pushLocalScope();
$$ = p.isInClass(); // MRI reuses $1 but we use the value for position.
p.setIsInClass(true);
} bodystmt keyword_end {
$$ = p.dispatch("on_class", $2, $3, $5);
p.popCurrentScope();
p.setIsInClass($4.booleanValue());
}
| keyword_class tLSHFT expr {
$$ = new Integer((p.isInClass() ? 2 : 0) & (p.isInDef() ? 1 : 0));
p.setInDef(false);
p.setIsInClass(false);
p.pushLocalScope();
} term bodystmt keyword_end {
$$ = p.dispatch("on_sclass", $3, $6);
p.popCurrentScope();
p.setInDef((($4.intValue()) & 1) != 0);
p.setIsInClass((($4.intValue()) & 2) != 0);
}
| keyword_module cpath {
if (p.isInDef()) {
p.yyerror("module definition in method body");
}
$$ = p.isInClass();
p.setIsInClass(true);
p.pushLocalScope();
} bodystmt keyword_end {
$$ = p.dispatch("on_module", $2, $4);
p.popCurrentScope();
}
| keyword_def fname {
p.setInDef(true);
p.pushLocalScope();
$$ = p.getCurrentArg();
p.setCurrentArg(null);
} f_arglist bodystmt keyword_end {
$$ = p.dispatch("on_def", $2, $4, $5);
p.popCurrentScope();
p.setInDef(false);
p.setCurrentArg($3);
}
| keyword_def singleton dot_or_colon {
p.setState(EXPR_FNAME);
$$ = p.isInDef();
p.setInDef(true);
} fname {
p.pushLocalScope();
p.setState(EXPR_ENDFN|EXPR_LABEL); /* force for args */
$$ = p.getCurrentArg();
p.setCurrentArg(null);
} f_arglist bodystmt keyword_end {
$$ = p.dispatch("on_defs", $2, $3, $5, $7, $8);
p.popCurrentScope();
p.setInDef($4.booleanValue());
p.setCurrentArg($6);
}
| keyword_break {
$$ = p.dispatch("on_break", p.dispatch("on_args_new"));
}
| keyword_next {
$$ = p.dispatch("on_next", p.dispatch("on_args_new"));
}
| keyword_redo {
$$ = p.dispatch("on_redo");
}
| keyword_retry {
$$ = p.dispatch("on_retry");
}
primary_value : primary {
$$ = $1;
}
then : term {
$$ = null;
}
| keyword_then
| term keyword_then {
$$ = $2;
}
do : term {
$$ = null;
}
| keyword_do_cond
if_tail : opt_else
| keyword_elsif expr_value then compstmt if_tail {
$$ = p.dispatch("on_elsif", $2, $4, $5);
}
opt_else : none
| keyword_else compstmt {
$$ = p.dispatch("on_else", $2);
}
for_var : lhs
| mlhs {
}
f_marg : f_norm_arg {
$$ = $1;
}
| tLPAREN f_margs rparen {
$$ = p.dispatch("on_mlhs_paren", $2);
}
// [!null]
f_marg_list : f_marg {
$$ = p.dispatch("on_mlhs_add", p.dispatch("on_mlhs_new"), $1);
}
| f_marg_list ',' f_marg {
$$ = p.dispatch("on_mlhs_add", $1, $3);
}
f_margs : f_marg_list {
$$ = $1;
}
| f_marg_list ',' tSTAR f_norm_arg {
$$ = p.dispatch("on_mlhs_add_star", $1, $4);
}
| f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list {
$$ = p.dispatch("on_mlhs_add_post",
p.dispatch("on_mlhs_add_star", $1, $4),
$6);
}
| f_marg_list ',' tSTAR {
$$ = p.dispatch("on_mlhs_add_star", $1, null);
}
| f_marg_list ',' tSTAR ',' f_marg_list {
$$ = p.dispatch("on_mlhs_add_post",
p.dispatch("on_mlhs_add_star", $1, null),
$5);
}
| tSTAR f_norm_arg {
$$ = p.dispatch("on_mlhs_add_star",
p.dispatch("on_mlhs_new"),
$2);
}
| tSTAR f_norm_arg ',' f_marg_list {
$$ = p.dispatch("on_mlhs_add_post",
p.dispatch("on_mlhs_add_star",
p.dispatch("on_mlhs_new"),
$2),
$4);
}
| tSTAR {
$$ = p.dispatch("on_mlhs_add_star",
p.dispatch("on_mlhs_new"),
null);
}
| tSTAR ',' f_marg_list {
$$ = p.dispatch("on_mlhs_add_post",
p.dispatch("on_mlhs_add_star",
p.dispatch("on_mlhs_new"),
null),
$3);
}
block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg {
$$ = p.new_args_tail($1, $3, $4);
}
| f_block_kwarg opt_f_block_arg {
$$ = p.new_args_tail($1, null, $2);
}
| f_kwrest opt_f_block_arg {
$$ = p.new_args_tail(null, $1, $2);
}
| f_block_arg {
$$ = p.new_args_tail(null, null, $1);
}
opt_block_args_tail : ',' block_args_tail {
$$ = $2;
}
| /* none */ {
$$ = p.new_args_tail(null, null, null);
}
// [!null]
block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail {
$$ = p.new_args($1, $3, $5, null, $6);
}
| f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail {
$$ = p.new_args($1, $3, $5, $7, $8);
}
| f_arg ',' f_block_optarg opt_block_args_tail {
$$ = p.new_args($1, $3, null, null, $4);
}
| f_arg ',' f_block_optarg ',' f_arg opt_block_args_tail {
$$ = p.new_args($1, $3, null, $5, $6);
}
| f_arg ',' f_rest_arg opt_block_args_tail {
$$ = p.new_args($1, null, $3, null, $4);
}
| f_arg ',' {
$$ = p.dispatch("on_excessed_comma",
p.new_args($1, null, null, null, null));
}
| f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail {
$$ = p.new_args($1, null, $3, $5, $6);
}
| f_arg opt_block_args_tail {
$$ = p.new_args($1, null, null, null, $2);
}
| f_block_optarg ',' f_rest_arg opt_block_args_tail {
$$ = p.new_args(null, $1, $3, null, $4);
}
| f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail {
$$ = p.new_args(null, $1, $3, $5, $6);
}
| f_block_optarg opt_block_args_tail {
$$ = p.new_args(null, $1, null, null, $2);
}
| f_block_optarg ',' f_arg opt_block_args_tail {
$$ = p.new_args(null, $1, null, $3, $4);
}
| f_rest_arg opt_block_args_tail {
$$ = p.new_args(null, null, $1, null, $2);
}
| f_rest_arg ',' f_arg opt_block_args_tail {
$$ = p.new_args(null, null, $1, $3, $4);
}
| block_args_tail {
$$ = p.new_args(null, null, null, null, $1);
}
opt_block_param : none
| block_param_def {
p.setCommandStart(true);
}
block_param_def : tPIPE opt_bv_decl tPIPE {
p.setCurrentArg(null);
$$ = p.dispatch("on_block_var",
p.new_args(null, null, null, null, null),
$2);
}
| tOROP {
$$ = p.dispatch("on_block_var",
p.new_args(null, null, null, null, null),
null);
}
| tPIPE block_param opt_bv_decl tPIPE {
p.setCurrentArg(null);
$$ = p.dispatch("on_block_var", $2, $3);
}
// shadowed block variables....
opt_bv_decl : opt_nl {
$$ = p.getContext().getRuntime().getFalse();
}
| opt_nl ';' bv_decls opt_nl {
$$ = $3;
}
// ENEBO: This is confusing...
bv_decls : bvar {
$$ = p.new_array($1);
}
| bv_decls ',' bvar {
$$ = $1.append($3);
}
bvar : tIDENTIFIER {
$$ = p.new_bv($1);
}
| f_bad_arg {
$$ = null;
}
lambda : /* none */ {
p.pushBlockScope();
$$ = p.getLeftParenBegin();
p.setLeftParenBegin(p.incrementParenNest());
} f_larglist {
$$ = Long.valueOf(p.getCmdArgumentState().getStack());
p.getCmdArgumentState().reset();
} lambda_body {
p.getCmdArgumentState().reset($3.longValue());
p.getCmdArgumentState().restart();
$$ = p.dispatch("on_lambda", $2, $4);
p.setLeftParenBegin($1);
p.popCurrentScope();
}
f_larglist : tLPAREN2 f_args opt_bv_decl tRPAREN {
$$ = p.dispatch("on_paren", $2);
}
| f_args {
$$ = $1;
}
lambda_body : tLAMBEG compstmt tRCURLY {
$$ = $2;
}
| keyword_do_lambda compstmt keyword_end {
$$ = $2;
}
do_block : keyword_do_block do_body keyword_end {
$$ = $2;
}
block_call : command do_block {
$$ = p.dispatch("on_method_add_block", $1, $2);
}
| block_call call_op2 operation2 opt_paren_args {
$$ = p.method_optarg(p.dispatch("on_call", $1, $2, $3), $4);
}
| block_call call_op2 operation2 opt_paren_args brace_block {
$$ = p.method_add_block(p.dispatch("on_command_call", $1, $2, $3, $4), $5);
}
| block_call call_op2 operation2 command_args do_block {
$$ = p.method_add_block(p.dispatch("on_command_call", $1, $2, $3, $4), $5);
}
// [!null]
method_call : fcall paren_args {
$$ = p.dispatch("on_method_add_arg", p.dispatch("on_fcall", $1), $2);
}
| primary_value call_op operation2 opt_paren_args {
$$ = p.method_optarg(p.dispatch("on_call", $1, $2, $3), $4);
}
| primary_value tCOLON2 operation2 paren_args {
$$ = p.method_optarg(p.dispatch("on_call", $1, p.intern("::"), $3), $4);
}
| primary_value tCOLON2 operation3 {
$$ = p.dispatch("on_call", $1, p.intern("::"), $3);
}
| primary_value call_op paren_args {
$$ = p.method_optarg(p.dispatch("on_call", $1, $2, p.intern("call")), $3);
}
| primary_value tCOLON2 paren_args {
$$ = p.method_optarg(p.dispatch("on_call", $1, p.intern("::"), p.intern("call")), $3);
}
| keyword_super paren_args {
$$ = p.dispatch("on_super", $2);
}
| keyword_super {
$$ = p.dispatch("on_zsuper");
}
| primary_value '[' opt_call_args rbracket {
$$ = p.dispatch("on_aref", $1, $3);
}
brace_block : tLCURLY brace_body tRCURLY {
$$ = $2;
}
| keyword_do {
p.pushBlockScope();
$$ = Long.valueOf(p.getCmdArgumentState().getStack());
p.getCmdArgumentState().reset();
} opt_block_param compstmt keyword_end {
$$ = p.dispatch("on_do_block", $3, $4);
p.getCmdArgumentState().reset($2.longValue());
p.popCurrentScope();
}
brace_body : {
p.pushBlockScope();
$$ = Long.valueOf(p.getCmdArgumentState().getStack()) >> 1;
p.getCmdArgumentState().reset();
} opt_block_param compstmt {
$$ = p.dispatch("on_brace_block", $2, $3);
p.getCmdArgumentState().reset($1.longValue());
p.popCurrentScope();
}
do_body : {
p.pushBlockScope();
$$ = Long.valueOf(p.getCmdArgumentState().getStack());
p.getCmdArgumentState().reset();
} opt_block_param bodystmt {
$$ = p.dispatch("on_do_block", $2, $3);
p.getCmdArgumentState().reset($1.longValue());
p.popCurrentScope();
}
case_body : keyword_when args then compstmt cases {
$$ = p.dispatch("on_when", $2, $4, $5);
}
cases : opt_else | case_body
opt_rescue : keyword_rescue exc_list exc_var then compstmt opt_rescue {
$$ = p.dispatch("on_rescue", $2, $3, $5, $6);
}
| {
$$ = null;
}
exc_list : arg_value {
$$ = p.new_array($1);
}
| mrhs {
$$ = $1;
}
| none
exc_var : tASSOC lhs {
$$ = $2;
}
| none
opt_ensure : keyword_ensure compstmt {
$$ = p.dispatch("on_ensure", $2);
}
| none
literal : numeric
| symbol {
$$ = p.dispatch("on_symbol_literal", $1);
}
| dsym
strings : string {
$$ = $1;
}
// [!null]
string : tCHAR {
$$ = $1;
}
| string1 {
$$ = $1;
}
| string string1 {
$$ = p.dispatch("on_string_concat", $1, $2);
}
string1 : tSTRING_BEG string_contents tSTRING_END {
p.heredoc_dedent($2);
p.setHeredocIndent(0);
$$ = p.dispatch("on_string_literal", $2);
}
xstring : tXSTRING_BEG xstring_contents tSTRING_END {
p.heredoc_dedent($2);
p.setHeredocIndent(0);
$$ = p.dispatch("on_xstring_literal", $2);
}
regexp : tREGEXP_BEG regexp_contents tREGEXP_END {
$$ = p.dispatch("on_regexp_literal", $2, $3);
}
words : tWORDS_BEG ' ' word_list tSTRING_END {
$$ = p.dispatch("on_array", $3);
}
word_list : /* none */ {
$$ = p.dispatch("on_words_new");
}
| word_list word ' ' {
$$ = p.dispatch("on_words_add", $1, $2);
}
word : string_content {
$$ = p.dispatch("on_word_add", p.dispatch("on_word_new"), $1);
}
| word string_content {
$$ = p.dispatch("on_word_add", $1, $2);
}
symbols : tSYMBOLS_BEG ' ' symbol_list tSTRING_END {
$$ = p.dispatch("on_array", $3);
}
symbol_list : /* none */ {
$$ = p.dispatch("on_symbols_new");
}
| symbol_list word ' ' {
$$ = p.dispatch("on_symbols_add", $1, $2);
}
qwords : tQWORDS_BEG ' ' qword_list tSTRING_END {
$$ = p.dispatch("on_array", $3);
}
qsymbols : tQSYMBOLS_BEG ' ' qsym_list tSTRING_END {
$$ = p.dispatch("on_array", $3);
}
qword_list : /* none */ {
$$ = p.dispatch("on_qwords_new");
}
| qword_list tSTRING_CONTENT ' ' {
$$ = p.dispatch("on_qwords_add", $1, $2);
}
qsym_list : /* none */ {
$$ = p.dispatch("on_qsymbols_new");
}
| qsym_list tSTRING_CONTENT ' ' {
$$ = p.dispatch("on_qsymbols_add", $1, $2);
}
string_contents : /* none */ {
$$ = p.dispatch("on_string_content");
}
| string_contents string_content {
$$ = p.dispatch("on_string_add", $1, $2);
}
xstring_contents: /* none */ {
$$ = p.dispatch("on_xstring_new");
}
| xstring_contents string_content {
$$ = p.dispatch("on_xstring_add", $1, $2);
}
regexp_contents: /* none */ {
$$ = p.dispatch("on_regexp_new");
}
| regexp_contents string_content {
$$ = p.dispatch("on_regexp_add", $1, $2);
}
string_content : tSTRING_CONTENT
| tSTRING_DVAR {
$$ = p.getStrTerm();
p.setStrTerm(null);
p.setState(EXPR_BEG);
} string_dvar {
p.setStrTerm($2);
$$ = p.dispatch("on_string_dvar", $3);
}
| tSTRING_DBEG {
$$ = p.getStrTerm();
p.setStrTerm(null);
p.getConditionState().stop();
} {
$$ = p.getCmdArgumentState().getStack();
p.getCmdArgumentState().reset();
} {
$$ = p.getState();
p.setState(EXPR_BEG);
} {
$$ = p.getBraceNest();
p.setBraceNest(0);
} {
$$ = p.getHeredocIndent();
p.setHeredocIndent(0);
} compstmt tSTRING_DEND {
p.getConditionState().restart();
p.setStrTerm($2);
p.getCmdArgumentState().reset($3.longValue());
p.setState($4);
p.setBraceNest($5);
p.setHeredocIndent($6);
$$ = p.dispatch("on_string_embexpr", $7);
}
string_dvar : tGVAR {
$$ = p.dispatch("on_var_ref", $1);
}
| tIVAR {
$$ = p.dispatch("on_var_ref", $1);
}
| tCVAR {
$$ = p.dispatch("on_var_ref", $1);
}
| backref
// Token:symbol
symbol : tSYMBEG sym {
p.setState(EXPR_END|EXPR_ENDARG);
$$ = p.dispatch("on_symbol", $2);
}
// Token:symbol
sym : fname | tIVAR | tGVAR | tCVAR
dsym : tSYMBEG xstring_contents tSTRING_END {
p.setState(EXPR_END|EXPR_ENDARG);
$$ = p.dispatch("on_dyna_symbol", $2);
}
numeric : simple_numeric {
$$ = $1;
}
| tUMINUS_NUM simple_numeric %prec tLOWEST {
$$ = p.dispatch("on_unary", p.intern("-@"), $2);
}
simple_numeric : tINTEGER {
$$ = $1;
}
| tFLOAT {
$$ = $1;
}
| tRATIONAL {
$$ = $1;
}
| tIMAGINARY {
$$ = $1;
}
// [!null]
var_ref : /*mri:user_variable*/ tIDENTIFIER {
if (p.is_id_var()) {
$$ = p.dispatch("on_var_ref", $1);
} else {
$$ = p.dispatch("on_vcall", $1);
}
}
| tIVAR {
$$ = p.dispatch("on_var_ref", $1);
}
| tGVAR {
$$ = p.dispatch("on_var_ref", $1);
}
| tCONSTANT {
$$ = p.dispatch("on_var_ref", $1);
}
| tCVAR {
$$ = p.dispatch("on_var_ref", $1);
} /*mri:user_variable*/
| /*mri:keyword_variable*/ keyword_nil {
$$ = p.dispatch("on_var_ref", $1);
}
| keyword_self {
$$ = p.dispatch("on_var_ref", $1);
}
| keyword_true {
$$ = p.dispatch("on_var_ref", $1);
}
| keyword_false {
$$ = p.dispatch("on_var_ref", $1);
}
| keyword__FILE__ {
$$ = p.dispatch("on_var_ref", $1);
}
| keyword__LINE__ {
$$ = p.dispatch("on_var_ref", $1);
}
| keyword__ENCODING__ {
$$ = p.dispatch("on_var_ref", $1);
} /*mri:keyword_variable*/
// [!null]
var_lhs : /*mri:user_variable*/ tIDENTIFIER {
$$ = p.dispatch("on_var_field", p.assignableIdentifier($1));
}
| tIVAR {
$$ = p.dispatch("on_var_field", $1);
}
| tGVAR {
$$ = p.dispatch("on_var_field", $1);
}
| tCONSTANT {
$$ = p.assignableConstant(p.dispatch("on_var_field", $1));
}
| tCVAR {
$$ = p.dispatch("on_var_field", $1);
} /*mri:user_variable*/
| /*mri:keyword_variable*/ keyword_nil {
p.yyerror("Can't assign to nil");
}
| keyword_self {
p.yyerror("Can't change the value of self");
}
| keyword_true {
p.yyerror("Can't assign to true");
}
| keyword_false {
p.yyerror("Can't assign to false");
}
| keyword__FILE__ {
p.yyerror("Can't assign to __FILE__");
}
| keyword__LINE__ {
p.yyerror("Can't assign to __LINE__");
}
| keyword__ENCODING__ {
p.yyerror("Can't assign to __ENCODING__");
} /*mri:keyword_variable*/
// [!null]
backref : tNTH_REF
| tBACK_REF
superclass : tLT {
p.setState(EXPR_BEG);
p.setCommandStart(true);
} expr_value term {
$$ = $3;
}
| /* none */ {
$$ = null;
}
// [!null]
// ENEBO: Look at command_start stuff I am ripping out
f_arglist : tLPAREN2 f_args rparen {
p.setState(EXPR_BEG);
p.setCommandStart(true);
$$ = p.dispatch("on_paren", $2);
}
| {
// $$ = lexer.inKwarg;
// p.inKwarg = true;
p.setState(p.getState() | EXPR_LABEL);
} f_args term {
// p.inKwarg = $1;
$$ = $2;
p.setState(EXPR_BEG);
p.setCommandStart(true);
}
args_tail : f_kwarg ',' f_kwrest opt_f_block_arg {
$$ = p.new_args_tail($1, $3, $4);
}
| f_kwarg opt_f_block_arg {
$$ = p.new_args_tail($1, null, $2);
}
| f_kwrest opt_f_block_arg {
$$ = p.new_args_tail(null, $1, $2);
}
| f_block_arg {
$$ = p.new_args_tail(null, null, $1);
}
opt_args_tail : ',' args_tail {
$$ = $2;
}
| /* none */ {
$$ = p.new_args_tail(null, null, null);
}
// [!null]
f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail {
$$ = p.new_args($1, $3, $5, null, $6);
}
| f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_args_tail {
$$ = p.new_args($1, $3, $5, $7, $8);
}
| f_arg ',' f_optarg opt_args_tail {
$$ = p.new_args($1, $3, null, null, $4);
}
| f_arg ',' f_optarg ',' f_arg opt_args_tail {
$$ = p.new_args($1, $3, null, $5, $6);
}
| f_arg ',' f_rest_arg opt_args_tail {
$$ = p.new_args($1, null, $3, null, $4);
}
| f_arg ',' f_rest_arg ',' f_arg opt_args_tail {
$$ = p.new_args($1, null, $3, $5, $6);
}
| f_arg opt_args_tail {
$$ = p.new_args($1, null, null, null, $2);
}
| f_optarg ',' f_rest_arg opt_args_tail {
$$ = p.new_args(null, $1, $3, null, $4);
}
| f_optarg ',' f_rest_arg ',' f_arg opt_args_tail {
$$ = p.new_args(null, $1, $3, $5, $6);
}
| f_optarg opt_args_tail {
$$ = p.new_args(null, $1, null, null, $2);
}
| f_optarg ',' f_arg opt_args_tail {
$$ = p.new_args(null, $1, null, $3, $4);
}
| f_rest_arg opt_args_tail {
$$ = p.new_args(null, null, $1, null, $2);
}
| f_rest_arg ',' f_arg opt_args_tail {
$$ = p.new_args(null, null, $1, $3, $4);
}
| args_tail {
$$ = p.new_args(null, null, null, null, $1);
}
| /* none */ {
$$ = p.new_args(null, null, null, null, null);
}
f_bad_arg : tCONSTANT {
$$ = p.dispatch("on_param_error", $1);
p.error();
}
| tIVAR {
$$ = p.dispatch("on_param_error", $1);
p.error();
}
| tGVAR {
$$ = p.dispatch("on_param_error", $1);
p.error();
}
| tCVAR {
$$ = p.dispatch("on_param_error", $1);
p.error();
}
// Token:f_norm_arg [!null]
f_norm_arg : f_bad_arg
| tIDENTIFIER {
$$ = p.arg_var(p.formal_argument($1));
}
f_arg_asgn : f_norm_arg {
p.setCurrentArg($1);
$$ = $1;
}
f_arg_item : f_arg_asgn {
p.setCurrentArg(null);
$$ = $1;
}
| tLPAREN f_margs rparen {
$$ = p.dispatch("on_mlhs_paren", $2);
}
// [!null]
f_arg : f_arg_item {
$$ = p.new_array($1);
}
| f_arg ',' f_arg_item {
$$ = $1.append($3);
}
f_label : tLABEL {
p.arg_var(p.formal_argument($1));
p.setCurrentArg($1);
$$ = $1;
}
f_kw : f_label arg_value {
p.setCurrentArg(null);
$$ = p.keyword_arg($1, $2);
}
| f_label {
p.setCurrentArg(null);
$$ = p.keyword_arg($1, p.getContext().getRuntime().getFalse());
}
f_block_kw : f_label primary_value {
$$ = p.keyword_arg($1, $2);
}
| f_label {
$$ = p.keyword_arg($1, p.getContext().getRuntime().getFalse());
}
f_block_kwarg : f_block_kw {
$$ = p.new_array($1);
}
| f_block_kwarg ',' f_block_kw {
$$ = $1.append($3);
}
f_kwarg : f_kw {
$$ = p.new_array($1);
}
| f_kwarg ',' f_kw {
$$ = $1.append($3);
}
kwrest_mark : tPOW {
$$ = $1;
}
| tDSTAR {
$$ = $1;
}
f_kwrest : kwrest_mark tIDENTIFIER {
p.shadowing_lvar($2);
$$ = p.dispatch("on_kwrest_param", $2);
}
| kwrest_mark {
$$ = p.dispatch("on_kwrest_param", null);
}
f_opt : f_arg_asgn '=' arg_value {
p.setCurrentArg(null);
$$ = p.new_assoc($1, $3);
}
f_block_opt : f_arg_asgn '=' primary_value {
p.setCurrentArg(null);
$$ = p.new_assoc($1, $3);
}
f_block_optarg : f_block_opt {
$$ = p.new_array($1);
}
| f_block_optarg ',' f_block_opt {
$$ = $1.append($3);
}
f_optarg : f_opt {
$$ = p.new_array($1);
}
| f_optarg ',' f_opt {
$$ = $1.append($3);
}
restarg_mark : tSTAR2 | tSTAR
// [!null]
f_rest_arg : restarg_mark tIDENTIFIER {
p.arg_var(p.shadowing_lvar($2));
$$ = p.dispatch("on_rest_param", $2);
}
| restarg_mark {
$$ = p.dispatch("on_rest_param", null);
}
// [!null]
blkarg_mark : tAMPER2 | tAMPER
// f_block_arg - Block argument def for function (foo(&block)) [!null]
f_block_arg : blkarg_mark tIDENTIFIER {
p.arg_var(p.shadowing_lvar($2));
$$ = p.dispatch("on_blockarg", $2);
}
opt_f_block_arg : ',' f_block_arg {
$$ = $2;
}
| /* none */ {
$$ = null;
}
singleton : var_ref {
$$ = $1;
}
| tLPAREN2 {
p.setState(EXPR_BEG);
} expr rparen {
$$ = p.dispatch("on_paren", $3);
}
// [!null]
assoc_list : none
| assocs trailer {
$$ = p.dispatch("on_assoclist_from_args", $1);
}
// [!null]
assocs : assoc {
$$ = p.new_array($1);
}
| assocs ',' assoc {
$$ = $1.append($3);
}
// [!null]
assoc : arg_value tASSOC arg_value {
$$ = p.dispatch("on_assoc_new", $1, $3);
}
| tLABEL arg_value {
$$ = p.dispatch("on_assoc_new", $1, $2);
}
| tSTRING_BEG string_contents tLABEL_END arg_value {
$$ = p.dispatch("on_assoc_new", p.dispatch("on_dyna_symbol", $2), $4);
}
| tDSTAR arg_value {
$$ = p.dispatch("on_assoc_splat", $2);
}
operation : tIDENTIFIER | tCONSTANT | tFID
operation2 : tIDENTIFIER | tCONSTANT | tFID | op
operation3 : tIDENTIFIER | tFID | op
dot_or_colon : tDOT {
$$ = $1;
}
| tCOLON2 {
$$ = $1;
}
call_op : tDOT {
$$ = p.intern(".");
}
| tANDDOT {
$$ = p.intern("&.");
}
call_op2 : call_op {
$$ = $1;
}
| tCOLON2 {
$$ = p.intern("::");
}
opt_terms : /* none */ | terms
opt_nl : /* none */ | '\n'
rparen : opt_nl tRPAREN {
$$ = $2;
}
rbracket : opt_nl tRBRACK {
$$ = $2;
}
trailer : /* none */ | '\n' | ','
term : ';'
| '\n'
terms : term
| terms ';'
none : /* none */ {
$$ = null;
}
none_block_pass : /* none */ {
$$ = null;
}
%%
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy