/vm/parser/grammar.y
Happy | 5839 lines | 5330 code | 509 blank | 0 comment | 0 complexity | 7e6e70a7e0ebcd435b0171e9a1a36655 MD5 | raw file
Possible License(s): GPL-2.0, BSD-2-Clause, LGPL-2.1, JSON, BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- /**********************************************************************
- parse.y -
- $Author: matz $
- $Date: 2004/11/29 06:13:51 $
- created at: Fri May 28 18:02:42 JST 1993
- Copyright (C) 1993-2003 Yukihiro Matsumoto
- **********************************************************************/
- %{
- #define YYDEBUG 1
- #define YYERROR_VERBOSE 1
- #include <stdio.h>
- #include <errno.h>
- #include <ctype.h>
- #include <string.h>
- #include <stdbool.h>
- #include "builtin/array.hpp"
- #include "parser/grammar_internal.hpp"
- #include "parser/grammar_runtime.hpp"
- #include "objectmemory.hpp"
- namespace rubinius {
- namespace parser {
- #undef VALUE
- #ifndef isnumber
- #define isnumber isdigit
- #endif
- #define ISALPHA isalpha
- #define ISSPACE isspace
- #define ISALNUM(x) (isalpha(x) || isnumber(x))
- #define ISDIGIT isdigit
- #define ISXDIGIT isxdigit
- #define ISUPPER isupper
- #define ismbchar(c) (0)
- #define mbclen(c) (1)
- #define ID2SYM(i) (Object*)i
- #define string_new(ptr, len) blk2bstr(ptr, len)
- #define string_new2(ptr) cstr2bstr(ptr)
- intptr_t syd_sourceline;
- static char *syd_sourcefile;
- #define ruby_sourceline syd_sourceline
- #define ruby_sourcefile syd_sourcefile
- static int
- syd_yyerror(const char *, rb_parse_state*);
- #define yyparse syd_yyparse
- #define yylex syd_yylex
- #define yyerror(str) syd_yyerror(str, (rb_parse_state*)parse_state)
- #define yylval syd_yylval
- #define yychar syd_yychar
- #define yydebug syd_yydebug
- #define YYPARSE_PARAM parse_state
- #define YYLEX_PARAM parse_state
- #define ID_SCOPE_SHIFT 3
- #define ID_SCOPE_MASK 0x07
- #define ID_LOCAL 0x01
- #define ID_INSTANCE 0x02
- #define ID_GLOBAL 0x03
- #define ID_ATTRSET 0x04
- #define ID_CONST 0x05
- #define ID_CLASS 0x06
- #define ID_JUNK 0x07
- #define ID_INTERNAL ID_JUNK
- #define is_notop_id(id) ((id)>tLAST_TOKEN)
- #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
- #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
- #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
- #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
- #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
- #define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
- #define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
- #define is_asgn_or_id(id) ((is_notop_id(id)) && \
- (((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
- ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
- ((id)&ID_SCOPE_MASK) == ID_CLASS))
- /* FIXME these went into the ruby_state instead of parse_state
- because a ton of other crap depends on it
- char *ruby_sourcefile; current source file
- int ruby_sourceline; current line no.
- */
- static int yylex(void*, void *);
- #define BITSTACK_PUSH(stack, n) (stack = (stack<<1)|((n)&1))
- #define BITSTACK_POP(stack) (stack >>= 1)
- #define BITSTACK_LEXPOP(stack) (stack = (stack >> 1) | (stack & 1))
- #define BITSTACK_SET_P(stack) (stack&1)
- #define COND_PUSH(n) BITSTACK_PUSH(vps->cond_stack, n)
- #define COND_POP() BITSTACK_POP(vps->cond_stack)
- #define COND_LEXPOP() BITSTACK_LEXPOP(vps->cond_stack)
- #define COND_P() BITSTACK_SET_P(vps->cond_stack)
- #define CMDARG_PUSH(n) BITSTACK_PUSH(vps->cmdarg_stack, n)
- #define CMDARG_POP() BITSTACK_POP(vps->cmdarg_stack)
- #define CMDARG_LEXPOP() BITSTACK_LEXPOP(vps->cmdarg_stack)
- #define CMDARG_P() BITSTACK_SET_P(vps->cmdarg_stack)
- /*
- static int class_nest = 0;
- static int in_single = 0;
- static int in_def = 0;
- static int compile_for_eval = 0;
- static ID cur_mid = 0;
- */
- static NODE *cond(NODE*,rb_parse_state*);
- static NODE *logop(enum node_type,NODE*,NODE*,rb_parse_state*);
- static int cond_negative(NODE**);
- static NODE *newline_node(rb_parse_state*,NODE*);
- static void fixpos(NODE*,NODE*);
- static int value_expr0(NODE*,rb_parse_state*);
- static void void_expr0(NODE *);
- static void void_stmts(NODE*,rb_parse_state*);
- static NODE *remove_begin(NODE*,rb_parse_state*);
- #define value_expr(node) value_expr0((node) = \
- remove_begin(node, (rb_parse_state*)parse_state), \
- (rb_parse_state*)parse_state)
- #define void_expr(node) void_expr0((node) = remove_begin(node, (rb_parse_state*)parse_state))
- static NODE *block_append(rb_parse_state*,NODE*,NODE*);
- static NODE *list_append(rb_parse_state*,NODE*,NODE*);
- static NODE *list_concat(NODE*,NODE*);
- static NODE *arg_concat(rb_parse_state*,NODE*,NODE*);
- static NODE *arg_prepend(rb_parse_state*,NODE*,NODE*);
- static NODE *literal_concat(rb_parse_state*,NODE*,NODE*);
- static NODE *new_evstr(rb_parse_state*,NODE*);
- static NODE *evstr2dstr(rb_parse_state*,NODE*);
- static NODE *call_op(NODE*,ID,int,NODE*,rb_parse_state*);
- /* static NODE *negate_lit(NODE*); */
- static NODE *ret_args(rb_parse_state*,NODE*);
- static NODE *arg_blk_pass(NODE*,NODE*);
- static NODE *new_call(rb_parse_state*,NODE*,ID,NODE*);
- static NODE *new_fcall(rb_parse_state*,ID,NODE*);
- static NODE *new_super(rb_parse_state*,NODE*);
- static NODE *new_yield(rb_parse_state*,NODE*);
- static NODE *syd_gettable(rb_parse_state*,ID);
- #define gettable(i) syd_gettable((rb_parse_state*)parse_state, i)
- static NODE *assignable(ID,NODE*,rb_parse_state*);
- static NODE *aryset(NODE*,NODE*,rb_parse_state*);
- static NODE *attrset(NODE*,ID,rb_parse_state*);
- static void rb_backref_error(NODE*,rb_parse_state*);
- static NODE *node_assign(NODE*,NODE*,rb_parse_state*);
- static NODE *match_gen(NODE*,NODE*,rb_parse_state*);
- static void syd_local_push(rb_parse_state*, int cnt);
- #define local_push(cnt) syd_local_push(vps, cnt)
- static void syd_local_pop(rb_parse_state*);
- #define local_pop() syd_local_pop(vps)
- static intptr_t syd_local_cnt(rb_parse_state*,ID);
- #define local_cnt(i) syd_local_cnt(vps, i)
- static int syd_local_id(rb_parse_state*,ID);
- #define local_id(i) syd_local_id(vps, i)
- static ID *syd_local_tbl(rb_parse_state *st);
- static ID convert_op(ID id);
- static void tokadd(char c, rb_parse_state *parse_state);
- static int tokadd_string(int, int, int, quark *, rb_parse_state*);
- #define SHOW_PARSER_WARNS 0
- static int rb_compile_error(rb_parse_state *st, const char *fmt, ...) {
- va_list ar;
- char msg[256];
- int count;
- va_start(ar, fmt);
- count = vsnprintf(msg, 256, fmt, ar);
- va_end(ar);
- syd_yyerror(msg, st);
- return count;
- }
- static int _debug_print(const char *fmt, ...) {
- #if SHOW_PARSER_WARNS
- va_list ar;
- int i;
- va_start(ar, fmt);
- i = vprintf(fmt, ar);
- va_end(ar);
- return i;
- #else
- return 0;
- #endif
- }
- #define rb_warn _debug_print
- #define rb_warning _debug_print
- static ID rb_intern(const char *name);
- static ID rb_id_attrset(ID);
- rb_parse_state *alloc_parse_state();
- static unsigned long scan_oct(const char *start, int len, int *retlen);
- static unsigned long scan_hex(const char *start, int len, int *retlen);
- static void reset_block(rb_parse_state *parse_state);
- static NODE *extract_block_vars(rb_parse_state *parse_state, NODE* node, var_table vars);
- #define ruby_verbose 0
- #define RE_OPTION_ONCE 0x80
- #define RE_OPTION_IGNORECASE (1L)
- #define RE_OPTION_EXTENDED (RE_OPTION_IGNORECASE<<1)
- #define RE_OPTION_MULTILINE (RE_OPTION_EXTENDED<<1)
- #define RE_OPTION_SINGLELINE (RE_OPTION_MULTILINE<<1)
- #define RE_OPTION_LONGEST (RE_OPTION_SINGLELINE<<1)
- #define RE_MAY_IGNORECASE (RE_OPTION_LONGEST<<1)
- #define RE_OPTIMIZE_ANCHOR (RE_MAY_IGNORECASE<<1)
- #define RE_OPTIMIZE_EXACTN (RE_OPTIMIZE_ANCHOR<<1)
- #define RE_OPTIMIZE_NO_BM (RE_OPTIMIZE_EXACTN<<1)
- #define RE_OPTIMIZE_BMATCH (RE_OPTIMIZE_NO_BM<<1)
- #define NODE_STRTERM NODE_ZARRAY /* nothing to gc */
- #define NODE_HEREDOC NODE_ARRAY /* 1, 3 to gc */
- #define SIGN_EXTEND(x,n) (((1<<((n)-1))^((x)&~(~0<<(n))))-(1<<((n)-1)))
- #define nd_func u1.id
- #if SIZEOF_SHORT != 2
- #define nd_term(node) SIGN_EXTEND((node)->u2.id, (CHAR_BIT*2))
- #else
- #define nd_term(node) ((signed short)(node)->u2.id)
- #endif
- #define nd_paren(node) (char)((node)->u2.id >> (CHAR_BIT*2))
- #define nd_nest u3.id
- /* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
- for instance). This is too low for Ruby to parse some files, such as
- date/format.rb, therefore bump the value up to at least Bison's default. */
- #ifdef OLD_YACC
- #ifndef YYMAXDEPTH
- #define YYMAXDEPTH 10000
- #endif
- #endif
- #define vps ((rb_parse_state*)parse_state)
- %}
- %pure-parser
- %union {
- NODE *node;
- ID id;
- int num;
- var_table vars;
- }
- %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__
- %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tXSTRING_BEG
- %token <node> tINTEGER tFLOAT tSTRING_CONTENT
- %token <node> tNTH_REF tBACK_REF
- %token <num> tREGEXP_END
- %type <node> singleton strings string string1 xstring regexp
- %type <node> string_contents xstring_contents string_content
- %type <node> words qwords word_list qword_list word
- %type <node> literal numeric dsym cpath
- %type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
- %type <node> expr_value arg_value primary_value
- %type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
- %type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
- %type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
- %type <node> mrhs superclass block_call block_command
- %type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
- %type <node> assoc_list assocs assoc undef_list backref string_dvar
- %type <node> block_var opt_block_var brace_block cmd_brace_block do_block lhs none
- %type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
- %type <id> fitem variable sym symbol operation operation2 operation3
- %type <id> cname fname op f_rest_arg
- %type <num> f_norm_arg f_arg
- %token tUPLUS /* unary+ */
- %token tUMINUS /* unary- */
- %token tUBS /* unary\ */
- %token tPOW /* ** */
- %token tCMP /* <=> */
- %token tEQ /* == */
- %token tEQQ /* === */
- %token tNEQ /* != */
- %token tGEQ /* >= */
- %token tLEQ /* <= */
- %token tANDOP tOROP /* && and || */
- %token tMATCH tNMATCH /* =~ and !~ */
- %token tDOT2 tDOT3 /* .. and ... */
- %token tAREF tASET /* [] and []= */
- %token tLSHFT tRSHFT /* << and >> */
- %token tCOLON2 /* :: */
- %token tCOLON3 /* :: at EXPR_BEG */
- %token <id> tOP_ASGN /* +=, -= etc. */
- %token tASSOC /* => */
- %token tLPAREN /* ( */
- %token tLPAREN_ARG /* ( */
- %token tRPAREN /* ) */
- %token tLBRACK /* [ */
- %token tLBRACE /* { */
- %token tLBRACE_ARG /* { */
- %token tSTAR /* * */
- %token tAMPER /* & */
- %token tSYMBEG tSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
- %token tSTRING_DBEG tSTRING_DVAR tSTRING_END
- /*
- * precedence table
- */
- %nonassoc tLOWEST
- %nonassoc tLBRACE_ARG
- %nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
- %left kOR kAND
- %right kNOT
- %nonassoc kDEFINED
- %right '=' tOP_ASGN
- %left kRESCUE_MOD
- %right '?' ':'
- %nonassoc tDOT2 tDOT3
- %left tOROP
- %left tANDOP
- %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
- %left '>' tGEQ '<' tLEQ
- %left '|' '^'
- %left '&'
- %left tLSHFT tRSHFT
- %left '+' '-'
- %left '*' '/' '%'
- %right tUMINUS_NUM tUMINUS
- %right tPOW
- %right '!' '~' tUPLUS
- %token tLAST_TOKEN
- %%
- program : {
- vps->lex_state = EXPR_BEG;
- vps->variables = var_table_create();
- class_nest = 0;
- }
- compstmt
- {
- if ($2 && !compile_for_eval) {
- /* last expression should not be void */
- if (nd_type($2) != NODE_BLOCK) void_expr($2);
- else {
- NODE *node = $2;
- while (node->nd_next) {
- node = node->nd_next;
- }
- void_expr(node->nd_head);
- }
- }
- vps->top = block_append(vps, vps->top, $2);
- class_nest = 0;
- }
- ;
- bodystmt : compstmt
- opt_rescue
- opt_else
- opt_ensure
- {
- $$ = $1;
- if ($2) {
- $$ = NEW_RESCUE($1, $2, $3);
- }
- else if ($3) {
- rb_warn("else without rescue is useless");
- $$ = block_append(vps, $$, $3);
- }
- if ($4) {
- $$ = NEW_ENSURE($$, $4);
- }
- fixpos($$, $1);
- }
- ;
- compstmt : stmts opt_terms
- {
- void_stmts($1, vps);
- $$ = $1;
- }
- ;
- stmts : none
- | stmt
- {
- $$ = newline_node(vps, $1);
- }
- | stmts terms stmt
- {
- $$ = block_append(vps, $1, newline_node(vps, $3));
- }
- | error stmt
- {
- $$ = remove_begin($2, vps);
- }
- ;
- stmt : kALIAS fitem {vps->lex_state = EXPR_FNAME;} fitem
- {
- $$ = NEW_ALIAS($2, $4);
- }
- | kALIAS tGVAR tGVAR
- {
- $$ = NEW_VALIAS($2, $3);
- }
- | kALIAS tGVAR tBACK_REF
- {
- char buf[3];
- snprintf(buf, sizeof(buf), "$%c", (char)$3->nd_nth);
- $$ = NEW_VALIAS($2, rb_intern(buf));
- }
- | kALIAS tGVAR tNTH_REF
- {
- yyerror("can't make alias for the number variables");
- $$ = 0;
- }
- | kUNDEF undef_list
- {
- $$ = $2;
- }
- | stmt kIF_MOD expr_value
- {
- $$ = NEW_IF(cond($3, vps), remove_begin($1, vps), 0);
- fixpos($$, $3);
- if (cond_negative(&$$->nd_cond)) {
- $$->nd_else = $$->nd_body;
- $$->nd_body = 0;
- }
- }
- | stmt kUNLESS_MOD expr_value
- {
- $$ = NEW_UNLESS(cond($3, vps), remove_begin($1, vps), 0);
- fixpos($$, $3);
- if (cond_negative(&$$->nd_cond)) {
- $$->nd_body = $$->nd_else;
- $$->nd_else = 0;
- }
- }
- | stmt kWHILE_MOD expr_value
- {
- if ($1 && nd_type($1) == NODE_BEGIN) {
- $$ = NEW_WHILE(cond($3, vps), $1->nd_body, 0);
- }
- else {
- $$ = NEW_WHILE(cond($3, vps), $1, 1);
- }
- if (cond_negative(&$$->nd_cond)) {
- nd_set_type($$, NODE_UNTIL);
- }
- }
- | stmt kUNTIL_MOD expr_value
- {
- if ($1 && nd_type($1) == NODE_BEGIN) {
- $$ = NEW_UNTIL(cond($3, vps), $1->nd_body, 0);
- }
- else {
- $$ = NEW_UNTIL(cond($3, vps), $1, 1);
- }
- if (cond_negative(&$$->nd_cond)) {
- nd_set_type($$, NODE_WHILE);
- }
- }
- | stmt kRESCUE_MOD stmt
- {
- NODE *resq = NEW_RESBODY(0, remove_begin($3, vps), 0);
- $$ = NEW_RESCUE(remove_begin($1, vps), resq, 0);
- }
- | klBEGIN
- {
- if (in_def || in_single) {
- yyerror("BEGIN in method");
- }
- local_push(0);
- }
- '{' compstmt '}'
- {
- /*
- ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
- NEW_PREEXE($4));
- */
- local_pop();
- $$ = 0;
- }
- | klEND '{' compstmt '}'
- {
- if (in_def || in_single) {
- rb_warn("END in method; use at_exit");
- }
- $$ = NEW_ITER(0, NEW_POSTEXE(), $3);
- }
- | lhs '=' command_call
- {
- $$ = node_assign($1, $3, vps);
- }
- | mlhs '=' command_call
- {
- value_expr($3);
- $1->nd_value = ($1->nd_head) ? NEW_TO_ARY($3) : NEW_ARRAY($3);
- $$ = $1;
- }
- | var_lhs tOP_ASGN command_call
- {
- value_expr($3);
- if ($1) {
- ID vid = $1->nd_vid;
- if ($2 == tOROP) {
- $1->nd_value = $3;
- $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
- if (is_asgn_or_id(vid)) {
- $$->nd_aid = vid;
- }
- }
- else if ($2 == tANDOP) {
- $1->nd_value = $3;
- $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
- }
- else {
- $$ = $1;
- $$->nd_value = call_op(gettable(vid),$2,1,$3, vps);
- }
- }
- else {
- $$ = 0;
- }
- }
- | primary_value '[' aref_args ']' tOP_ASGN command_call
- {
- NODE *args;
- value_expr($6);
- if (!$3) $3 = NEW_ZARRAY();
- args = arg_concat(vps, $6, $3);
- if ($5 == tOROP) {
- $5 = 0;
- }
- else if ($5 == tANDOP) {
- $5 = 1;
- }
- $$ = NEW_OP_ASGN1($1, $5, args);
- fixpos($$, $1);
- }
- | primary_value '.' tIDENTIFIER tOP_ASGN command_call
- {
- value_expr($5);
- if ($4 == tOROP) {
- $4 = 0;
- }
- else if ($4 == tANDOP) {
- $4 = 1;
- }
- $$ = NEW_OP_ASGN2($1, $3, $4, $5);
- fixpos($$, $1);
- }
- | primary_value '.' tCONSTANT tOP_ASGN command_call
- {
- value_expr($5);
- if ($4 == tOROP) {
- $4 = 0;
- }
- else if ($4 == tANDOP) {
- $4 = 1;
- }
- $$ = NEW_OP_ASGN2($1, $3, $4, $5);
- fixpos($$, $1);
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
- {
- value_expr($5);
- if ($4 == tOROP) {
- $4 = 0;
- }
- else if ($4 == tANDOP) {
- $4 = 1;
- }
- $$ = NEW_OP_ASGN2($1, $3, $4, $5);
- fixpos($$, $1);
- }
- | backref tOP_ASGN command_call
- {
- rb_backref_error($1, vps);
- $$ = 0;
- }
- | lhs '=' mrhs
- {
- $$ = node_assign($1, NEW_SVALUE($3), vps);
- }
- | mlhs '=' arg_value
- {
- $1->nd_value = ($1->nd_head) ? NEW_TO_ARY($3) : NEW_ARRAY($3);
- $$ = $1;
- }
- | mlhs '=' mrhs
- {
- $1->nd_value = $3;
- $$ = $1;
- }
- | expr
- ;
- expr : command_call
- | expr kAND expr
- {
- $$ = logop(NODE_AND, $1, $3, vps);
- }
- | expr kOR expr
- {
- $$ = logop(NODE_OR, $1, $3, vps);
- }
- | kNOT expr
- {
- $$ = NEW_NOT(cond($2, vps));
- }
- | '!' command_call
- {
- $$ = NEW_NOT(cond($2, vps));
- }
- | arg
- ;
- expr_value : expr
- {
- value_expr($$);
- $$ = $1;
- }
- ;
- command_call : command
- | block_command
- | kRETURN call_args
- {
- $$ = NEW_RETURN(ret_args(vps, $2));
- }
- | kBREAK call_args
- {
- $$ = NEW_BREAK(ret_args(vps, $2));
- }
- | kNEXT call_args
- {
- $$ = NEW_NEXT(ret_args(vps, $2));
- }
- ;
- block_command : block_call
- | block_call '.' operation2 command_args
- {
- $$ = new_call(vps, $1, $3, $4);
- }
- | block_call tCOLON2 operation2 command_args
- {
- $$ = new_call(vps, $1, $3, $4);
- }
- ;
- cmd_brace_block : tLBRACE_ARG
- {
- $<num>1 = ruby_sourceline;
- reset_block(vps);
- }
- opt_block_var { $<vars>$ = vps->block_vars; }
- compstmt
- '}'
- {
- $$ = NEW_ITER($3, 0, extract_block_vars(vps, $5, $<vars>4));
- nd_set_line($$, $<num>1);
- }
- ;
- command : operation command_args %prec tLOWEST
- {
- $$ = new_fcall(vps, $1, $2);
- fixpos($$, $2);
- }
- | operation command_args cmd_brace_block
- {
- $$ = new_fcall(vps, $1, $2);
- if ($3) {
- if (nd_type($$) == NODE_BLOCK_PASS) {
- rb_compile_error(vps, "both block arg and actual block given");
- }
- $3->nd_iter = $$;
- $$ = $3;
- }
- fixpos($$, $2);
- }
- | primary_value '.' operation2 command_args %prec tLOWEST
- {
- $$ = new_call(vps, $1, $3, $4);
- fixpos($$, $1);
- }
- | primary_value '.' operation2 command_args cmd_brace_block
- {
- $$ = new_call(vps, $1, $3, $4);
- if ($5) {
- if (nd_type($$) == NODE_BLOCK_PASS) {
- rb_compile_error(vps, "both block arg and actual block given");
- }
- $5->nd_iter = $$;
- $$ = $5;
- }
- fixpos($$, $1);
- }
- | primary_value tCOLON2 operation2 command_args %prec tLOWEST
- {
- $$ = new_call(vps, $1, $3, $4);
- fixpos($$, $1);
- }
- | primary_value tCOLON2 operation2 command_args cmd_brace_block
- {
- $$ = new_call(vps, $1, $3, $4);
- if ($5) {
- if (nd_type($$) == NODE_BLOCK_PASS) {
- rb_compile_error(vps, "both block arg and actual block given");
- }
- $5->nd_iter = $$;
- $$ = $5;
- }
- fixpos($$, $1);
- }
- | kSUPER command_args
- {
- $$ = new_super(vps, $2);
- fixpos($$, $2);
- }
- | kYIELD command_args
- {
- $$ = new_yield(vps, $2);
- fixpos($$, $2);
- }
- ;
- mlhs : mlhs_basic
- | tLPAREN mlhs_entry ')'
- {
- $$ = $2;
- }
- ;
- mlhs_entry : mlhs_basic
- | tLPAREN mlhs_entry ')'
- {
- $$ = NEW_MASGN(NEW_LIST($2), 0);
- }
- ;
- mlhs_basic : mlhs_head
- {
- $$ = NEW_MASGN($1, 0);
- }
- | mlhs_head mlhs_item
- {
- $$ = NEW_MASGN(list_append(vps, $1,$2), 0);
- }
- | mlhs_head tSTAR mlhs_node
- {
- $$ = NEW_MASGN($1, $3);
- }
- | mlhs_head tSTAR
- {
- $$ = NEW_MASGN($1, -1);
- }
- | tSTAR mlhs_node
- {
- $$ = NEW_MASGN(0, $2);
- }
- | tSTAR
- {
- $$ = NEW_MASGN(0, -1);
- }
- ;
- mlhs_item : mlhs_node
- | tLPAREN mlhs_entry ')'
- {
- $$ = $2;
- }
- ;
- mlhs_head : mlhs_item ','
- {
- $$ = NEW_LIST($1);
- }
- | mlhs_head mlhs_item ','
- {
- $$ = list_append(vps, $1, $2);
- }
- ;
- mlhs_node : variable
- {
- $$ = assignable($1, 0, vps);
- }
- | primary_value '[' aref_args ']'
- {
- $$ = aryset($1, $3, vps);
- }
- | primary_value '.' tIDENTIFIER
- {
- $$ = attrset($1, $3, vps);
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- $$ = attrset($1, $3, vps);
- }
- | primary_value '.' tCONSTANT
- {
- $$ = attrset($1, $3, vps);
- }
- | primary_value tCOLON2 tCONSTANT
- {
- if (in_def || in_single)
- yyerror("dynamic constant assignment");
- $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
- }
- | tCOLON3 tCONSTANT
- {
- if (in_def || in_single)
- yyerror("dynamic constant assignment");
- $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
- }
- | backref
- {
- rb_backref_error($1, vps);
- $$ = 0;
- }
- ;
- lhs : variable
- {
- $$ = assignable($1, 0, vps);
- }
- | primary_value '[' aref_args ']'
- {
- $$ = aryset($1, $3, vps);
- }
- | primary_value '.' tIDENTIFIER
- {
- $$ = attrset($1, $3, vps);
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- $$ = attrset($1, $3, vps);
- }
- | primary_value '.' tCONSTANT
- {
- $$ = attrset($1, $3, vps);
- }
- | primary_value tCOLON2 tCONSTANT
- {
- if (in_def || in_single)
- yyerror("dynamic constant assignment");
- $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
- }
- | tCOLON3 tCONSTANT
- {
- if (in_def || in_single)
- yyerror("dynamic constant assignment");
- $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
- }
- | backref
- {
- rb_backref_error($1, vps);
- $$ = 0;
- }
- ;
- cname : tIDENTIFIER
- {
- yyerror("class/module name must be CONSTANT");
- }
- | tCONSTANT
- ;
- cpath : tCOLON3 cname
- {
- $$ = NEW_COLON3($2);
- }
- | cname
- {
- $$ = NEW_COLON2(0, $$);
- }
- | primary_value tCOLON2 cname
- {
- $$ = NEW_COLON2($1, $3);
- }
- ;
- fname : tIDENTIFIER
- | tCONSTANT
- | tFID
- | op
- {
- vps->lex_state = EXPR_END;
- $$ = convert_op($1);
- }
- | reswords
- {
- vps->lex_state = EXPR_END;
- $$ = $<id>1;
- }
- ;
- fitem : fname
- | symbol
- ;
- undef_list : fitem
- {
- $$ = NEW_UNDEF($1);
- }
- | undef_list ',' {vps->lex_state = EXPR_FNAME;} fitem
- {
- $$ = block_append(vps, $1, NEW_UNDEF($4));
- }
- ;
- op : '|' { $$ = '|'; }
- | '^' { $$ = '^'; }
- | '&' { $$ = '&'; }
- | tCMP { $$ = tCMP; }
- | tEQ { $$ = tEQ; }
- | tEQQ { $$ = tEQQ; }
- | tMATCH { $$ = tMATCH; }
- | '>' { $$ = '>'; }
- | tGEQ { $$ = tGEQ; }
- | '<' { $$ = '<'; }
- | tLEQ { $$ = tLEQ; }
- | tLSHFT { $$ = tLSHFT; }
- | tRSHFT { $$ = tRSHFT; }
- | '+' { $$ = '+'; }
- | '-' { $$ = '-'; }
- | '*' { $$ = '*'; }
- | tSTAR { $$ = '*'; }
- | '/' { $$ = '/'; }
- | '%' { $$ = '%'; }
- | tPOW { $$ = tPOW; }
- | '~' { $$ = '~'; }
- | tUPLUS { $$ = tUPLUS; }
- | tUMINUS { $$ = tUMINUS; }
- | tAREF { $$ = tAREF; }
- | tASET { $$ = tASET; }
- | '`' { $$ = '`'; }
- ;
- 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_MOD | kUNLESS_MOD | kWHILE_MOD | kUNTIL_MOD | kRESCUE_MOD
- ;
- arg : lhs '=' arg
- {
- $$ = node_assign($1, $3, vps);
- }
- | lhs '=' arg kRESCUE_MOD arg
- {
- $$ = node_assign($1, NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0), vps);
- }
- | var_lhs tOP_ASGN arg
- {
- value_expr($3);
- if ($1) {
- ID vid = $1->nd_vid;
- if ($2 == tOROP) {
- $1->nd_value = $3;
- $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
- if (is_asgn_or_id(vid)) {
- $$->nd_aid = vid;
- }
- }
- else if ($2 == tANDOP) {
- $1->nd_value = $3;
- $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
- }
- else {
- $$ = $1;
- $$->nd_value = call_op(gettable(vid),$2,1,$3, vps);
- }
- }
- else {
- $$ = 0;
- }
- }
- | primary_value '[' aref_args ']' tOP_ASGN arg
- {
- NODE *args;
- value_expr($6);
- if (!$3) $3 = NEW_ZARRAY();
- args = arg_concat(vps, $6, $3);
- if ($5 == tOROP) {
- $5 = 0;
- }
- else if ($5 == tANDOP) {
- $5 = 1;
- }
- $$ = NEW_OP_ASGN1($1, $5, args);
- fixpos($$, $1);
- }
- | primary_value '.' tIDENTIFIER tOP_ASGN arg
- {
- value_expr($5);
- if ($4 == tOROP) {
- $4 = 0;
- }
- else if ($4 == tANDOP) {
- $4 = 1;
- }
- $$ = NEW_OP_ASGN2($1, $3, $4, $5);
- fixpos($$, $1);
- }
- | primary_value '.' tCONSTANT tOP_ASGN arg
- {
- value_expr($5);
- if ($4 == tOROP) {
- $4 = 0;
- }
- else if ($4 == tANDOP) {
- $4 = 1;
- }
- $$ = NEW_OP_ASGN2($1, $3, $4, $5);
- fixpos($$, $1);
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
- {
- value_expr($5);
- if ($4 == tOROP) {
- $4 = 0;
- }
- else if ($4 == tANDOP) {
- $4 = 1;
- }
- $$ = NEW_OP_ASGN2($1, $3, $4, $5);
- fixpos($$, $1);
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
- {
- yyerror("constant re-assignment");
- $$ = 0;
- }
- | tCOLON3 tCONSTANT tOP_ASGN arg
- {
- yyerror("constant re-assignment");
- $$ = 0;
- }
- | backref tOP_ASGN arg
- {
- rb_backref_error($1, vps);
- $$ = 0;
- }
- | arg tDOT2 arg
- {
- value_expr($1);
- value_expr($3);
- $$ = NEW_DOT2($1, $3);
- }
- | arg tDOT3 arg
- {
- value_expr($1);
- value_expr($3);
- $$ = NEW_DOT3($1, $3);
- }
- | arg '+' arg
- {
- $$ = call_op($1, '+', 1, $3, vps);
- }
- | arg '-' arg
- {
- $$ = call_op($1, '-', 1, $3, vps);
- }
- | arg '*' arg
- {
- $$ = call_op($1, '*', 1, $3, vps);
- }
- | arg '/' arg
- {
- $$ = call_op($1, '/', 1, $3, vps);
- }
- | arg '%' arg
- {
- $$ = call_op($1, '%', 1, $3, vps);
- }
- | arg tPOW arg
- {
- $$ = call_op($1, tPOW, 1, $3, vps);
- }
- | tUMINUS_NUM tINTEGER tPOW arg
- {
- $$ = call_op(call_op($2, tPOW, 1, $4, vps), tUMINUS, 0, 0, vps);
- }
- | tUMINUS_NUM tFLOAT tPOW arg
- {
- $$ = call_op(call_op($2, tPOW, 1, $4, vps), tUMINUS, 0, 0, vps);
- }
- | tUPLUS arg
- {
- if ($2 && nd_type($2) == NODE_LIT) {
- $$ = $2;
- }
- else {
- $$ = call_op($2, tUPLUS, 0, 0, vps);
- }
- }
- | tUMINUS arg
- {
- $$ = call_op($2, tUMINUS, 0, 0, vps);
- }
- | arg '|' arg
- {
- $$ = call_op($1, '|', 1, $3, vps);
- }
- | arg '^' arg
- {
- $$ = call_op($1, '^', 1, $3, vps);
- }
- | arg '&' arg
- {
- $$ = call_op($1, '&', 1, $3, vps);
- }
- | arg tCMP arg
- {
- $$ = call_op($1, tCMP, 1, $3, vps);
- }
- | arg '>' arg
- {
- $$ = call_op($1, '>', 1, $3, vps);
- }
- | arg tGEQ arg
- {
- $$ = call_op($1, tGEQ, 1, $3, vps);
- }
- | arg '<' arg
- {
- $$ = call_op($1, '<', 1, $3, vps);
- }
- | arg tLEQ arg
- {
- $$ = call_op($1, tLEQ, 1, $3, vps);
- }
- | arg tEQ arg
- {
- $$ = call_op($1, tEQ, 1, $3, vps);
- }
- | arg tEQQ arg
- {
- $$ = call_op($1, tEQQ, 1, $3, vps);
- }
- | arg tNEQ arg
- {
- $$ = NEW_NOT(call_op($1, tEQ, 1, $3, vps));
- }
- | arg tMATCH arg
- {
- $$ = match_gen($1, $3, vps);
- }
- | arg tNMATCH arg
- {
- $$ = NEW_NOT(match_gen($1, $3, vps));
- }
- | '!' arg
- {
- $$ = NEW_NOT(cond($2, vps));
- }
- | '~' arg
- {
- $$ = call_op($2, '~', 0, 0, vps);
- }
- | arg tLSHFT arg
- {
- $$ = call_op($1, tLSHFT, 1, $3, vps);
- }
- | arg tRSHFT arg
- {
- $$ = call_op($1, tRSHFT, 1, $3, vps);
- }
- | arg tANDOP arg
- {
- $$ = logop(NODE_AND, $1, $3, vps);
- }
- | arg tOROP arg
- {
- $$ = logop(NODE_OR, $1, $3, vps);
- }
- | kDEFINED opt_nl {vps->in_defined = 1;} arg
- {
- vps->in_defined = 0;
- $$ = NEW_DEFINED($4);
- }
- | arg '?' {vps->ternary_colon++;} arg ':' arg
- {
- $$ = NEW_IF(cond($1, vps), $4, $6);
- fixpos($$, $1);
- vps->ternary_colon--;
- }
- | primary
- {
- $$ = $1;
- }
- ;
- arg_value : arg
- {
- value_expr($1);
- $$ = $1;
- }
- ;
- aref_args : none
- | command opt_nl
- {
- rb_warn("parenthesize argument(s) for future version");
- $$ = NEW_LIST($1);
- }
- | args trailer
- {
- $$ = $1;
- }
- | args ',' tSTAR arg opt_nl
- {
- value_expr($4);
- $$ = arg_concat(vps, $1, $4);
- }
- | assocs trailer
- {
- $$ = NEW_LIST(NEW_HASH($1));
- }
- | tSTAR arg opt_nl
- {
- value_expr($2);
- $$ = NEW_NEWLINE(NEW_SPLAT($2));
- }
- ;
- paren_args : '(' none ')'
- {
- $$ = $2;
- }
- | '(' call_args opt_nl ')'
- {
- $$ = $2;
- }
- | '(' block_call opt_nl ')'
- {
- rb_warn("parenthesize argument for future version");
- $$ = NEW_LIST($2);
- }
- | '(' args ',' block_call opt_nl ')'
- {
- rb_warn("parenthesize argument for future version");
- $$ = list_append(vps, $2, $4);
- }
- ;
- opt_paren_args : none
- | paren_args
- ;
- call_args : command
- {
- rb_warn("parenthesize argument(s) for future version");
- $$ = NEW_LIST($1);
- }
- | args opt_block_arg
- {
- $$ = arg_blk_pass($1, $2);
- }
- | args ',' tSTAR arg_value opt_block_arg
- {
- $$ = arg_concat(vps, $1, $4);
- $$ = arg_blk_pass($$, $5);
- }
- | assocs opt_block_arg
- {
- $$ = NEW_LIST(NEW_HASH($1));
- $$ = arg_blk_pass($$, $2);
- }
- | assocs ',' tSTAR arg_value opt_block_arg
- {
- $$ = arg_concat(vps, NEW_LIST(NEW_HASH($1)), $4);
- $$ = arg_blk_pass($$, $5);
- }
- | args ',' assocs opt_block_arg
- {
- $$ = list_append(vps, $1, NEW_HASH($3));
- $$ = arg_blk_pass($$, $4);
- }
- | args ',' assocs ',' tSTAR arg opt_block_arg
- {
- value_expr($6);
- $$ = arg_concat(vps, list_append(vps, $1, NEW_HASH($3)), $6);
- $$ = arg_blk_pass($$, $7);
- }
- | tSTAR arg_value opt_block_arg
- {
- $$ = arg_blk_pass(NEW_SPLAT($2), $3);
- }
- | block_arg
- ;
- call_args2 : arg_value ',' args opt_block_arg
- {
- $$ = arg_blk_pass(list_concat(NEW_LIST($1),$3), $4);
- }
- | arg_value ',' block_arg
- {
- $$ = arg_blk_pass($1, $3);
- }
- | arg_value ',' tSTAR arg_value opt_block_arg
- {
- $$ = arg_concat(vps, NEW_LIST($1), $4);
- $$ = arg_blk_pass($$, $5);
- }
- | arg_value ',' args ',' tSTAR arg_value opt_block_arg
- {
- $$ = arg_concat(vps, list_concat(NEW_LIST($1),$3), $6);
- $$ = arg_blk_pass($$, $7);
- }
- | assocs opt_block_arg
- {
- $$ = NEW_LIST(NEW_HASH($1));
- $$ = arg_blk_pass($$, $2);
- }
- | assocs ',' tSTAR arg_value opt_block_arg
- {
- $$ = arg_concat(vps, NEW_LIST(NEW_HASH($1)), $4);
- $$ = arg_blk_pass($$, $5);
- }
- | arg_value ',' assocs opt_block_arg
- {
- $$ = list_append(vps, NEW_LIST($1), NEW_HASH($3));
- $$ = arg_blk_pass($$, $4);
- }
- | arg_value ',' args ',' assocs opt_block_arg
- {
- $$ = list_append(vps, list_concat(NEW_LIST($1),$3), NEW_HASH($5));
- $$ = arg_blk_pass($$, $6);
- }
- | arg_value ',' assocs ',' tSTAR arg_value opt_block_arg
- {
- $$ = arg_concat(vps, list_append(vps, NEW_LIST($1), NEW_HASH($3)), $6);
- $$ = arg_blk_pass($$, $7);
- }
- | arg_value ',' args ',' assocs ',' tSTAR arg_value opt_block_arg
- {
- $$ = arg_concat(vps, list_append(vps,
- list_concat(NEW_LIST($1), $3), NEW_HASH($5)), $8);
- $$ = arg_blk_pass($$, $9);
- }
- | tSTAR arg_value opt_block_arg
- {
- $$ = arg_blk_pass(NEW_SPLAT($2), $3);
- }
- | block_arg
- ;
- command_args : {
- $<num>$ = vps->cmdarg_stack;
- CMDARG_PUSH(1);
- }
- open_args
- {
- /* CMDARG_POP() */
- vps->cmdarg_stack = $<num>1;
- $$ = $2;
- }
- ;
- open_args : call_args
- | tLPAREN_ARG {vps->lex_state = EXPR_ENDARG;} ')'
- {
- rb_warn("don't put space before argument parentheses");
- $$ = 0;
- }
- | tLPAREN_ARG call_args2 {v…
Large files files are truncated, but you can click here to view the full file