blob: b4b16358a0ef404946683f82c48127d62ddf0947 [file] [log] [blame]
grammar Ruby;
class DefaultRubyParser extends Parser;
options {
importVocab=Ruby;
}
program : /*{
lexer.setState(LexState.EXPR_BEG);
support.initTopLocalVariables();
}*/ compstmt /*{
if ($2 != null) {
// last expression should not be void
if ($2 instanceof BlockNode) {
support.checkUselessStatement($<BlockNode>2.getLast());
} else {
support.checkUselessStatement($2);
}
}
support.getResult().seAST(support.addRootNode($2));
}*/
;
bodystmt : compstmt opt_rescue opt_else opt_ensure /*{
Node node = $1;
if ($2 != null) {
node = new RescueNode(getPosition($1, true), $1, $2, $3);
} else if ($3 != null) {
warnings.warn(getPosition($1), "else without rescue is useless");
node = support.appendToBlock($1, $3);
}
if ($4 != null) {
node = new EnsureNode(getPosition($1), node, $4);
}
$$ = node;
}*/
;
compstmt : stmts opt_terms /*{
if ($1 instanceof BlockNode) {
support.checkUselessStatements($<BlockNode>1);
}
$$ = $1;
}*/
;
stmts : none
| stmt /*{
$$ = support.newline_node($1, getPosition($1, true));
}*/
| stmts terms stmt /*{
$$ = support.appendToBlock($1, support.newline_node($3, getPosition($3, true)));
}*/
/*| error stmt {
$$ = $2;
}*/
;
stmt : ALIAS fitem /*{
lexer.setState(LexState.EXPR_FNAME);
}*/ fitem /*{
$$ = new AliasNode(support.union($1, $4), (String) $2.getValue(), (String) $4.getValue());
}*/
| ALIAS GVAR GVAR /*{
$$ = new VAliasNode(getPosition($1), (String) $2.getValue(), (String) $3.getValue());
}*/
| ALIAS GVAR BACK_REF /*{
$$ = new VAliasNode(getPosition($1), (String) $2.getValue(), "$" + $<BackRefNode>3.getType()); // XXX
}*/
| ALIAS GVAR NTH_REF /*{
yyerror("can't make alias for the number variables");
}*/
| UNDEF undef_list /*{
$$ = $2;
}*/
| stmt IF_MOD expr_value /*{
$$ = new IfNode(support.union($1, $3), support.getConditionNode($3), $1, null);
}*/
| stmt UNLESS_MOD expr_value /*{
$$ = new IfNode(support.union($1, $3), support.getConditionNode($3), null, $1);
}*/
| stmt WHILE_MOD expr_value /*{
if ($1 != null && $1 instanceof BeginNode) {
$$ = new WhileNode(getPosition($1), support.getConditionNode($3), $<BeginNode>1.getBodyNode(), false);
} else {
$$ = new WhileNode(getPosition($1), support.getConditionNode($3), $1, true);
}
}*/
| stmt UNTIL_MOD expr_value /*{
if ($1 != null && $1 instanceof BeginNode) {
$$ = new UntilNode(getPosition($1), support.getConditionNode($3), $<BeginNode>1.getBodyNode());
} else {
$$ = new UntilNode(getPosition($1), support.getConditionNode($3), $1);
}
}*/
| stmt RESCUE_MOD stmt /*{
$$ = new RescueNode(getPosition($1), $1, new RescueBodyNode(getPosition($1), null,$3, null), null);
}*/
| LBEGIN /*{
if (support.isInDef() || support.isInSingle()) {
yyerror("BEGIN in method");
}
support.pushLocalScope();
}*/ LCURLY compstmt RCURLY /*{
support.getResult().addBeginNode(support.getCurrentScope(), $4);
support.popCurrentScope();
$$ = null; //XXX 0;
}*/
| LEND LCURLY compstmt RCURLY /*{
if (support.isInDef() || support.isInSingle()) {
yyerror("END in method; use at_exit");
}
// FIXME: Totally broken if scoping is important...though if not this is an improvement over iterNode
support.getResult().addEndNode(new PostExeNode(getPosition($1), $3));
$$ = null;
}*/
| lhs '=' command_call /*{
support.checkExpression($3);
$$ = support.node_assign($1, $3);
}*/
| mlhs '=' command_call /*{
support.checkExpression($3);
if ($1.getHeadNode() != null) {
$1.setValueNode(new ToAryNode(getPosition($1), $3));
} else {
$1.setValueNode(new ArrayNode(getPosition($1), $3));
}
$$ = $1;
}*/
| var_lhs OP_ASGN command_call /*{
support.checkExpression($3);
String name = $<INameNode>1.getName();
String asgnOp = (String) $2.getValue();
if (asgnOp.equals("||")) {
$1.setValueNode($3);
$$ = new OpAsgnOrNode(support.union($1, $3), support.gettable2(name, $1.getPosition()), $1);
} else if (asgnOp.equals("&&")) {
$1.setValueNode($3);
$$ = new OpAsgnAndNode(support.union($1, $3), support.gettable2(name, $1.getPosition()), $1);
} else {
$1.setValueNode(support.getOperatorCallNode(support.gettable2(name, $1.getPosition()), asgnOp, $3));
$1.setPosition(support.union($1, $3));
$$ = $1;
}
}*/
| primary_value '[' aref_args RBRACK OP_ASGN command_call /*{
$$ = new OpElementAsgnNode(getPosition($1), $1, (String) $5.getValue(), $3, $6);
}*/
| primary_value DOT IDENTIFIER OP_ASGN command_call /*{
$$ = new OpAsgnNode(getPosition($1), $1, $5, (String) $3.getValue(), (String) $4.getValue());
}*/
| primary_value DOT CONSTANT OP_ASGN command_call /*{
$$ = new OpAsgnNode(getPosition($1), $1, $5, (String) $3.getValue(), (String) $4.getValue());
}*/
| primary_value COLON2 IDENTIFIER OP_ASGN command_call /*{
$$ = new OpAsgnNode(getPosition($1), $1, $5, (String) $3.getValue(), (String) $4.getValue());
}*/
| backref OP_ASGN command_call /*{
support.backrefAssignError($1);
}*/
| lhs '=' mrhs /*{
$$ = support.node_assign($1, new SValueNode(getPosition($1), $3));
}*/
| mlhs '=' arg_value /*{
if ($1.getHeadNode() != null) {
$1.setValueNode(new ToAryNode(getPosition($1), $3));
} else {
$1.setValueNode(new ArrayNode(getPosition($1), $3));
}
$$ = $1;
}*/
| mlhs '=' mrhs /*{
$<AssignableNode>1.setValueNode($3);
$$ = $1;
$1.setPosition(support.union($1, $3));
}*/
| expr
;
expr : command_call
| expr AND expr /*{
$$ = support.newAndNode($1, $3);
}*/
| expr OR expr /*{
$$ = support.newOrNode($1, $3);
}*/
| NOT expr /*{
$$ = new NotNode(support.union($1, $2), support.getConditionNode($2));
}*/
| BANG command_call /*{
$$ = new NotNode(support.union($1, $2), support.getConditionNode($2));
}*/
| arg
;
expr_value : expr /*{
support.checkExpression($1);
}*/
;
command_call : command
| block_command
| RETURN call_args /*{
$$ = new ReturnNode(support.union($1, $2), support.ret_args($2, getPosition($1)));
}*/
| BREAK call_args /*{
$$ = new BreakNode(support.union($1, $2), support.ret_args($2, getPosition($1)));
}*/
| NEXT call_args /*{
$$ = new NextNode(support.union($1, $2), support.ret_args($2, getPosition($1)));
}*/
;
block_command : block_call
| block_call DOT operation2 command_args /*{
$$ = support.new_call($1, $3, $4, null);
}*/
| block_call COLON2 operation2 command_args /*{
$$ = support.new_call($1, $3, $4, null);
}*/
;
cmd_brace_block : LBRACE_ARG /*{
support.pushBlockScope();
}*/ opt_block_var compstmt RCURLY /*{
$$ = new IterNode(getPosition($1), $3, support.getCurrentScope(), $4);
support.popCurrentScope();
}*/
;
command : operation command_args /*%prec LOWEST*/ /*{
$$ = support.new_fcall($1, $2, null);
}*/
| operation command_args cmd_brace_block /*{
$$ = support.new_fcall($1, $2, $3);
}*/
| primary_value DOT operation2 command_args /*%prec LOWEST*/ /*{
$$ = support.new_call($1, $3, $4, null);
}*/
| primary_value DOT operation2 command_args cmd_brace_block /*{
$$ = support.new_call($1, $3, $4, $5);
}*/
| primary_value COLON2 operation2 command_args /*%prec LOWEST*/ /*{
$$ = support.new_call($1, $3, $4, null);
}*/
| primary_value COLON2 operation2 command_args cmd_brace_block /*{
$$ = support.new_call($1, $3, $4, $5);
}*/
| SUPER command_args /*{
$$ = support.new_super($2, $1); // .setPosFrom($2);
}*/
| YIELD command_args /*{
$$ = support.new_yield(getPosition($1), $2);
}*/
;
mlhs : mlhs_basic
| LPAREN mlhs_entry RPAREN /*{
$$ = $2;
}*/
;
mlhs_entry : mlhs_basic
| LPAREN mlhs_entry RPAREN /*{
$$ = new MultipleAsgnNode(getPosition($1), new ArrayNode(getPosition($1), $2), null);
}*/
;
mlhs_basic : mlhs_head /*{
$$ = new MultipleAsgnNode(getPosition($1), $1, null);
}*/
| mlhs_head mlhs_item /*{
$$ = new MultipleAsgnNode(support.union($<Node>1, $<Node>2), $1.add($2), null);
$<Node>1.setPosition(support.union($<Node>1, $<Node>2));
}*/
| mlhs_head STAR mlhs_node /*{
$$ = new MultipleAsgnNode(getPosition($1), $1, $3);
}*/
| mlhs_head STAR /*{
$$ = new MultipleAsgnNode(getPosition($1), $1, new StarNode(getPosition(null)));
}*/
| STAR mlhs_node /*{
$$ = new MultipleAsgnNode(getPosition($1), null, $2);
}*/
| STAR /*{
$$ = new MultipleAsgnNode(getPosition($1), null, new StarNode(getPosition(null)));
}*/
;
mlhs_item : mlhs_node
| LPAREN mlhs_entry RPAREN /*{
$$ = $2;
}*/
;
mlhs_head : mlhs_item ',' /*{
$$ = new ArrayNode($1.getPosition(), $1);
}*/
| mlhs_head mlhs_item ',' /*{
$$ = $1.add($2);
}*/
;
mlhs_node : variable /*{
$$ = support.assignable($1, null);
}*/
| primary_value '[' aref_args RBRACK /*{
$$ = support.aryset($1, $3);
}*/
| primary_value DOT IDENTIFIER /*{
$$ = support.attrset($1, (String) $3.getValue());
}*/
| primary_value COLON2 IDENTIFIER /*{
$$ = support.attrset($1, (String) $3.getValue());
}*/
| primary_value DOT CONSTANT /*{
$$ = support.attrset($1, (String) $3.getValue());
}*/
| primary_value COLON2 CONSTANT /*{
if (support.isInDef() || support.isInSingle()) {
yyerror("dynamic constant assignment");
}
ISourcePosition position = support.union($1, $3);
$$ = new ConstDeclNode(position, null, new Colon2Node(position, $1, (String) $3.getValue()), null);
}*/
| COLON3 CONSTANT /*{
if (support.isInDef() || support.isInSingle()) {
yyerror("dynamic constant assignment");
}
ISourcePosition position = support.union($1, $2);
$$ = new ConstDeclNode(position, null, new Colon3Node(position, (String) $2.getValue()), null);
}*/
| backref /*{
support.backrefAssignError($1);
}*/
;
lhs : variable /*{
$$ = support.assignable($1, null);
}*/
| primary_value '[' aref_args RBRACK /*{
$$ = support.aryset($1, $3);
}*/
| primary_value DOT IDENTIFIER /*{
$$ = support.attrset($1, (String) $3.getValue());
}*/
| primary_value COLON2 IDENTIFIER /*{
$$ = support.attrset($1, (String) $3.getValue());
}*/
| primary_value DOT CONSTANT /*{
$$ = support.attrset($1, (String) $3.getValue());
}*/
| primary_value COLON2 CONSTANT /*{
if (support.isInDef() || support.isInSingle()) {
yyerror("dynamic constant assignment");
}
ISourcePosition position = support.union($1, $3);
$$ = new ConstDeclNode(position, null, new Colon2Node(position, $1, (String) $3.getValue()), null);
}*/
| COLON3 CONSTANT /*{
if (support.isInDef() || support.isInSingle()) {
yyerror("dynamic constant assignment");
}
ISourcePosition position = support.union($1, $2);
$$ = new ConstDeclNode(position, null, new Colon3Node(position, (String) $2.getValue()), null);
}*/
| backref /*{
support.backrefAssignError($1);
}*/
;
cname : IDENTIFIER /*{
yyerror("class/module name must be CONSTANT");
}*/
| CONSTANT
;
cpath : COLON3 cname /*{
$$ = new Colon3Node(support.union($1, $2), (String) $2.getValue());
}*/
| cname /*{
$$ = new Colon2Node($1.getPosition(), null, (String) $1.getValue());
}*/
| primary_value COLON2 cname /*{
$$ = new Colon2Node(support.union($1, $3), $1, (String) $3.getValue());
}*/
;
// Token:fname - A function name [!null]
fname : IDENTIFIER | CONSTANT | FID
| op /*{
lexer.setState(LexState.EXPR_END);
$$ = $1;
}*/
// FIXME: reswords is really Keyword which is not a Token...This should bomb
| reswords /*{
lexer.setState(LexState.EXPR_END);
$$ = $<>1;
}*/
;
fitem : fname | symbol
;
undef_list : fitem /*{
$$ = new UndefNode(getPosition($1), (String) $1.getValue());
}*/
| undef_list ',' /*{
lexer.setState(LexState.EXPR_FNAME);
}*/ fitem /*{
$$ = support.appendToBlock($1, new UndefNode(getPosition($1), (String) $4.getValue()));
}*/
;
// Token:op - inline operations [!null]
op : PIPE | CARET | AMPER2 | CMP | EQ | EQQ | MATCH | GT
| GEQ | LT | LEQ | LSHFT | RSHFT | PLUS | MINUS | STAR2
| STAR | DIVIDE | PERCENT | POW | TILDE | UPLUS | UMINUS
| AREF | ASET | BACK_REF2
;
// Keyword:reswords - reserved words [!null]
reswords : U_LINE_U | U_FILE_U | LBEGIN | LEND
| ALIAS | AND | BEGIN | BREAK | CASE | CLASS | DEF
| DEFINED | DO | ELSE | ELSIF | END | ENSURE | FALSE
| FOR | IN | MODULE | NEXT | NIL | NOT
| OR | REDO | RESCUE | RETRY | RETURN | SELF | SUPER
| THEN | TRUE | UNDEF | WHEN | YIELD
| IF_MOD | UNLESS_MOD | WHILE_MOD | UNTIL_MOD | RESCUE_MOD
;
arg : lhs '=' arg /*{
$$ = support.node_assign($1, $3);
// FIXME: Consider fixing node_assign itself rather than single case
$<Node>$.setPosition(support.union($1, $3));
}*/
| lhs '=' arg RESCUE_MOD arg /*{
ISourcePosition position = support.union($4, $5);
$$ = support.node_assign($1, new RescueNode(position, $3, new RescueBodyNode(position, null, $5, null), null));
}*/
| var_lhs OP_ASGN arg /*{
support.checkExpression($3);
String name = $<INameNode>1.getName();
String asgnOp = (String) $2.getValue();
if (asgnOp.equals("||")) {
$1.setValueNode($3);
$$ = new OpAsgnOrNode(support.union($1, $3), support.gettable2(name, $1.getPosition()), $1);
} else if (asgnOp.equals("&&")) {
$1.setValueNode($3);
$$ = new OpAsgnAndNode(support.union($1, $3), support.gettable2(name, $1.getPosition()), $1);
} else {
$1.setValueNode(support.getOperatorCallNode(support.gettable2(name, $1.getPosition()), asgnOp, $3));
$1.setPosition(support.union($1, $3));
$$ = $1;
}
}*/
| primary_value '[' aref_args RBRACK OP_ASGN arg /*{
$$ = new OpElementAsgnNode(getPosition($1), $1, (String) $5.getValue(), $3, $6);
}*/
| primary_value DOT IDENTIFIER OP_ASGN arg /*{
$$ = new OpAsgnNode(getPosition($1), $1, $5, (String) $3.getValue(), (String) $4.getValue());
}*/
| primary_value DOT CONSTANT OP_ASGN arg /*{
$$ = new OpAsgnNode(getPosition($1), $1, $5, (String) $3.getValue(), (String) $4.getValue());
}*/
| primary_value COLON2 IDENTIFIER OP_ASGN arg /*{
$$ = new OpAsgnNode(getPosition($1), $1, $5, (String) $3.getValue(), (String) $4.getValue());
}*/
| primary_value COLON2 CONSTANT OP_ASGN arg /*{
yyerror("constant re-assignment");
}*/
| COLON3 CONSTANT OP_ASGN arg /*{
yyerror("constant re-assignment");
}*/
| backref OP_ASGN arg /*{
support.backrefAssignError($1);
}*/
| arg DOT2 arg /*{
support.checkExpression($1);
support.checkExpression($3);
$$ = new DotNode(support.union($1, $3), $1, $3, false);
}*/
| arg DOT3 arg /*{
support.checkExpression($1);
support.checkExpression($3);
$$ = new DotNode(support.union($1, $3), $1, $3, true);
}*/
| arg PLUS arg /*{
$$ = support.getOperatorCallNode($1, "+", $3, getPosition(null));
}*/
| arg MINUS arg /*{
$$ = support.getOperatorCallNode($1, "-", $3, getPosition(null));
}*/
| arg STAR2 arg /*{
$$ = support.getOperatorCallNode($1, "*", $3, getPosition(null));
}*/
| arg DIVIDE arg /*{
$$ = support.getOperatorCallNode($1, "/", $3, getPosition(null));
}*/
| arg PERCENT arg /*{
$$ = support.getOperatorCallNode($1, "%", $3, getPosition(null));
}*/
| arg POW arg /*{
$$ = support.getOperatorCallNode($1, "**", $3, getPosition(null));
}*/
| UMINUS_NUM INTEGER POW arg /*{
$$ = support.getOperatorCallNode(support.getOperatorCallNode($2, "**", $4, getPosition(null)), "-@");
}*/
| UMINUS_NUM FLOAT POW arg /*{
$$ = support.getOperatorCallNode(support.getOperatorCallNode($2, "**", $4, getPosition(null)), "-@");
}*/
| UPLUS arg /*{
if ($2 != null && $2 instanceof ILiteralNode) {
$$ = $2;
} else {
$$ = support.getOperatorCallNode($2, "+@");
}
}*/
| UMINUS arg /*{
$$ = support.getOperatorCallNode($2, "-@");
}*/
| arg PIPE arg /*{
$$ = support.getOperatorCallNode($1, "|", $3, getPosition(null));
}*/
| arg CARET arg /*{
$$ = support.getOperatorCallNode($1, "^", $3, getPosition(null));
}*/
| arg AMPER2 arg /*{
$$ = support.getOperatorCallNode($1, "&", $3, getPosition(null));
}*/
| arg CMP arg /*{
$$ = support.getOperatorCallNode($1, "<=>", $3, getPosition(null));
}*/
| arg GT arg /*{
$$ = support.getOperatorCallNode($1, ">", $3, getPosition(null));
}*/
| arg GEQ arg /*{
$$ = support.getOperatorCallNode($1, ">=", $3, getPosition(null));
}*/
| arg LT arg /*{
$$ = support.getOperatorCallNode($1, "<", $3, getPosition(null));
}*/
| arg LEQ arg /*{
$$ = support.getOperatorCallNode($1, "<=", $3, getPosition(null));
}*/
| arg EQ arg /*{
$$ = support.getOperatorCallNode($1, "==", $3, getPosition(null));
}*/
| arg EQQ arg /*{
$$ = support.getOperatorCallNode($1, "===", $3, getPosition(null));
}*/
| arg NEQ arg /*{
$$ = new NotNode(support.union($1, $3), support.getOperatorCallNode($1, "==", $3, getPosition(null)));
}*/
| arg MATCH arg /*{
$$ = support.getMatchNode($1, $3);
}*/
| arg NMATCH arg /*{
$$ = new NotNode(support.union($1, $3), support.getMatchNode($1, $3));
}*/
| BANG arg /*{
$$ = new NotNode(support.union($1, $2), support.getConditionNode($2));
}*/
| TILDE arg /*{
$$ = support.getOperatorCallNode($2, "~");
}*/
| arg LSHFT arg /*{
$$ = support.getOperatorCallNode($1, "<<", $3, getPosition(null));
}*/
| arg RSHFT arg /*{
$$ = support.getOperatorCallNode($1, ">>", $3, getPosition(null));
}*/
| arg ANDOP arg /*{
$$ = support.newAndNode($1, $3);
}*/
| arg OROP arg /*{
$$ = support.newOrNode($1, $3);
}*/
| DEFINED opt_nl arg /*{
$$ = new DefinedNode(getPosition($1), $3);
}*/
| arg '?' arg ':' arg /*{
$$ = new IfNode(getPosition($1), support.getConditionNode($1), $3, $5);
}*/
| primary /*{
$$ = $1;
}*/
;
arg_value : arg /*{
support.checkExpression($1);
$$ = $1;
}*/
;
aref_args : none
| command opt_nl /*{
warnings.warn(getPosition($1), "parenthesize argument(s) for future version");
$$ = new ArrayNode(getPosition($1), $1);
}*/
| args trailer /*{
$$ = $1;
}*/
| args ',' STAR arg opt_nl /*{
support.checkExpression($4);
$$ = support.arg_concat(getPosition($1), $1, $4);
}*/
| assocs trailer /*{
$$ = new ArrayNode(getPosition($1), new HashNode(getPosition(null), $1));
}*/
| STAR arg opt_nl /*{
support.checkExpression($2);
$$ = new NewlineNode(getPosition($1), new SplatNode(getPosition($1), $2));
}*/
;
paren_args : LPAREN2 none RPAREN /*{
$$ = new ArrayNode(support.union($1, $3));
}*/
| LPAREN2 call_args opt_nl RPAREN /*{
$$ = $2;
$<Node>$.setPosition(support.union($1, $4));
}*/
| LPAREN2 block_call opt_nl RPAREN /*{
warnings.warn(getPosition($1), "parenthesize argument(s) for future version");
$$ = new ArrayNode(getPosition($1), $2);
}*/
| LPAREN2 args ',' block_call opt_nl RPAREN /*{
warnings.warn(getPosition($1), "parenthesize argument(s) for future version");
$$ = $2.add($4);
}*/
;
opt_paren_args: none | paren_args
;
// Node:call_args - Arguments for a function call
call_args : command /*{
warnings.warn($1.getPosition(), "parenthesize argument(s) for future version");
$$ = new ArrayNode(getPosition($1), $1);
}*/
| args opt_block_arg /*{
$$ = support.arg_blk_pass($1, $2);
}*/
| args ',' STAR arg_value opt_block_arg /*{
$$ = support.arg_concat(getPosition($1), $1, $4);
$$ = support.arg_blk_pass($<Node>$, $5);
}*/
| assocs opt_block_arg /*{
$$ = new ArrayNode(getPosition($1), new HashNode(getPosition(null), $1));
$$ = support.arg_blk_pass((Node)$$, $2);
}*/
| assocs ',' STAR arg_value opt_block_arg /*{
$$ = support.arg_concat(getPosition($1), new ArrayNode(getPosition($1), new HashNode(getPosition(null), $1)), $4);
$$ = support.arg_blk_pass((Node)$$, $5);
}*/
| args ',' assocs opt_block_arg /*{
$$ = $1.add(new HashNode(getPosition(null), $3));
$$ = support.arg_blk_pass((Node)$$, $4);
}*/
| args ',' assocs ',' STAR arg opt_block_arg /*{
support.checkExpression($6);
$$ = support.arg_concat(getPosition($1), $1.add(new HashNode(getPosition(null), $3)), $6);
$$ = support.arg_blk_pass((Node)$$, $7);
}*/
| STAR arg_value opt_block_arg /*{
$$ = support.arg_blk_pass(new SplatNode(getPosition($1), $2), $3);
}*/
| block_arg /*{}*/
;
call_args2 : arg_value ',' args opt_block_arg /*{
$$ = support.arg_blk_pass(new ArrayNode(getPosition($1), $1).addAll($3), $4);
}*/
| arg_value ',' block_arg /*{
$$ = support.arg_blk_pass(new ArrayNode(getPosition($1), $1), $3);
}*/
| arg_value ',' STAR arg_value opt_block_arg /*{
$$ = support.arg_concat(getPosition($1), new ArrayNode(getPosition($1), $1), $4);
$$ = support.arg_blk_pass((Node)$$, $5);
}*/
| arg_value ',' args ',' STAR arg_value opt_block_arg /*{
$$ = support.arg_concat(getPosition($1), new ArrayNode(getPosition($1), $1).addAll(new HashNode(getPosition(null), $3)), $6);
$$ = support.arg_blk_pass((Node)$$, $7);
}*/
| assocs opt_block_arg /*{
$$ = new ArrayNode(getPosition($1), new HashNode(getPosition(null), $1));
$$ = support.arg_blk_pass((Node)$$, $2);
}*/
| assocs ',' STAR arg_value opt_block_arg /*{
$$ = support.arg_concat(getPosition($1), new ArrayNode(getPosition($1), new HashNode(getPosition(null), $1)), $4);
$$ = support.arg_blk_pass((Node)$$, $5);
}*/
| arg_value ',' assocs opt_block_arg /*{
$$ = new ArrayNode(getPosition($1), $1).add(new HashNode(getPosition(null), $3));
$$ = support.arg_blk_pass((Node)$$, $4);
}*/
| arg_value ',' args ',' assocs opt_block_arg /*{
$$ = new ArrayNode(getPosition($1), $1).addAll($3).add(new HashNode(getPosition(null), $5));
$$ = support.arg_blk_pass((Node)$$, $6);
}*/
| arg_value ',' assocs ',' STAR arg_value opt_block_arg /*{
$$ = support.arg_concat(getPosition($1), new ArrayNode(getPosition($1), $1).add(new HashNode(getPosition(null), $3)), $6);
$$ = support.arg_blk_pass((Node)$$, $7);
}*/
| arg_value ',' args ',' assocs ',' STAR arg_value opt_block_arg /*{
$$ = support.arg_concat(getPosition($1), new ArrayNode(getPosition($1), $1).addAll($3).add(new HashNode(getPosition(null), $5)), $8);
$$ = support.arg_blk_pass((Node)$$, $9);
}*/
| STAR arg_value opt_block_arg /*{
$$ = support.arg_blk_pass(new SplatNode(getPosition($1), $2), $3);
}*/
| block_arg /*{}*/
;
command_args : /* none */ /*{
$$ = new Long(lexer.getCmdArgumentState().begin());
}*/ open_args /*{
lexer.getCmdArgumentState().reset($<Long>1.longValue());
$$ = $2;
}*/
;
open_args : call_args
| LPAREN_ARG /*{
lexer.setState(LexState.EXPR_ENDARG);
}*/ RPAREN /*{
warnings.warn(getPosition($1), "don't put space before argument parentheses");
$$ = null;
}*/
| LPAREN_ARG call_args2 /*{
lexer.setState(LexState.EXPR_ENDARG);
}*/ RPAREN /*{
warnings.warn(getPosition($1), "don't put space before argument parentheses");
$$ = $2;
}*/
;
block_arg : AMPER arg_value /*{
support.checkExpression($2);
$$ = new BlockPassNode(support.union($1, $2), $2);
}*/
;
opt_block_arg : ',' block_arg /*{
$$ = $2;
}*/
| none_block_pass
;
args : arg_value /*{
$$ = new ArrayNode(getPosition2($1), $1);
}*/
| args ',' arg_value /*{
$$ = $1.add($3);
}*/
;
mrhs : args ',' arg_value /*{
$$ = $1.add($3);
}*/
| args ',' STAR arg_value /*{
$$ = support.arg_concat(getPosition($1), $1, $4);
}*/
| STAR arg_value /*{
$$ = new SplatNode(getPosition($1), $2);
}*/
;
primary : literal
| strings
| xstring
| regexp
| words
| qwords
| var_ref
| backref
| FID /*{
$$ = new FCallNode($1.getPosition(), (String) $1.getValue(), null);
}*/
| BEGIN bodystmt END /*{
$$ = new BeginNode(support.union($1, $3), $2);
}*/
| LPAREN_ARG expr /*{
lexer.setState(LexState.EXPR_ENDARG);
}*/ opt_nl RPAREN /*{
warnings.warning(getPosition($1), "(...) interpreted as grouped expression");
$$ = $2;
}*/
| LPAREN compstmt RPAREN /*{
$$ = $2;
}*/
| primary_value COLON2 CONSTANT /*{
$$ = new Colon2Node(support.union($1, $3), $1, (String) $3.getValue());
}*/
| COLON3 CONSTANT /*{
$$ = new Colon3Node(support.union($1, $2), (String) $2.getValue());
}*/
| primary_value '[' aref_args RBRACK /*{
if ($1 instanceof SelfNode) {
$$ = new FCallNode(getPosition($1), "[]", $3);
} else {
$$ = new CallNode(getPosition($1), $1, "[]", $3);
}
}*/
| LBRACK aref_args RBRACK /*{
ISourcePosition position = support.union($1, $3);
if ($2 == null) {
$$ = new ZArrayNode(position); // zero length array
} else {
$$ = $2;
$<ISourcePositionHolder>$.setPosition(position);
}
}*/
| LBRACE assoc_list RCURLY /*{
$$ = new HashNode(support.union($1, $3), $2);
}*/
| RETURN /*{
$$ = new ReturnNode($1.getPosition(), null);
}*/
| YIELD LPAREN2 call_args RPAREN /*{
$$ = support.new_yield(support.union($1, $4), $3);
}*/
| YIELD LPAREN2 RPAREN /*{
$$ = new YieldNode(support.union($1, $3), null, false);
}*/
| YIELD /*{
$$ = new YieldNode($1.getPosition(), null, false);
}*/
| DEFINED opt_nl LPAREN2 expr RPAREN /*{
$$ = new DefinedNode(getPosition($1), $4);
}*/
| operation brace_block /*{
$$ = new FCallNode(support.union($1, $2), (String) $1.getValue(), null, $2);
}*/
| method_call
| method_call brace_block /*{
if ($1 != null &&
$<BlockAcceptingNode>1.getIterNode() instanceof BlockPassNode) {
throw new SyntaxException(getPosition($1), "Both block arg and actual block given.");
}
$<BlockAcceptingNode>1.setIterNode($2);
$<Node>1.setPosition(support.union($1, $2));
}*/
| IF expr_value then compstmt if_tail END /*{
$$ = new IfNode(support.union($1, $6), support.getConditionNode($2), $4, $5);
}*/
| UNLESS expr_value then compstmt opt_else END /*{
$$ = new IfNode(support.union($1, $6), support.getConditionNode($2), $5, $4);
}*/
| WHILE /*{
lexer.getConditionState().begin();
}*/ expr_value do /*{
lexer.getConditionState().end();
}*/ compstmt END /*{
$$ = new WhileNode(support.union($1, $7), support.getConditionNode($3), $6);
}*/
| UNTIL /*{
lexer.getConditionState().begin();
}*/ expr_value do /*{
lexer.getConditionState().end();
}*/ compstmt END /*{
$$ = new UntilNode(getPosition($1), support.getConditionNode($3), $6);
}*/
| CASE expr_value opt_terms case_body END /*{
$$ = new CaseNode(support.union($1, $5), $2, $4);
}*/
| CASE opt_terms case_body END /*{
$$ = new CaseNode(support.union($1, $4), null, $3);
}*/
| CASE opt_terms ELSE compstmt END /*{
$$ = $4;
}*/
| FOR block_var IN /*{
lexer.getConditionState().begin();
}*/ expr_value do /*{
lexer.getConditionState().end();
}*/ compstmt END /*{
$$ = new ForNode(support.union($1, $9), $2, $8, $5);
}*/
| CLASS cpath superclass /*{
if (support.isInDef() || support.isInSingle()) {
yyerror("class definition in method body");
}
support.pushLocalScope();
}*/ bodystmt END /*{
$$ = new ClassNode(support.union($1, $6), $<Colon3Node>2, support.getCurrentScope(), $5, $3);
support.popCurrentScope();
}*/
| CLASS LSHFT expr /*{
$$ = new Boolean(support.isInDef());
support.setInDef(false);
}*/ term /*{
$$ = new Integer(support.getInSingle());
support.setInSingle(0);
support.pushLocalScope();
}*/ bodystmt END /*{
$$ = new SClassNode(support.union($1, $8), $3, support.getCurrentScope(), $7);
support.popCurrentScope();
support.setInDef($<Boolean>4.booleanValue());
support.setInSingle($<Integer>6.intValue());
}*/
| MODULE cpath /*{
if (support.isInDef() || support.isInSingle()) {
yyerror("module definition in method body");
}
support.pushLocalScope();
}*/ bodystmt END /*{
$$ = new ModuleNode(support.union($1, $5), $<Colon3Node>2, support.getCurrentScope(), $4);
support.popCurrentScope();
}*/
| DEF fname /*{
support.setInDef(true);
support.pushLocalScope();
}*/ f_arglist bodystmt END /*{
// NOEX_PRIVATE for toplevel
$$ = new DefnNode(support.union($1, $6), new ArgumentNode($2.getPosition(), (String) $2.getValue()), $<ArgsNode>4, support.getCurrentScope(), $5, Visibility.PRIVATE);
support.popCurrentScope();
support.setInDef(false);
}*/
| DEF singleton dot_or_colon /*{
lexer.setState(LexState.EXPR_FNAME);
}*/ fname /*{
support.setInSingle(support.getInSingle() + 1);
support.pushLocalScope();
lexer.setState(LexState.EXPR_END); // force for args
}*/ f_arglist bodystmt END /*{
$$ = new DefsNode(support.union($1, $9), $2, new ArgumentNode($5.getPosition(), (String) $5.getValue()), $<ArgsNode>7, support.getCurrentScope(), $8);
support.popCurrentScope();
support.setInSingle(support.getInSingle() - 1);
}*/
| BREAK /*{
$$ = new BreakNode($1.getPosition());
}*/
| NEXT /*{
$$ = new NextNode($1.getPosition());
}*/
| REDO /*{
$$ = new RedoNode($1.getPosition());
}*/
| RETRY /*{
$$ = new RetryNode($1.getPosition());
}*/
;
primary_value : primary /*{
support.checkExpression($1);
$$ = $1;
}*/
;
then : term
| ':'
| THEN
| term THEN
;
do : term
| ':'
| DO_COND
;
if_tail : opt_else
| ELSIF expr_value then compstmt if_tail /*{
//mirko: support.union($<ISourcePositionHolder>1.getPosition(), getPosition($<ISourcePositionHolder>1)) ?
$$ = new IfNode(getPosition($1), support.getConditionNode($2), $4, $5);
}*/
;
opt_else : none
| ELSE compstmt /*{
$$ = $2;
}*/
;
block_var : lhs
| mlhs /*{}*/
;
opt_block_var : none
| PIPE /* none */ PIPE /*{
$$ = new ZeroArgNode(support.union($1, $2));
}*/
| OROP /*{
$$ = new ZeroArgNode($1.getPosition());
}*/
| PIPE block_var PIPE /*{
$$ = $2;
// Include pipes on multiple arg type
if ($2 instanceof MultipleAsgnNode) {
$2.setPosition(support.union($1, $3));
}
}*/
;
do_block : DO_BLOCK /*{
support.pushBlockScope();
}*/ opt_block_var compstmt END /*{
$$ = new IterNode(support.union($1, $5), $3, support.getCurrentScope(), $4);
support.popCurrentScope();
}*/
;
block_call : command do_block /*{
if ($1 != null &&
$<BlockAcceptingNode>1.getIterNode() instanceof BlockPassNode) {
throw new SyntaxException(getPosition($1), "Both block arg and actual block given.");
}
$<BlockAcceptingNode>1.setIterNode($2);
$<Node>1.setPosition(support.union($1, $2));
}*/
| block_call DOT operation2 opt_paren_args /*{
$$ = support.new_call($1, $3, $4, null);
}*/
| block_call COLON2 operation2 opt_paren_args /*{
$$ = support.new_call($1, $3, $4, null);
}*/
;
method_call : operation paren_args /*{
$$ = support.new_fcall($1, $2, null);
}*/
| primary_value DOT operation2 opt_paren_args /*{
$$ = support.new_call($1, $3, $4, null);
}*/
| primary_value COLON2 operation2 paren_args /*{
$$ = support.new_call($1, $3, $4, null);
}*/
| primary_value COLON2 operation3 /*{
$$ = support.new_call($1, $3, null, null);
}*/
| SUPER paren_args /*{
$$ = support.new_super($2, $1);
}*/
| SUPER /*{
$$ = new ZSuperNode($1.getPosition());
}*/
;
// IterNode:brace_block - block invocation argument (foo >{...}< | foo >do end<) [!null]
brace_block : LCURLY /*{
support.pushBlockScope();
}*/ opt_block_var compstmt RCURLY /*{
$$ = new IterNode(support.union($1, $5), $3, support.getCurrentScope(), $4);
support.popCurrentScope();
}*/
| DO /*{
support.pushBlockScope();
}*/ opt_block_var compstmt END /*{
$$ = new IterNode(support.union($1, $5), $3, support.getCurrentScope(), $4);
$<ISourcePositionHolder>0.setPosition(support.union($<ISourcePositionHolder>0, $<ISourcePositionHolder>$));
support.popCurrentScope();
}*/
;
case_body : WHEN when_args then compstmt cases /*{
$$ = new WhenNode(support.union($1, support.unwrapNewlineNode($4)), $2, $4, $5);
}*/
;
when_args : args
| args ',' STAR arg_value /*{
$$ = $1.add(new WhenNode(getPosition($1), $4, null, null));
}*/
| STAR arg_value /*{
$$ = new ArrayNode(getPosition($1), new WhenNode(getPosition($1), $2, null, null));
}*/
;
cases : opt_else | case_body
;
opt_rescue : RESCUE exc_list exc_var then compstmt opt_rescue /*{
Node node;
if ($3 != null) {
node = support.appendToBlock(support.node_assign($3, new GlobalVarNode(getPosition($1), "$!")), $5);
if($5 != null) {
node.setPosition(support.unwrapNewlineNode($5).getPosition());
}
} else {
node = $5;
}
$$ = new RescueBodyNode(getPosition($1, true), $2, node, $6);
}*/
| /*{$$ = null;}*/
;
exc_list : arg_value /*{
$$ = new ArrayNode($1.getPosition(), $1);
}*/
| mrhs
| none
;
exc_var : ASSOC lhs /*{
$$ = $2;
}*/
| none
;
opt_ensure : ENSURE compstmt /*{
if ($2 != null) {
$$ = $2;
} else {
$$ = new NilNode(getPosition(null));
}
}*/
| none
;
literal : numeric
| symbol /*{
$$ = new SymbolNode($1.getPosition(), (String) $1.getValue());
}*/
| dsym
;
strings : string /*{
if ($1 instanceof EvStrNode) {
$$ = new DStrNode(getPosition($1)).add($1);
} else {
$$ = $1;
}
}*/
;
string : string1
| string string1 /*{
$$ = support.literal_concat(getPosition($1), $1, $2);
}*/
;
string1 : STRING_BEG string_contents STRING_END /*{
$$ = $2;
$<ISourcePositionHolder>$.setPosition(support.union($1, $3));
int extraLength = ((String) $1.getValue()).length() - 1;
// We may need to subtract addition offset off of first
// string fragment (we optimistically take one off in
// ParserSupport.literal_concat). Check token length
// and subtract as neeeded.
if (($2 instanceof DStrNode) && extraLength > 0) {
Node strNode = ((DStrNode)$2).get(0);
assert strNode != null;
strNode.getPosition().adjustStartOffset(-extraLength);
}
}*/
;
xstring : XSTRING_BEG xstring_contents STRING_END /*{
ISourcePosition position = support.union($1, $3);
if ($2 == null) {
$$ = new XStrNode(position, null);
} else if ($2 instanceof StrNode) {
$$ = new XStrNode(position, (ByteList) $<StrNode>2.getValue().clone());
} else if ($2 instanceof DStrNode) {
$$ = new DXStrNode(position, $<DStrNode>2);
$<Node>$.setPosition(position);
} else {
$$ = new DXStrNode(position).add($2);
}
}*/
;
regexp : REGEXP_BEG xstring_contents REGEXP_END /*{
int options = $3.getOptions();
Node node = $2;
if (node == null) {
$$ = new RegexpNode(getPosition($1), ByteList.create(""), options & ~ReOptions.RE_OPTION_ONCE);
} else if (node instanceof StrNode) {
$$ = new RegexpNode($2.getPosition(), (ByteList) ((StrNode) node).getValue().clone(), options & ~ReOptions.RE_OPTION_ONCE);
} else if (node instanceof DStrNode) {
$$ = new DRegexpNode(getPosition($1), (DStrNode) node, options, (options & ReOptions.RE_OPTION_ONCE) != 0);
} else {
$$ = new DRegexpNode(getPosition($1), options, (options & ReOptions.RE_OPTION_ONCE) != 0).add(node);
}
}*/
;
words : WORDS_BEG ' ' STRING_END /*{
$$ = new ZArrayNode(support.union($1, $3));
}*/
| WORDS_BEG word_list STRING_END /*{
$$ = $2;
$<ISourcePositionHolder>$.setPosition(support.union($1, $3));
}*/
;
word_list : /* none */ /*{
$$ = new ArrayNode(getPosition(null));
}*/
| word_list word ' ' /*{
$$ = $1.add($2 instanceof EvStrNode ? new DStrNode(getPosition($1)).add($2) : $2);
}*/
;
word : string_content
| word string_content /*{
$$ = support.literal_concat(getPosition($1), $1, $2);
}*/
;
qwords : QWORDS_BEG ' ' STRING_END /*{
$$ = new ZArrayNode(support.union($1, $3));
}*/
| QWORDS_BEG qword_list STRING_END /*{
$$ = $2;
$<ISourcePositionHolder>$.setPosition(support.union($1, $3));
}*/
;
qword_list : /* none */ /*{
$$ = new ArrayNode(getPosition(null));
}*/
| qword_list STRING_CONTENT ' ' /*{
$$ = $1.add($2);
}*/
;
string_contents: /* none */ /*{
$$ = new StrNode($<Token>0.getPosition(), ByteList.create(""));
}*/
| string_contents string_content /*{
$$ = support.literal_concat(getPosition($1), $1, $2);
}*/
;
xstring_contents: /* none */ /*{
$$ = null;
}*/
| xstring_contents string_content /*{
$$ = support.literal_concat(getPosition($1), $1, $2);
}*/
;
string_content : STRING_CONTENT /*{
$$ = $1;
}*/
| STRING_DVAR /*{
$$ = lexer.getStrTerm();
lexer.setStrTerm(null);
lexer.setState(LexState.EXPR_BEG);
}*/ string_dvar /*{
lexer.setStrTerm($<StrTerm>2);
$$ = new EvStrNode(support.union($1, $3), $3);
}*/
| STRING_DBEG /*{
$$ = lexer.getStrTerm();
lexer.setStrTerm(null);
lexer.setState(LexState.EXPR_BEG);
}*/ compstmt RCURLY /*{
lexer.setStrTerm($<StrTerm>2);
$$ = support.newEvStrNode(support.union($1, $4), $3);
}*/
;
string_dvar : GVAR /*{
$$ = new GlobalVarNode($1.getPosition(), (String) $1.getValue());
}*/
| IVAR /*{
$$ = new InstVarNode($1.getPosition(), (String) $1.getValue());
}*/
| CVAR /*{
$$ = new ClassVarNode($1.getPosition(), (String) $1.getValue());
}*/
| backref
;
symbol : SYMBEG sym /*{
lexer.setState(LexState.EXPR_END);
$$ = $2;
$<ISourcePositionHolder>$.setPosition(support.union($1, $2));
}*/
;
sym : fname | IVAR | GVAR | CVAR
;
dsym : SYMBEG xstring_contents STRING_END /*{
lexer.setState(LexState.EXPR_END);
// DStrNode: :"some text #{some expression}"
// StrNode: :"some text"
// EvStrNode :"#{some expression}"
DStrNode node;
if ($2 == null) {
yyerror("empty symbol literal");
}
if ($2 instanceof DStrNode) {
$$ = new DSymbolNode(support.union($1, $3), $<DStrNode>2);
} else {
ISourcePosition position = support.union($2, $3);
// We substract one since tsymbeg is longer than one
// and we cannot union it directly so we assume quote
// is one character long and subtract for it.
position.adjustStartOffset(-1);
$2.setPosition(position);
$$ = new DSymbolNode(support.union($1, $3));
$<DSymbolNode>$.add($2);
}
}*/
;
// Node:numeric - numeric value [!null]
numeric : INTEGER | FLOAT /*{
$$ = $1;
}*/
| UMINUS_NUM INTEGER /*%prec LOWEST*/ /*{
$$ = support.negateInteger($2);
}*/
| UMINUS_NUM FLOAT /*%prec LOWEST*/ /*{
$$ = support.negateFloat($2);
}*/
;
// Token:variable - name (special and normal onces)
variable : IDENTIFIER | IVAR | GVAR | CONSTANT | CVAR
| NIL /*{
$$ = new Token("nil", $1.getPosition());
}*/
| SELF /*{
$$ = new Token("self", $1.getPosition());
}*/
| TRUE /*{
$$ = new Token("true", $1.getPosition());
}*/
| FALSE /*{
$$ = new Token("false", $1.getPosition());
}*/
| U_FILE_U /*{
$$ = new Token("__FILE__", $1.getPosition());
}*/
| U_LINE_U /*{
$$ = new Token("__LINE__", $1.getPosition());
}*/
;
var_ref : variable /*{
$$ = support.gettable((String) $1.getValue(), $1.getPosition());
}*/
;
var_lhs : variable /*{
$$ = support.assignable($1, null);
}*/
;
backref : NTH_REF | BACK_REF
;
superclass : term /*{
$$ = null;
}*/
| LT /*{
lexer.setState(LexState.EXPR_BEG);
}*/ expr_value term /*{
$$ = $3;
}*/
/*| error term {
yyerrok();
$$ = null;
}*/
;
// f_arglist: Function Argument list for definitions
f_arglist : LPAREN2 f_args opt_nl RPAREN /*{
$$ = $2;
$<ISourcePositionHolder>$.setPosition(support.union($1, $4));
lexer.setState(LexState.EXPR_BEG);
}*/
| f_args term /*{
$$ = $1;
}*/
;
f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg /*{
$$ = new ArgsNode(support.union($1, $6), $1, $3, ((Integer) $5.getValue()).intValue(), $6);
}*/
| f_arg ',' f_optarg opt_f_block_arg /*{
$$ = new ArgsNode(getPosition($1), $1, $3, -1, $4);
}*/
| f_arg ',' f_rest_arg opt_f_block_arg /*{
$$ = new ArgsNode(support.union($1, $4), $1, null, ((Integer) $3.getValue()).intValue(), $4);
}*/
| f_arg opt_f_block_arg /*{
$$ = new ArgsNode($<ISourcePositionHolder>1.getPosition(), $1, null, -1, $2);
}*/
| f_optarg ',' f_rest_arg opt_f_block_arg /*{
$$ = new ArgsNode(getPosition($1), null, $1, ((Integer) $3.getValue()).intValue(), $4);
}*/
| f_optarg opt_f_block_arg /*{
$$ = new ArgsNode(getPosition($1), null, $1, -1, $2);
}*/
| f_rest_arg opt_f_block_arg /*{
$$ = new ArgsNode(getPosition($1), null, null, ((Integer) $1.getValue()).intValue(), $2);
}*/
| f_block_arg /*{
$$ = new ArgsNode(getPosition($1), null, null, -1, $1);
}*/
| /* none */ /*{
$$ = new ArgsNode(support.createEmptyArgsNodePosition(getPosition(null)), null, null, -1, null);
}*/
;
f_norm_arg : CONSTANT /*{
yyerror("formal argument cannot be a constant");
}*/
| IVAR /*{
yyerror("formal argument cannot be an instance variable");
}*/
| CVAR /*{
yyerror("formal argument cannot be a class variable");
}*/
| IDENTIFIER /*{
String identifier = (String) $1.getValue();
if (IdUtil.getVarType(identifier) != IdUtil.LOCAL_VAR) {
yyerror("formal argument must be local variable");
} else if (support.getCurrentScope().getLocalScope().isDefined(identifier) >= 0) {
yyerror("duplicate argument name");
}
support.getCurrentScope().getLocalScope().addVariable(identifier);
$$ = $1;
}*/
;
f_arg : f_norm_arg /*{
$$ = new ListNode($<ISourcePositionHolder>1.getPosition());
((ListNode) $$).add(new ArgumentNode($<ISourcePositionHolder>1.getPosition(), (String) $1.getValue()));
}*/
| f_arg ',' f_norm_arg /*{
$1.add(new ArgumentNode($<ISourcePositionHolder>3.getPosition(), (String) $3.getValue()));
$1.setPosition(support.union($1, $3));
$$ = $1;
}*/
;
f_opt : IDENTIFIER '=' arg_value /*{
String identifier = (String) $1.getValue();
if (IdUtil.getVarType(identifier) != IdUtil.LOCAL_VAR) {
yyerror("formal argument must be local variable");
} else if (support.getCurrentScope().getLocalScope().isDefined(identifier) >= 0) {
yyerror("duplicate optional argument name");
}
support.getCurrentScope().getLocalScope().addVariable(identifier);
$$ = support.assignable($1, $3);
}*/
;
f_optarg : f_opt /*{
$$ = new BlockNode(getPosition($1)).add($1);
}*/
| f_optarg ',' f_opt /*{
$$ = support.appendToBlock($1, $3);
}*/
;
restarg_mark : STAR2 | STAR
;
f_rest_arg : restarg_mark IDENTIFIER /*{
String identifier = (String) $2.getValue();
if (IdUtil.getVarType(identifier) != IdUtil.LOCAL_VAR) {
yyerror("rest argument must be local variable");
} else if (support.getCurrentScope().getLocalScope().isDefined(identifier) >= 0) {
yyerror("duplicate rest argument name");
}
$1.setValue(new Integer(support.getCurrentScope().getLocalScope().addVariable(identifier)));
$$ = $1;
}*/
| restarg_mark /*{
$1.setValue(new Integer(-2));
$$ = $1;
}*/
;
blkarg_mark : AMPER2 | AMPER
;
f_block_arg : blkarg_mark IDENTIFIER /*{
String identifier = (String) $2.getValue();
if (IdUtil.getVarType(identifier) != IdUtil.LOCAL_VAR) {
yyerror("block argument must be local variable");
} else if (support.getCurrentScope().getLocalScope().isDefined(identifier) >= 0) {
yyerror("duplicate block argument name");
}
$$ = new BlockArgNode(support.union($1, $2), support.getCurrentScope().getLocalScope().addVariable(identifier), identifier);
}*/
;
opt_f_block_arg: ',' f_block_arg /*{
$$ = $2;
}*/
| /* none */ /*{
$$ = null;
}*/
;
singleton : var_ref /*{
if (!($1 instanceof SelfNode)) {
support.checkExpression($1);
}
$$ = $1;
}*/
| LPAREN2 /*{
lexer.setState(LexState.EXPR_BEG);
}*/ expr opt_nl RPAREN /*{
if ($3 instanceof ILiteralNode) {
yyerror("Can't define single method for literals.");
}
support.checkExpression($3);
$$ = $3;
}*/
;
// ListNode:assoc_list - list of hash values pairs, like assocs but also
// will accept ordinary list-style (e.g. a,b,c,d or a=>b,c=>d) [?null]
assoc_list : none /*{ // [!null]
$$ = new ArrayNode(getPosition(null));
}*/
| assocs trailer /*{ // [!null]
$$ = $1;
}*/
| args trailer /*{
if ($1.size() % 2 != 0) {
yyerror("Odd number list for Hash.");
}
$$ = $1;
}*/
;
// ListNode:assocs - list of hash value pairs (e.g. a => b, c => d) [!null]
assocs : assoc // [!null]
| assocs ',' assoc /*{ // [!null]
$$ = $1.addAll($3);
}*/
;
// ListNode:assoc - A single hash value pair (e.g. a => b) [!null]
assoc : arg_value ASSOC arg_value /*{ // [!null]
$$ = new ArrayNode(support.union($1, $3), $1).add($3);
}*/
;
operation : IDENTIFIER | CONSTANT | FID
;
operation2 : IDENTIFIER | CONSTANT | FID | op
;
operation3 : IDENTIFIER | FID | op
;
dot_or_colon : DOT | COLON2
;
opt_terms : /* none */ | terms
;
opt_nl : /* none */ | '\n'
;
trailer : /* none */ | '\n' | ','
;
term : ';' /*{
yyerrok();
}*/
| '\n'
;
terms : term
| terms ';' /*{
yyerrok();
}*/
;
none : /* none */ /*{
$$ = null;
}*/
;
none_block_pass: /* none */ /*{
$$ = null;
}*/
;