00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 %{
00013
00014 #define YYDEBUG 1
00015 #define YYERROR_VERBOSE 1
00016 #define YYSTACK_USE_ALLOCA 0
00017
00018 #include "ruby/ruby.h"
00019 #include "ruby/st.h"
00020 #include "ruby/encoding.h"
00021 #include "internal.h"
00022 #include "node.h"
00023 #include "parse.h"
00024 #include "id.h"
00025 #include "regenc.h"
00026 #include <stdio.h>
00027 #include <errno.h>
00028 #include <ctype.h>
00029
00030 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00031
00032 #define YYMALLOC(size) rb_parser_malloc(parser, (size))
00033 #define YYREALLOC(ptr, size) rb_parser_realloc(parser, (ptr), (size))
00034 #define YYCALLOC(nelem, size) rb_parser_calloc(parser, (nelem), (size))
00035 #define YYFREE(ptr) rb_parser_free(parser, (ptr))
00036 #define malloc YYMALLOC
00037 #define realloc YYREALLOC
00038 #define calloc YYCALLOC
00039 #define free YYFREE
00040
00041 #ifndef RIPPER
00042 static ID register_symid(ID, const char *, long, rb_encoding *);
00043 #define REGISTER_SYMID(id, name) register_symid((id), (name), strlen(name), enc)
00044 #include "id.c"
00045 #endif
00046
00047 #define is_notop_id(id) ((id)>tLAST_TOKEN)
00048 #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
00049 #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
00050 #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
00051 #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
00052 #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
00053 #define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
00054 #define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
00055
00056 #define is_asgn_or_id(id) ((is_notop_id(id)) && \
00057 (((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
00058 ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
00059 ((id)&ID_SCOPE_MASK) == ID_CLASS))
00060
00061 enum lex_state_e {
00062 EXPR_BEG,
00063 EXPR_END,
00064 EXPR_ENDARG,
00065 EXPR_ENDFN,
00066 EXPR_ARG,
00067 EXPR_CMDARG,
00068 EXPR_MID,
00069 EXPR_FNAME,
00070 EXPR_DOT,
00071 EXPR_CLASS,
00072 EXPR_VALUE,
00073 EXPR_MAX_STATE
00074 };
00075
00076 typedef VALUE stack_type;
00077
00078 # define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1))
00079 # define BITSTACK_POP(stack) ((stack) = (stack) >> 1)
00080 # define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1))
00081 # define BITSTACK_SET_P(stack) ((stack)&1)
00082
00083 #define COND_PUSH(n) BITSTACK_PUSH(cond_stack, (n))
00084 #define COND_POP() BITSTACK_POP(cond_stack)
00085 #define COND_LEXPOP() BITSTACK_LEXPOP(cond_stack)
00086 #define COND_P() BITSTACK_SET_P(cond_stack)
00087
00088 #define CMDARG_PUSH(n) BITSTACK_PUSH(cmdarg_stack, (n))
00089 #define CMDARG_POP() BITSTACK_POP(cmdarg_stack)
00090 #define CMDARG_LEXPOP() BITSTACK_LEXPOP(cmdarg_stack)
00091 #define CMDARG_P() BITSTACK_SET_P(cmdarg_stack)
00092
00093 struct vtable {
00094 ID *tbl;
00095 int pos;
00096 int capa;
00097 struct vtable *prev;
00098 };
00099
00100 struct local_vars {
00101 struct vtable *args;
00102 struct vtable *vars;
00103 struct vtable *used;
00104 struct local_vars *prev;
00105 };
00106
00107 #define DVARS_INHERIT ((void*)1)
00108 #define DVARS_TOPSCOPE NULL
00109 #define DVARS_SPECIAL_P(tbl) (!POINTER_P(tbl))
00110 #define POINTER_P(val) ((VALUE)(val) & ~(VALUE)3)
00111
00112 static int
00113 vtable_size(const struct vtable *tbl)
00114 {
00115 if (POINTER_P(tbl)) {
00116 return tbl->pos;
00117 }
00118 else {
00119 return 0;
00120 }
00121 }
00122
00123 #define VTBL_DEBUG 0
00124
00125 static struct vtable *
00126 vtable_alloc(struct vtable *prev)
00127 {
00128 struct vtable *tbl = ALLOC(struct vtable);
00129 tbl->pos = 0;
00130 tbl->capa = 8;
00131 tbl->tbl = ALLOC_N(ID, tbl->capa);
00132 tbl->prev = prev;
00133 if (VTBL_DEBUG) printf("vtable_alloc: %p\n", (void *)tbl);
00134 return tbl;
00135 }
00136
00137 static void
00138 vtable_free(struct vtable *tbl)
00139 {
00140 if (VTBL_DEBUG)printf("vtable_free: %p\n", (void *)tbl);
00141 if (POINTER_P(tbl)) {
00142 if (tbl->tbl) {
00143 xfree(tbl->tbl);
00144 }
00145 xfree(tbl);
00146 }
00147 }
00148
00149 static void
00150 vtable_add(struct vtable *tbl, ID id)
00151 {
00152 if (!POINTER_P(tbl)) {
00153 rb_bug("vtable_add: vtable is not allocated (%p)", (void *)tbl);
00154 }
00155 if (VTBL_DEBUG) printf("vtable_add: %p, %s\n", (void *)tbl, rb_id2name(id));
00156
00157 if (tbl->pos == tbl->capa) {
00158 tbl->capa = tbl->capa * 2;
00159 REALLOC_N(tbl->tbl, ID, tbl->capa);
00160 }
00161 tbl->tbl[tbl->pos++] = id;
00162 }
00163
00164 static int
00165 vtable_included(const struct vtable * tbl, ID id)
00166 {
00167 int i;
00168
00169 if (POINTER_P(tbl)) {
00170 for (i = 0; i < tbl->pos; i++) {
00171 if (tbl->tbl[i] == id) {
00172 return i+1;
00173 }
00174 }
00175 }
00176 return 0;
00177 }
00178
00179
00180 #ifndef RIPPER
00181 typedef struct token_info {
00182 const char *token;
00183 int linenum;
00184 int column;
00185 int nonspc;
00186 struct token_info *next;
00187 } token_info;
00188 #endif
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 struct parser_params {
00200 int is_ripper;
00201 NODE *heap;
00202
00203 YYSTYPE *parser_yylval;
00204 VALUE eofp;
00205
00206 NODE *parser_lex_strterm;
00207 enum lex_state_e parser_lex_state;
00208 stack_type parser_cond_stack;
00209 stack_type parser_cmdarg_stack;
00210 int parser_class_nest;
00211 int parser_paren_nest;
00212 int parser_lpar_beg;
00213 int parser_in_single;
00214 int parser_in_def;
00215 int parser_compile_for_eval;
00216 VALUE parser_cur_mid;
00217 int parser_in_defined;
00218 char *parser_tokenbuf;
00219 int parser_tokidx;
00220 int parser_toksiz;
00221 VALUE parser_lex_input;
00222 VALUE parser_lex_lastline;
00223 VALUE parser_lex_nextline;
00224 const char *parser_lex_pbeg;
00225 const char *parser_lex_p;
00226 const char *parser_lex_pend;
00227 int parser_heredoc_end;
00228 int parser_command_start;
00229 NODE *parser_deferred_nodes;
00230 long parser_lex_gets_ptr;
00231 VALUE (*parser_lex_gets)(struct parser_params*,VALUE);
00232 struct local_vars *parser_lvtbl;
00233 int parser_ruby__end__seen;
00234 int line_count;
00235 int has_shebang;
00236 char *parser_ruby_sourcefile;
00237 int parser_ruby_sourceline;
00238 rb_encoding *enc;
00239 rb_encoding *utf8;
00240
00241 int parser_yydebug;
00242
00243 #ifndef RIPPER
00244
00245 NODE *parser_eval_tree_begin;
00246 NODE *parser_eval_tree;
00247 VALUE debug_lines;
00248 VALUE coverage;
00249 int nerr;
00250
00251 int parser_token_info_enabled;
00252 token_info *parser_token_info;
00253 #else
00254
00255 VALUE parser_ruby_sourcefile_string;
00256 const char *tokp;
00257 VALUE delayed;
00258 int delayed_line;
00259 int delayed_col;
00260
00261 VALUE value;
00262 VALUE result;
00263 VALUE parsing_thread;
00264 int toplevel_p;
00265 #endif
00266 };
00267
00268 #define UTF8_ENC() (parser->utf8 ? parser->utf8 : \
00269 (parser->utf8 = rb_utf8_encoding()))
00270 #define STR_NEW(p,n) rb_enc_str_new((p),(n),parser->enc)
00271 #define STR_NEW0() rb_enc_str_new(0,0,parser->enc)
00272 #define STR_NEW2(p) rb_enc_str_new((p),strlen(p),parser->enc)
00273 #define STR_NEW3(p,n,e,func) parser_str_new((p),(n),(e),(func),parser->enc)
00274 #define ENC_SINGLE(cr) ((cr)==ENC_CODERANGE_7BIT)
00275 #define TOK_INTERN(mb) rb_intern3(tok(), toklen(), parser->enc)
00276
00277 static int parser_yyerror(struct parser_params*, const char*);
00278 #define yyerror(msg) parser_yyerror(parser, (msg))
00279
00280 #define YYLEX_PARAM parser
00281
00282 #define lex_strterm (parser->parser_lex_strterm)
00283 #define lex_state (parser->parser_lex_state)
00284 #define cond_stack (parser->parser_cond_stack)
00285 #define cmdarg_stack (parser->parser_cmdarg_stack)
00286 #define class_nest (parser->parser_class_nest)
00287 #define paren_nest (parser->parser_paren_nest)
00288 #define lpar_beg (parser->parser_lpar_beg)
00289 #define in_single (parser->parser_in_single)
00290 #define in_def (parser->parser_in_def)
00291 #define compile_for_eval (parser->parser_compile_for_eval)
00292 #define cur_mid (parser->parser_cur_mid)
00293 #define in_defined (parser->parser_in_defined)
00294 #define tokenbuf (parser->parser_tokenbuf)
00295 #define tokidx (parser->parser_tokidx)
00296 #define toksiz (parser->parser_toksiz)
00297 #define lex_input (parser->parser_lex_input)
00298 #define lex_lastline (parser->parser_lex_lastline)
00299 #define lex_nextline (parser->parser_lex_nextline)
00300 #define lex_pbeg (parser->parser_lex_pbeg)
00301 #define lex_p (parser->parser_lex_p)
00302 #define lex_pend (parser->parser_lex_pend)
00303 #define heredoc_end (parser->parser_heredoc_end)
00304 #define command_start (parser->parser_command_start)
00305 #define deferred_nodes (parser->parser_deferred_nodes)
00306 #define lex_gets_ptr (parser->parser_lex_gets_ptr)
00307 #define lex_gets (parser->parser_lex_gets)
00308 #define lvtbl (parser->parser_lvtbl)
00309 #define ruby__end__seen (parser->parser_ruby__end__seen)
00310 #define ruby_sourceline (parser->parser_ruby_sourceline)
00311 #define ruby_sourcefile (parser->parser_ruby_sourcefile)
00312 #define current_enc (parser->enc)
00313 #define yydebug (parser->parser_yydebug)
00314 #ifdef RIPPER
00315 #else
00316 #define ruby_eval_tree (parser->parser_eval_tree)
00317 #define ruby_eval_tree_begin (parser->parser_eval_tree_begin)
00318 #define ruby_debug_lines (parser->debug_lines)
00319 #define ruby_coverage (parser->coverage)
00320 #endif
00321
00322 static int yylex(void*, void*);
00323
00324 #ifndef RIPPER
00325 #define yyparse ruby_yyparse
00326
00327 static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE);
00328 #define rb_node_newnode(type, a1, a2, a3) node_newnode(parser, (type), (a1), (a2), (a3))
00329
00330 static NODE *cond_gen(struct parser_params*,NODE*);
00331 #define cond(node) cond_gen(parser, (node))
00332 static NODE *logop_gen(struct parser_params*,enum node_type,NODE*,NODE*);
00333 #define logop(type,node1,node2) logop_gen(parser, (type), (node1), (node2))
00334
00335 static NODE *newline_node(NODE*);
00336 static void fixpos(NODE*,NODE*);
00337
00338 static int value_expr_gen(struct parser_params*,NODE*);
00339 static void void_expr_gen(struct parser_params*,NODE*);
00340 static NODE *remove_begin(NODE*);
00341 #define value_expr(node) value_expr_gen(parser, (node) = remove_begin(node))
00342 #define void_expr0(node) void_expr_gen(parser, (node))
00343 #define void_expr(node) void_expr0((node) = remove_begin(node))
00344 static void void_stmts_gen(struct parser_params*,NODE*);
00345 #define void_stmts(node) void_stmts_gen(parser, (node))
00346 static void reduce_nodes_gen(struct parser_params*,NODE**);
00347 #define reduce_nodes(n) reduce_nodes_gen(parser,(n))
00348 static void block_dup_check_gen(struct parser_params*,NODE*,NODE*);
00349 #define block_dup_check(n1,n2) block_dup_check_gen(parser,(n1),(n2))
00350
00351 static NODE *block_append_gen(struct parser_params*,NODE*,NODE*);
00352 #define block_append(h,t) block_append_gen(parser,(h),(t))
00353 static NODE *list_append_gen(struct parser_params*,NODE*,NODE*);
00354 #define list_append(l,i) list_append_gen(parser,(l),(i))
00355 static NODE *list_concat_gen(struct parser_params*,NODE*,NODE*);
00356 #define list_concat(h,t) list_concat_gen(parser,(h),(t))
00357 static NODE *arg_append_gen(struct parser_params*,NODE*,NODE*);
00358 #define arg_append(h,t) arg_append_gen(parser,(h),(t))
00359 static NODE *arg_concat_gen(struct parser_params*,NODE*,NODE*);
00360 #define arg_concat(h,t) arg_concat_gen(parser,(h),(t))
00361 static NODE *literal_concat_gen(struct parser_params*,NODE*,NODE*);
00362 #define literal_concat(h,t) literal_concat_gen(parser,(h),(t))
00363 static int literal_concat0(struct parser_params *, VALUE, VALUE);
00364 static NODE *new_evstr_gen(struct parser_params*,NODE*);
00365 #define new_evstr(n) new_evstr_gen(parser,(n))
00366 static NODE *evstr2dstr_gen(struct parser_params*,NODE*);
00367 #define evstr2dstr(n) evstr2dstr_gen(parser,(n))
00368 static NODE *splat_array(NODE*);
00369
00370 static NODE *call_bin_op_gen(struct parser_params*,NODE*,ID,NODE*);
00371 #define call_bin_op(recv,id,arg1) call_bin_op_gen(parser, (recv),(id),(arg1))
00372 static NODE *call_uni_op_gen(struct parser_params*,NODE*,ID);
00373 #define call_uni_op(recv,id) call_uni_op_gen(parser, (recv),(id))
00374
00375 static NODE *new_args_gen(struct parser_params*,NODE*,NODE*,ID,NODE*,ID);
00376 #define new_args(f,o,r,p,b) new_args_gen(parser, (f),(o),(r),(p),(b))
00377
00378 static NODE *negate_lit(NODE*);
00379 static NODE *ret_args_gen(struct parser_params*,NODE*);
00380 #define ret_args(node) ret_args_gen(parser, (node))
00381 static NODE *arg_blk_pass(NODE*,NODE*);
00382 static NODE *new_yield_gen(struct parser_params*,NODE*);
00383 #define new_yield(node) new_yield_gen(parser, (node))
00384
00385 static NODE *gettable_gen(struct parser_params*,ID);
00386 #define gettable(id) gettable_gen(parser,(id))
00387 static NODE *assignable_gen(struct parser_params*,ID,NODE*);
00388 #define assignable(id,node) assignable_gen(parser, (id), (node))
00389
00390 static NODE *aryset_gen(struct parser_params*,NODE*,NODE*);
00391 #define aryset(node1,node2) aryset_gen(parser, (node1), (node2))
00392 static NODE *attrset_gen(struct parser_params*,NODE*,ID);
00393 #define attrset(node,id) attrset_gen(parser, (node), (id))
00394
00395 static void rb_backref_error_gen(struct parser_params*,NODE*);
00396 #define rb_backref_error(n) rb_backref_error_gen(parser,(n))
00397 static NODE *node_assign_gen(struct parser_params*,NODE*,NODE*);
00398 #define node_assign(node1, node2) node_assign_gen(parser, (node1), (node2))
00399
00400 static NODE *match_op_gen(struct parser_params*,NODE*,NODE*);
00401 #define match_op(node1,node2) match_op_gen(parser, (node1), (node2))
00402
00403 static ID *local_tbl_gen(struct parser_params*);
00404 #define local_tbl() local_tbl_gen(parser)
00405
00406 static void fixup_nodes(NODE **);
00407
00408 static VALUE reg_compile_gen(struct parser_params*, VALUE, int);
00409 #define reg_compile(str,options) reg_compile_gen(parser, (str), (options))
00410 static void reg_fragment_setenc_gen(struct parser_params*, VALUE, int);
00411 #define reg_fragment_setenc(str,options) reg_fragment_setenc_gen(parser, (str), (options))
00412 static int reg_fragment_check_gen(struct parser_params*, VALUE, int);
00413 #define reg_fragment_check(str,options) reg_fragment_check_gen(parser, (str), (options))
00414 static NODE *reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match);
00415 #define reg_named_capture_assign(regexp,match) reg_named_capture_assign_gen(parser,(regexp),(match))
00416
00417 #define get_id(id) (id)
00418 #define get_value(val) (val)
00419 #else
00420 #define remove_begin(node) (node)
00421 #define rb_dvar_defined(id) 0
00422 #define rb_local_defined(id) 0
00423 static ID ripper_get_id(VALUE);
00424 #define get_id(id) ripper_get_id(id)
00425 static VALUE ripper_get_value(VALUE);
00426 #define get_value(val) ripper_get_value(val)
00427 static VALUE assignable_gen(struct parser_params*,VALUE);
00428 #define assignable(lhs,node) assignable_gen(parser, (lhs))
00429 static int id_is_var_gen(struct parser_params *parser, ID id);
00430 #define id_is_var(id) id_is_var_gen(parser, (id))
00431 #endif
00432
00433 static ID formal_argument_gen(struct parser_params*, ID);
00434 #define formal_argument(id) formal_argument_gen(parser, (id))
00435 static ID shadowing_lvar_gen(struct parser_params*,ID);
00436 #define shadowing_lvar(name) shadowing_lvar_gen(parser, (name))
00437 static void new_bv_gen(struct parser_params*,ID);
00438 #define new_bv(id) new_bv_gen(parser, (id))
00439
00440 static void local_push_gen(struct parser_params*,int);
00441 #define local_push(top) local_push_gen(parser,(top))
00442 static void local_pop_gen(struct parser_params*);
00443 #define local_pop() local_pop_gen(parser)
00444 static int local_var_gen(struct parser_params*, ID);
00445 #define local_var(id) local_var_gen(parser, (id));
00446 static int arg_var_gen(struct parser_params*, ID);
00447 #define arg_var(id) arg_var_gen(parser, (id))
00448 static int local_id_gen(struct parser_params*, ID);
00449 #define local_id(id) local_id_gen(parser, (id))
00450 static ID internal_id_gen(struct parser_params*);
00451 #define internal_id() internal_id_gen(parser)
00452
00453 static const struct vtable *dyna_push_gen(struct parser_params *);
00454 #define dyna_push() dyna_push_gen(parser)
00455 static void dyna_pop_gen(struct parser_params*, const struct vtable *);
00456 #define dyna_pop(node) dyna_pop_gen(parser, (node))
00457 static int dyna_in_block_gen(struct parser_params*);
00458 #define dyna_in_block() dyna_in_block_gen(parser)
00459 #define dyna_var(id) local_var(id)
00460 static int dvar_defined_gen(struct parser_params*,ID,int);
00461 #define dvar_defined(id) dvar_defined_gen(parser, (id), 0)
00462 #define dvar_defined_get(id) dvar_defined_gen(parser, (id), 1)
00463 static int dvar_curr_gen(struct parser_params*,ID);
00464 #define dvar_curr(id) dvar_curr_gen(parser, (id))
00465
00466 static int lvar_defined_gen(struct parser_params*, ID);
00467 #define lvar_defined(id) lvar_defined_gen(parser, (id))
00468
00469 #define RE_OPTION_ONCE (1<<16)
00470 #define RE_OPTION_ENCODING_SHIFT 8
00471 #define RE_OPTION_ENCODING(e) (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)
00472 #define RE_OPTION_ENCODING_IDX(o) (((o)>>RE_OPTION_ENCODING_SHIFT)&0xff)
00473 #define RE_OPTION_ENCODING_NONE(o) ((o)&RE_OPTION_ARG_ENCODING_NONE)
00474 #define RE_OPTION_MASK 0xff
00475 #define RE_OPTION_ARG_ENCODING_NONE 32
00476
00477 #define NODE_STRTERM NODE_ZARRAY
00478 #define NODE_HEREDOC NODE_ARRAY
00479 #define SIGN_EXTEND(x,n) (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))
00480 #define nd_func u1.id
00481 #if SIZEOF_SHORT == 2
00482 #define nd_term(node) ((signed short)(node)->u2.id)
00483 #else
00484 #define nd_term(node) SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)
00485 #endif
00486 #define nd_paren(node) (char)((node)->u2.id >> CHAR_BIT*2)
00487 #define nd_nest u3.cnt
00488
00489
00490
00491 #ifdef RIPPER
00492 #define RIPPER_VERSION "0.1.0"
00493
00494 #include "eventids1.c"
00495 #include "eventids2.c"
00496 static ID ripper_id_gets;
00497
00498 static VALUE ripper_dispatch0(struct parser_params*,ID);
00499 static VALUE ripper_dispatch1(struct parser_params*,ID,VALUE);
00500 static VALUE ripper_dispatch2(struct parser_params*,ID,VALUE,VALUE);
00501 static VALUE ripper_dispatch3(struct parser_params*,ID,VALUE,VALUE,VALUE);
00502 static VALUE ripper_dispatch4(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE);
00503 static VALUE ripper_dispatch5(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE);
00504
00505 #define dispatch0(n) ripper_dispatch0(parser, TOKEN_PASTE(ripper_id_, n))
00506 #define dispatch1(n,a) ripper_dispatch1(parser, TOKEN_PASTE(ripper_id_, n), (a))
00507 #define dispatch2(n,a,b) ripper_dispatch2(parser, TOKEN_PASTE(ripper_id_, n), (a), (b))
00508 #define dispatch3(n,a,b,c) ripper_dispatch3(parser, TOKEN_PASTE(ripper_id_, n), (a), (b), (c))
00509 #define dispatch4(n,a,b,c,d) ripper_dispatch4(parser, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d))
00510 #define dispatch5(n,a,b,c,d,e) ripper_dispatch5(parser, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d), (e))
00511
00512 #define yyparse ripper_yyparse
00513
00514 #define ripper_intern(s) ID2SYM(rb_intern(s))
00515 static VALUE ripper_id2sym(ID);
00516 #ifdef __GNUC__
00517 #define ripper_id2sym(id) ((id) < 256 && rb_ispunct(id) ? \
00518 ID2SYM(id) : ripper_id2sym(id))
00519 #endif
00520
00521 #define arg_new() dispatch0(args_new)
00522 #define arg_add(l,a) dispatch2(args_add, (l), (a))
00523 #define arg_add_star(l,a) dispatch2(args_add_star, (l), (a))
00524 #define arg_add_block(l,b) dispatch2(args_add_block, (l), (b))
00525 #define arg_add_optblock(l,b) ((b)==Qundef? (l) : dispatch2(args_add_block, (l), (b)))
00526 #define bare_assoc(v) dispatch1(bare_assoc_hash, (v))
00527 #define arg_add_assocs(l,b) arg_add((l), bare_assoc(b))
00528
00529 #define args2mrhs(a) dispatch1(mrhs_new_from_args, (a))
00530 #define mrhs_new() dispatch0(mrhs_new)
00531 #define mrhs_add(l,a) dispatch2(mrhs_add, (l), (a))
00532 #define mrhs_add_star(l,a) dispatch2(mrhs_add_star, (l), (a))
00533
00534 #define mlhs_new() dispatch0(mlhs_new)
00535 #define mlhs_add(l,a) dispatch2(mlhs_add, (l), (a))
00536 #define mlhs_add_star(l,a) dispatch2(mlhs_add_star, (l), (a))
00537
00538 #define params_new(pars, opts, rest, pars2, blk) \
00539 dispatch5(params, (pars), (opts), (rest), (pars2), (blk))
00540
00541 #define blockvar_new(p,v) dispatch2(block_var, (p), (v))
00542 #define blockvar_add_star(l,a) dispatch2(block_var_add_star, (l), (a))
00543 #define blockvar_add_block(l,a) dispatch2(block_var_add_block, (l), (a))
00544
00545 #define method_optarg(m,a) ((a)==Qundef ? (m) : dispatch2(method_add_arg,(m),(a)))
00546 #define method_arg(m,a) dispatch2(method_add_arg,(m),(a))
00547 #define method_add_block(m,b) dispatch2(method_add_block, (m), (b))
00548
00549 #define escape_Qundef(x) ((x)==Qundef ? Qnil : (x))
00550
00551 #define FIXME 0
00552
00553 #endif
00554
00555 #ifndef RIPPER
00556 # define ifndef_ripper(x) (x)
00557 #else
00558 # define ifndef_ripper(x)
00559 #endif
00560
00561 #ifndef RIPPER
00562 # define rb_warn0(fmt) rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt))
00563 # define rb_warnI(fmt,a) rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))
00564 # define rb_warnS(fmt,a) rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))
00565 # define rb_warning0(fmt) rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt))
00566 # define rb_warningS(fmt,a) rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt), (a))
00567 #else
00568 # define rb_warn0(fmt) ripper_warn0(parser, (fmt))
00569 # define rb_warnI(fmt,a) ripper_warnI(parser, (fmt), (a))
00570 # define rb_warnS(fmt,a) ripper_warnS(parser, (fmt), (a))
00571 # define rb_warning0(fmt) ripper_warning0(parser, (fmt))
00572 # define rb_warningS(fmt,a) ripper_warningS(parser, (fmt), (a))
00573 static void ripper_warn0(struct parser_params*, const char*);
00574 static void ripper_warnI(struct parser_params*, const char*, int);
00575 #if 0
00576 static void ripper_warnS(struct parser_params*, const char*, const char*);
00577 #endif
00578 static void ripper_warning0(struct parser_params*, const char*);
00579 static void ripper_warningS(struct parser_params*, const char*, const char*);
00580 #endif
00581
00582 #ifdef RIPPER
00583 static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
00584 # define rb_compile_error ripper_compile_error
00585 # define compile_error ripper_compile_error
00586 # define PARSER_ARG parser,
00587 #else
00588 # define rb_compile_error rb_compile_error_with_enc
00589 # define compile_error parser->nerr++,rb_compile_error_with_enc
00590 # define PARSER_ARG ruby_sourcefile, ruby_sourceline, current_enc,
00591 #endif
00592
00593
00594
00595
00596 #ifdef OLD_YACC
00597 #ifndef YYMAXDEPTH
00598 #define YYMAXDEPTH 10000
00599 #endif
00600 #endif
00601
00602 #ifndef RIPPER
00603 static void token_info_push(struct parser_params*, const char *token);
00604 static void token_info_pop(struct parser_params*, const char *token);
00605 #define token_info_push(token) (RTEST(ruby_verbose) ? token_info_push(parser, (token)) : (void)0)
00606 #define token_info_pop(token) (RTEST(ruby_verbose) ? token_info_pop(parser, (token)) : (void)0)
00607 #else
00608 #define token_info_push(token)
00609 #define token_info_pop(token)
00610 #endif
00611 %}
00612
00613 %pure_parser
00614 %parse-param {struct parser_params *parser}
00615
00616 %union {
00617 VALUE val;
00618 NODE *node;
00619 ID id;
00620 int num;
00621 const struct vtable *vars;
00622 }
00623
00624
00625
00626
00627 %token <val>
00628
00629 keyword_class
00630 keyword_module
00631 keyword_def
00632 keyword_undef
00633 keyword_begin
00634 keyword_rescue
00635 keyword_ensure
00636 keyword_end
00637 keyword_if
00638 keyword_unless
00639 keyword_then
00640 keyword_elsif
00641 keyword_else
00642 keyword_case
00643 keyword_when
00644 keyword_while
00645 keyword_until
00646 keyword_for
00647 keyword_break
00648 keyword_next
00649 keyword_redo
00650 keyword_retry
00651 keyword_in
00652 keyword_do
00653 keyword_do_cond
00654 keyword_do_block
00655 keyword_do_LAMBDA
00656 keyword_return
00657 keyword_yield
00658 keyword_super
00659 keyword_self
00660 keyword_nil
00661 keyword_true
00662 keyword_false
00663 keyword_and
00664 keyword_or
00665 keyword_not
00666 modifier_if
00667 modifier_unless
00668 modifier_while
00669 modifier_until
00670 modifier_rescue
00671 keyword_alias
00672 keyword_defined
00673 keyword_BEGIN
00674 keyword_END
00675 keyword__LINE__
00676 keyword__FILE__
00677 keyword__ENCODING__
00678
00679 %token <val> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
00680 %token <val> tINTEGER tFLOAT tSTRING_CONTENT tCHAR
00681 %token <val> tNTH_REF tBACK_REF
00682 %token <val> tREGEXP_END
00683
00684 %type <val> singleton strings string string1 xstring regexp
00685 %type <val> string_contents xstring_contents regexp_contents string_content
00686 %type <val> words qwords word_list qword_list word
00687 %type <val> literal numeric dsym cpath
00688 %type <val> top_compstmt top_stmts top_stmt
00689 %type <val> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
00690 %type <val> expr_value arg_value primary_value
00691 %type <val> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
00692 %type <val> args call_args opt_call_args
00693 %type <val> paren_args opt_paren_args
00694 %type <val> command_args aref_args opt_block_arg block_arg var_ref var_lhs
00695 %type <val> command_asgn mrhs superclass block_call block_command
00696 %type <val> f_block_optarg f_block_opt
00697 %type <val> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
00698 %type <val> assoc_list assocs assoc undef_list backref string_dvar for_var
00699 %type <val> block_param opt_block_param block_param_def f_opt
00700 %type <val> bv_decls opt_bv_decl bvar
00701 %type <val> lambda f_larglist lambda_body
00702 %type <val> brace_block cmd_brace_block do_block lhs none fitem
00703 %type <val> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner
00704 %type <val> fsym keyword_variable user_variable sym symbol operation operation2 operation3
00705 %type <val> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
00706
00707
00708 %type <val> program reswords then do dot_or_colon
00709
00710 %token tUPLUS
00711 %token tUMINUS
00712 %token tPOW
00713 %token tCMP
00714 %token tEQ
00715 %token tEQQ
00716 %token tNEQ
00717 %token tGEQ
00718 %token tLEQ
00719 %token tANDOP tOROP
00720 %token tMATCH tNMATCH
00721 %token tDOT2 tDOT3
00722 %token tAREF tASET
00723 %token tLSHFT tRSHFT
00724 %token tCOLON2
00725 %token tCOLON3
00726 %token <val> tOP_ASGN
00727 %token tASSOC
00728 %token tLPAREN
00729 %token tLPAREN_ARG
00730 %token tRPAREN
00731 %token tLBRACK
00732 %token tLBRACE
00733 %token tLBRACE_ARG
00734 %token tSTAR
00735 %token tAMPER
00736 %token tLAMBDA
00737 %token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
00738 %token tSTRING_DBEG tSTRING_DVAR tSTRING_END tLAMBEG
00739
00740
00741
00742
00743
00744 %nonassoc tLOWEST
00745 %nonassoc tLBRACE_ARG
00746
00747 %nonassoc modifier_if modifier_unless modifier_while modifier_until
00748 %left keyword_or keyword_and
00749 %right keyword_not
00750 %nonassoc keyword_defined
00751 %right '=' tOP_ASGN
00752 %left modifier_rescue
00753 %right '?' ':'
00754 %nonassoc tDOT2 tDOT3
00755 %left tOROP
00756 %left tANDOP
00757 %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
00758 %left '>' tGEQ '<' tLEQ
00759 %left '|' '^'
00760 %left '&'
00761 %left tLSHFT tRSHFT
00762 %left '+' '-'
00763 %left '*' '/' '%'
00764 %right tUMINUS_NUM tUMINUS
00765 %right tPOW
00766 %right '!' '~' tUPLUS
00767
00768 %nonassoc idNULL
00769 %nonassoc idRespond_to
00770 %nonassoc idIFUNC
00771 %nonassoc idCFUNC
00772 %nonassoc id_core_set_method_alias
00773 %nonassoc id_core_set_variable_alias
00774 %nonassoc id_core_undef_method
00775 %nonassoc id_core_define_method
00776 %nonassoc id_core_define_singleton_method
00777 %nonassoc id_core_set_postexe
00778
00779 %token tLAST_TOKEN
00780
00781 %%
00782 program : {
00783 lex_state = EXPR_BEG;
00784 #if 0
00785 local_push(compile_for_eval || rb_parse_in_main());
00786 #endif
00787 local_push(0);
00788
00789 }
00790 top_compstmt
00791 {
00792 #if 0
00793 if ($2 && !compile_for_eval) {
00794
00795 if (nd_type($2) != NODE_BLOCK) void_expr($2);
00796 else {
00797 NODE *node = $2;
00798 while (node->nd_next) {
00799 node = node->nd_next;
00800 }
00801 void_expr(node->nd_head);
00802 }
00803 }
00804 ruby_eval_tree = NEW_SCOPE(0, block_append(ruby_eval_tree, $2));
00805 #endif
00806 $$ = $2;
00807 parser->result = dispatch1(program, $$);
00808
00809 local_pop();
00810 }
00811 ;
00812
00813 top_compstmt : top_stmts opt_terms
00814 {
00815 #if 0
00816 void_stmts($1);
00817 fixup_nodes(&deferred_nodes);
00818 #endif
00819
00820 $$ = $1;
00821 }
00822 ;
00823
00824 top_stmts : none
00825 {
00826 #if 0
00827 $$ = NEW_BEGIN(0);
00828 #endif
00829 $$ = dispatch2(stmts_add, dispatch0(stmts_new),
00830 dispatch0(void_stmt));
00831
00832 }
00833 | top_stmt
00834 {
00835 #if 0
00836 $$ = newline_node($1);
00837 #endif
00838 $$ = dispatch2(stmts_add, dispatch0(stmts_new), $1);
00839
00840 }
00841 | top_stmts terms top_stmt
00842 {
00843 #if 0
00844 $$ = block_append($1, newline_node($3));
00845 #endif
00846 $$ = dispatch2(stmts_add, $1, $3);
00847
00848 }
00849 | error top_stmt
00850 {
00851 $$ = remove_begin($2);
00852 }
00853 ;
00854
00855 top_stmt : stmt
00856 | keyword_BEGIN
00857 {
00858 if (in_def || in_single) {
00859 yyerror("BEGIN in method");
00860 }
00861 #if 0
00862
00863 #endif
00864
00865 }
00866 '{' top_compstmt '}'
00867 {
00868 #if 0
00869 ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
00870 $4);
00871
00872
00873 $$ = NEW_BEGIN(0);
00874 #endif
00875 $$ = dispatch1(BEGIN, $4);
00876
00877 }
00878 ;
00879
00880 bodystmt : compstmt
00881 opt_rescue
00882 opt_else
00883 opt_ensure
00884 {
00885 #if 0
00886 $$ = $1;
00887 if ($2) {
00888 $$ = NEW_RESCUE($1, $2, $3);
00889 }
00890 else if ($3) {
00891 rb_warn0("else without rescue is useless");
00892 $$ = block_append($$, $3);
00893 }
00894 if ($4) {
00895 if ($$) {
00896 $$ = NEW_ENSURE($$, $4);
00897 }
00898 else {
00899 $$ = block_append($4, NEW_NIL());
00900 }
00901 }
00902 fixpos($$, $1);
00903 #endif
00904 $$ = dispatch4(bodystmt,
00905 escape_Qundef($1),
00906 escape_Qundef($2),
00907 escape_Qundef($3),
00908 escape_Qundef($4));
00909
00910 }
00911 ;
00912
00913 compstmt : stmts opt_terms
00914 {
00915 #if 0
00916 void_stmts($1);
00917 fixup_nodes(&deferred_nodes);
00918 #endif
00919
00920 $$ = $1;
00921 }
00922 ;
00923
00924 stmts : none
00925 {
00926 #if 0
00927 $$ = NEW_BEGIN(0);
00928 #endif
00929 $$ = dispatch2(stmts_add, dispatch0(stmts_new),
00930 dispatch0(void_stmt));
00931
00932 }
00933 | stmt
00934 {
00935 #if 0
00936 $$ = newline_node($1);
00937 #endif
00938 $$ = dispatch2(stmts_add, dispatch0(stmts_new), $1);
00939
00940 }
00941 | stmts terms stmt
00942 {
00943 #if 0
00944 $$ = block_append($1, newline_node($3));
00945 #endif
00946 $$ = dispatch2(stmts_add, $1, $3);
00947
00948 }
00949 | error stmt
00950 {
00951 $$ = remove_begin($2);
00952 }
00953 ;
00954
00955 stmt : keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
00956 {
00957 #if 0
00958 $$ = NEW_ALIAS($2, $4);
00959 #endif
00960 $$ = dispatch2(alias, $2, $4);
00961
00962 }
00963 | keyword_alias tGVAR tGVAR
00964 {
00965 #if 0
00966 $$ = NEW_VALIAS($2, $3);
00967 #endif
00968 $$ = dispatch2(var_alias, $2, $3);
00969
00970 }
00971 | keyword_alias tGVAR tBACK_REF
00972 {
00973 #if 0
00974 char buf[2];
00975 buf[0] = '$';
00976 buf[1] = (char)$3->nd_nth;
00977 $$ = NEW_VALIAS($2, rb_intern2(buf, 2));
00978 #endif
00979 $$ = dispatch2(var_alias, $2, $3);
00980
00981 }
00982 | keyword_alias tGVAR tNTH_REF
00983 {
00984 #if 0
00985 yyerror("can't make alias for the number variables");
00986 $$ = NEW_BEGIN(0);
00987 #endif
00988 $$ = dispatch2(var_alias, $2, $3);
00989 $$ = dispatch1(alias_error, $$);
00990
00991 }
00992 | keyword_undef undef_list
00993 {
00994 #if 0
00995 $$ = $2;
00996 #endif
00997 $$ = dispatch1(undef, $2);
00998
00999 }
01000 | stmt modifier_if expr_value
01001 {
01002 #if 0
01003 $$ = NEW_IF(cond($3), remove_begin($1), 0);
01004 fixpos($$, $3);
01005 #endif
01006 $$ = dispatch2(if_mod, $3, $1);
01007
01008 }
01009 | stmt modifier_unless expr_value
01010 {
01011 #if 0
01012 $$ = NEW_UNLESS(cond($3), remove_begin($1), 0);
01013 fixpos($$, $3);
01014 #endif
01015 $$ = dispatch2(unless_mod, $3, $1);
01016
01017 }
01018 | stmt modifier_while expr_value
01019 {
01020 #if 0
01021 if ($1 && nd_type($1) == NODE_BEGIN) {
01022 $$ = NEW_WHILE(cond($3), $1->nd_body, 0);
01023 }
01024 else {
01025 $$ = NEW_WHILE(cond($3), $1, 1);
01026 }
01027 #endif
01028 $$ = dispatch2(while_mod, $3, $1);
01029
01030 }
01031 | stmt modifier_until expr_value
01032 {
01033 #if 0
01034 if ($1 && nd_type($1) == NODE_BEGIN) {
01035 $$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
01036 }
01037 else {
01038 $$ = NEW_UNTIL(cond($3), $1, 1);
01039 }
01040 #endif
01041 $$ = dispatch2(until_mod, $3, $1);
01042
01043 }
01044 | stmt modifier_rescue stmt
01045 {
01046 #if 0
01047 NODE *resq = NEW_RESBODY(0, remove_begin($3), 0);
01048 $$ = NEW_RESCUE(remove_begin($1), resq, 0);
01049 #endif
01050 $$ = dispatch2(rescue_mod, $1, $3);
01051
01052 }
01053 | keyword_END '{' compstmt '}'
01054 {
01055 if (in_def || in_single) {
01056 rb_warn0("END in method; use at_exit");
01057 }
01058 #if 0
01059 $$ = NEW_POSTEXE(NEW_NODE(
01060 NODE_SCOPE, 0 , $3 , 0 ));
01061 #endif
01062 $$ = dispatch1(END, $3);
01063
01064 }
01065 | command_asgn
01066 | mlhs '=' command_call
01067 {
01068 #if 0
01069 value_expr($3);
01070 $1->nd_value = $3;
01071 $$ = $1;
01072 #endif
01073 $$ = dispatch2(massign, $1, $3);
01074
01075 }
01076 | var_lhs tOP_ASGN command_call
01077 {
01078 #if 0
01079 value_expr($3);
01080 if ($1) {
01081 ID vid = $1->nd_vid;
01082 if ($2 == tOROP) {
01083 $1->nd_value = $3;
01084 $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
01085 if (is_asgn_or_id(vid)) {
01086 $$->nd_aid = vid;
01087 }
01088 }
01089 else if ($2 == tANDOP) {
01090 $1->nd_value = $3;
01091 $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
01092 }
01093 else {
01094 $$ = $1;
01095 $$->nd_value = NEW_CALL(gettable(vid), $2, NEW_LIST($3));
01096 }
01097 }
01098 else {
01099 $$ = NEW_BEGIN(0);
01100 }
01101 #endif
01102 $$ = dispatch3(opassign, $1, $2, $3);
01103
01104 }
01105 | primary_value '[' opt_call_args rbracket tOP_ASGN command_call
01106 {
01107 #if 0
01108 NODE *args;
01109
01110 value_expr($6);
01111 if (!$3) $3 = NEW_ZARRAY();
01112 args = arg_concat($3, $6);
01113 if ($5 == tOROP) {
01114 $5 = 0;
01115 }
01116 else if ($5 == tANDOP) {
01117 $5 = 1;
01118 }
01119 $$ = NEW_OP_ASGN1($1, $5, args);
01120 fixpos($$, $1);
01121 #endif
01122 $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01123 $$ = dispatch3(opassign, $$, $5, $6);
01124
01125 }
01126 | primary_value '.' tIDENTIFIER tOP_ASGN command_call
01127 {
01128 #if 0
01129 value_expr($5);
01130 if ($4 == tOROP) {
01131 $4 = 0;
01132 }
01133 else if ($4 == tANDOP) {
01134 $4 = 1;
01135 }
01136 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
01137 fixpos($$, $1);
01138 #endif
01139 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01140 $$ = dispatch3(opassign, $$, $4, $5);
01141
01142 }
01143 | primary_value '.' tCONSTANT tOP_ASGN command_call
01144 {
01145 #if 0
01146 value_expr($5);
01147 if ($4 == tOROP) {
01148 $4 = 0;
01149 }
01150 else if ($4 == tANDOP) {
01151 $4 = 1;
01152 }
01153 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
01154 fixpos($$, $1);
01155 #endif
01156 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01157 $$ = dispatch3(opassign, $$, $4, $5);
01158
01159 }
01160 | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
01161 {
01162 #if 0
01163 yyerror("constant re-assignment");
01164 $$ = 0;
01165 #endif
01166 $$ = dispatch2(const_path_field, $1, $3);
01167 $$ = dispatch3(opassign, $$, $4, $5);
01168 $$ = dispatch1(assign_error, $$);
01169
01170 }
01171 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
01172 {
01173 #if 0
01174 value_expr($5);
01175 if ($4 == tOROP) {
01176 $4 = 0;
01177 }
01178 else if ($4 == tANDOP) {
01179 $4 = 1;
01180 }
01181 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
01182 fixpos($$, $1);
01183 #endif
01184 $$ = dispatch3(field, $1, ripper_intern("::"), $3);
01185 $$ = dispatch3(opassign, $$, $4, $5);
01186
01187 }
01188 | backref tOP_ASGN command_call
01189 {
01190 #if 0
01191 rb_backref_error($1);
01192 $$ = NEW_BEGIN(0);
01193 #endif
01194 $$ = dispatch2(assign, dispatch1(var_field, $1), $3);
01195 $$ = dispatch1(assign_error, $$);
01196
01197 }
01198 | lhs '=' mrhs
01199 {
01200 #if 0
01201 value_expr($3);
01202 $$ = node_assign($1, $3);
01203 #endif
01204 $$ = dispatch2(assign, $1, $3);
01205
01206 }
01207 | mlhs '=' arg_value
01208 {
01209 #if 0
01210 $1->nd_value = $3;
01211 $$ = $1;
01212 #endif
01213 $$ = dispatch2(massign, $1, $3);
01214
01215 }
01216 | mlhs '=' mrhs
01217 {
01218 #if 0
01219 $1->nd_value = $3;
01220 $$ = $1;
01221 #endif
01222 $$ = dispatch2(massign, $1, $3);
01223
01224 }
01225 | expr
01226 ;
01227
01228 command_asgn : lhs '=' command_call
01229 {
01230 #if 0
01231 value_expr($3);
01232 $$ = node_assign($1, $3);
01233 #endif
01234 $$ = dispatch2(assign, $1, $3);
01235
01236 }
01237 | lhs '=' command_asgn
01238 {
01239 #if 0
01240 value_expr($3);
01241 $$ = node_assign($1, $3);
01242 #endif
01243 $$ = dispatch2(assign, $1, $3);
01244
01245 }
01246 ;
01247
01248
01249 expr : command_call
01250 | expr keyword_and expr
01251 {
01252 #if 0
01253 $$ = logop(NODE_AND, $1, $3);
01254 #endif
01255 $$ = dispatch3(binary, $1, ripper_intern("and"), $3);
01256
01257 }
01258 | expr keyword_or expr
01259 {
01260 #if 0
01261 $$ = logop(NODE_OR, $1, $3);
01262 #endif
01263 $$ = dispatch3(binary, $1, ripper_intern("or"), $3);
01264
01265 }
01266 | keyword_not opt_nl expr
01267 {
01268 #if 0
01269 $$ = call_uni_op(cond($3), '!');
01270 #endif
01271 $$ = dispatch2(unary, ripper_intern("not"), $3);
01272
01273 }
01274 | '!' command_call
01275 {
01276 #if 0
01277 $$ = call_uni_op(cond($2), '!');
01278 #endif
01279 $$ = dispatch2(unary, ripper_id2sym('!'), $2);
01280
01281 }
01282 | arg
01283 ;
01284
01285 expr_value : expr
01286 {
01287 #if 0
01288 value_expr($1);
01289 $$ = $1;
01290 if (!$$) $$ = NEW_NIL();
01291 #endif
01292 $$ = $1;
01293
01294 }
01295 ;
01296
01297 command_call : command
01298 | block_command
01299 ;
01300
01301 block_command : block_call
01302 | block_call '.' operation2 command_args
01303 {
01304 #if 0
01305 $$ = NEW_CALL($1, $3, $4);
01306 #endif
01307 $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
01308 $$ = method_arg($$, $4);
01309
01310 }
01311 | block_call tCOLON2 operation2 command_args
01312 {
01313 #if 0
01314 $$ = NEW_CALL($1, $3, $4);
01315 #endif
01316 $$ = dispatch3(call, $1, ripper_intern("::"), $3);
01317 $$ = method_arg($$, $4);
01318
01319 }
01320 ;
01321
01322 cmd_brace_block : tLBRACE_ARG
01323 {
01324 $<vars>1 = dyna_push();
01325 #if 0
01326 $<num>$ = ruby_sourceline;
01327 #endif
01328
01329 }
01330 opt_block_param
01331 compstmt
01332 '}'
01333 {
01334 #if 0
01335 $$ = NEW_ITER($3,$4);
01336 nd_set_line($$, $<num>2);
01337 #endif
01338 $$ = dispatch2(brace_block, escape_Qundef($3), $4);
01339
01340 dyna_pop($<vars>1);
01341 }
01342 ;
01343
01344 command : operation command_args %prec tLOWEST
01345 {
01346 #if 0
01347 $$ = NEW_FCALL($1, $2);
01348 fixpos($$, $2);
01349 #endif
01350 $$ = dispatch2(command, $1, $2);
01351
01352 }
01353 | operation command_args cmd_brace_block
01354 {
01355 #if 0
01356 block_dup_check($2,$3);
01357 $3->nd_iter = NEW_FCALL($1, $2);
01358 $$ = $3;
01359 fixpos($$, $2);
01360 #endif
01361 $$ = dispatch2(command, $1, $2);
01362 $$ = method_add_block($$, $3);
01363
01364 }
01365 | primary_value '.' operation2 command_args %prec tLOWEST
01366 {
01367 #if 0
01368 $$ = NEW_CALL($1, $3, $4);
01369 fixpos($$, $1);
01370 #endif
01371 $$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
01372
01373 }
01374 | primary_value '.' operation2 command_args cmd_brace_block
01375 {
01376 #if 0
01377 block_dup_check($4,$5);
01378 $5->nd_iter = NEW_CALL($1, $3, $4);
01379 $$ = $5;
01380 fixpos($$, $1);
01381 #endif
01382 $$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
01383 $$ = method_add_block($$, $5);
01384
01385 }
01386 | primary_value tCOLON2 operation2 command_args %prec tLOWEST
01387 {
01388 #if 0
01389 $$ = NEW_CALL($1, $3, $4);
01390 fixpos($$, $1);
01391 #endif
01392 $$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
01393
01394 }
01395 | primary_value tCOLON2 operation2 command_args cmd_brace_block
01396 {
01397 #if 0
01398 block_dup_check($4,$5);
01399 $5->nd_iter = NEW_CALL($1, $3, $4);
01400 $$ = $5;
01401 fixpos($$, $1);
01402 #endif
01403 $$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
01404 $$ = method_add_block($$, $5);
01405
01406 }
01407 | keyword_super command_args
01408 {
01409 #if 0
01410 $$ = NEW_SUPER($2);
01411 fixpos($$, $2);
01412 #endif
01413 $$ = dispatch1(super, $2);
01414
01415 }
01416 | keyword_yield command_args
01417 {
01418 #if 0
01419 $$ = new_yield($2);
01420 fixpos($$, $2);
01421 #endif
01422 $$ = dispatch1(yield, $2);
01423
01424 }
01425 | keyword_return call_args
01426 {
01427 #if 0
01428 $$ = NEW_RETURN(ret_args($2));
01429 #endif
01430 $$ = dispatch1(return, $2);
01431
01432 }
01433 | keyword_break call_args
01434 {
01435 #if 0
01436 $$ = NEW_BREAK(ret_args($2));
01437 #endif
01438 $$ = dispatch1(break, $2);
01439
01440 }
01441 | keyword_next call_args
01442 {
01443 #if 0
01444 $$ = NEW_NEXT(ret_args($2));
01445 #endif
01446 $$ = dispatch1(next, $2);
01447
01448 }
01449 ;
01450
01451 mlhs : mlhs_basic
01452 | tLPAREN mlhs_inner rparen
01453 {
01454 #if 0
01455 $$ = $2;
01456 #endif
01457 $$ = dispatch1(mlhs_paren, $2);
01458
01459 }
01460 ;
01461
01462 mlhs_inner : mlhs_basic
01463 | tLPAREN mlhs_inner rparen
01464 {
01465 #if 0
01466 $$ = NEW_MASGN(NEW_LIST($2), 0);
01467 #endif
01468 $$ = dispatch1(mlhs_paren, $2);
01469
01470 }
01471 ;
01472
01473 mlhs_basic : mlhs_head
01474 {
01475 #if 0
01476 $$ = NEW_MASGN($1, 0);
01477 #endif
01478 $$ = $1;
01479
01480 }
01481 | mlhs_head mlhs_item
01482 {
01483 #if 0
01484 $$ = NEW_MASGN(list_append($1,$2), 0);
01485 #endif
01486 $$ = mlhs_add($1, $2);
01487
01488 }
01489 | mlhs_head tSTAR mlhs_node
01490 {
01491 #if 0
01492 $$ = NEW_MASGN($1, $3);
01493 #endif
01494 $$ = mlhs_add_star($1, $3);
01495
01496 }
01497 | mlhs_head tSTAR mlhs_node ',' mlhs_post
01498 {
01499 #if 0
01500 $$ = NEW_MASGN($1, NEW_POSTARG($3,$5));
01501 #endif
01502 $1 = mlhs_add_star($1, $3);
01503 $$ = mlhs_add($1, $5);
01504
01505 }
01506 | mlhs_head tSTAR
01507 {
01508 #if 0
01509 $$ = NEW_MASGN($1, -1);
01510 #endif
01511 $$ = mlhs_add_star($1, Qnil);
01512
01513 }
01514 | mlhs_head tSTAR ',' mlhs_post
01515 {
01516 #if 0
01517 $$ = NEW_MASGN($1, NEW_POSTARG(-1, $4));
01518 #endif
01519 $1 = mlhs_add_star($1, Qnil);
01520 $$ = mlhs_add($1, $4);
01521
01522 }
01523 | tSTAR mlhs_node
01524 {
01525 #if 0
01526 $$ = NEW_MASGN(0, $2);
01527 #endif
01528 $$ = mlhs_add_star(mlhs_new(), $2);
01529
01530 }
01531 | tSTAR mlhs_node ',' mlhs_post
01532 {
01533 #if 0
01534 $$ = NEW_MASGN(0, NEW_POSTARG($2,$4));
01535 #endif
01536 $2 = mlhs_add_star(mlhs_new(), $2);
01537 $$ = mlhs_add($2, $4);
01538
01539 }
01540 | tSTAR
01541 {
01542 #if 0
01543 $$ = NEW_MASGN(0, -1);
01544 #endif
01545 $$ = mlhs_add_star(mlhs_new(), Qnil);
01546
01547 }
01548 | tSTAR ',' mlhs_post
01549 {
01550 #if 0
01551 $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
01552 #endif
01553 $$ = mlhs_add_star(mlhs_new(), Qnil);
01554 $$ = mlhs_add($$, $3);
01555
01556 }
01557 ;
01558
01559 mlhs_item : mlhs_node
01560 | tLPAREN mlhs_inner rparen
01561 {
01562 #if 0
01563 $$ = $2;
01564 #endif
01565 $$ = dispatch1(mlhs_paren, $2);
01566
01567 }
01568 ;
01569
01570 mlhs_head : mlhs_item ','
01571 {
01572 #if 0
01573 $$ = NEW_LIST($1);
01574 #endif
01575 $$ = mlhs_add(mlhs_new(), $1);
01576
01577 }
01578 | mlhs_head mlhs_item ','
01579 {
01580 #if 0
01581 $$ = list_append($1, $2);
01582 #endif
01583 $$ = mlhs_add($1, $2);
01584
01585 }
01586 ;
01587
01588 mlhs_post : mlhs_item
01589 {
01590 #if 0
01591 $$ = NEW_LIST($1);
01592 #endif
01593 $$ = mlhs_add(mlhs_new(), $1);
01594
01595 }
01596 | mlhs_post ',' mlhs_item
01597 {
01598 #if 0
01599 $$ = list_append($1, $3);
01600 #endif
01601 $$ = mlhs_add($1, $3);
01602
01603 }
01604 ;
01605
01606 mlhs_node : user_variable
01607 {
01608 $$ = assignable($1, 0);
01609 }
01610 | keyword_variable
01611 {
01612 $$ = assignable($1, 0);
01613 }
01614 | primary_value '[' opt_call_args rbracket
01615 {
01616 #if 0
01617 $$ = aryset($1, $3);
01618 #endif
01619 $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01620
01621 }
01622 | primary_value '.' tIDENTIFIER
01623 {
01624 #if 0
01625 $$ = attrset($1, $3);
01626 #endif
01627 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01628
01629 }
01630 | primary_value tCOLON2 tIDENTIFIER
01631 {
01632 #if 0
01633 $$ = attrset($1, $3);
01634 #endif
01635 $$ = dispatch2(const_path_field, $1, $3);
01636
01637 }
01638 | primary_value '.' tCONSTANT
01639 {
01640 #if 0
01641 $$ = attrset($1, $3);
01642 #endif
01643 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01644
01645 }
01646 | primary_value tCOLON2 tCONSTANT
01647 {
01648 #if 0
01649 if (in_def || in_single)
01650 yyerror("dynamic constant assignment");
01651 $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
01652 #endif
01653 if (in_def || in_single)
01654 yyerror("dynamic constant assignment");
01655 $$ = dispatch2(const_path_field, $1, $3);
01656
01657 }
01658 | tCOLON3 tCONSTANT
01659 {
01660 #if 0
01661 if (in_def || in_single)
01662 yyerror("dynamic constant assignment");
01663 $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
01664 #endif
01665 $$ = dispatch1(top_const_field, $2);
01666
01667 }
01668 | backref
01669 {
01670 #if 0
01671 rb_backref_error($1);
01672 $$ = NEW_BEGIN(0);
01673 #endif
01674 $$ = dispatch1(var_field, $1);
01675 $$ = dispatch1(assign_error, $$);
01676
01677 }
01678 ;
01679
01680 lhs : user_variable
01681 {
01682 $$ = assignable($1, 0);
01683 #if 0
01684 if (!$$) $$ = NEW_BEGIN(0);
01685 #endif
01686 $$ = dispatch1(var_field, $$);
01687
01688 }
01689 | keyword_variable
01690 {
01691 $$ = assignable($1, 0);
01692 #if 0
01693 if (!$$) $$ = NEW_BEGIN(0);
01694 #endif
01695 $$ = dispatch1(var_field, $$);
01696
01697 }
01698 | primary_value '[' opt_call_args rbracket
01699 {
01700 #if 0
01701 $$ = aryset($1, $3);
01702 #endif
01703 $$ = dispatch2(aref_field, $1, escape_Qundef($3));
01704
01705 }
01706 | primary_value '.' tIDENTIFIER
01707 {
01708 #if 0
01709 $$ = attrset($1, $3);
01710 #endif
01711 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01712
01713 }
01714 | primary_value tCOLON2 tIDENTIFIER
01715 {
01716 #if 0
01717 $$ = attrset($1, $3);
01718 #endif
01719 $$ = dispatch3(field, $1, ripper_intern("::"), $3);
01720
01721 }
01722 | primary_value '.' tCONSTANT
01723 {
01724 #if 0
01725 $$ = attrset($1, $3);
01726 #endif
01727 $$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
01728
01729 }
01730 | primary_value tCOLON2 tCONSTANT
01731 {
01732 #if 0
01733 if (in_def || in_single)
01734 yyerror("dynamic constant assignment");
01735 $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
01736 #endif
01737 $$ = dispatch2(const_path_field, $1, $3);
01738 if (in_def || in_single) {
01739 $$ = dispatch1(assign_error, $$);
01740 }
01741
01742 }
01743 | tCOLON3 tCONSTANT
01744 {
01745 #if 0
01746 if (in_def || in_single)
01747 yyerror("dynamic constant assignment");
01748 $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
01749 #endif
01750 $$ = dispatch1(top_const_field, $2);
01751 if (in_def || in_single) {
01752 $$ = dispatch1(assign_error, $$);
01753 }
01754
01755 }
01756 | backref
01757 {
01758 #if 0
01759 rb_backref_error($1);
01760 $$ = NEW_BEGIN(0);
01761 #endif
01762 $$ = dispatch1(assign_error, $1);
01763
01764 }
01765 ;
01766
01767 cname : tIDENTIFIER
01768 {
01769 #if 0
01770 yyerror("class/module name must be CONSTANT");
01771 #endif
01772 $$ = dispatch1(class_name_error, $1);
01773
01774 }
01775 | tCONSTANT
01776 ;
01777
01778 cpath : tCOLON3 cname
01779 {
01780 #if 0
01781 $$ = NEW_COLON3($2);
01782 #endif
01783 $$ = dispatch1(top_const_ref, $2);
01784
01785 }
01786 | cname
01787 {
01788 #if 0
01789 $$ = NEW_COLON2(0, $$);
01790 #endif
01791 $$ = dispatch1(const_ref, $1);
01792
01793 }
01794 | primary_value tCOLON2 cname
01795 {
01796 #if 0
01797 $$ = NEW_COLON2($1, $3);
01798 #endif
01799 $$ = dispatch2(const_path_ref, $1, $3);
01800
01801 }
01802 ;
01803
01804 fname : tIDENTIFIER
01805 | tCONSTANT
01806 | tFID
01807 | op
01808 {
01809 lex_state = EXPR_ENDFN;
01810 $$ = $1;
01811 }
01812 | reswords
01813 {
01814 lex_state = EXPR_ENDFN;
01815 #if 0
01816 $$ = $<id>1;
01817 #endif
01818 $$ = $1;
01819
01820 }
01821 ;
01822
01823 fsym : fname
01824 | symbol
01825 ;
01826
01827 fitem : fsym
01828 {
01829 #if 0
01830 $$ = NEW_LIT(ID2SYM($1));
01831 #endif
01832 $$ = dispatch1(symbol_literal, $1);
01833
01834 }
01835 | dsym
01836 ;
01837
01838 undef_list : fitem
01839 {
01840 #if 0
01841 $$ = NEW_UNDEF($1);
01842 #endif
01843 $$ = rb_ary_new3(1, $1);
01844
01845 }
01846 | undef_list ',' {lex_state = EXPR_FNAME;} fitem
01847 {
01848 #if 0
01849 $$ = block_append($1, NEW_UNDEF($4));
01850 #endif
01851 rb_ary_push($1, $4);
01852
01853 }
01854 ;
01855
01856 op : '|' { ifndef_ripper($$ = '|'); }
01857 | '^' { ifndef_ripper($$ = '^'); }
01858 | '&' { ifndef_ripper($$ = '&'); }
01859 | tCMP { ifndef_ripper($$ = tCMP); }
01860 | tEQ { ifndef_ripper($$ = tEQ); }
01861 | tEQQ { ifndef_ripper($$ = tEQQ); }
01862 | tMATCH { ifndef_ripper($$ = tMATCH); }
01863 | tNMATCH { ifndef_ripper($$ = tNMATCH); }
01864 | '>' { ifndef_ripper($$ = '>'); }
01865 | tGEQ { ifndef_ripper($$ = tGEQ); }
01866 | '<' { ifndef_ripper($$ = '<'); }
01867 | tLEQ { ifndef_ripper($$ = tLEQ); }
01868 | tNEQ { ifndef_ripper($$ = tNEQ); }
01869 | tLSHFT { ifndef_ripper($$ = tLSHFT); }
01870 | tRSHFT { ifndef_ripper($$ = tRSHFT); }
01871 | '+' { ifndef_ripper($$ = '+'); }
01872 | '-' { ifndef_ripper($$ = '-'); }
01873 | '*' { ifndef_ripper($$ = '*'); }
01874 | tSTAR { ifndef_ripper($$ = '*'); }
01875 | '/' { ifndef_ripper($$ = '/'); }
01876 | '%' { ifndef_ripper($$ = '%'); }
01877 | tPOW { ifndef_ripper($$ = tPOW); }
01878 | '!' { ifndef_ripper($$ = '!'); }
01879 | '~' { ifndef_ripper($$ = '~'); }
01880 | tUPLUS { ifndef_ripper($$ = tUPLUS); }
01881 | tUMINUS { ifndef_ripper($$ = tUMINUS); }
01882 | tAREF { ifndef_ripper($$ = tAREF); }
01883 | tASET { ifndef_ripper($$ = tASET); }
01884 | '`' { ifndef_ripper($$ = '`'); }
01885 ;
01886
01887 reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
01888 | keyword_BEGIN | keyword_END
01889 | keyword_alias | keyword_and | keyword_begin
01890 | keyword_break | keyword_case | keyword_class | keyword_def
01891 | keyword_defined | keyword_do | keyword_else | keyword_elsif
01892 | keyword_end | keyword_ensure | keyword_false
01893 | keyword_for | keyword_in | keyword_module | keyword_next
01894 | keyword_nil | keyword_not | keyword_or | keyword_redo
01895 | keyword_rescue | keyword_retry | keyword_return | keyword_self
01896 | keyword_super | keyword_then | keyword_true | keyword_undef
01897 | keyword_when | keyword_yield | keyword_if | keyword_unless
01898 | keyword_while | keyword_until
01899 ;
01900
01901 arg : lhs '=' arg
01902 {
01903 #if 0
01904 value_expr($3);
01905 $$ = node_assign($1, $3);
01906 #endif
01907 $$ = dispatch2(assign, $1, $3);
01908
01909 }
01910 | lhs '=' arg modifier_rescue arg
01911 {
01912 #if 0
01913 value_expr($3);
01914 $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0);
01915 $$ = node_assign($1, $3);
01916 #endif
01917 $$ = dispatch2(assign, $1, dispatch2(rescue_mod, $3, $5));
01918
01919 }
01920 | var_lhs tOP_ASGN arg
01921 {
01922 #if 0
01923 value_expr($3);
01924 if ($1) {
01925 ID vid = $1->nd_vid;
01926 if ($2 == tOROP) {
01927 $1->nd_value = $3;
01928 $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
01929 if (is_asgn_or_id(vid)) {
01930 $$->nd_aid = vid;
01931 }
01932 }
01933 else if ($2 == tANDOP) {
01934 $1->nd_value = $3;
01935 $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
01936 }
01937 else {
01938 $$ = $1;
01939 $$->nd_value = NEW_CALL(gettable(vid), $2, NEW_LIST($3));
01940 }
01941 }
01942 else {
01943 $$ = NEW_BEGIN(0);
01944 }
01945 #endif
01946 $$ = dispatch3(opassign, $1, $2, $3);
01947
01948 }
01949 | var_lhs tOP_ASGN arg modifier_rescue arg
01950 {
01951 #if 0
01952 value_expr($3);
01953 $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0);
01954 if ($1) {
01955 ID vid = $1->nd_vid;
01956 if ($2 == tOROP) {
01957 $1->nd_value = $3;
01958 $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
01959 if (is_asgn_or_id(vid)) {
01960 $$->nd_aid = vid;
01961 }
01962 }
01963 else if ($2 == tANDOP) {
01964 $1->nd_value = $3;
01965 $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
01966 }
01967 else {
01968 $$ = $1;
01969 $$->nd_value = NEW_CALL(gettable(vid), $2, NEW_LIST($3));
01970 }
01971 }
01972 else {
01973 $$ = NEW_BEGIN(0);
01974 }
01975 #endif
01976 $3 = dispatch2(rescue_mod, $3, $5);
01977 $$ = dispatch3(opassign, $1, $2, $3);
01978
01979 }
01980 | primary_value '[' opt_call_args rbracket tOP_ASGN arg
01981 {
01982 #if 0
01983 NODE *args;
01984
01985 value_expr($6);
01986 if (!$3) $3 = NEW_ZARRAY();
01987 if (nd_type($3) == NODE_BLOCK_PASS) {
01988 args = NEW_ARGSCAT($3, $6);
01989 }
01990 else {
01991 args = arg_concat($3, $6);
01992 }
01993 if ($5 == tOROP) {
01994 $5 = 0;
01995 }
01996 else if ($5 == tANDOP) {
01997 $5 = 1;
01998 }
01999 $$ = NEW_OP_ASGN1($1, $5, args);
02000 fixpos($$, $1);
02001 #endif
02002 $1 = dispatch2(aref_field, $1, escape_Qundef($3));
02003 $$ = dispatch3(opassign, $1, $5, $6);
02004
02005 }
02006 | primary_value '.' tIDENTIFIER tOP_ASGN arg
02007 {
02008 #if 0
02009 value_expr($5);
02010 if ($4 == tOROP) {
02011 $4 = 0;
02012 }
02013 else if ($4 == tANDOP) {
02014 $4 = 1;
02015 }
02016 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
02017 fixpos($$, $1);
02018 #endif
02019 $1 = dispatch3(field, $1, ripper_id2sym('.'), $3);
02020 $$ = dispatch3(opassign, $1, $4, $5);
02021
02022 }
02023 | primary_value '.' tCONSTANT tOP_ASGN arg
02024 {
02025 #if 0
02026 value_expr($5);
02027 if ($4 == tOROP) {
02028 $4 = 0;
02029 }
02030 else if ($4 == tANDOP) {
02031 $4 = 1;
02032 }
02033 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
02034 fixpos($$, $1);
02035 #endif
02036 $1 = dispatch3(field, $1, ripper_id2sym('.'), $3);
02037 $$ = dispatch3(opassign, $1, $4, $5);
02038
02039 }
02040 | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
02041 {
02042 #if 0
02043 value_expr($5);
02044 if ($4 == tOROP) {
02045 $4 = 0;
02046 }
02047 else if ($4 == tANDOP) {
02048 $4 = 1;
02049 }
02050 $$ = NEW_OP_ASGN2($1, $3, $4, $5);
02051 fixpos($$, $1);
02052 #endif
02053 $1 = dispatch3(field, $1, ripper_intern("::"), $3);
02054 $$ = dispatch3(opassign, $1, $4, $5);
02055
02056 }
02057 | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
02058 {
02059 #if 0
02060 yyerror("constant re-assignment");
02061 $$ = NEW_BEGIN(0);
02062 #endif
02063 $$ = dispatch2(const_path_field, $1, $3);
02064 $$ = dispatch3(opassign, $$, $4, $5);
02065 $$ = dispatch1(assign_error, $$);
02066
02067 }
02068 | tCOLON3 tCONSTANT tOP_ASGN arg
02069 {
02070 #if 0
02071 yyerror("constant re-assignment");
02072 $$ = NEW_BEGIN(0);
02073 #endif
02074 $$ = dispatch1(top_const_field, $2);
02075 $$ = dispatch3(opassign, $$, $3, $4);
02076 $$ = dispatch1(assign_error, $$);
02077
02078 }
02079 | backref tOP_ASGN arg
02080 {
02081 #if 0
02082 rb_backref_error($1);
02083 $$ = NEW_BEGIN(0);
02084 #endif
02085 $$ = dispatch1(var_field, $1);
02086 $$ = dispatch3(opassign, $$, $2, $3);
02087 $$ = dispatch1(assign_error, $$);
02088
02089 }
02090 | arg tDOT2 arg
02091 {
02092 #if 0
02093 value_expr($1);
02094 value_expr($3);
02095 $$ = NEW_DOT2($1, $3);
02096 if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) &&
02097 nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) {
02098 deferred_nodes = list_append(deferred_nodes, $$);
02099 }
02100 #endif
02101 $$ = dispatch2(dot2, $1, $3);
02102
02103 }
02104 | arg tDOT3 arg
02105 {
02106 #if 0
02107 value_expr($1);
02108 value_expr($3);
02109 $$ = NEW_DOT3($1, $3);
02110 if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) &&
02111 nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) {
02112 deferred_nodes = list_append(deferred_nodes, $$);
02113 }
02114 #endif
02115 $$ = dispatch2(dot3, $1, $3);
02116
02117 }
02118 | arg '+' arg
02119 {
02120 #if 0
02121 $$ = call_bin_op($1, '+', $3);
02122 #endif
02123 $$ = dispatch3(binary, $1, ID2SYM('+'), $3);
02124
02125 }
02126 | arg '-' arg
02127 {
02128 #if 0
02129 $$ = call_bin_op($1, '-', $3);
02130 #endif
02131 $$ = dispatch3(binary, $1, ID2SYM('-'), $3);
02132
02133 }
02134 | arg '*' arg
02135 {
02136 #if 0
02137 $$ = call_bin_op($1, '*', $3);
02138 #endif
02139 $$ = dispatch3(binary, $1, ID2SYM('*'), $3);
02140
02141 }
02142 | arg '/' arg
02143 {
02144 #if 0
02145 $$ = call_bin_op($1, '/', $3);
02146 #endif
02147 $$ = dispatch3(binary, $1, ID2SYM('/'), $3);
02148
02149 }
02150 | arg '%' arg
02151 {
02152 #if 0
02153 $$ = call_bin_op($1, '%', $3);
02154 #endif
02155 $$ = dispatch3(binary, $1, ID2SYM('%'), $3);
02156
02157 }
02158 | arg tPOW arg
02159 {
02160 #if 0
02161 $$ = call_bin_op($1, tPOW, $3);
02162 #endif
02163 $$ = dispatch3(binary, $1, ripper_intern("**"), $3);
02164
02165 }
02166 | tUMINUS_NUM tINTEGER tPOW arg
02167 {
02168 #if 0
02169 $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);
02170 #endif
02171 $$ = dispatch3(binary, $2, ripper_intern("**"), $4);
02172 $$ = dispatch2(unary, ripper_intern("-@"), $$);
02173
02174 }
02175 | tUMINUS_NUM tFLOAT tPOW arg
02176 {
02177 #if 0
02178 $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0);
02179 #endif
02180 $$ = dispatch3(binary, $2, ripper_intern("**"), $4);
02181 $$ = dispatch2(unary, ripper_intern("-@"), $$);
02182
02183 }
02184 | tUPLUS arg
02185 {
02186 #if 0
02187 $$ = call_uni_op($2, tUPLUS);
02188 #endif
02189 $$ = dispatch2(unary, ripper_intern("+@"), $2);
02190
02191 }
02192 | tUMINUS arg
02193 {
02194 #if 0
02195 $$ = call_uni_op($2, tUMINUS);
02196 #endif
02197 $$ = dispatch2(unary, ripper_intern("-@"), $2);
02198
02199 }
02200 | arg '|' arg
02201 {
02202 #if 0
02203 $$ = call_bin_op($1, '|', $3);
02204 #endif
02205 $$ = dispatch3(binary, $1, ID2SYM('|'), $3);
02206
02207 }
02208 | arg '^' arg
02209 {
02210 #if 0
02211 $$ = call_bin_op($1, '^', $3);
02212 #endif
02213 $$ = dispatch3(binary, $1, ID2SYM('^'), $3);
02214
02215 }
02216 | arg '&' arg
02217 {
02218 #if 0
02219 $$ = call_bin_op($1, '&', $3);
02220 #endif
02221 $$ = dispatch3(binary, $1, ID2SYM('&'), $3);
02222
02223 }
02224 | arg tCMP arg
02225 {
02226 #if 0
02227 $$ = call_bin_op($1, tCMP, $3);
02228 #endif
02229 $$ = dispatch3(binary, $1, ripper_intern("<=>"), $3);
02230
02231 }
02232 | arg '>' arg
02233 {
02234 #if 0
02235 $$ = call_bin_op($1, '>', $3);
02236 #endif
02237 $$ = dispatch3(binary, $1, ID2SYM('>'), $3);
02238
02239 }
02240 | arg tGEQ arg
02241 {
02242 #if 0
02243 $$ = call_bin_op($1, tGEQ, $3);
02244 #endif
02245 $$ = dispatch3(binary, $1, ripper_intern(">="), $3);
02246
02247 }
02248 | arg '<' arg
02249 {
02250 #if 0
02251 $$ = call_bin_op($1, '<', $3);
02252 #endif
02253 $$ = dispatch3(binary, $1, ID2SYM('<'), $3);
02254
02255 }
02256 | arg tLEQ arg
02257 {
02258 #if 0
02259 $$ = call_bin_op($1, tLEQ, $3);
02260 #endif
02261 $$ = dispatch3(binary, $1, ripper_intern("<="), $3);
02262
02263 }
02264 | arg tEQ arg
02265 {
02266 #if 0
02267 $$ = call_bin_op($1, tEQ, $3);
02268 #endif
02269 $$ = dispatch3(binary, $1, ripper_intern("=="), $3);
02270
02271 }
02272 | arg tEQQ arg
02273 {
02274 #if 0
02275 $$ = call_bin_op($1, tEQQ, $3);
02276 #endif
02277 $$ = dispatch3(binary, $1, ripper_intern("==="), $3);
02278
02279 }
02280 | arg tNEQ arg
02281 {
02282 #if 0
02283 $$ = call_bin_op($1, tNEQ, $3);
02284 #endif
02285 $$ = dispatch3(binary, $1, ripper_intern("!="), $3);
02286
02287 }
02288 | arg tMATCH arg
02289 {
02290 #if 0
02291 $$ = match_op($1, $3);
02292 if (nd_type($1) == NODE_LIT && TYPE($1->nd_lit) == T_REGEXP) {
02293 $$ = reg_named_capture_assign($1->nd_lit, $$);
02294 }
02295 #endif
02296 $$ = dispatch3(binary, $1, ripper_intern("=~"), $3);
02297
02298 }
02299 | arg tNMATCH arg
02300 {
02301 #if 0
02302 $$ = call_bin_op($1, tNMATCH, $3);
02303 #endif
02304 $$ = dispatch3(binary, $1, ripper_intern("!~"), $3);
02305
02306 }
02307 | '!' arg
02308 {
02309 #if 0
02310 $$ = call_uni_op(cond($2), '!');
02311 #endif
02312 $$ = dispatch2(unary, ID2SYM('!'), $2);
02313
02314 }
02315 | '~' arg
02316 {
02317 #if 0
02318 $$ = call_uni_op($2, '~');
02319 #endif
02320 $$ = dispatch2(unary, ID2SYM('~'), $2);
02321
02322 }
02323 | arg tLSHFT arg
02324 {
02325 #if 0
02326 $$ = call_bin_op($1, tLSHFT, $3);
02327 #endif
02328 $$ = dispatch3(binary, $1, ripper_intern("<<"), $3);
02329
02330 }
02331 | arg tRSHFT arg
02332 {
02333 #if 0
02334 $$ = call_bin_op($1, tRSHFT, $3);
02335 #endif
02336 $$ = dispatch3(binary, $1, ripper_intern(">>"), $3);
02337
02338 }
02339 | arg tANDOP arg
02340 {
02341 #if 0
02342 $$ = logop(NODE_AND, $1, $3);
02343 #endif
02344 $$ = dispatch3(binary, $1, ripper_intern("&&"), $3);
02345
02346 }
02347 | arg tOROP arg
02348 {
02349 #if 0
02350 $$ = logop(NODE_OR, $1, $3);
02351 #endif
02352 $$ = dispatch3(binary, $1, ripper_intern("||"), $3);
02353
02354 }
02355 | keyword_defined opt_nl {in_defined = 1;} arg
02356 {
02357 #if 0
02358 in_defined = 0;
02359 $$ = NEW_DEFINED($4);
02360 #endif
02361 in_defined = 0;
02362 $$ = dispatch1(defined, $4);
02363
02364 }
02365 | arg '?' arg opt_nl ':' arg
02366 {
02367 #if 0
02368 value_expr($1);
02369 $$ = NEW_IF(cond($1), $3, $6);
02370 fixpos($$, $1);
02371 #endif
02372 $$ = dispatch3(ifop, $1, $3, $6);
02373
02374 }
02375 | primary
02376 {
02377 $$ = $1;
02378 }
02379 ;
02380
02381 arg_value : arg
02382 {
02383 #if 0
02384 value_expr($1);
02385 $$ = $1;
02386 if (!$$) $$ = NEW_NIL();
02387 #endif
02388 $$ = $1;
02389
02390 }
02391 ;
02392
02393 aref_args : none
02394 | args trailer
02395 {
02396 $$ = $1;
02397 }
02398 | args ',' assocs trailer
02399 {
02400 #if 0
02401 $$ = arg_append($1, NEW_HASH($3));
02402 #endif
02403 $$ = arg_add_assocs($1, $3);
02404
02405 }
02406 | assocs trailer
02407 {
02408 #if 0
02409 $$ = NEW_LIST(NEW_HASH($1));
02410 #endif
02411 $$ = arg_add_assocs(arg_new(), $1);
02412
02413 }
02414 ;
02415
02416 paren_args : '(' opt_call_args rparen
02417 {
02418 #if 0
02419 $$ = $2;
02420 #endif
02421 $$ = dispatch1(arg_paren, escape_Qundef($2));
02422
02423 }
02424 ;
02425
02426 opt_paren_args : none
02427 | paren_args
02428 ;
02429
02430 opt_call_args : none
02431 | call_args
02432 | args ','
02433 {
02434 $$ = $1;
02435 }
02436 | args ',' assocs ','
02437 {
02438 #if 0
02439 $$ = arg_append($1, NEW_HASH($3));
02440 #endif
02441 $$ = arg_add_assocs($1, $3);
02442
02443 }
02444 | assocs ','
02445 {
02446 #if 0
02447 $$ = NEW_LIST(NEW_HASH($1));
02448 #endif
02449 $$ = arg_add_assocs(arg_new(), $1);
02450
02451 }
02452 ;
02453
02454 call_args : command
02455 {
02456 #if 0
02457 value_expr($1);
02458 $$ = NEW_LIST($1);
02459 #endif
02460 $$ = arg_add(arg_new(), $1);
02461
02462 }
02463 | args opt_block_arg
02464 {
02465 #if 0
02466 $$ = arg_blk_pass($1, $2);
02467 #endif
02468 $$ = arg_add_optblock($1, $2);
02469
02470 }
02471 | assocs opt_block_arg
02472 {
02473 #if 0
02474 $$ = NEW_LIST(NEW_HASH($1));
02475 $$ = arg_blk_pass($$, $2);
02476 #endif
02477 $$ = arg_add_assocs(arg_new(), $1);
02478 $$ = arg_add_optblock($$, $2);
02479
02480 }
02481 | args ',' assocs opt_block_arg
02482 {
02483 #if 0
02484 $$ = arg_append($1, NEW_HASH($3));
02485 $$ = arg_blk_pass($$, $4);
02486 #endif
02487 $$ = arg_add_optblock(arg_add_assocs($1, $3), $4);
02488
02489 }
02490 | block_arg
02491
02492
02493 {
02494 $$ = arg_add_block(arg_new(), $1);
02495 }
02496
02497 ;
02498
02499 command_args : {
02500 $<val>$ = cmdarg_stack;
02501 CMDARG_PUSH(1);
02502 }
02503 call_args
02504 {
02505
02506 cmdarg_stack = $<val>1;
02507 $$ = $2;
02508 }
02509 ;
02510
02511 block_arg : tAMPER arg_value
02512 {
02513 #if 0
02514 $$ = NEW_BLOCK_PASS($2);
02515 #endif
02516 $$ = $2;
02517
02518 }
02519 ;
02520
02521 opt_block_arg : ',' block_arg
02522 {
02523 $$ = $2;
02524 }
02525 | none
02526 {
02527 $$ = 0;
02528 }
02529 ;
02530
02531 args : arg_value
02532 {
02533 #if 0
02534 $$ = NEW_LIST($1);
02535 #endif
02536 $$ = arg_add(arg_new(), $1);
02537
02538 }
02539 | tSTAR arg_value
02540 {
02541 #if 0
02542 $$ = NEW_SPLAT($2);
02543 #endif
02544 $$ = arg_add_star(arg_new(), $2);
02545
02546 }
02547 | args ',' arg_value
02548 {
02549 #if 0
02550 NODE *n1;
02551 if ((n1 = splat_array($1)) != 0) {
02552 $$ = list_append(n1, $3);
02553 }
02554 else {
02555 $$ = arg_append($1, $3);
02556 }
02557 #endif
02558 $$ = arg_add($1, $3);
02559
02560 }
02561 | args ',' tSTAR arg_value
02562 {
02563 #if 0
02564 NODE *n1;
02565 if ((nd_type($4) == NODE_ARRAY) && (n1 = splat_array($1)) != 0) {
02566 $$ = list_concat(n1, $4);
02567 }
02568 else {
02569 $$ = arg_concat($1, $4);
02570 }
02571 #endif
02572 $$ = arg_add_star($1, $4);
02573
02574 }
02575 ;
02576
02577 mrhs : args ',' arg_value
02578 {
02579 #if 0
02580 NODE *n1;
02581 if ((n1 = splat_array($1)) != 0) {
02582 $$ = list_append(n1, $3);
02583 }
02584 else {
02585 $$ = arg_append($1, $3);
02586 }
02587 #endif
02588 $$ = mrhs_add(args2mrhs($1), $3);
02589
02590 }
02591 | args ',' tSTAR arg_value
02592 {
02593 #if 0
02594 NODE *n1;
02595 if (nd_type($4) == NODE_ARRAY &&
02596 (n1 = splat_array($1)) != 0) {
02597 $$ = list_concat(n1, $4);
02598 }
02599 else {
02600 $$ = arg_concat($1, $4);
02601 }
02602 #endif
02603 $$ = mrhs_add_star(args2mrhs($1), $4);
02604
02605 }
02606 | tSTAR arg_value
02607 {
02608 #if 0
02609 $$ = NEW_SPLAT($2);
02610 #endif
02611 $$ = mrhs_add_star(mrhs_new(), $2);
02612
02613 }
02614 ;
02615
02616 primary : literal
02617 | strings
02618 | xstring
02619 | regexp
02620 | words
02621 | qwords
02622 | var_ref
02623 | backref
02624 | tFID
02625 {
02626 #if 0
02627 $$ = NEW_FCALL($1, 0);
02628 #endif
02629 $$ = method_arg(dispatch1(fcall, $1), arg_new());
02630
02631 }
02632 | k_begin
02633 {
02634 #if 0
02635 $<num>$ = ruby_sourceline;
02636 #endif
02637
02638 }
02639 bodystmt
02640 k_end
02641 {
02642 #if 0
02643 if ($3 == NULL) {
02644 $$ = NEW_NIL();
02645 }
02646 else {
02647 if (nd_type($3) == NODE_RESCUE ||
02648 nd_type($3) == NODE_ENSURE)
02649 nd_set_line($3, $<num>2);
02650 $$ = NEW_BEGIN($3);
02651 }
02652 nd_set_line($$, $<num>2);
02653 #endif
02654 $$ = dispatch1(begin, $3);
02655
02656 }
02657 | tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} rparen
02658 {
02659 rb_warning0("(...) interpreted as grouped expression");
02660 #if 0
02661 $$ = $2;
02662 #endif
02663 $$ = dispatch1(paren, $2);
02664
02665 }
02666 | tLPAREN compstmt ')'
02667 {
02668 #if 0
02669 $$ = $2;
02670 #endif
02671 $$ = dispatch1(paren, $2);
02672
02673 }
02674 | primary_value tCOLON2 tCONSTANT
02675 {
02676 #if 0
02677 $$ = NEW_COLON2($1, $3);
02678 #endif
02679 $$ = dispatch2(const_path_ref, $1, $3);
02680
02681 }
02682 | tCOLON3 tCONSTANT
02683 {
02684 #if 0
02685 $$ = NEW_COLON3($2);
02686 #endif
02687 $$ = dispatch1(top_const_ref, $2);
02688
02689 }
02690 | tLBRACK aref_args ']'
02691 {
02692 #if 0
02693 if ($2 == 0) {
02694 $$ = NEW_ZARRAY();
02695 }
02696 else {
02697 $$ = $2;
02698 }
02699 #endif
02700 $$ = dispatch1(array, escape_Qundef($2));
02701
02702 }
02703 | tLBRACE assoc_list '}'
02704 {
02705 #if 0
02706 $$ = NEW_HASH($2);
02707 #endif
02708 $$ = dispatch1(hash, escape_Qundef($2));
02709
02710 }
02711 | keyword_return
02712 {
02713 #if 0
02714 $$ = NEW_RETURN(0);
02715 #endif
02716 $$ = dispatch0(return0);
02717
02718 }
02719 | keyword_yield '(' call_args rparen
02720 {
02721 #if 0
02722 $$ = new_yield($3);
02723 #endif
02724 $$ = dispatch1(yield, dispatch1(paren, $3));
02725
02726 }
02727 | keyword_yield '(' rparen
02728 {
02729 #if 0
02730 $$ = NEW_YIELD(0, Qfalse);
02731 #endif
02732 $$ = dispatch1(yield, dispatch1(paren, arg_new()));
02733
02734 }
02735 | keyword_yield
02736 {
02737 #if 0
02738 $$ = NEW_YIELD(0, Qfalse);
02739 #endif
02740 $$ = dispatch0(yield0);
02741
02742 }
02743 | keyword_defined opt_nl '(' {in_defined = 1;} expr rparen
02744 {
02745 #if 0
02746 in_defined = 0;
02747 $$ = NEW_DEFINED($5);
02748 #endif
02749 in_defined = 0;
02750 $$ = dispatch1(defined, $5);
02751
02752 }
02753 | keyword_not '(' expr rparen
02754 {
02755 #if 0
02756 $$ = call_uni_op(cond($3), '!');
02757 #endif
02758 $$ = dispatch2(unary, ripper_intern("not"), $3);
02759
02760 }
02761 | keyword_not '(' rparen
02762 {
02763 #if 0
02764 $$ = call_uni_op(cond(NEW_NIL()), '!');
02765 #endif
02766 $$ = dispatch2(unary, ripper_intern("not"), Qnil);
02767
02768 }
02769 | operation brace_block
02770 {
02771 #if 0
02772 $2->nd_iter = NEW_FCALL($1, 0);
02773 $$ = $2;
02774 fixpos($2->nd_iter, $2);
02775 #endif
02776 $$ = method_arg(dispatch1(fcall, $1), arg_new());
02777 $$ = method_add_block($$, $2);
02778
02779 }
02780 | method_call
02781 | method_call brace_block
02782 {
02783 #if 0
02784 block_dup_check($1->nd_args, $2);
02785 $2->nd_iter = $1;
02786 $$ = $2;
02787 fixpos($$, $1);
02788 #endif
02789 $$ = method_add_block($1, $2);
02790
02791 }
02792 | tLAMBDA lambda
02793 {
02794 $$ = $2;
02795 }
02796 | k_if expr_value then
02797 compstmt
02798 if_tail
02799 k_end
02800 {
02801 #if 0
02802 $$ = NEW_IF(cond($2), $4, $5);
02803 fixpos($$, $2);
02804 #endif
02805 $$ = dispatch3(if, $2, $4, escape_Qundef($5));
02806
02807 }
02808 | k_unless expr_value then
02809 compstmt
02810 opt_else
02811 k_end
02812 {
02813 #if 0
02814 $$ = NEW_UNLESS(cond($2), $4, $5);
02815 fixpos($$, $2);
02816 #endif
02817 $$ = dispatch3(unless, $2, $4, escape_Qundef($5));
02818
02819 }
02820 | k_while {COND_PUSH(1);} expr_value do {COND_POP();}
02821 compstmt
02822 k_end
02823 {
02824 #if 0
02825 $$ = NEW_WHILE(cond($3), $6, 1);
02826 fixpos($$, $3);
02827 #endif
02828 $$ = dispatch2(while, $3, $6);
02829
02830 }
02831 | k_until {COND_PUSH(1);} expr_value do {COND_POP();}
02832 compstmt
02833 k_end
02834 {
02835 #if 0
02836 $$ = NEW_UNTIL(cond($3), $6, 1);
02837 fixpos($$, $3);
02838 #endif
02839 $$ = dispatch2(until, $3, $6);
02840
02841 }
02842 | k_case expr_value opt_terms
02843 case_body
02844 k_end
02845 {
02846 #if 0
02847 $$ = NEW_CASE($2, $4);
02848 fixpos($$, $2);
02849 #endif
02850 $$ = dispatch2(case, $2, $4);
02851
02852 }
02853 | k_case opt_terms case_body k_end
02854 {
02855 #if 0
02856 $$ = NEW_CASE(0, $3);
02857 #endif
02858 $$ = dispatch2(case, Qnil, $3);
02859
02860 }
02861 | k_for for_var keyword_in
02862 {COND_PUSH(1);}
02863 expr_value do
02864 {COND_POP();}
02865 compstmt
02866 k_end
02867 {
02868 #if 0
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878 ID id = internal_id();
02879 ID *tbl = ALLOC_N(ID, 2);
02880 NODE *m = NEW_ARGS_AUX(0, 0);
02881 NODE *args, *scope;
02882
02883 if (nd_type($2) == NODE_MASGN) {
02884
02885
02886
02887
02888 NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1)));
02889 NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0)));
02890 m->nd_next = block_append(
02891 NEW_IF(
02892 NEW_NODE(NODE_AND,
02893 NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("length"), 0),
02894 rb_intern("=="), one),
02895 NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero),
02896 rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))),
02897 0),
02898 NEW_DASGN_CURR(id,
02899 NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero)),
02900 0),
02901 node_assign($2, NEW_DVAR(id)));
02902
02903 args = new_args(m, 0, id, 0, 0);
02904 }
02905 else {
02906 if (nd_type($2) == NODE_LASGN ||
02907 nd_type($2) == NODE_DASGN ||
02908 nd_type($2) == NODE_DASGN_CURR) {
02909 $2->nd_value = NEW_DVAR(id);
02910 m->nd_plen = 1;
02911 m->nd_next = $2;
02912 args = new_args(m, 0, 0, 0, 0);
02913 }
02914 else {
02915 m->nd_next = node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id));
02916 args = new_args(m, 0, id, 0, 0);
02917 }
02918 }
02919 scope = NEW_NODE(NODE_SCOPE, tbl, $8, args);
02920 tbl[0] = 1; tbl[1] = id;
02921 $$ = NEW_FOR(0, $5, scope);
02922 fixpos($$, $2);
02923 #endif
02924 $$ = dispatch3(for, $2, $5, $8);
02925
02926 }
02927 | k_class cpath superclass
02928 {
02929 if (in_def || in_single)
02930 yyerror("class definition in method body");
02931 local_push(0);
02932 #if 0
02933 $<num>$ = ruby_sourceline;
02934 #endif
02935
02936 }
02937 bodystmt
02938 k_end
02939 {
02940 #if 0
02941 $$ = NEW_CLASS($2, $5, $3);
02942 nd_set_line($$, $<num>4);
02943 #endif
02944 $$ = dispatch3(class, $2, $3, $5);
02945
02946 local_pop();
02947 }
02948 | k_class tLSHFT expr
02949 {
02950 $<num>$ = in_def;
02951 in_def = 0;
02952 }
02953 term
02954 {
02955 $<num>$ = in_single;
02956 in_single = 0;
02957 local_push(0);
02958 }
02959 bodystmt
02960 k_end
02961 {
02962 #if 0
02963 $$ = NEW_SCLASS($3, $7);
02964 fixpos($$, $3);
02965 #endif
02966 $$ = dispatch2(sclass, $3, $7);
02967
02968 local_pop();
02969 in_def = $<num>4;
02970 in_single = $<num>6;
02971 }
02972 | k_module cpath
02973 {
02974 if (in_def || in_single)
02975 yyerror("module definition in method body");
02976 local_push(0);
02977 #if 0
02978 $<num>$ = ruby_sourceline;
02979 #endif
02980
02981 }
02982 bodystmt
02983 k_end
02984 {
02985 #if 0
02986 $$ = NEW_MODULE($2, $4);
02987 nd_set_line($$, $<num>3);
02988 #endif
02989 $$ = dispatch2(module, $2, $4);
02990
02991 local_pop();
02992 }
02993 | k_def fname
02994 {
02995 $<id>$ = cur_mid;
02996 cur_mid = $2;
02997 in_def++;
02998 local_push(0);
02999 }
03000 f_arglist
03001 bodystmt
03002 k_end
03003 {
03004 #if 0
03005 NODE *body = remove_begin($5);
03006 reduce_nodes(&body);
03007 $$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
03008 nd_set_line($$, $<num>1);
03009 #endif
03010 $$ = dispatch3(def, $2, $4, $5);
03011
03012 local_pop();
03013 in_def--;
03014 cur_mid = $<id>3;
03015 }
03016 | k_def singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
03017 {
03018 in_single++;
03019 lex_state = EXPR_ENDFN;
03020 local_push(0);
03021 }
03022 f_arglist
03023 bodystmt
03024 k_end
03025 {
03026 #if 0
03027 NODE *body = remove_begin($8);
03028 reduce_nodes(&body);
03029 $$ = NEW_DEFS($2, $5, $7, body);
03030 nd_set_line($$, $<num>1);
03031 #endif
03032 $$ = dispatch5(defs, $2, $3, $5, $7, $8);
03033
03034 local_pop();
03035 in_single--;
03036 }
03037 | keyword_break
03038 {
03039 #if 0
03040 $$ = NEW_BREAK(0);
03041 #endif
03042 $$ = dispatch1(break, arg_new());
03043
03044 }
03045 | keyword_next
03046 {
03047 #if 0
03048 $$ = NEW_NEXT(0);
03049 #endif
03050 $$ = dispatch1(next, arg_new());
03051
03052 }
03053 | keyword_redo
03054 {
03055 #if 0
03056 $$ = NEW_REDO();
03057 #endif
03058 $$ = dispatch0(redo);
03059
03060 }
03061 | keyword_retry
03062 {
03063 #if 0
03064 $$ = NEW_RETRY();
03065 #endif
03066 $$ = dispatch0(retry);
03067
03068 }
03069 ;
03070
03071 primary_value : primary
03072 {
03073 #if 0
03074 value_expr($1);
03075 $$ = $1;
03076 if (!$$) $$ = NEW_NIL();
03077 #endif
03078 $$ = $1;
03079
03080 }
03081 ;
03082
03083 k_begin : keyword_begin
03084 {
03085 token_info_push("begin");
03086 }
03087 ;
03088
03089 k_if : keyword_if
03090 {
03091 token_info_push("if");
03092 }
03093 ;
03094
03095 k_unless : keyword_unless
03096 {
03097 token_info_push("unless");
03098 }
03099 ;
03100
03101 k_while : keyword_while
03102 {
03103 token_info_push("while");
03104 }
03105 ;
03106
03107 k_until : keyword_until
03108 {
03109 token_info_push("until");
03110 }
03111 ;
03112
03113 k_case : keyword_case
03114 {
03115 token_info_push("case");
03116 }
03117 ;
03118
03119 k_for : keyword_for
03120 {
03121 token_info_push("for");
03122 }
03123 ;
03124
03125 k_class : keyword_class
03126 {
03127 token_info_push("class");
03128 }
03129 ;
03130
03131 k_module : keyword_module
03132 {
03133 token_info_push("module");
03134 }
03135 ;
03136
03137 k_def : keyword_def
03138 {
03139 token_info_push("def");
03140 #if 0
03141 $<num>$ = ruby_sourceline;
03142 #endif
03143
03144 }
03145 ;
03146
03147 k_end : keyword_end
03148 {
03149 token_info_pop("end");
03150 }
03151 ;
03152
03153 then : term
03154
03155
03156 { $$ = Qnil; }
03157
03158 | keyword_then
03159 | term keyword_then
03160
03161
03162 { $$ = $2; }
03163
03164 ;
03165
03166 do : term
03167
03168
03169 { $$ = Qnil; }
03170
03171 | keyword_do_cond
03172 ;
03173
03174 if_tail : opt_else
03175 | keyword_elsif expr_value then
03176 compstmt
03177 if_tail
03178 {
03179 #if 0
03180 $$ = NEW_IF(cond($2), $4, $5);
03181 fixpos($$, $2);
03182 #endif
03183 $$ = dispatch3(elsif, $2, $4, escape_Qundef($5));
03184
03185 }
03186 ;
03187
03188 opt_else : none
03189 | keyword_else compstmt
03190 {
03191 #if 0
03192 $$ = $2;
03193 #endif
03194 $$ = dispatch1(else, $2);
03195
03196 }
03197 ;
03198
03199 for_var : lhs
03200 | mlhs
03201 ;
03202
03203 f_marg : f_norm_arg
03204 {
03205 $$ = assignable($1, 0);
03206 #if 0
03207 #endif
03208 $$ = dispatch1(mlhs_paren, $$);
03209
03210 }
03211 | tLPAREN f_margs rparen
03212 {
03213 #if 0
03214 $$ = $2;
03215 #endif
03216 $$ = dispatch1(mlhs_paren, $2);
03217
03218 }
03219 ;
03220
03221 f_marg_list : f_marg
03222 {
03223 #if 0
03224 $$ = NEW_LIST($1);
03225 #endif
03226 $$ = mlhs_add(mlhs_new(), $1);
03227
03228 }
03229 | f_marg_list ',' f_marg
03230 {
03231 #if 0
03232 $$ = list_append($1, $3);
03233 #endif
03234 $$ = mlhs_add($1, $3);
03235
03236 }
03237 ;
03238
03239 f_margs : f_marg_list
03240 {
03241 #if 0
03242 $$ = NEW_MASGN($1, 0);
03243 #endif
03244 $$ = $1;
03245
03246 }
03247 | f_marg_list ',' tSTAR f_norm_arg
03248 {
03249 $$ = assignable($4, 0);
03250 #if 0
03251 $$ = NEW_MASGN($1, $$);
03252 #endif
03253 $$ = mlhs_add_star($1, $$);
03254
03255 }
03256 | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
03257 {
03258 $$ = assignable($4, 0);
03259 #if 0
03260 $$ = NEW_MASGN($1, NEW_POSTARG($$, $6));
03261 #endif
03262 $$ = mlhs_add_star($1, $$);
03263
03264 }
03265 | f_marg_list ',' tSTAR
03266 {
03267 #if 0
03268 $$ = NEW_MASGN($1, -1);
03269 #endif
03270 $$ = mlhs_add_star($1, Qnil);
03271
03272 }
03273 | f_marg_list ',' tSTAR ',' f_marg_list
03274 {
03275 #if 0
03276 $$ = NEW_MASGN($1, NEW_POSTARG(-1, $5));
03277 #endif
03278 $$ = mlhs_add_star($1, $5);
03279
03280 }
03281 | tSTAR f_norm_arg
03282 {
03283 $$ = assignable($2, 0);
03284 #if 0
03285 $$ = NEW_MASGN(0, $$);
03286 #endif
03287 $$ = mlhs_add_star(mlhs_new(), $$);
03288
03289 }
03290 | tSTAR f_norm_arg ',' f_marg_list
03291 {
03292 $$ = assignable($2, 0);
03293 #if 0
03294 $$ = NEW_MASGN(0, NEW_POSTARG($$, $4));
03295 #endif
03296 #if 0
03297 TODO: Check me
03298 #endif
03299 $$ = mlhs_add_star($$, $4);
03300
03301 }
03302 | tSTAR
03303 {
03304 #if 0
03305 $$ = NEW_MASGN(0, -1);
03306 #endif
03307 $$ = mlhs_add_star(mlhs_new(), Qnil);
03308
03309 }
03310 | tSTAR ',' f_marg_list
03311 {
03312 #if 0
03313 $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3));
03314 #endif
03315 $$ = mlhs_add_star(mlhs_new(), Qnil);
03316
03317 }
03318 ;
03319
03320 block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
03321 {
03322 #if 0
03323 $$ = new_args($1, $3, $5, 0, $6);
03324 #endif
03325 $$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
03326
03327 }
03328 | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
03329 {
03330 #if 0
03331 $$ = new_args($1, $3, $5, $7, $8);
03332 #endif
03333 $$ = params_new($1, $3, $5, $7, escape_Qundef($8));
03334
03335 }
03336 | f_arg ',' f_block_optarg opt_f_block_arg
03337 {
03338 #if 0
03339 $$ = new_args($1, $3, 0, 0, $4);
03340 #endif
03341 $$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
03342
03343 }
03344 | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
03345 {
03346 #if 0
03347 $$ = new_args($1, $3, 0, $5, $6);
03348 #endif
03349 $$ = params_new($1, $3, Qnil, $5, escape_Qundef($6));
03350
03351 }
03352 | f_arg ',' f_rest_arg opt_f_block_arg
03353 {
03354 #if 0
03355 $$ = new_args($1, 0, $3, 0, $4);
03356 #endif
03357 $$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
03358
03359 }
03360 | f_arg ','
03361 {
03362 #if 0
03363 $$ = new_args($1, 0, 1, 0, 0);
03364 #endif
03365 $$ = params_new($1, Qnil, Qnil, Qnil, Qnil);
03366 dispatch1(excessed_comma, $$);
03367
03368 }
03369 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
03370 {
03371 #if 0
03372 $$ = new_args($1, 0, $3, $5, $6);
03373 #endif
03374 $$ = params_new($1, Qnil, $3, $5, escape_Qundef($6));
03375
03376 }
03377 | f_arg opt_f_block_arg
03378 {
03379 #if 0
03380 $$ = new_args($1, 0, 0, 0, $2);
03381 #endif
03382 $$ = params_new($1, Qnil,Qnil, Qnil, escape_Qundef($2));
03383
03384 }
03385 | f_block_optarg ',' f_rest_arg opt_f_block_arg
03386 {
03387 #if 0
03388 $$ = new_args(0, $1, $3, 0, $4);
03389 #endif
03390 $$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
03391
03392 }
03393 | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
03394 {
03395 #if 0
03396 $$ = new_args(0, $1, $3, $5, $6);
03397 #endif
03398 $$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
03399
03400 }
03401 | f_block_optarg opt_f_block_arg
03402 {
03403 #if 0
03404 $$ = new_args(0, $1, 0, 0, $2);
03405 #endif
03406 $$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
03407
03408 }
03409 | f_block_optarg ',' f_arg opt_f_block_arg
03410 {
03411 #if 0
03412 $$ = new_args(0, $1, 0, $3, $4);
03413 #endif
03414 $$ = params_new(Qnil, $1, Qnil, $3, escape_Qundef($4));
03415
03416 }
03417 | f_rest_arg opt_f_block_arg
03418 {
03419 #if 0
03420 $$ = new_args(0, 0, $1, 0, $2);
03421 #endif
03422 $$ = params_new(Qnil, Qnil, $1, Qnil, escape_Qundef($2));
03423
03424 }
03425 | f_rest_arg ',' f_arg opt_f_block_arg
03426 {
03427 #if 0
03428 $$ = new_args(0, 0, $1, $3, $4);
03429 #endif
03430 $$ = params_new(Qnil, Qnil, $1, $3, escape_Qundef($4));
03431
03432 }
03433 | f_block_arg
03434 {
03435 #if 0
03436 $$ = new_args(0, 0, 0, 0, $1);
03437 #endif
03438 $$ = params_new(Qnil, Qnil, Qnil, Qnil, $1);
03439
03440 }
03441 ;
03442
03443 opt_block_param : none
03444 | block_param_def
03445 {
03446 command_start = TRUE;
03447 }
03448 ;
03449
03450 block_param_def : '|' opt_bv_decl '|'
03451 {
03452 #if 0
03453 $$ = 0;
03454 #endif
03455 $$ = blockvar_new(params_new(Qnil,Qnil,Qnil,Qnil,Qnil),
03456 escape_Qundef($2));
03457
03458 }
03459 | tOROP
03460 {
03461 #if 0
03462 $$ = 0;
03463 #endif
03464 $$ = blockvar_new(params_new(Qnil,Qnil,Qnil,Qnil,Qnil),
03465 Qnil);
03466
03467 }
03468 | '|' block_param opt_bv_decl '|'
03469 {
03470 #if 0
03471 $$ = $2;
03472 #endif
03473 $$ = blockvar_new(escape_Qundef($2), escape_Qundef($3));
03474
03475 }
03476 ;
03477
03478
03479 opt_bv_decl : none
03480 | ';' bv_decls
03481 {
03482 #if 0
03483 $$ = 0;
03484 #endif
03485 $$ = $2;
03486
03487 }
03488 ;
03489
03490 bv_decls : bvar
03491
03492
03493 {
03494 $$ = rb_ary_new3(1, $1);
03495 }
03496
03497 | bv_decls ',' bvar
03498
03499
03500 {
03501 rb_ary_push($$, $3);
03502 }
03503
03504 ;
03505
03506 bvar : tIDENTIFIER
03507 {
03508 new_bv(get_id($1));
03509 #if 0
03510 #endif
03511 $$ = get_value($1);
03512
03513 }
03514 | f_bad_arg
03515 {
03516 $$ = 0;
03517 }
03518 ;
03519
03520 lambda : {
03521 $<vars>$ = dyna_push();
03522 }
03523 {
03524 $<num>$ = lpar_beg;
03525 lpar_beg = ++paren_nest;
03526 }
03527 f_larglist
03528 lambda_body
03529 {
03530 lpar_beg = $<num>2;
03531 #if 0
03532 $$ = $3;
03533 $$->nd_body = NEW_SCOPE($3->nd_head, $4);
03534 #endif
03535 $$ = dispatch2(lambda, $3, $4);
03536
03537 dyna_pop($<vars>1);
03538 }
03539 ;
03540
03541 f_larglist : '(' f_args opt_bv_decl rparen
03542 {
03543 #if 0
03544 $$ = NEW_LAMBDA($2);
03545 #endif
03546 $$ = dispatch1(paren, $2);
03547
03548 }
03549 | f_args
03550 {
03551 #if 0
03552 $$ = NEW_LAMBDA($1);
03553 #endif
03554 $$ = $1;
03555
03556 }
03557 ;
03558
03559 lambda_body : tLAMBEG compstmt '}'
03560 {
03561 $$ = $2;
03562 }
03563 | keyword_do_LAMBDA compstmt keyword_end
03564 {
03565 $$ = $2;
03566 }
03567 ;
03568
03569 do_block : keyword_do_block
03570 {
03571 $<vars>1 = dyna_push();
03572 #if 0
03573 $<num>$ = ruby_sourceline;
03574 #endif
03575 }
03576 opt_block_param
03577 compstmt
03578 keyword_end
03579 {
03580 #if 0
03581 $$ = NEW_ITER($3,$4);
03582 nd_set_line($$, $<num>2);
03583 #endif
03584 $$ = dispatch2(do_block, escape_Qundef($3), $4);
03585
03586 dyna_pop($<vars>1);
03587 }
03588 ;
03589
03590 block_call : command do_block
03591 {
03592 #if 0
03593 if (nd_type($1) == NODE_YIELD) {
03594 compile_error(PARSER_ARG "block given to yield");
03595 }
03596 else {
03597 block_dup_check($1->nd_args, $2);
03598 }
03599 $2->nd_iter = $1;
03600 $$ = $2;
03601 fixpos($$, $1);
03602 #endif
03603 $$ = method_add_block($1, $2);
03604
03605 }
03606 | block_call '.' operation2 opt_paren_args
03607 {
03608 #if 0
03609 $$ = NEW_CALL($1, $3, $4);
03610 #endif
03611 $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
03612 $$ = method_optarg($$, $4);
03613
03614 }
03615 | block_call tCOLON2 operation2 opt_paren_args
03616 {
03617 #if 0
03618 $$ = NEW_CALL($1, $3, $4);
03619 #endif
03620 $$ = dispatch3(call, $1, ripper_intern("::"), $3);
03621 $$ = method_optarg($$, $4);
03622
03623 }
03624 ;
03625
03626 method_call : operation paren_args
03627 {
03628 #if 0
03629 $$ = NEW_FCALL($1, $2);
03630 fixpos($$, $2);
03631 #endif
03632 $$ = method_arg(dispatch1(fcall, $1), $2);
03633
03634 }
03635 | primary_value '.' operation2 opt_paren_args
03636 {
03637 #if 0
03638 $$ = NEW_CALL($1, $3, $4);
03639 fixpos($$, $1);
03640 #endif
03641 $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
03642 $$ = method_optarg($$, $4);
03643
03644 }
03645 | primary_value tCOLON2 operation2 paren_args
03646 {
03647 #if 0
03648 $$ = NEW_CALL($1, $3, $4);
03649 fixpos($$, $1);
03650 #endif
03651 $$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
03652 $$ = method_optarg($$, $4);
03653
03654 }
03655 | primary_value tCOLON2 operation3
03656 {
03657 #if 0
03658 $$ = NEW_CALL($1, $3, 0);
03659 #endif
03660 $$ = dispatch3(call, $1, ripper_intern("::"), $3);
03661
03662 }
03663 | primary_value '.' paren_args
03664 {
03665 #if 0
03666 $$ = NEW_CALL($1, rb_intern("call"), $3);
03667 fixpos($$, $1);
03668 #endif
03669 $$ = dispatch3(call, $1, ripper_id2sym('.'),
03670 ripper_intern("call"));
03671 $$ = method_optarg($$, $3);
03672
03673 }
03674 | primary_value tCOLON2 paren_args
03675 {
03676 #if 0
03677 $$ = NEW_CALL($1, rb_intern("call"), $3);
03678 fixpos($$, $1);
03679 #endif
03680 $$ = dispatch3(call, $1, ripper_intern("::"),
03681 ripper_intern("call"));
03682 $$ = method_optarg($$, $3);
03683
03684 }
03685 | keyword_super paren_args
03686 {
03687 #if 0
03688 $$ = NEW_SUPER($2);
03689 #endif
03690 $$ = dispatch1(super, $2);
03691
03692 }
03693 | keyword_super
03694 {
03695 #if 0
03696 $$ = NEW_ZSUPER();
03697 #endif
03698 $$ = dispatch0(zsuper);
03699
03700 }
03701 | primary_value '[' opt_call_args rbracket
03702 {
03703 #if 0
03704 if ($1 && nd_type($1) == NODE_SELF)
03705 $$ = NEW_FCALL(tAREF, $3);
03706 else
03707 $$ = NEW_CALL($1, tAREF, $3);
03708 fixpos($$, $1);
03709 #endif
03710 $$ = dispatch2(aref, $1, escape_Qundef($3));
03711
03712 }
03713 ;
03714
03715 brace_block : '{'
03716 {
03717 $<vars>1 = dyna_push();
03718 #if 0
03719 $<num>$ = ruby_sourceline;
03720 #endif
03721
03722 }
03723 opt_block_param
03724 compstmt '}'
03725 {
03726 #if 0
03727 $$ = NEW_ITER($3,$4);
03728 nd_set_line($$, $<num>2);
03729 #endif
03730 $$ = dispatch2(brace_block, escape_Qundef($3), $4);
03731
03732 dyna_pop($<vars>1);
03733 }
03734 | keyword_do
03735 {
03736 $<vars>1 = dyna_push();
03737 #if 0
03738 $<num>$ = ruby_sourceline;
03739 #endif
03740
03741 }
03742 opt_block_param
03743 compstmt keyword_end
03744 {
03745 #if 0
03746 $$ = NEW_ITER($3,$4);
03747 nd_set_line($$, $<num>2);
03748 #endif
03749 $$ = dispatch2(do_block, escape_Qundef($3), $4);
03750
03751 dyna_pop($<vars>1);
03752 }
03753 ;
03754
03755 case_body : keyword_when args then
03756 compstmt
03757 cases
03758 {
03759 #if 0
03760 $$ = NEW_WHEN($2, $4, $5);
03761 #endif
03762 $$ = dispatch3(when, $2, $4, escape_Qundef($5));
03763
03764 }
03765 ;
03766
03767 cases : opt_else
03768 | case_body
03769 ;
03770
03771 opt_rescue : keyword_rescue exc_list exc_var then
03772 compstmt
03773 opt_rescue
03774 {
03775 #if 0
03776 if ($3) {
03777 $3 = node_assign($3, NEW_ERRINFO());
03778 $5 = block_append($3, $5);
03779 }
03780 $$ = NEW_RESBODY($2, $5, $6);
03781 fixpos($$, $2?$2:$5);
03782 #endif
03783 $$ = dispatch4(rescue,
03784 escape_Qundef($2),
03785 escape_Qundef($3),
03786 escape_Qundef($5),
03787 escape_Qundef($6));
03788
03789 }
03790 | none
03791 ;
03792
03793 exc_list : arg_value
03794 {
03795 #if 0
03796 $$ = NEW_LIST($1);
03797 #endif
03798 $$ = rb_ary_new3(1, $1);
03799
03800 }
03801 | mrhs
03802 {
03803 #if 0
03804 if (!($$ = splat_array($1))) $$ = $1;
03805 #endif
03806 $$ = $1;
03807
03808 }
03809 | none
03810 ;
03811
03812 exc_var : tASSOC lhs
03813 {
03814 $$ = $2;
03815 }
03816 | none
03817 ;
03818
03819 opt_ensure : keyword_ensure compstmt
03820 {
03821 #if 0
03822 $$ = $2;
03823 #endif
03824 $$ = dispatch1(ensure, $2);
03825
03826 }
03827 | none
03828 ;
03829
03830 literal : numeric
03831 | symbol
03832 {
03833 #if 0
03834 $$ = NEW_LIT(ID2SYM($1));
03835 #endif
03836 $$ = dispatch1(symbol_literal, $1);
03837
03838 }
03839 | dsym
03840 ;
03841
03842 strings : string
03843 {
03844 #if 0
03845 NODE *node = $1;
03846 if (!node) {
03847 node = NEW_STR(STR_NEW0());
03848 }
03849 else {
03850 node = evstr2dstr(node);
03851 }
03852 $$ = node;
03853 #endif
03854 $$ = $1;
03855
03856 }
03857 ;
03858
03859 string : tCHAR
03860 | string1
03861 | string string1
03862 {
03863 #if 0
03864 $$ = literal_concat($1, $2);
03865 #endif
03866 $$ = dispatch2(string_concat, $1, $2);
03867
03868 }
03869 ;
03870
03871 string1 : tSTRING_BEG string_contents tSTRING_END
03872 {
03873 #if 0
03874 $$ = $2;
03875 #endif
03876 $$ = dispatch1(string_literal, $2);
03877
03878 }
03879 ;
03880
03881 xstring : tXSTRING_BEG xstring_contents tSTRING_END
03882 {
03883 #if 0
03884 NODE *node = $2;
03885 if (!node) {
03886 node = NEW_XSTR(STR_NEW0());
03887 }
03888 else {
03889 switch (nd_type(node)) {
03890 case NODE_STR:
03891 nd_set_type(node, NODE_XSTR);
03892 break;
03893 case NODE_DSTR:
03894 nd_set_type(node, NODE_DXSTR);
03895 break;
03896 default:
03897 node = NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node));
03898 break;
03899 }
03900 }
03901 $$ = node;
03902 #endif
03903 $$ = dispatch1(xstring_literal, $2);
03904
03905 }
03906 ;
03907
03908 regexp : tREGEXP_BEG regexp_contents tREGEXP_END
03909 {
03910 #if 0
03911 int options = $3;
03912 NODE *node = $2;
03913 NODE *list, *prev;
03914 if (!node) {
03915 node = NEW_LIT(reg_compile(STR_NEW0(), options));
03916 }
03917 else switch (nd_type(node)) {
03918 case NODE_STR:
03919 {
03920 VALUE src = node->nd_lit;
03921 nd_set_type(node, NODE_LIT);
03922 node->nd_lit = reg_compile(src, options);
03923 }
03924 break;
03925 default:
03926 node = NEW_NODE(NODE_DSTR, STR_NEW0(), 1, NEW_LIST(node));
03927 case NODE_DSTR:
03928 if (options & RE_OPTION_ONCE) {
03929 nd_set_type(node, NODE_DREGX_ONCE);
03930 }
03931 else {
03932 nd_set_type(node, NODE_DREGX);
03933 }
03934 node->nd_cflag = options & RE_OPTION_MASK;
03935 if (!NIL_P(node->nd_lit)) reg_fragment_check(node->nd_lit, options);
03936 for (list = (prev = node)->nd_next; list; list = list->nd_next) {
03937 if (nd_type(list->nd_head) == NODE_STR) {
03938 VALUE tail = list->nd_head->nd_lit;
03939 if (reg_fragment_check(tail, options) && prev && !NIL_P(prev->nd_lit)) {
03940 VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit;
03941 if (!literal_concat0(parser, lit, tail)) {
03942 node = 0;
03943 break;
03944 }
03945 rb_str_resize(tail, 0);
03946 prev->nd_next = list->nd_next;
03947 rb_gc_force_recycle((VALUE)list->nd_head);
03948 rb_gc_force_recycle((VALUE)list);
03949 list = prev;
03950 }
03951 else {
03952 prev = list;
03953 }
03954 }
03955 else {
03956 prev = 0;
03957 }
03958 }
03959 if (!node->nd_next) {
03960 VALUE src = node->nd_lit;
03961 nd_set_type(node, NODE_LIT);
03962 node->nd_lit = reg_compile(src, options);
03963 }
03964 break;
03965 }
03966 $$ = node;
03967 #endif
03968 $$ = dispatch2(regexp_literal, $2, $3);
03969
03970 }
03971 ;
03972
03973 words : tWORDS_BEG ' ' tSTRING_END
03974 {
03975 #if 0
03976 $$ = NEW_ZARRAY();
03977 #endif
03978 $$ = dispatch0(words_new);
03979 $$ = dispatch1(array, $$);
03980
03981 }
03982 | tWORDS_BEG word_list tSTRING_END
03983 {
03984 #if 0
03985 $$ = $2;
03986 #endif
03987 $$ = dispatch1(array, $2);
03988
03989 }
03990 ;
03991
03992 word_list :
03993 {
03994 #if 0
03995 $$ = 0;
03996 #endif
03997 $$ = dispatch0(words_new);
03998
03999 }
04000 | word_list word ' '
04001 {
04002 #if 0
04003 $$ = list_append($1, evstr2dstr($2));
04004 #endif
04005 $$ = dispatch2(words_add, $1, $2);
04006
04007 }
04008 ;
04009
04010 word : string_content
04011
04012
04013 {
04014 $$ = dispatch0(word_new);
04015 $$ = dispatch2(word_add, $$, $1);
04016 }
04017
04018 | word string_content
04019 {
04020 #if 0
04021 $$ = literal_concat($1, $2);
04022 #endif
04023 $$ = dispatch2(word_add, $1, $2);
04024
04025 }
04026 ;
04027
04028 qwords : tQWORDS_BEG ' ' tSTRING_END
04029 {
04030 #if 0
04031 $$ = NEW_ZARRAY();
04032 #endif
04033 $$ = dispatch0(qwords_new);
04034 $$ = dispatch1(array, $$);
04035
04036 }
04037 | tQWORDS_BEG qword_list tSTRING_END
04038 {
04039 #if 0
04040 $$ = $2;
04041 #endif
04042 $$ = dispatch1(array, $2);
04043
04044 }
04045 ;
04046
04047 qword_list :
04048 {
04049 #if 0
04050 $$ = 0;
04051 #endif
04052 $$ = dispatch0(qwords_new);
04053
04054 }
04055 | qword_list tSTRING_CONTENT ' '
04056 {
04057 #if 0
04058 $$ = list_append($1, $2);
04059 #endif
04060 $$ = dispatch2(qwords_add, $1, $2);
04061
04062 }
04063 ;
04064
04065 string_contents :
04066 {
04067 #if 0
04068 $$ = 0;
04069 #endif
04070 $$ = dispatch0(string_content);
04071
04072 }
04073 | string_contents string_content
04074 {
04075 #if 0
04076 $$ = literal_concat($1, $2);
04077 #endif
04078 $$ = dispatch2(string_add, $1, $2);
04079
04080 }
04081 ;
04082
04083 xstring_contents:
04084 {
04085 #if 0
04086 $$ = 0;
04087 #endif
04088 $$ = dispatch0(xstring_new);
04089
04090 }
04091 | xstring_contents string_content
04092 {
04093 #if 0
04094 $$ = literal_concat($1, $2);
04095 #endif
04096 $$ = dispatch2(xstring_add, $1, $2);
04097
04098 }
04099 ;
04100
04101 regexp_contents:
04102 {
04103 #if 0
04104 $$ = 0;
04105 #endif
04106 $$ = dispatch0(regexp_new);
04107
04108 }
04109 | regexp_contents string_content
04110 {
04111 #if 0
04112 NODE *head = $1, *tail = $2;
04113 if (!head) {
04114 $$ = tail;
04115 }
04116 else if (!tail) {
04117 $$ = head;
04118 }
04119 else {
04120 switch (nd_type(head)) {
04121 case NODE_STR:
04122 nd_set_type(head, NODE_DSTR);
04123 break;
04124 case NODE_DSTR:
04125 break;
04126 default:
04127 head = list_append(NEW_DSTR(Qnil), head);
04128 break;
04129 }
04130 $$ = list_append(head, tail);
04131 }
04132 #endif
04133 $$ = dispatch2(regexp_add, $1, $2);
04134
04135 }
04136 ;
04137
04138 string_content : tSTRING_CONTENT
04139 | tSTRING_DVAR
04140 {
04141 $<node>$ = lex_strterm;
04142 lex_strterm = 0;
04143 lex_state = EXPR_BEG;
04144 }
04145 string_dvar
04146 {
04147 #if 0
04148 lex_strterm = $<node>2;
04149 $$ = NEW_EVSTR($3);
04150 #endif
04151 lex_strterm = $<node>2;
04152 $$ = dispatch1(string_dvar, $3);
04153
04154 }
04155 | tSTRING_DBEG
04156 {
04157 $<val>1 = cond_stack;
04158 $<val>$ = cmdarg_stack;
04159 cond_stack = 0;
04160 cmdarg_stack = 0;
04161 }
04162 {
04163 $<node>$ = lex_strterm;
04164 lex_strterm = 0;
04165 lex_state = EXPR_BEG;
04166 }
04167 compstmt '}'
04168 {
04169 cond_stack = $<val>1;
04170 cmdarg_stack = $<val>2;
04171 lex_strterm = $<node>3;
04172 #if 0
04173 if ($4) $4->flags &= ~NODE_FL_NEWLINE;
04174 $$ = new_evstr($4);
04175 #endif
04176 $$ = dispatch1(string_embexpr, $4);
04177
04178 }
04179 ;
04180
04181 string_dvar : tGVAR
04182 {
04183 #if 0
04184 $$ = NEW_GVAR($1);
04185 #endif
04186 $$ = dispatch1(var_ref, $1);
04187
04188 }
04189 | tIVAR
04190 {
04191 #if 0
04192 $$ = NEW_IVAR($1);
04193 #endif
04194 $$ = dispatch1(var_ref, $1);
04195
04196 }
04197 | tCVAR
04198 {
04199 #if 0
04200 $$ = NEW_CVAR($1);
04201 #endif
04202 $$ = dispatch1(var_ref, $1);
04203
04204 }
04205 | backref
04206 ;
04207
04208 symbol : tSYMBEG sym
04209 {
04210 lex_state = EXPR_END;
04211 #if 0
04212 $$ = $2;
04213 #endif
04214 $$ = dispatch1(symbol, $2);
04215
04216 }
04217 ;
04218
04219 sym : fname
04220 | tIVAR
04221 | tGVAR
04222 | tCVAR
04223 ;
04224
04225 dsym : tSYMBEG xstring_contents tSTRING_END
04226 {
04227 lex_state = EXPR_END;
04228 #if 0
04229 if (!($$ = $2)) {
04230 $$ = NEW_LIT(ID2SYM(rb_intern("")));
04231 }
04232 else {
04233 VALUE lit;
04234
04235 switch (nd_type($$)) {
04236 case NODE_DSTR:
04237 nd_set_type($$, NODE_DSYM);
04238 break;
04239 case NODE_STR:
04240 lit = $$->nd_lit;
04241 $$->nd_lit = ID2SYM(rb_intern_str(lit));
04242 nd_set_type($$, NODE_LIT);
04243 break;
04244 default:
04245 $$ = NEW_NODE(NODE_DSYM, Qnil, 1, NEW_LIST($$));
04246 break;
04247 }
04248 }
04249 #endif
04250 $$ = dispatch1(dyna_symbol, $2);
04251
04252 }
04253 ;
04254
04255 numeric : tINTEGER
04256 | tFLOAT
04257 | tUMINUS_NUM tINTEGER %prec tLOWEST
04258 {
04259 #if 0
04260 $$ = negate_lit($2);
04261 #endif
04262 $$ = dispatch2(unary, ripper_intern("-@"), $2);
04263
04264 }
04265 | tUMINUS_NUM tFLOAT %prec tLOWEST
04266 {
04267 #if 0
04268 $$ = negate_lit($2);
04269 #endif
04270 $$ = dispatch2(unary, ripper_intern("-@"), $2);
04271
04272 }
04273 ;
04274
04275 user_variable : tIDENTIFIER
04276 | tIVAR
04277 | tGVAR
04278 | tCONSTANT
04279 | tCVAR
04280 ;
04281
04282 keyword_variable: keyword_nil {ifndef_ripper($$ = keyword_nil);}
04283 | keyword_self {ifndef_ripper($$ = keyword_self);}
04284 | keyword_true {ifndef_ripper($$ = keyword_true);}
04285 | keyword_false {ifndef_ripper($$ = keyword_false);}
04286 | keyword__FILE__ {ifndef_ripper($$ = keyword__FILE__);}
04287 | keyword__LINE__ {ifndef_ripper($$ = keyword__LINE__);}
04288 | keyword__ENCODING__ {ifndef_ripper($$ = keyword__ENCODING__);}
04289 ;
04290
04291 var_ref : user_variable
04292 {
04293 #if 0
04294 if (!($$ = gettable($1))) $$ = NEW_BEGIN(0);
04295 #endif
04296 if (id_is_var(get_id($1))) {
04297 $$ = dispatch1(var_ref, $1);
04298 }
04299 else {
04300 $$ = dispatch1(vcall, $1);
04301 }
04302
04303 }
04304 | keyword_variable
04305 {
04306 #if 0
04307 if (!($$ = gettable($1))) $$ = NEW_BEGIN(0);
04308 #endif
04309 $$ = dispatch1(var_ref, $1);
04310
04311 }
04312 ;
04313
04314 var_lhs : user_variable
04315 {
04316 $$ = assignable($1, 0);
04317 #if 0
04318 #endif
04319 $$ = dispatch1(var_field, $$);
04320
04321 }
04322 | keyword_variable
04323 {
04324 $$ = assignable($1, 0);
04325 #if 0
04326 #endif
04327 $$ = dispatch1(var_field, $$);
04328
04329 }
04330 ;
04331
04332 backref : tNTH_REF
04333 | tBACK_REF
04334 ;
04335
04336 superclass : term
04337 {
04338 #if 0
04339 $$ = 0;
04340 #endif
04341 $$ = Qnil;
04342
04343 }
04344 | '<'
04345 {
04346 lex_state = EXPR_BEG;
04347 }
04348 expr_value term
04349 {
04350 $$ = $3;
04351 }
04352 | error term
04353 {
04354 #if 0
04355 yyerrok;
04356 $$ = 0;
04357 #endif
04358 yyerrok;
04359 $$ = Qnil;
04360
04361 }
04362 ;
04363
04364 f_arglist : '(' f_args rparen
04365 {
04366 #if 0
04367 $$ = $2;
04368 #endif
04369 $$ = dispatch1(paren, $2);
04370
04371 lex_state = EXPR_BEG;
04372 command_start = TRUE;
04373 }
04374 | f_args term
04375 {
04376 $$ = $1;
04377 lex_state = EXPR_BEG;
04378 command_start = TRUE;
04379 }
04380 ;
04381
04382 f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
04383 {
04384 #if 0
04385 $$ = new_args($1, $3, $5, 0, $6);
04386 #endif
04387 $$ = params_new($1, $3, $5, Qnil, escape_Qundef($6));
04388
04389 }
04390 | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
04391 {
04392 #if 0
04393 $$ = new_args($1, $3, $5, $7, $8);
04394 #endif
04395 $$ = params_new($1, $3, $5, $7, escape_Qundef($8));
04396
04397 }
04398 | f_arg ',' f_optarg opt_f_block_arg
04399 {
04400 #if 0
04401 $$ = new_args($1, $3, 0, 0, $4);
04402 #endif
04403 $$ = params_new($1, $3, Qnil, Qnil, escape_Qundef($4));
04404
04405 }
04406 | f_arg ',' f_optarg ',' f_arg opt_f_block_arg
04407 {
04408 #if 0
04409 $$ = new_args($1, $3, 0, $5, $6);
04410 #endif
04411 $$ = params_new($1, $3, Qnil, $5, escape_Qundef($6));
04412
04413 }
04414 | f_arg ',' f_rest_arg opt_f_block_arg
04415 {
04416 #if 0
04417 $$ = new_args($1, 0, $3, 0, $4);
04418 #endif
04419 $$ = params_new($1, Qnil, $3, Qnil, escape_Qundef($4));
04420
04421 }
04422 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
04423 {
04424 #if 0
04425 $$ = new_args($1, 0, $3, $5, $6);
04426 #endif
04427 $$ = params_new($1, Qnil, $3, $5, escape_Qundef($6));
04428
04429 }
04430 | f_arg opt_f_block_arg
04431 {
04432 #if 0
04433 $$ = new_args($1, 0, 0, 0, $2);
04434 #endif
04435 $$ = params_new($1, Qnil, Qnil, Qnil,escape_Qundef($2));
04436
04437 }
04438 | f_optarg ',' f_rest_arg opt_f_block_arg
04439 {
04440 #if 0
04441 $$ = new_args(0, $1, $3, 0, $4);
04442 #endif
04443 $$ = params_new(Qnil, $1, $3, Qnil, escape_Qundef($4));
04444
04445 }
04446 | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
04447 {
04448 #if 0
04449 $$ = new_args(0, $1, $3, $5, $6);
04450 #endif
04451 $$ = params_new(Qnil, $1, $3, $5, escape_Qundef($6));
04452
04453 }
04454 | f_optarg opt_f_block_arg
04455 {
04456 #if 0
04457 $$ = new_args(0, $1, 0, 0, $2);
04458 #endif
04459 $$ = params_new(Qnil, $1, Qnil, Qnil,escape_Qundef($2));
04460
04461 }
04462 | f_optarg ',' f_arg opt_f_block_arg
04463 {
04464 #if 0
04465 $$ = new_args(0, $1, 0, $3, $4);
04466 #endif
04467 $$ = params_new(Qnil, $1, Qnil, $3, escape_Qundef($4));
04468
04469 }
04470 | f_rest_arg opt_f_block_arg
04471 {
04472 #if 0
04473 $$ = new_args(0, 0, $1, 0, $2);
04474 #endif
04475 $$ = params_new(Qnil, Qnil, $1, Qnil,escape_Qundef($2));
04476
04477 }
04478 | f_rest_arg ',' f_arg opt_f_block_arg
04479 {
04480 #if 0
04481 $$ = new_args(0, 0, $1, $3, $4);
04482 #endif
04483 $$ = params_new(Qnil, Qnil, $1, $3, escape_Qundef($4));
04484
04485 }
04486 | f_block_arg
04487 {
04488 #if 0
04489 $$ = new_args(0, 0, 0, 0, $1);
04490 #endif
04491 $$ = params_new(Qnil, Qnil, Qnil, Qnil, $1);
04492
04493 }
04494 |
04495 {
04496 #if 0
04497 $$ = new_args(0, 0, 0, 0, 0);
04498 #endif
04499 $$ = params_new(Qnil, Qnil, Qnil, Qnil, Qnil);
04500
04501 }
04502 ;
04503
04504 f_bad_arg : tCONSTANT
04505 {
04506 #if 0
04507 yyerror("formal argument cannot be a constant");
04508 $$ = 0;
04509 #endif
04510 $$ = dispatch1(param_error, $1);
04511
04512 }
04513 | tIVAR
04514 {
04515 #if 0
04516 yyerror("formal argument cannot be an instance variable");
04517 $$ = 0;
04518 #endif
04519 $$ = dispatch1(param_error, $1);
04520
04521 }
04522 | tGVAR
04523 {
04524 #if 0
04525 yyerror("formal argument cannot be a global variable");
04526 $$ = 0;
04527 #endif
04528 $$ = dispatch1(param_error, $1);
04529
04530 }
04531 | tCVAR
04532 {
04533 #if 0
04534 yyerror("formal argument cannot be a class variable");
04535 $$ = 0;
04536 #endif
04537 $$ = dispatch1(param_error, $1);
04538
04539 }
04540 ;
04541
04542 f_norm_arg : f_bad_arg
04543 | tIDENTIFIER
04544 {
04545 formal_argument(get_id($1));
04546 $$ = $1;
04547 }
04548 ;
04549
04550 f_arg_item : f_norm_arg
04551 {
04552 arg_var(get_id($1));
04553 #if 0
04554 $$ = NEW_ARGS_AUX($1, 1);
04555 #endif
04556 $$ = get_value($1);
04557
04558 }
04559 | tLPAREN f_margs rparen
04560 {
04561 ID tid = internal_id();
04562 arg_var(tid);
04563 #if 0
04564 if (dyna_in_block()) {
04565 $2->nd_value = NEW_DVAR(tid);
04566 }
04567 else {
04568 $2->nd_value = NEW_LVAR(tid);
04569 }
04570 $$ = NEW_ARGS_AUX(tid, 1);
04571 $$->nd_next = $2;
04572 #endif
04573 $$ = dispatch1(mlhs_paren, $2);
04574
04575 }
04576 ;
04577
04578 f_arg : f_arg_item
04579
04580
04581 {
04582 $$ = rb_ary_new3(1, $1);
04583 }
04584
04585 | f_arg ',' f_arg_item
04586 {
04587 #if 0
04588 $$ = $1;
04589 $$->nd_plen++;
04590 $$->nd_next = block_append($$->nd_next, $3->nd_next);
04591 rb_gc_force_recycle((VALUE)$3);
04592 #endif
04593 $$ = rb_ary_push($1, $3);
04594
04595 }
04596 ;
04597
04598 f_opt : tIDENTIFIER '=' arg_value
04599 {
04600 arg_var(formal_argument(get_id($1)));
04601 $$ = assignable($1, $3);
04602 #if 0
04603 $$ = NEW_OPT_ARG(0, $$);
04604 #endif
04605 $$ = rb_assoc_new($$, $3);
04606
04607 }
04608 ;
04609
04610 f_block_opt : tIDENTIFIER '=' primary_value
04611 {
04612 arg_var(formal_argument(get_id($1)));
04613 $$ = assignable($1, $3);
04614 #if 0
04615 $$ = NEW_OPT_ARG(0, $$);
04616 #endif
04617 $$ = rb_assoc_new($$, $3);
04618
04619 }
04620 ;
04621
04622 f_block_optarg : f_block_opt
04623 {
04624 #if 0
04625 $$ = $1;
04626 #endif
04627 $$ = rb_ary_new3(1, $1);
04628
04629 }
04630 | f_block_optarg ',' f_block_opt
04631 {
04632 #if 0
04633 NODE *opts = $1;
04634
04635 while (opts->nd_next) {
04636 opts = opts->nd_next;
04637 }
04638 opts->nd_next = $3;
04639 $$ = $1;
04640 #endif
04641 $$ = rb_ary_push($1, $3);
04642
04643 }
04644 ;
04645
04646 f_optarg : f_opt
04647 {
04648 #if 0
04649 $$ = $1;
04650 #endif
04651 $$ = rb_ary_new3(1, $1);
04652
04653 }
04654 | f_optarg ',' f_opt
04655 {
04656 #if 0
04657 NODE *opts = $1;
04658
04659 while (opts->nd_next) {
04660 opts = opts->nd_next;
04661 }
04662 opts->nd_next = $3;
04663 $$ = $1;
04664 #endif
04665 $$ = rb_ary_push($1, $3);
04666
04667 }
04668 ;
04669
04670 restarg_mark : '*'
04671 | tSTAR
04672 ;
04673
04674 f_rest_arg : restarg_mark tIDENTIFIER
04675 {
04676 #if 0
04677 if (!is_local_id($2))
04678 yyerror("rest argument must be local variable");
04679 #endif
04680 arg_var(shadowing_lvar(get_id($2)));
04681 #if 0
04682 $$ = $2;
04683 #endif
04684 $$ = dispatch1(rest_param, $2);
04685
04686 }
04687 | restarg_mark
04688 {
04689 #if 0
04690 $$ = internal_id();
04691 arg_var($$);
04692 #endif
04693 $$ = dispatch1(rest_param, Qnil);
04694
04695 }
04696 ;
04697
04698 blkarg_mark : '&'
04699 | tAMPER
04700 ;
04701
04702 f_block_arg : blkarg_mark tIDENTIFIER
04703 {
04704 #if 0
04705 if (!is_local_id($2))
04706 yyerror("block argument must be local variable");
04707 else if (!dyna_in_block() && local_id($2))
04708 yyerror("duplicated block argument name");
04709 #endif
04710 arg_var(shadowing_lvar(get_id($2)));
04711 #if 0
04712 $$ = $2;
04713 #endif
04714 $$ = dispatch1(blockarg, $2);
04715
04716 }
04717 ;
04718
04719 opt_f_block_arg : ',' f_block_arg
04720 {
04721 $$ = $2;
04722 }
04723 | none
04724 {
04725 #if 0
04726 $$ = 0;
04727 #endif
04728 $$ = Qundef;
04729
04730 }
04731 ;
04732
04733 singleton : var_ref
04734 {
04735 #if 0
04736 value_expr($1);
04737 $$ = $1;
04738 if (!$$) $$ = NEW_NIL();
04739 #endif
04740 $$ = $1;
04741
04742 }
04743 | '(' {lex_state = EXPR_BEG;} expr rparen
04744 {
04745 #if 0
04746 if ($3 == 0) {
04747 yyerror("can't define singleton method for ().");
04748 }
04749 else {
04750 switch (nd_type($3)) {
04751 case NODE_STR:
04752 case NODE_DSTR:
04753 case NODE_XSTR:
04754 case NODE_DXSTR:
04755 case NODE_DREGX:
04756 case NODE_LIT:
04757 case NODE_ARRAY:
04758 case NODE_ZARRAY:
04759 yyerror("can't define singleton method for literals");
04760 default:
04761 value_expr($3);
04762 break;
04763 }
04764 }
04765 $$ = $3;
04766 #endif
04767 $$ = dispatch1(paren, $3);
04768
04769 }
04770 ;
04771
04772 assoc_list : none
04773 | assocs trailer
04774 {
04775 #if 0
04776 $$ = $1;
04777 #endif
04778 $$ = dispatch1(assoclist_from_args, $1);
04779
04780 }
04781 ;
04782
04783 assocs : assoc
04784
04785
04786 {
04787 $$ = rb_ary_new3(1, $1);
04788 }
04789
04790 | assocs ',' assoc
04791 {
04792 #if 0
04793 $$ = list_concat($1, $3);
04794 #endif
04795 $$ = rb_ary_push($1, $3);
04796
04797 }
04798 ;
04799
04800 assoc : arg_value tASSOC arg_value
04801 {
04802 #if 0
04803 $$ = list_append(NEW_LIST($1), $3);
04804 #endif
04805 $$ = dispatch2(assoc_new, $1, $3);
04806
04807 }
04808 | tLABEL arg_value
04809 {
04810 #if 0
04811 $$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2);
04812 #endif
04813 $$ = dispatch2(assoc_new, $1, $2);
04814
04815 }
04816 ;
04817
04818 operation : tIDENTIFIER
04819 | tCONSTANT
04820 | tFID
04821 ;
04822
04823 operation2 : tIDENTIFIER
04824 | tCONSTANT
04825 | tFID
04826 | op
04827 ;
04828
04829 operation3 : tIDENTIFIER
04830 | tFID
04831 | op
04832 ;
04833
04834 dot_or_colon : '.'
04835
04836
04837 { $$ = $<val>1; }
04838
04839 | tCOLON2
04840
04841
04842 { $$ = $<val>1; }
04843
04844 ;
04845
04846 opt_terms :
04847 | terms
04848 ;
04849
04850 opt_nl :
04851 | '\n'
04852 ;
04853
04854 rparen : opt_nl ')'
04855 ;
04856
04857 rbracket : opt_nl ']'
04858 ;
04859
04860 trailer :
04861 | '\n'
04862 | ','
04863 ;
04864
04865 term : ';' {yyerrok;}
04866 | '\n'
04867 ;
04868
04869 terms : term
04870 | terms ';' {yyerrok;}
04871 ;
04872
04873 none :
04874 {
04875 #if 0
04876 $$ = 0;
04877 #endif
04878 $$ = Qundef;
04879
04880 }
04881 ;
04882 %%
04883 # undef parser
04884 # undef yylex
04885 # undef yylval
04886 # define yylval (*((YYSTYPE*)(parser->parser_yylval)))
04887
04888 static int parser_regx_options(struct parser_params*);
04889 static int parser_tokadd_string(struct parser_params*,int,int,int,long*,rb_encoding**);
04890 static void parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc);
04891 static int parser_parse_string(struct parser_params*,NODE*);
04892 static int parser_here_document(struct parser_params*,NODE*);
04893
04894
04895 # define nextc() parser_nextc(parser)
04896 # define pushback(c) parser_pushback(parser, (c))
04897 # define newtok() parser_newtok(parser)
04898 # define tokspace(n) parser_tokspace(parser, (n))
04899 # define tokadd(c) parser_tokadd(parser, (c))
04900 # define tok_hex(numlen) parser_tok_hex(parser, (numlen))
04901 # define read_escape(flags,e) parser_read_escape(parser, (flags), (e))
04902 # define tokadd_escape(e) parser_tokadd_escape(parser, (e))
04903 # define regx_options() parser_regx_options(parser)
04904 # define tokadd_string(f,t,p,n,e) parser_tokadd_string(parser,(f),(t),(p),(n),(e))
04905 # define parse_string(n) parser_parse_string(parser,(n))
04906 # define tokaddmbc(c, enc) parser_tokaddmbc(parser, (c), (enc))
04907 # define here_document(n) parser_here_document(parser,(n))
04908 # define heredoc_identifier() parser_heredoc_identifier(parser)
04909 # define heredoc_restore(n) parser_heredoc_restore(parser,(n))
04910 # define whole_match_p(e,l,i) parser_whole_match_p(parser,(e),(l),(i))
04911
04912 #ifndef RIPPER
04913 # define set_yylval_str(x) (yylval.node = NEW_STR(x))
04914 # define set_yylval_num(x) (yylval.num = (x))
04915 # define set_yylval_id(x) (yylval.id = (x))
04916 # define set_yylval_name(x) (yylval.id = (x))
04917 # define set_yylval_literal(x) (yylval.node = NEW_LIT(x))
04918 # define set_yylval_node(x) (yylval.node = (x))
04919 # define yylval_id() (yylval.id)
04920 #else
04921 static inline VALUE
04922 ripper_yylval_id(ID x)
04923 {
04924 return (VALUE)NEW_LASGN(x, ID2SYM(x));
04925 }
04926 # define set_yylval_str(x) (void)(x)
04927 # define set_yylval_num(x) (void)(x)
04928 # define set_yylval_id(x) (void)(x)
04929 # define set_yylval_name(x) (void)(yylval.val = ripper_yylval_id(x))
04930 # define set_yylval_literal(x) (void)(x)
04931 # define set_yylval_node(x) (void)(x)
04932 # define yylval_id() yylval.id
04933 #endif
04934
04935 #ifndef RIPPER
04936 #define ripper_flush(p) (void)(p)
04937 #else
04938 #define ripper_flush(p) ((p)->tokp = (p)->parser_lex_p)
04939
04940 #define yylval_rval (*(RB_TYPE_P(yylval.val, T_NODE) ? &yylval.node->nd_rval : &yylval.val))
04941
04942 static int
04943 ripper_has_scan_event(struct parser_params *parser)
04944 {
04945
04946 if (lex_p < parser->tokp) rb_raise(rb_eRuntimeError, "lex_p < tokp");
04947 return lex_p > parser->tokp;
04948 }
04949
04950 static VALUE
04951 ripper_scan_event_val(struct parser_params *parser, int t)
04952 {
04953 VALUE str = STR_NEW(parser->tokp, lex_p - parser->tokp);
04954 VALUE rval = ripper_dispatch1(parser, ripper_token2eventid(t), str);
04955 ripper_flush(parser);
04956 return rval;
04957 }
04958
04959 static void
04960 ripper_dispatch_scan_event(struct parser_params *parser, int t)
04961 {
04962 if (!ripper_has_scan_event(parser)) return;
04963 yylval_rval = ripper_scan_event_val(parser, t);
04964 }
04965
04966 static void
04967 ripper_dispatch_ignored_scan_event(struct parser_params *parser, int t)
04968 {
04969 if (!ripper_has_scan_event(parser)) return;
04970 (void)ripper_scan_event_val(parser, t);
04971 }
04972
04973 static void
04974 ripper_dispatch_delayed_token(struct parser_params *parser, int t)
04975 {
04976 int saved_line = ruby_sourceline;
04977 const char *saved_tokp = parser->tokp;
04978
04979 ruby_sourceline = parser->delayed_line;
04980 parser->tokp = lex_pbeg + parser->delayed_col;
04981 yylval_rval = ripper_dispatch1(parser, ripper_token2eventid(t), parser->delayed);
04982 parser->delayed = Qnil;
04983 ruby_sourceline = saved_line;
04984 parser->tokp = saved_tokp;
04985 }
04986 #endif
04987
04988 #include "ruby/regex.h"
04989 #include "ruby/util.h"
04990
04991
04992
04993
04994
04995 #undef SIGN_EXTEND_CHAR
04996 #if __STDC__
04997 # define SIGN_EXTEND_CHAR(c) ((signed char)(c))
04998 #else
04999
05000 # define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
05001 #endif
05002
05003 #define parser_encoding_name() (parser->enc->name)
05004 #define parser_mbclen() mbclen((lex_p-1),lex_pend,parser->enc)
05005 #define parser_precise_mbclen() rb_enc_precise_mbclen((lex_p-1),lex_pend,parser->enc)
05006 #define is_identchar(p,e,enc) (rb_enc_isalnum(*(p),(enc)) || (*(p)) == '_' || !ISASCII(*(p)))
05007 #define parser_is_identchar() (!parser->eofp && is_identchar((lex_p-1),lex_pend,parser->enc))
05008
05009 #define parser_isascii() ISASCII(*(lex_p-1))
05010
05011 #ifndef RIPPER
05012 static int
05013 token_info_get_column(struct parser_params *parser, const char *token)
05014 {
05015 int column = 1;
05016 const char *p, *pend = lex_p - strlen(token);
05017 for (p = lex_pbeg; p < pend; p++) {
05018 if (*p == '\t') {
05019 column = (((column - 1) / 8) + 1) * 8;
05020 }
05021 column++;
05022 }
05023 return column;
05024 }
05025
05026 static int
05027 token_info_has_nonspaces(struct parser_params *parser, const char *token)
05028 {
05029 const char *p, *pend = lex_p - strlen(token);
05030 for (p = lex_pbeg; p < pend; p++) {
05031 if (*p != ' ' && *p != '\t') {
05032 return 1;
05033 }
05034 }
05035 return 0;
05036 }
05037
05038 #undef token_info_push
05039 static void
05040 token_info_push(struct parser_params *parser, const char *token)
05041 {
05042 token_info *ptinfo;
05043
05044 if (!parser->parser_token_info_enabled) return;
05045 ptinfo = ALLOC(token_info);
05046 ptinfo->token = token;
05047 ptinfo->linenum = ruby_sourceline;
05048 ptinfo->column = token_info_get_column(parser, token);
05049 ptinfo->nonspc = token_info_has_nonspaces(parser, token);
05050 ptinfo->next = parser->parser_token_info;
05051
05052 parser->parser_token_info = ptinfo;
05053 }
05054
05055 #undef token_info_pop
05056 static void
05057 token_info_pop(struct parser_params *parser, const char *token)
05058 {
05059 int linenum;
05060 token_info *ptinfo = parser->parser_token_info;
05061
05062 if (!ptinfo) return;
05063 parser->parser_token_info = ptinfo->next;
05064 if (token_info_get_column(parser, token) == ptinfo->column) {
05065 goto finish;
05066 }
05067 linenum = ruby_sourceline;
05068 if (linenum == ptinfo->linenum) {
05069 goto finish;
05070 }
05071 if (token_info_has_nonspaces(parser, token) || ptinfo->nonspc) {
05072 goto finish;
05073 }
05074 if (parser->parser_token_info_enabled) {
05075 rb_compile_warn(ruby_sourcefile, linenum,
05076 "mismatched indentations at '%s' with '%s' at %d",
05077 token, ptinfo->token, ptinfo->linenum);
05078 }
05079
05080 finish:
05081 xfree(ptinfo);
05082 }
05083 #endif
05084
05085 static int
05086 parser_yyerror(struct parser_params *parser, const char *msg)
05087 {
05088 #ifndef RIPPER
05089 const int max_line_margin = 30;
05090 const char *p, *pe;
05091 char *buf;
05092 long len;
05093 int i;
05094
05095 compile_error(PARSER_ARG "%s", msg);
05096 p = lex_p;
05097 while (lex_pbeg <= p) {
05098 if (*p == '\n') break;
05099 p--;
05100 }
05101 p++;
05102
05103 pe = lex_p;
05104 while (pe < lex_pend) {
05105 if (*pe == '\n') break;
05106 pe++;
05107 }
05108
05109 len = pe - p;
05110 if (len > 4) {
05111 char *p2;
05112 const char *pre = "", *post = "";
05113
05114 if (len > max_line_margin * 2 + 10) {
05115 if (lex_p - p > max_line_margin) {
05116 p = rb_enc_prev_char(p, lex_p - max_line_margin, pe, rb_enc_get(lex_lastline));
05117 pre = "...";
05118 }
05119 if (pe - lex_p > max_line_margin) {
05120 pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, pe, rb_enc_get(lex_lastline));
05121 post = "...";
05122 }
05123 len = pe - p;
05124 }
05125 buf = ALLOCA_N(char, len+2);
05126 MEMCPY(buf, p, char, len);
05127 buf[len] = '\0';
05128 rb_compile_error_append("%s%s%s", pre, buf, post);
05129
05130 i = (int)(lex_p - p);
05131 p2 = buf; pe = buf + len;
05132
05133 while (p2 < pe) {
05134 if (*p2 != '\t') *p2 = ' ';
05135 p2++;
05136 }
05137 buf[i] = '^';
05138 buf[i+1] = '\0';
05139 rb_compile_error_append("%s%s", pre, buf);
05140 }
05141 #else
05142 dispatch1(parse_error, STR_NEW2(msg));
05143 #endif
05144 return 0;
05145 }
05146
05147 static void parser_prepare(struct parser_params *parser);
05148
05149 #ifndef RIPPER
05150 static VALUE
05151 debug_lines(const char *f)
05152 {
05153 ID script_lines;
05154 CONST_ID(script_lines, "SCRIPT_LINES__");
05155 if (rb_const_defined_at(rb_cObject, script_lines)) {
05156 VALUE hash = rb_const_get_at(rb_cObject, script_lines);
05157 if (TYPE(hash) == T_HASH) {
05158 VALUE fname = rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding());
05159 VALUE lines = rb_ary_new();
05160 rb_hash_aset(hash, fname, lines);
05161 return lines;
05162 }
05163 }
05164 return 0;
05165 }
05166
05167 static VALUE
05168 coverage(const char *f, int n)
05169 {
05170 VALUE coverages = rb_get_coverages();
05171 if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
05172 VALUE fname = rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding());
05173 VALUE lines = rb_ary_new2(n);
05174 int i;
05175 RBASIC(lines)->klass = 0;
05176 for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil;
05177 RARRAY(lines)->as.heap.len = n;
05178 rb_hash_aset(coverages, fname, lines);
05179 return lines;
05180 }
05181 return 0;
05182 }
05183
05184 static int
05185 e_option_supplied(struct parser_params *parser)
05186 {
05187 return strcmp(ruby_sourcefile, "-e") == 0;
05188 }
05189
05190 static VALUE
05191 yycompile0(VALUE arg, int tracing)
05192 {
05193 int n;
05194 NODE *tree;
05195 struct parser_params *parser = (struct parser_params *)arg;
05196
05197 if (!compile_for_eval && rb_safe_level() == 0) {
05198 ruby_debug_lines = debug_lines(ruby_sourcefile);
05199 if (ruby_debug_lines && ruby_sourceline > 0) {
05200 VALUE str = STR_NEW0();
05201 n = ruby_sourceline;
05202 do {
05203 rb_ary_push(ruby_debug_lines, str);
05204 } while (--n);
05205 }
05206
05207 if (!e_option_supplied(parser)) {
05208 ruby_coverage = coverage(ruby_sourcefile, ruby_sourceline);
05209 }
05210 }
05211
05212 parser_prepare(parser);
05213 deferred_nodes = 0;
05214 #ifndef RIPPER
05215 parser->parser_token_info_enabled = !compile_for_eval && RTEST(ruby_verbose);
05216 #endif
05217 n = yyparse((void*)parser);
05218 ruby_debug_lines = 0;
05219 ruby_coverage = 0;
05220 compile_for_eval = 0;
05221
05222 lex_strterm = 0;
05223 lex_p = lex_pbeg = lex_pend = 0;
05224 lex_lastline = lex_nextline = 0;
05225 if (parser->nerr) {
05226 return 0;
05227 }
05228 tree = ruby_eval_tree;
05229 if (!tree) {
05230 tree = NEW_NIL();
05231 }
05232 else if (ruby_eval_tree_begin) {
05233 tree->nd_body = NEW_PRELUDE(ruby_eval_tree_begin, tree->nd_body);
05234 }
05235 return (VALUE)tree;
05236 }
05237
05238 static NODE*
05239 yycompile(struct parser_params *parser, const char *f, int line)
05240 {
05241 ruby_sourcefile = ruby_strdup(f);
05242 ruby_sourceline = line - 1;
05243 return (NODE *)ruby_suppress_tracing(yycompile0, (VALUE)parser, TRUE);
05244 }
05245 #endif
05246
05247 static rb_encoding *
05248 must_be_ascii_compatible(VALUE s)
05249 {
05250 rb_encoding *enc = rb_enc_get(s);
05251 if (!rb_enc_asciicompat(enc)) {
05252 rb_raise(rb_eArgError, "invalid source encoding");
05253 }
05254 return enc;
05255 }
05256
05257 static VALUE
05258 lex_get_str(struct parser_params *parser, VALUE s)
05259 {
05260 char *beg, *end, *pend;
05261 rb_encoding *enc = must_be_ascii_compatible(s);
05262
05263 beg = RSTRING_PTR(s);
05264 if (lex_gets_ptr) {
05265 if (RSTRING_LEN(s) == lex_gets_ptr) return Qnil;
05266 beg += lex_gets_ptr;
05267 }
05268 pend = RSTRING_PTR(s) + RSTRING_LEN(s);
05269 end = beg;
05270 while (end < pend) {
05271 if (*end++ == '\n') break;
05272 }
05273 lex_gets_ptr = end - RSTRING_PTR(s);
05274 return rb_enc_str_new(beg, end - beg, enc);
05275 }
05276
05277 static VALUE
05278 lex_getline(struct parser_params *parser)
05279 {
05280 VALUE line = (*parser->parser_lex_gets)(parser, parser->parser_lex_input);
05281 if (NIL_P(line)) return line;
05282 must_be_ascii_compatible(line);
05283 #ifndef RIPPER
05284 if (ruby_debug_lines) {
05285 rb_enc_associate(line, parser->enc);
05286 rb_ary_push(ruby_debug_lines, line);
05287 }
05288 if (ruby_coverage) {
05289 rb_ary_push(ruby_coverage, Qnil);
05290 }
05291 #endif
05292 return line;
05293 }
05294
05295 #ifdef RIPPER
05296 static rb_data_type_t parser_data_type;
05297 #else
05298 static const rb_data_type_t parser_data_type;
05299
05300 static NODE*
05301 parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line)
05302 {
05303 struct parser_params *parser;
05304 NODE *node;
05305 volatile VALUE tmp;
05306
05307 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
05308 lex_gets = lex_get_str;
05309 lex_gets_ptr = 0;
05310 lex_input = s;
05311 lex_pbeg = lex_p = lex_pend = 0;
05312 compile_for_eval = rb_parse_in_eval();
05313
05314 node = yycompile(parser, f, line);
05315 tmp = vparser;
05316
05317 return node;
05318 }
05319
05320 NODE*
05321 rb_compile_string(const char *f, VALUE s, int line)
05322 {
05323 must_be_ascii_compatible(s);
05324 return parser_compile_string(rb_parser_new(), f, s, line);
05325 }
05326
05327 NODE*
05328 rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line)
05329 {
05330 must_be_ascii_compatible(s);
05331 return parser_compile_string(vparser, f, s, line);
05332 }
05333
05334 NODE*
05335 rb_compile_cstr(const char *f, const char *s, int len, int line)
05336 {
05337 VALUE str = rb_str_new(s, len);
05338 return parser_compile_string(rb_parser_new(), f, str, line);
05339 }
05340
05341 NODE*
05342 rb_parser_compile_cstr(volatile VALUE vparser, const char *f, const char *s, int len, int line)
05343 {
05344 VALUE str = rb_str_new(s, len);
05345 return parser_compile_string(vparser, f, str, line);
05346 }
05347
05348 static VALUE
05349 lex_io_gets(struct parser_params *parser, VALUE io)
05350 {
05351 return rb_io_gets(io);
05352 }
05353
05354 NODE*
05355 rb_compile_file(const char *f, VALUE file, int start)
05356 {
05357 VALUE volatile vparser = rb_parser_new();
05358
05359 return rb_parser_compile_file(vparser, f, file, start);
05360 }
05361
05362 NODE*
05363 rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start)
05364 {
05365 struct parser_params *parser;
05366 volatile VALUE tmp;
05367 NODE *node;
05368
05369 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
05370 lex_gets = lex_io_gets;
05371 lex_input = file;
05372 lex_pbeg = lex_p = lex_pend = 0;
05373 compile_for_eval = rb_parse_in_eval();
05374
05375 node = yycompile(parser, f, start);
05376 tmp = vparser;
05377
05378 return node;
05379 }
05380 #endif
05381
05382 #define STR_FUNC_ESCAPE 0x01
05383 #define STR_FUNC_EXPAND 0x02
05384 #define STR_FUNC_REGEXP 0x04
05385 #define STR_FUNC_QWORDS 0x08
05386 #define STR_FUNC_SYMBOL 0x10
05387 #define STR_FUNC_INDENT 0x20
05388
05389 enum string_type {
05390 str_squote = (0),
05391 str_dquote = (STR_FUNC_EXPAND),
05392 str_xquote = (STR_FUNC_EXPAND),
05393 str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
05394 str_sword = (STR_FUNC_QWORDS),
05395 str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
05396 str_ssym = (STR_FUNC_SYMBOL),
05397 str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND)
05398 };
05399
05400 static VALUE
05401 parser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *enc0)
05402 {
05403 VALUE str;
05404
05405 str = rb_enc_str_new(p, n, enc);
05406 if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
05407 if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
05408 }
05409 else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) {
05410 rb_enc_associate(str, rb_ascii8bit_encoding());
05411 }
05412 }
05413
05414 return str;
05415 }
05416
05417 #define lex_goto_eol(parser) ((parser)->parser_lex_p = (parser)->parser_lex_pend)
05418 #define lex_eol_p() (lex_p >= lex_pend)
05419 #define peek(c) peek_n((c), 0)
05420 #define peek_n(c,n) (lex_p+(n) < lex_pend && (c) == (unsigned char)lex_p[n])
05421
05422 static inline int
05423 parser_nextc(struct parser_params *parser)
05424 {
05425 int c;
05426
05427 if (lex_p == lex_pend) {
05428 VALUE v = lex_nextline;
05429 lex_nextline = 0;
05430 if (!v) {
05431 if (parser->eofp)
05432 return -1;
05433
05434 if (!lex_input || NIL_P(v = lex_getline(parser))) {
05435 parser->eofp = Qtrue;
05436 lex_goto_eol(parser);
05437 return -1;
05438 }
05439 }
05440 {
05441 #ifdef RIPPER
05442 if (parser->tokp < lex_pend) {
05443 if (NIL_P(parser->delayed)) {
05444 parser->delayed = rb_str_buf_new(1024);
05445 rb_enc_associate(parser->delayed, parser->enc);
05446 rb_str_buf_cat(parser->delayed,
05447 parser->tokp, lex_pend - parser->tokp);
05448 parser->delayed_line = ruby_sourceline;
05449 parser->delayed_col = (int)(parser->tokp - lex_pbeg);
05450 }
05451 else {
05452 rb_str_buf_cat(parser->delayed,
05453 parser->tokp, lex_pend - parser->tokp);
05454 }
05455 }
05456 #endif
05457 if (heredoc_end > 0) {
05458 ruby_sourceline = heredoc_end;
05459 heredoc_end = 0;
05460 }
05461 ruby_sourceline++;
05462 parser->line_count++;
05463 lex_pbeg = lex_p = RSTRING_PTR(v);
05464 lex_pend = lex_p + RSTRING_LEN(v);
05465 ripper_flush(parser);
05466 lex_lastline = v;
05467 }
05468 }
05469 c = (unsigned char)*lex_p++;
05470 if (c == '\r' && peek('\n')) {
05471 lex_p++;
05472 c = '\n';
05473 }
05474
05475 return c;
05476 }
05477
05478 static void
05479 parser_pushback(struct parser_params *parser, int c)
05480 {
05481 if (c == -1) return;
05482 lex_p--;
05483 if (lex_p > lex_pbeg && lex_p[0] == '\n' && lex_p[-1] == '\r') {
05484 lex_p--;
05485 }
05486 }
05487
05488 #define was_bol() (lex_p == lex_pbeg + 1)
05489
05490 #define tokfix() (tokenbuf[tokidx]='\0')
05491 #define tok() tokenbuf
05492 #define toklen() tokidx
05493 #define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
05494
05495 static char*
05496 parser_newtok(struct parser_params *parser)
05497 {
05498 tokidx = 0;
05499 if (!tokenbuf) {
05500 toksiz = 60;
05501 tokenbuf = ALLOC_N(char, 60);
05502 }
05503 if (toksiz > 4096) {
05504 toksiz = 60;
05505 REALLOC_N(tokenbuf, char, 60);
05506 }
05507 return tokenbuf;
05508 }
05509
05510 static char *
05511 parser_tokspace(struct parser_params *parser, int n)
05512 {
05513 tokidx += n;
05514
05515 if (tokidx >= toksiz) {
05516 do {toksiz *= 2;} while (toksiz < tokidx);
05517 REALLOC_N(tokenbuf, char, toksiz);
05518 }
05519 return &tokenbuf[tokidx-n];
05520 }
05521
05522 static void
05523 parser_tokadd(struct parser_params *parser, int c)
05524 {
05525 tokenbuf[tokidx++] = (char)c;
05526 if (tokidx >= toksiz) {
05527 toksiz *= 2;
05528 REALLOC_N(tokenbuf, char, toksiz);
05529 }
05530 }
05531
05532 static int
05533 parser_tok_hex(struct parser_params *parser, size_t *numlen)
05534 {
05535 int c;
05536
05537 c = scan_hex(lex_p, 2, numlen);
05538 if (!*numlen) {
05539 yyerror("invalid hex escape");
05540 return 0;
05541 }
05542 lex_p += *numlen;
05543 return c;
05544 }
05545
05546 #define tokcopy(n) memcpy(tokspace(n), lex_p - (n), (n))
05547
05548 static int
05549 parser_tokadd_utf8(struct parser_params *parser, rb_encoding **encp,
05550 int string_literal, int symbol_literal, int regexp_literal)
05551 {
05552
05553
05554
05555
05556
05557
05558
05559 int codepoint;
05560 size_t numlen;
05561
05562 if (regexp_literal) { tokadd('\\'); tokadd('u'); }
05563
05564 if (peek('{')) {
05565 do {
05566 if (regexp_literal) { tokadd(*lex_p); }
05567 nextc();
05568 codepoint = scan_hex(lex_p, 6, &numlen);
05569 if (numlen == 0) {
05570 yyerror("invalid Unicode escape");
05571 return 0;
05572 }
05573 if (codepoint > 0x10ffff) {
05574 yyerror("invalid Unicode codepoint (too large)");
05575 return 0;
05576 }
05577 lex_p += numlen;
05578 if (regexp_literal) {
05579 tokcopy((int)numlen);
05580 }
05581 else if (codepoint >= 0x80) {
05582 *encp = UTF8_ENC();
05583 if (string_literal) tokaddmbc(codepoint, *encp);
05584 }
05585 else if (string_literal) {
05586 tokadd(codepoint);
05587 }
05588 } while (string_literal && (peek(' ') || peek('\t')));
05589
05590 if (!peek('}')) {
05591 yyerror("unterminated Unicode escape");
05592 return 0;
05593 }
05594
05595 if (regexp_literal) { tokadd('}'); }
05596 nextc();
05597 }
05598 else {
05599 codepoint = scan_hex(lex_p, 4, &numlen);
05600 if (numlen < 4) {
05601 yyerror("invalid Unicode escape");
05602 return 0;
05603 }
05604 lex_p += 4;
05605 if (regexp_literal) {
05606 tokcopy(4);
05607 }
05608 else if (codepoint >= 0x80) {
05609 *encp = UTF8_ENC();
05610 if (string_literal) tokaddmbc(codepoint, *encp);
05611 }
05612 else if (string_literal) {
05613 tokadd(codepoint);
05614 }
05615 }
05616
05617 return codepoint;
05618 }
05619
05620 #define ESCAPE_CONTROL 1
05621 #define ESCAPE_META 2
05622
05623 static int
05624 parser_read_escape(struct parser_params *parser, int flags,
05625 rb_encoding **encp)
05626 {
05627 int c;
05628 size_t numlen;
05629
05630 switch (c = nextc()) {
05631 case '\\':
05632 return c;
05633
05634 case 'n':
05635 return '\n';
05636
05637 case 't':
05638 return '\t';
05639
05640 case 'r':
05641 return '\r';
05642
05643 case 'f':
05644 return '\f';
05645
05646 case 'v':
05647 return '\13';
05648
05649 case 'a':
05650 return '\007';
05651
05652 case 'e':
05653 return 033;
05654
05655 case '0': case '1': case '2': case '3':
05656 case '4': case '5': case '6': case '7':
05657 pushback(c);
05658 c = scan_oct(lex_p, 3, &numlen);
05659 lex_p += numlen;
05660 return c;
05661
05662 case 'x':
05663 c = tok_hex(&numlen);
05664 if (numlen == 0) return 0;
05665 return c;
05666
05667 case 'b':
05668 return '\010';
05669
05670 case 's':
05671 return ' ';
05672
05673 case 'M':
05674 if (flags & ESCAPE_META) goto eof;
05675 if ((c = nextc()) != '-') {
05676 pushback(c);
05677 goto eof;
05678 }
05679 if ((c = nextc()) == '\\') {
05680 if (peek('u')) goto eof;
05681 return read_escape(flags|ESCAPE_META, encp) | 0x80;
05682 }
05683 else if (c == -1 || !ISASCII(c)) goto eof;
05684 else {
05685 return ((c & 0xff) | 0x80);
05686 }
05687
05688 case 'C':
05689 if ((c = nextc()) != '-') {
05690 pushback(c);
05691 goto eof;
05692 }
05693 case 'c':
05694 if (flags & ESCAPE_CONTROL) goto eof;
05695 if ((c = nextc())== '\\') {
05696 if (peek('u')) goto eof;
05697 c = read_escape(flags|ESCAPE_CONTROL, encp);
05698 }
05699 else if (c == '?')
05700 return 0177;
05701 else if (c == -1 || !ISASCII(c)) goto eof;
05702 return c & 0x9f;
05703
05704 eof:
05705 case -1:
05706 yyerror("Invalid escape character syntax");
05707 return '\0';
05708
05709 default:
05710 return c;
05711 }
05712 }
05713
05714 static void
05715 parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc)
05716 {
05717 int len = rb_enc_codelen(c, enc);
05718 rb_enc_mbcput(c, tokspace(len), enc);
05719 }
05720
05721 static int
05722 parser_tokadd_escape(struct parser_params *parser, rb_encoding **encp)
05723 {
05724 int c;
05725 int flags = 0;
05726 size_t numlen;
05727
05728 first:
05729 switch (c = nextc()) {
05730 case '\n':
05731 return 0;
05732
05733 case '0': case '1': case '2': case '3':
05734 case '4': case '5': case '6': case '7':
05735 {
05736 ruby_scan_oct(--lex_p, 3, &numlen);
05737 if (numlen == 0) goto eof;
05738 lex_p += numlen;
05739 tokcopy((int)numlen + 1);
05740 }
05741 return 0;
05742
05743 case 'x':
05744 {
05745 tok_hex(&numlen);
05746 if (numlen == 0) return -1;
05747 tokcopy((int)numlen + 2);
05748 }
05749 return 0;
05750
05751 case 'M':
05752 if (flags & ESCAPE_META) goto eof;
05753 if ((c = nextc()) != '-') {
05754 pushback(c);
05755 goto eof;
05756 }
05757 tokcopy(3);
05758 flags |= ESCAPE_META;
05759 goto escaped;
05760
05761 case 'C':
05762 if (flags & ESCAPE_CONTROL) goto eof;
05763 if ((c = nextc()) != '-') {
05764 pushback(c);
05765 goto eof;
05766 }
05767 tokcopy(3);
05768 goto escaped;
05769
05770 case 'c':
05771 if (flags & ESCAPE_CONTROL) goto eof;
05772 tokcopy(2);
05773 flags |= ESCAPE_CONTROL;
05774 escaped:
05775 if ((c = nextc()) == '\\') {
05776 goto first;
05777 }
05778 else if (c == -1) goto eof;
05779 tokadd(c);
05780 return 0;
05781
05782 eof:
05783 case -1:
05784 yyerror("Invalid escape character syntax");
05785 return -1;
05786
05787 default:
05788 tokadd('\\');
05789 tokadd(c);
05790 }
05791 return 0;
05792 }
05793
05794 static int
05795 parser_regx_options(struct parser_params *parser)
05796 {
05797 int kcode = 0;
05798 int kopt = 0;
05799 int options = 0;
05800 int c, opt, kc;
05801
05802 newtok();
05803 while (c = nextc(), ISALPHA(c)) {
05804 if (c == 'o') {
05805 options |= RE_OPTION_ONCE;
05806 }
05807 else if (rb_char_to_option_kcode(c, &opt, &kc)) {
05808 if (kc >= 0) {
05809 if (kc != rb_ascii8bit_encindex()) kcode = c;
05810 kopt = opt;
05811 }
05812 else {
05813 options |= opt;
05814 }
05815 }
05816 else {
05817 tokadd(c);
05818 }
05819 }
05820 options |= kopt;
05821 pushback(c);
05822 if (toklen()) {
05823 tokfix();
05824 compile_error(PARSER_ARG "unknown regexp option%s - %s",
05825 toklen() > 1 ? "s" : "", tok());
05826 }
05827 return options | RE_OPTION_ENCODING(kcode);
05828 }
05829
05830 static void
05831 dispose_string(VALUE str)
05832 {
05833
05834 if (RBASIC(str)->flags & RSTRING_NOEMBED)
05835 xfree(RSTRING_PTR(str));
05836 rb_gc_force_recycle(str);
05837 }
05838
05839 static int
05840 parser_tokadd_mbchar(struct parser_params *parser, int c)
05841 {
05842 int len = parser_precise_mbclen();
05843 if (!MBCLEN_CHARFOUND_P(len)) {
05844 compile_error(PARSER_ARG "invalid multibyte char (%s)", parser_encoding_name());
05845 return -1;
05846 }
05847 tokadd(c);
05848 lex_p += --len;
05849 if (len > 0) tokcopy(len);
05850 return c;
05851 }
05852
05853 #define tokadd_mbchar(c) parser_tokadd_mbchar(parser, (c))
05854
05855 static int
05856 parser_tokadd_string(struct parser_params *parser,
05857 int func, int term, int paren, long *nest,
05858 rb_encoding **encp)
05859 {
05860 int c;
05861 int has_nonascii = 0;
05862 rb_encoding *enc = *encp;
05863 char *errbuf = 0;
05864 static const char mixed_msg[] = "%s mixed within %s source";
05865
05866 #define mixed_error(enc1, enc2) if (!errbuf) { \
05867 size_t len = sizeof(mixed_msg) - 4; \
05868 len += strlen(rb_enc_name(enc1)); \
05869 len += strlen(rb_enc_name(enc2)); \
05870 errbuf = ALLOCA_N(char, len); \
05871 snprintf(errbuf, len, mixed_msg, \
05872 rb_enc_name(enc1), \
05873 rb_enc_name(enc2)); \
05874 yyerror(errbuf); \
05875 }
05876 #define mixed_escape(beg, enc1, enc2) do { \
05877 const char *pos = lex_p; \
05878 lex_p = (beg); \
05879 mixed_error((enc1), (enc2)); \
05880 lex_p = pos; \
05881 } while (0)
05882
05883 while ((c = nextc()) != -1) {
05884 if (paren && c == paren) {
05885 ++*nest;
05886 }
05887 else if (c == term) {
05888 if (!nest || !*nest) {
05889 pushback(c);
05890 break;
05891 }
05892 --*nest;
05893 }
05894 else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) {
05895 int c2 = *lex_p;
05896 if (c2 == '$' || c2 == '@' || c2 == '{') {
05897 pushback(c);
05898 break;
05899 }
05900 }
05901 else if (c == '\\') {
05902 const char *beg = lex_p - 1;
05903 c = nextc();
05904 switch (c) {
05905 case '\n':
05906 if (func & STR_FUNC_QWORDS) break;
05907 if (func & STR_FUNC_EXPAND) continue;
05908 tokadd('\\');
05909 break;
05910
05911 case '\\':
05912 if (func & STR_FUNC_ESCAPE) tokadd(c);
05913 break;
05914
05915 case 'u':
05916 if ((func & STR_FUNC_EXPAND) == 0) {
05917 tokadd('\\');
05918 break;
05919 }
05920 parser_tokadd_utf8(parser, &enc, 1,
05921 func & STR_FUNC_SYMBOL,
05922 func & STR_FUNC_REGEXP);
05923 if (has_nonascii && enc != *encp) {
05924 mixed_escape(beg, enc, *encp);
05925 }
05926 continue;
05927
05928 default:
05929 if (c == -1) return -1;
05930 if (!ISASCII(c)) {
05931 if ((func & STR_FUNC_EXPAND) == 0) tokadd('\\');
05932 goto non_ascii;
05933 }
05934 if (func & STR_FUNC_REGEXP) {
05935 pushback(c);
05936 if ((c = tokadd_escape(&enc)) < 0)
05937 return -1;
05938 if (has_nonascii && enc != *encp) {
05939 mixed_escape(beg, enc, *encp);
05940 }
05941 continue;
05942 }
05943 else if (func & STR_FUNC_EXPAND) {
05944 pushback(c);
05945 if (func & STR_FUNC_ESCAPE) tokadd('\\');
05946 c = read_escape(0, &enc);
05947 }
05948 else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
05949
05950 }
05951 else if (c != term && !(paren && c == paren)) {
05952 tokadd('\\');
05953 pushback(c);
05954 continue;
05955 }
05956 }
05957 }
05958 else if (!parser_isascii()) {
05959 non_ascii:
05960 has_nonascii = 1;
05961 if (enc != *encp) {
05962 mixed_error(enc, *encp);
05963 continue;
05964 }
05965 if (tokadd_mbchar(c) == -1) return -1;
05966 continue;
05967 }
05968 else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
05969 pushback(c);
05970 break;
05971 }
05972 if (c & 0x80) {
05973 has_nonascii = 1;
05974 if (enc != *encp) {
05975 mixed_error(enc, *encp);
05976 continue;
05977 }
05978 }
05979 tokadd(c);
05980 }
05981 *encp = enc;
05982 return c;
05983 }
05984
05985 #define NEW_STRTERM(func, term, paren) \
05986 rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
05987
05988 #ifdef RIPPER
05989 static void
05990 ripper_flush_string_content(struct parser_params *parser, rb_encoding *enc)
05991 {
05992 if (!NIL_P(parser->delayed)) {
05993 ptrdiff_t len = lex_p - parser->tokp;
05994 if (len > 0) {
05995 rb_enc_str_buf_cat(parser->delayed, parser->tokp, len, enc);
05996 }
05997 ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
05998 parser->tokp = lex_p;
05999 }
06000 }
06001
06002 #define flush_string_content(enc) ripper_flush_string_content(parser, (enc))
06003 #else
06004 #define flush_string_content(enc) ((void)(enc))
06005 #endif
06006
06007 static int
06008 parser_parse_string(struct parser_params *parser, NODE *quote)
06009 {
06010 int func = (int)quote->nd_func;
06011 int term = nd_term(quote);
06012 int paren = nd_paren(quote);
06013 int c, space = 0;
06014 rb_encoding *enc = parser->enc;
06015
06016 if (func == -1) return tSTRING_END;
06017 c = nextc();
06018 if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
06019 do {c = nextc();} while (ISSPACE(c));
06020 space = 1;
06021 }
06022 if (c == term && !quote->nd_nest) {
06023 if (func & STR_FUNC_QWORDS) {
06024 quote->nd_func = -1;
06025 return ' ';
06026 }
06027 if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
06028 set_yylval_num(regx_options());
06029 return tREGEXP_END;
06030 }
06031 if (space) {
06032 pushback(c);
06033 return ' ';
06034 }
06035 newtok();
06036 if ((func & STR_FUNC_EXPAND) && c == '#') {
06037 switch (c = nextc()) {
06038 case '$':
06039 case '@':
06040 pushback(c);
06041 return tSTRING_DVAR;
06042 case '{':
06043 return tSTRING_DBEG;
06044 }
06045 tokadd('#');
06046 }
06047 pushback(c);
06048 if (tokadd_string(func, term, paren, "e->nd_nest,
06049 &enc) == -1) {
06050 ruby_sourceline = nd_line(quote);
06051 if (func & STR_FUNC_REGEXP) {
06052 if (parser->eofp)
06053 compile_error(PARSER_ARG "unterminated regexp meets end of file");
06054 return tREGEXP_END;
06055 }
06056 else {
06057 if (parser->eofp)
06058 compile_error(PARSER_ARG "unterminated string meets end of file");
06059 return tSTRING_END;
06060 }
06061 }
06062
06063 tokfix();
06064 set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
06065 flush_string_content(enc);
06066
06067 return tSTRING_CONTENT;
06068 }
06069
06070 static int
06071 parser_heredoc_identifier(struct parser_params *parser)
06072 {
06073 int c = nextc(), term, func = 0;
06074 long len;
06075
06076 if (c == '-') {
06077 c = nextc();
06078 func = STR_FUNC_INDENT;
06079 }
06080 switch (c) {
06081 case '\'':
06082 func |= str_squote; goto quoted;
06083 case '"':
06084 func |= str_dquote; goto quoted;
06085 case '`':
06086 func |= str_xquote;
06087 quoted:
06088 newtok();
06089 tokadd(func);
06090 term = c;
06091 while ((c = nextc()) != -1 && c != term) {
06092 if (tokadd_mbchar(c) == -1) return 0;
06093 }
06094 if (c == -1) {
06095 compile_error(PARSER_ARG "unterminated here document identifier");
06096 return 0;
06097 }
06098 break;
06099
06100 default:
06101 if (!parser_is_identchar()) {
06102 pushback(c);
06103 if (func & STR_FUNC_INDENT) {
06104 pushback('-');
06105 }
06106 return 0;
06107 }
06108 newtok();
06109 term = '"';
06110 tokadd(func |= str_dquote);
06111 do {
06112 if (tokadd_mbchar(c) == -1) return 0;
06113 } while ((c = nextc()) != -1 && parser_is_identchar());
06114 pushback(c);
06115 break;
06116 }
06117
06118 tokfix();
06119 #ifdef RIPPER
06120 ripper_dispatch_scan_event(parser, tHEREDOC_BEG);
06121 #endif
06122 len = lex_p - lex_pbeg;
06123 lex_goto_eol(parser);
06124 lex_strterm = rb_node_newnode(NODE_HEREDOC,
06125 STR_NEW(tok(), toklen()),
06126 len,
06127 lex_lastline);
06128 nd_set_line(lex_strterm, ruby_sourceline);
06129 ripper_flush(parser);
06130 return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
06131 }
06132
06133 static void
06134 parser_heredoc_restore(struct parser_params *parser, NODE *here)
06135 {
06136 VALUE line;
06137
06138 line = here->nd_orig;
06139 lex_lastline = line;
06140 lex_pbeg = RSTRING_PTR(line);
06141 lex_pend = lex_pbeg + RSTRING_LEN(line);
06142 lex_p = lex_pbeg + here->nd_nth;
06143 heredoc_end = ruby_sourceline;
06144 ruby_sourceline = nd_line(here);
06145 dispose_string(here->nd_lit);
06146 rb_gc_force_recycle((VALUE)here);
06147 ripper_flush(parser);
06148 }
06149
06150 static int
06151 parser_whole_match_p(struct parser_params *parser,
06152 const char *eos, long len, int indent)
06153 {
06154 const char *p = lex_pbeg;
06155 long n;
06156
06157 if (indent) {
06158 while (*p && ISSPACE(*p)) p++;
06159 }
06160 n = lex_pend - (p + len);
06161 if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return FALSE;
06162 return strncmp(eos, p, len) == 0;
06163 }
06164
06165 #ifdef RIPPER
06166 static void
06167 ripper_dispatch_heredoc_end(struct parser_params *parser)
06168 {
06169 if (!NIL_P(parser->delayed))
06170 ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06171 lex_goto_eol(parser);
06172 ripper_dispatch_ignored_scan_event(parser, tHEREDOC_END);
06173 }
06174
06175 #define dispatch_heredoc_end() ripper_dispatch_heredoc_end(parser)
06176 #else
06177 #define dispatch_heredoc_end() ((void)0)
06178 #endif
06179
06180 static int
06181 parser_here_document(struct parser_params *parser, NODE *here)
06182 {
06183 int c, func, indent = 0;
06184 const char *eos, *p, *pend;
06185 long len;
06186 VALUE str = 0;
06187 rb_encoding *enc = parser->enc;
06188
06189 eos = RSTRING_PTR(here->nd_lit);
06190 len = RSTRING_LEN(here->nd_lit) - 1;
06191 indent = (func = *eos++) & STR_FUNC_INDENT;
06192
06193 if ((c = nextc()) == -1) {
06194 error:
06195 compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos);
06196 #ifdef RIPPER
06197 if (NIL_P(parser->delayed)) {
06198 ripper_dispatch_scan_event(parser, tSTRING_CONTENT);
06199 }
06200 else {
06201 if (str ||
06202 ((len = lex_p - parser->tokp) > 0 &&
06203 (str = STR_NEW3(parser->tokp, len, enc, func), 1))) {
06204 rb_str_append(parser->delayed, str);
06205 }
06206 ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
06207 }
06208 lex_goto_eol(parser);
06209 #endif
06210 restore:
06211 heredoc_restore(lex_strterm);
06212 lex_strterm = 0;
06213 return 0;
06214 }
06215 if (was_bol() && whole_match_p(eos, len, indent)) {
06216 dispatch_heredoc_end();
06217 heredoc_restore(lex_strterm);
06218 return tSTRING_END;
06219 }
06220
06221 if (!(func & STR_FUNC_EXPAND)) {
06222 do {
06223 p = RSTRING_PTR(lex_lastline);
06224 pend = lex_pend;
06225 if (pend > p) {
06226 switch (pend[-1]) {
06227 case '\n':
06228 if (--pend == p || pend[-1] != '\r') {
06229 pend++;
06230 break;
06231 }
06232 case '\r':
06233 --pend;
06234 }
06235 }
06236 if (str)
06237 rb_str_cat(str, p, pend - p);
06238 else
06239 str = STR_NEW(p, pend - p);
06240 if (pend < lex_pend) rb_str_cat(str, "\n", 1);
06241 lex_goto_eol(parser);
06242 if (nextc() == -1) {
06243 if (str) dispose_string(str);
06244 goto error;
06245 }
06246 } while (!whole_match_p(eos, len, indent));
06247 }
06248 else {
06249
06250 newtok();
06251 if (c == '#') {
06252 switch (c = nextc()) {
06253 case '$':
06254 case '@':
06255 pushback(c);
06256 return tSTRING_DVAR;
06257 case '{':
06258 return tSTRING_DBEG;
06259 }
06260 tokadd('#');
06261 }
06262 do {
06263 pushback(c);
06264 if ((c = tokadd_string(func, '\n', 0, NULL, &enc)) == -1) {
06265 if (parser->eofp) goto error;
06266 goto restore;
06267 }
06268 if (c != '\n') {
06269 set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));
06270 flush_string_content(enc);
06271 return tSTRING_CONTENT;
06272 }
06273 tokadd(nextc());
06274
06275 if ((c = nextc()) == -1) goto error;
06276 } while (!whole_match_p(eos, len, indent));
06277 str = STR_NEW3(tok(), toklen(), enc, func);
06278 }
06279 dispatch_heredoc_end();
06280 heredoc_restore(lex_strterm);
06281 lex_strterm = NEW_STRTERM(-1, 0, 0);
06282 set_yylval_str(str);
06283 return tSTRING_CONTENT;
06284 }
06285
06286 #include "lex.c"
06287
06288 static void
06289 arg_ambiguous_gen(struct parser_params *parser)
06290 {
06291 #ifndef RIPPER
06292 rb_warning0("ambiguous first argument; put parentheses or even spaces");
06293 #else
06294 dispatch0(arg_ambiguous);
06295 #endif
06296 }
06297 #define arg_ambiguous() (arg_ambiguous_gen(parser), 1)
06298
06299 static ID
06300 formal_argument_gen(struct parser_params *parser, ID lhs)
06301 {
06302 #ifndef RIPPER
06303 if (!is_local_id(lhs))
06304 yyerror("formal argument must be local variable");
06305 #endif
06306 shadowing_lvar(lhs);
06307 return lhs;
06308 }
06309
06310 static int
06311 lvar_defined_gen(struct parser_params *parser, ID id)
06312 {
06313 return (dyna_in_block() && dvar_defined_get(id)) || local_id(id);
06314 }
06315
06316
06317 static long
06318 parser_encode_length(struct parser_params *parser, const char *name, long len)
06319 {
06320 long nlen;
06321
06322 if (len > 5 && name[nlen = len - 5] == '-') {
06323 if (rb_memcicmp(name + nlen + 1, "unix", 4) == 0)
06324 return nlen;
06325 }
06326 if (len > 4 && name[nlen = len - 4] == '-') {
06327 if (rb_memcicmp(name + nlen + 1, "dos", 3) == 0)
06328 return nlen;
06329 if (rb_memcicmp(name + nlen + 1, "mac", 3) == 0 &&
06330 !(len == 8 && rb_memcicmp(name, "utf8-mac", len) == 0))
06331
06332 return nlen;
06333 }
06334 return len;
06335 }
06336
06337 static void
06338 parser_set_encode(struct parser_params *parser, const char *name)
06339 {
06340 int idx = rb_enc_find_index(name);
06341 rb_encoding *enc;
06342 VALUE excargs[3];
06343
06344 if (idx < 0) {
06345 excargs[1] = rb_sprintf("unknown encoding name: %s", name);
06346 error:
06347 excargs[0] = rb_eArgError;
06348 excargs[2] = rb_make_backtrace();
06349 rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline));
06350 rb_exc_raise(rb_make_exception(3, excargs));
06351 }
06352 enc = rb_enc_from_index(idx);
06353 if (!rb_enc_asciicompat(enc)) {
06354 excargs[1] = rb_sprintf("%s is not ASCII compatible", rb_enc_name(enc));
06355 goto error;
06356 }
06357 parser->enc = enc;
06358 #ifndef RIPPER
06359 if (ruby_debug_lines) {
06360 long i, n = RARRAY_LEN(ruby_debug_lines);
06361 const VALUE *p = RARRAY_PTR(ruby_debug_lines);
06362 for (i = 0; i < n; ++i) {
06363 rb_enc_associate_index(*p, idx);
06364 }
06365 }
06366 #endif
06367 }
06368
06369 static int
06370 comment_at_top(struct parser_params *parser)
06371 {
06372 const char *p = lex_pbeg, *pend = lex_p - 1;
06373 if (parser->line_count != (parser->has_shebang ? 2 : 1)) return 0;
06374 while (p < pend) {
06375 if (!ISSPACE(*p)) return 0;
06376 p++;
06377 }
06378 return 1;
06379 }
06380
06381 #ifndef RIPPER
06382 typedef long (*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, long len);
06383 typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);
06384
06385 static void
06386 magic_comment_encoding(struct parser_params *parser, const char *name, const char *val)
06387 {
06388 if (!comment_at_top(parser)) {
06389 return;
06390 }
06391 parser_set_encode(parser, val);
06392 }
06393
06394 static void
06395 parser_set_token_info(struct parser_params *parser, const char *name, const char *val)
06396 {
06397 int *p = &parser->parser_token_info_enabled;
06398
06399 switch (*val) {
06400 case 't': case 'T':
06401 if (strcasecmp(val, "true") == 0) {
06402 *p = TRUE;
06403 return;
06404 }
06405 break;
06406 case 'f': case 'F':
06407 if (strcasecmp(val, "false") == 0) {
06408 *p = FALSE;
06409 return;
06410 }
06411 break;
06412 }
06413 rb_compile_warning(ruby_sourcefile, ruby_sourceline, "invalid value for %s: %s", name, val);
06414 }
06415
06416 struct magic_comment {
06417 const char *name;
06418 rb_magic_comment_setter_t func;
06419 rb_magic_comment_length_t length;
06420 };
06421
06422 static const struct magic_comment magic_comments[] = {
06423 {"coding", magic_comment_encoding, parser_encode_length},
06424 {"encoding", magic_comment_encoding, parser_encode_length},
06425 {"warn_indent", parser_set_token_info},
06426 };
06427 #endif
06428
06429 static const char *
06430 magic_comment_marker(const char *str, long len)
06431 {
06432 long i = 2;
06433
06434 while (i < len) {
06435 switch (str[i]) {
06436 case '-':
06437 if (str[i-1] == '*' && str[i-2] == '-') {
06438 return str + i + 1;
06439 }
06440 i += 2;
06441 break;
06442 case '*':
06443 if (i + 1 >= len) return 0;
06444 if (str[i+1] != '-') {
06445 i += 4;
06446 }
06447 else if (str[i-1] != '-') {
06448 i += 2;
06449 }
06450 else {
06451 return str + i + 2;
06452 }
06453 break;
06454 default:
06455 i += 3;
06456 break;
06457 }
06458 }
06459 return 0;
06460 }
06461
06462 static int
06463 parser_magic_comment(struct parser_params *parser, const char *str, long len)
06464 {
06465 VALUE name = 0, val = 0;
06466 const char *beg, *end, *vbeg, *vend;
06467 #define str_copy(_s, _p, _n) ((_s) \
06468 ? (void)(rb_str_resize((_s), (_n)), \
06469 MEMCPY(RSTRING_PTR(_s), (_p), char, (_n)), (_s)) \
06470 : (void)((_s) = STR_NEW((_p), (_n))))
06471
06472 if (len <= 7) return FALSE;
06473 if (!(beg = magic_comment_marker(str, len))) return FALSE;
06474 if (!(end = magic_comment_marker(beg, str + len - beg))) return FALSE;
06475 str = beg;
06476 len = end - beg - 3;
06477
06478
06479 while (len > 0) {
06480 #ifndef RIPPER
06481 const struct magic_comment *p = magic_comments;
06482 #endif
06483 char *s;
06484 int i;
06485 long n = 0;
06486
06487 for (; len > 0 && *str; str++, --len) {
06488 switch (*str) {
06489 case '\'': case '"': case ':': case ';':
06490 continue;
06491 }
06492 if (!ISSPACE(*str)) break;
06493 }
06494 for (beg = str; len > 0; str++, --len) {
06495 switch (*str) {
06496 case '\'': case '"': case ':': case ';':
06497 break;
06498 default:
06499 if (ISSPACE(*str)) break;
06500 continue;
06501 }
06502 break;
06503 }
06504 for (end = str; len > 0 && ISSPACE(*str); str++, --len);
06505 if (!len) break;
06506 if (*str != ':') continue;
06507
06508 do str++; while (--len > 0 && ISSPACE(*str));
06509 if (!len) break;
06510 if (*str == '"') {
06511 for (vbeg = ++str; --len > 0 && *str != '"'; str++) {
06512 if (*str == '\\') {
06513 --len;
06514 ++str;
06515 }
06516 }
06517 vend = str;
06518 if (len) {
06519 --len;
06520 ++str;
06521 }
06522 }
06523 else {
06524 for (vbeg = str; len > 0 && *str != '"' && *str != ';' && !ISSPACE(*str); --len, str++);
06525 vend = str;
06526 }
06527 while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++;
06528
06529 n = end - beg;
06530 str_copy(name, beg, n);
06531 s = RSTRING_PTR(name);
06532 for (i = 0; i < n; ++i) {
06533 if (s[i] == '-') s[i] = '_';
06534 }
06535 #ifndef RIPPER
06536 do {
06537 if (STRNCASECMP(p->name, s, n) == 0) {
06538 n = vend - vbeg;
06539 if (p->length) {
06540 n = (*p->length)(parser, vbeg, n);
06541 }
06542 str_copy(val, vbeg, n);
06543 (*p->func)(parser, s, RSTRING_PTR(val));
06544 break;
06545 }
06546 } while (++p < magic_comments + numberof(magic_comments));
06547 #else
06548 str_copy(val, vbeg, vend - vbeg);
06549 dispatch2(magic_comment, name, val);
06550 #endif
06551 }
06552
06553 return TRUE;
06554 }
06555
06556 static void
06557 set_file_encoding(struct parser_params *parser, const char *str, const char *send)
06558 {
06559 int sep = 0;
06560 const char *beg = str;
06561 VALUE s;
06562
06563 for (;;) {
06564 if (send - str <= 6) return;
06565 switch (str[6]) {
06566 case 'C': case 'c': str += 6; continue;
06567 case 'O': case 'o': str += 5; continue;
06568 case 'D': case 'd': str += 4; continue;
06569 case 'I': case 'i': str += 3; continue;
06570 case 'N': case 'n': str += 2; continue;
06571 case 'G': case 'g': str += 1; continue;
06572 case '=': case ':':
06573 sep = 1;
06574 str += 6;
06575 break;
06576 default:
06577 str += 6;
06578 if (ISSPACE(*str)) break;
06579 continue;
06580 }
06581 if (STRNCASECMP(str-6, "coding", 6) == 0) break;
06582 }
06583 for (;;) {
06584 do {
06585 if (++str >= send) return;
06586 } while (ISSPACE(*str));
06587 if (sep) break;
06588 if (*str != '=' && *str != ':') return;
06589 sep = 1;
06590 str++;
06591 }
06592 beg = str;
06593 while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send);
06594 s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg));
06595 parser_set_encode(parser, RSTRING_PTR(s));
06596 rb_str_resize(s, 0);
06597 }
06598
06599 static void
06600 parser_prepare(struct parser_params *parser)
06601 {
06602 int c = nextc();
06603 switch (c) {
06604 case '#':
06605 if (peek('!')) parser->has_shebang = 1;
06606 break;
06607 case 0xef:
06608 if (lex_pend - lex_p >= 2 &&
06609 (unsigned char)lex_p[0] == 0xbb &&
06610 (unsigned char)lex_p[1] == 0xbf) {
06611 parser->enc = rb_utf8_encoding();
06612 lex_p += 2;
06613 lex_pbeg = lex_p;
06614 return;
06615 }
06616 break;
06617 case EOF:
06618 return;
06619 }
06620 pushback(c);
06621 parser->enc = rb_enc_get(lex_lastline);
06622 }
06623
06624 #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
06625 #define IS_END() (lex_state == EXPR_END || lex_state == EXPR_ENDARG || lex_state == EXPR_ENDFN)
06626 #define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || lex_state == EXPR_VALUE || lex_state == EXPR_CLASS)
06627 #define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
06628 #define IS_LABEL_POSSIBLE() ((lex_state == EXPR_BEG && !cmd_state) || IS_ARG())
06629 #define IS_LABEL_SUFFIX(n) (peek_n(':',(n)) && !peek_n(':', (n)+1))
06630
06631 #ifndef RIPPER
06632 #define ambiguous_operator(op, syn) ( \
06633 rb_warning0("`"op"' after local variable is interpreted as binary operator"), \
06634 rb_warning0("even though it seems like "syn""))
06635 #else
06636 #define ambiguous_operator(op, syn) dispatch2(operator_ambiguous, ripper_intern(op), rb_str_new_cstr(syn))
06637 #endif
06638 #define warn_balanced(op, syn) ((void) \
06639 (last_state != EXPR_CLASS && last_state != EXPR_DOT && \
06640 last_state != EXPR_FNAME && last_state != EXPR_ENDFN && \
06641 last_state != EXPR_ENDARG && \
06642 space_seen && !ISSPACE(c) && \
06643 (ambiguous_operator(op, syn), 0)))
06644
06645 static int
06646 parser_yylex(struct parser_params *parser)
06647 {
06648 register int c;
06649 int space_seen = 0;
06650 int cmd_state;
06651 enum lex_state_e last_state;
06652 rb_encoding *enc;
06653 int mb;
06654 #ifdef RIPPER
06655 int fallthru = FALSE;
06656 #endif
06657
06658 if (lex_strterm) {
06659 int token;
06660 if (nd_type(lex_strterm) == NODE_HEREDOC) {
06661 token = here_document(lex_strterm);
06662 if (token == tSTRING_END) {
06663 lex_strterm = 0;
06664 lex_state = EXPR_END;
06665 }
06666 }
06667 else {
06668 token = parse_string(lex_strterm);
06669 if (token == tSTRING_END || token == tREGEXP_END) {
06670 rb_gc_force_recycle((VALUE)lex_strterm);
06671 lex_strterm = 0;
06672 lex_state = EXPR_END;
06673 }
06674 }
06675 return token;
06676 }
06677 cmd_state = command_start;
06678 command_start = FALSE;
06679 retry:
06680 last_state = lex_state;
06681 switch (c = nextc()) {
06682 case '\0':
06683 case '\004':
06684 case '\032':
06685 case -1:
06686 return 0;
06687
06688
06689 case ' ': case '\t': case '\f': case '\r':
06690 case '\13':
06691 space_seen = 1;
06692 #ifdef RIPPER
06693 while ((c = nextc())) {
06694 switch (c) {
06695 case ' ': case '\t': case '\f': case '\r':
06696 case '\13':
06697 break;
06698 default:
06699 goto outofloop;
06700 }
06701 }
06702 outofloop:
06703 pushback(c);
06704 ripper_dispatch_scan_event(parser, tSP);
06705 #endif
06706 goto retry;
06707
06708 case '#':
06709
06710 if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) {
06711 if (comment_at_top(parser)) {
06712 set_file_encoding(parser, lex_p, lex_pend);
06713 }
06714 }
06715 lex_p = lex_pend;
06716 #ifdef RIPPER
06717 ripper_dispatch_scan_event(parser, tCOMMENT);
06718 fallthru = TRUE;
06719 #endif
06720
06721 case '\n':
06722 switch (lex_state) {
06723 case EXPR_BEG:
06724 case EXPR_FNAME:
06725 case EXPR_DOT:
06726 case EXPR_CLASS:
06727 case EXPR_VALUE:
06728 #ifdef RIPPER
06729 if (!fallthru) {
06730 ripper_dispatch_scan_event(parser, tIGNORED_NL);
06731 }
06732 fallthru = FALSE;
06733 #endif
06734 goto retry;
06735 default:
06736 break;
06737 }
06738 while ((c = nextc())) {
06739 switch (c) {
06740 case ' ': case '\t': case '\f': case '\r':
06741 case '\13':
06742 space_seen = 1;
06743 break;
06744 case '.': {
06745 if ((c = nextc()) != '.') {
06746 pushback(c);
06747 pushback('.');
06748 goto retry;
06749 }
06750 }
06751 default:
06752 --ruby_sourceline;
06753 lex_nextline = lex_lastline;
06754 case -1:
06755 lex_goto_eol(parser);
06756 #ifdef RIPPER
06757 if (c != -1) {
06758 parser->tokp = lex_p;
06759 }
06760 #endif
06761 goto normal_newline;
06762 }
06763 }
06764 normal_newline:
06765 command_start = TRUE;
06766 lex_state = EXPR_BEG;
06767 return '\n';
06768
06769 case '*':
06770 if ((c = nextc()) == '*') {
06771 if ((c = nextc()) == '=') {
06772 set_yylval_id(tPOW);
06773 lex_state = EXPR_BEG;
06774 return tOP_ASGN;
06775 }
06776 pushback(c);
06777 c = tPOW;
06778 }
06779 else {
06780 if (c == '=') {
06781 set_yylval_id('*');
06782 lex_state = EXPR_BEG;
06783 return tOP_ASGN;
06784 }
06785 pushback(c);
06786 if (IS_SPCARG(c)) {
06787 rb_warning0("`*' interpreted as argument prefix");
06788 c = tSTAR;
06789 }
06790 else if (IS_BEG()) {
06791 c = tSTAR;
06792 }
06793 else {
06794 warn_balanced("*", "argument prefix");
06795 c = '*';
06796 }
06797 }
06798 switch (lex_state) {
06799 case EXPR_FNAME: case EXPR_DOT:
06800 lex_state = EXPR_ARG; break;
06801 default:
06802 lex_state = EXPR_BEG; break;
06803 }
06804 return c;
06805
06806 case '!':
06807 c = nextc();
06808 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
06809 lex_state = EXPR_ARG;
06810 if (c == '@') {
06811 return '!';
06812 }
06813 }
06814 else {
06815 lex_state = EXPR_BEG;
06816 }
06817 if (c == '=') {
06818 return tNEQ;
06819 }
06820 if (c == '~') {
06821 return tNMATCH;
06822 }
06823 pushback(c);
06824 return '!';
06825
06826 case '=':
06827 if (was_bol()) {
06828
06829 if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
06830 #ifdef RIPPER
06831 int first_p = TRUE;
06832
06833 lex_goto_eol(parser);
06834 ripper_dispatch_scan_event(parser, tEMBDOC_BEG);
06835 #endif
06836 for (;;) {
06837 lex_goto_eol(parser);
06838 #ifdef RIPPER
06839 if (!first_p) {
06840 ripper_dispatch_scan_event(parser, tEMBDOC);
06841 }
06842 first_p = FALSE;
06843 #endif
06844 c = nextc();
06845 if (c == -1) {
06846 compile_error(PARSER_ARG "embedded document meets end of file");
06847 return 0;
06848 }
06849 if (c != '=') continue;
06850 if (strncmp(lex_p, "end", 3) == 0 &&
06851 (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
06852 break;
06853 }
06854 }
06855 lex_goto_eol(parser);
06856 #ifdef RIPPER
06857 ripper_dispatch_scan_event(parser, tEMBDOC_END);
06858 #endif
06859 goto retry;
06860 }
06861 }
06862
06863 switch (lex_state) {
06864 case EXPR_FNAME: case EXPR_DOT:
06865 lex_state = EXPR_ARG; break;
06866 default:
06867 lex_state = EXPR_BEG; break;
06868 }
06869 if ((c = nextc()) == '=') {
06870 if ((c = nextc()) == '=') {
06871 return tEQQ;
06872 }
06873 pushback(c);
06874 return tEQ;
06875 }
06876 if (c == '~') {
06877 return tMATCH;
06878 }
06879 else if (c == '>') {
06880 return tASSOC;
06881 }
06882 pushback(c);
06883 return '=';
06884
06885 case '<':
06886 last_state = lex_state;
06887 c = nextc();
06888 if (c == '<' &&
06889 lex_state != EXPR_DOT &&
06890 lex_state != EXPR_CLASS &&
06891 !IS_END() &&
06892 (!IS_ARG() || space_seen)) {
06893 int token = heredoc_identifier();
06894 if (token) return token;
06895 }
06896 switch (lex_state) {
06897 case EXPR_FNAME: case EXPR_DOT:
06898 lex_state = EXPR_ARG; break;
06899 default:
06900 lex_state = EXPR_BEG; break;
06901 }
06902 if (c == '=') {
06903 if ((c = nextc()) == '>') {
06904 return tCMP;
06905 }
06906 pushback(c);
06907 return tLEQ;
06908 }
06909 if (c == '<') {
06910 if ((c = nextc()) == '=') {
06911 set_yylval_id(tLSHFT);
06912 lex_state = EXPR_BEG;
06913 return tOP_ASGN;
06914 }
06915 pushback(c);
06916 warn_balanced("<<", "here document");
06917 return tLSHFT;
06918 }
06919 pushback(c);
06920 return '<';
06921
06922 case '>':
06923 switch (lex_state) {
06924 case EXPR_FNAME: case EXPR_DOT:
06925 lex_state = EXPR_ARG; break;
06926 default:
06927 lex_state = EXPR_BEG; break;
06928 }
06929 if ((c = nextc()) == '=') {
06930 return tGEQ;
06931 }
06932 if (c == '>') {
06933 if ((c = nextc()) == '=') {
06934 set_yylval_id(tRSHFT);
06935 lex_state = EXPR_BEG;
06936 return tOP_ASGN;
06937 }
06938 pushback(c);
06939 return tRSHFT;
06940 }
06941 pushback(c);
06942 return '>';
06943
06944 case '"':
06945 lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
06946 return tSTRING_BEG;
06947
06948 case '`':
06949 if (lex_state == EXPR_FNAME) {
06950 lex_state = EXPR_ENDFN;
06951 return c;
06952 }
06953 if (lex_state == EXPR_DOT) {
06954 if (cmd_state)
06955 lex_state = EXPR_CMDARG;
06956 else
06957 lex_state = EXPR_ARG;
06958 return c;
06959 }
06960 lex_strterm = NEW_STRTERM(str_xquote, '`', 0);
06961 return tXSTRING_BEG;
06962
06963 case '\'':
06964 lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
06965 return tSTRING_BEG;
06966
06967 case '?':
06968 if (IS_END()) {
06969 lex_state = EXPR_VALUE;
06970 return '?';
06971 }
06972 c = nextc();
06973 if (c == -1) {
06974 compile_error(PARSER_ARG "incomplete character syntax");
06975 return 0;
06976 }
06977 if (rb_enc_isspace(c, parser->enc)) {
06978 if (!IS_ARG()) {
06979 int c2 = 0;
06980 switch (c) {
06981 case ' ':
06982 c2 = 's';
06983 break;
06984 case '\n':
06985 c2 = 'n';
06986 break;
06987 case '\t':
06988 c2 = 't';
06989 break;
06990 case '\v':
06991 c2 = 'v';
06992 break;
06993 case '\r':
06994 c2 = 'r';
06995 break;
06996 case '\f':
06997 c2 = 'f';
06998 break;
06999 }
07000 if (c2) {
07001 rb_warnI("invalid character syntax; use ?\\%c", c2);
07002 }
07003 }
07004 ternary:
07005 pushback(c);
07006 lex_state = EXPR_VALUE;
07007 return '?';
07008 }
07009 newtok();
07010 enc = parser->enc;
07011 if (!parser_isascii()) {
07012 if (tokadd_mbchar(c) == -1) return 0;
07013 }
07014 else if ((rb_enc_isalnum(c, parser->enc) || c == '_') &&
07015 lex_p < lex_pend && is_identchar(lex_p, lex_pend, parser->enc)) {
07016 goto ternary;
07017 }
07018 else if (c == '\\') {
07019 if (peek('u')) {
07020 nextc();
07021 c = parser_tokadd_utf8(parser, &enc, 0, 0, 0);
07022 if (0x80 <= c) {
07023 tokaddmbc(c, enc);
07024 }
07025 else {
07026 tokadd(c);
07027 }
07028 }
07029 else if (!lex_eol_p() && !(c = *lex_p, ISASCII(c))) {
07030 nextc();
07031 if (tokadd_mbchar(c) == -1) return 0;
07032 }
07033 else {
07034 c = read_escape(0, &enc);
07035 tokadd(c);
07036 }
07037 }
07038 else {
07039 tokadd(c);
07040 }
07041 tokfix();
07042 set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0));
07043 lex_state = EXPR_END;
07044 return tCHAR;
07045
07046 case '&':
07047 if ((c = nextc()) == '&') {
07048 lex_state = EXPR_BEG;
07049 if ((c = nextc()) == '=') {
07050 set_yylval_id(tANDOP);
07051 lex_state = EXPR_BEG;
07052 return tOP_ASGN;
07053 }
07054 pushback(c);
07055 return tANDOP;
07056 }
07057 else if (c == '=') {
07058 set_yylval_id('&');
07059 lex_state = EXPR_BEG;
07060 return tOP_ASGN;
07061 }
07062 pushback(c);
07063 if (IS_SPCARG(c)) {
07064 rb_warning0("`&' interpreted as argument prefix");
07065 c = tAMPER;
07066 }
07067 else if (IS_BEG()) {
07068 c = tAMPER;
07069 }
07070 else {
07071 warn_balanced("&", "argument prefix");
07072 c = '&';
07073 }
07074 switch (lex_state) {
07075 case EXPR_FNAME: case EXPR_DOT:
07076 lex_state = EXPR_ARG; break;
07077 default:
07078 lex_state = EXPR_BEG;
07079 }
07080 return c;
07081
07082 case '|':
07083 if ((c = nextc()) == '|') {
07084 lex_state = EXPR_BEG;
07085 if ((c = nextc()) == '=') {
07086 set_yylval_id(tOROP);
07087 lex_state = EXPR_BEG;
07088 return tOP_ASGN;
07089 }
07090 pushback(c);
07091 return tOROP;
07092 }
07093 if (c == '=') {
07094 set_yylval_id('|');
07095 lex_state = EXPR_BEG;
07096 return tOP_ASGN;
07097 }
07098 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07099 lex_state = EXPR_ARG;
07100 }
07101 else {
07102 lex_state = EXPR_BEG;
07103 }
07104 pushback(c);
07105 return '|';
07106
07107 case '+':
07108 c = nextc();
07109 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07110 lex_state = EXPR_ARG;
07111 if (c == '@') {
07112 return tUPLUS;
07113 }
07114 pushback(c);
07115 return '+';
07116 }
07117 if (c == '=') {
07118 set_yylval_id('+');
07119 lex_state = EXPR_BEG;
07120 return tOP_ASGN;
07121 }
07122 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) {
07123 lex_state = EXPR_BEG;
07124 pushback(c);
07125 if (c != -1 && ISDIGIT(c)) {
07126 c = '+';
07127 goto start_num;
07128 }
07129 return tUPLUS;
07130 }
07131 lex_state = EXPR_BEG;
07132 pushback(c);
07133 warn_balanced("+", "unary operator");
07134 return '+';
07135
07136 case '-':
07137 c = nextc();
07138 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07139 lex_state = EXPR_ARG;
07140 if (c == '@') {
07141 return tUMINUS;
07142 }
07143 pushback(c);
07144 return '-';
07145 }
07146 if (c == '=') {
07147 set_yylval_id('-');
07148 lex_state = EXPR_BEG;
07149 return tOP_ASGN;
07150 }
07151 if (c == '>') {
07152 lex_state = EXPR_ARG;
07153 return tLAMBDA;
07154 }
07155 if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) {
07156 lex_state = EXPR_BEG;
07157 pushback(c);
07158 if (c != -1 && ISDIGIT(c)) {
07159 return tUMINUS_NUM;
07160 }
07161 return tUMINUS;
07162 }
07163 lex_state = EXPR_BEG;
07164 pushback(c);
07165 warn_balanced("-", "unary operator");
07166 return '-';
07167
07168 case '.':
07169 lex_state = EXPR_BEG;
07170 if ((c = nextc()) == '.') {
07171 if ((c = nextc()) == '.') {
07172 return tDOT3;
07173 }
07174 pushback(c);
07175 return tDOT2;
07176 }
07177 pushback(c);
07178 if (c != -1 && ISDIGIT(c)) {
07179 yyerror("no .<digit> floating literal anymore; put 0 before dot");
07180 }
07181 lex_state = EXPR_DOT;
07182 return '.';
07183
07184 start_num:
07185 case '0': case '1': case '2': case '3': case '4':
07186 case '5': case '6': case '7': case '8': case '9':
07187 {
07188 int is_float, seen_point, seen_e, nondigit;
07189
07190 is_float = seen_point = seen_e = nondigit = 0;
07191 lex_state = EXPR_END;
07192 newtok();
07193 if (c == '-' || c == '+') {
07194 tokadd(c);
07195 c = nextc();
07196 }
07197 if (c == '0') {
07198 #define no_digits() do {yyerror("numeric literal without digits"); return 0;} while (0)
07199 int start = toklen();
07200 c = nextc();
07201 if (c == 'x' || c == 'X') {
07202
07203 c = nextc();
07204 if (c != -1 && ISXDIGIT(c)) {
07205 do {
07206 if (c == '_') {
07207 if (nondigit) break;
07208 nondigit = c;
07209 continue;
07210 }
07211 if (!ISXDIGIT(c)) break;
07212 nondigit = 0;
07213 tokadd(c);
07214 } while ((c = nextc()) != -1);
07215 }
07216 pushback(c);
07217 tokfix();
07218 if (toklen() == start) {
07219 no_digits();
07220 }
07221 else if (nondigit) goto trailing_uc;
07222 set_yylval_literal(rb_cstr_to_inum(tok(), 16, FALSE));
07223 return tINTEGER;
07224 }
07225 if (c == 'b' || c == 'B') {
07226
07227 c = nextc();
07228 if (c == '0' || c == '1') {
07229 do {
07230 if (c == '_') {
07231 if (nondigit) break;
07232 nondigit = c;
07233 continue;
07234 }
07235 if (c != '0' && c != '1') break;
07236 nondigit = 0;
07237 tokadd(c);
07238 } while ((c = nextc()) != -1);
07239 }
07240 pushback(c);
07241 tokfix();
07242 if (toklen() == start) {
07243 no_digits();
07244 }
07245 else if (nondigit) goto trailing_uc;
07246 set_yylval_literal(rb_cstr_to_inum(tok(), 2, FALSE));
07247 return tINTEGER;
07248 }
07249 if (c == 'd' || c == 'D') {
07250
07251 c = nextc();
07252 if (c != -1 && ISDIGIT(c)) {
07253 do {
07254 if (c == '_') {
07255 if (nondigit) break;
07256 nondigit = c;
07257 continue;
07258 }
07259 if (!ISDIGIT(c)) break;
07260 nondigit = 0;
07261 tokadd(c);
07262 } while ((c = nextc()) != -1);
07263 }
07264 pushback(c);
07265 tokfix();
07266 if (toklen() == start) {
07267 no_digits();
07268 }
07269 else if (nondigit) goto trailing_uc;
07270 set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE));
07271 return tINTEGER;
07272 }
07273 if (c == '_') {
07274
07275 goto octal_number;
07276 }
07277 if (c == 'o' || c == 'O') {
07278
07279 c = nextc();
07280 if (c == -1 || c == '_' || !ISDIGIT(c)) {
07281 no_digits();
07282 }
07283 }
07284 if (c >= '0' && c <= '7') {
07285
07286 octal_number:
07287 do {
07288 if (c == '_') {
07289 if (nondigit) break;
07290 nondigit = c;
07291 continue;
07292 }
07293 if (c < '0' || c > '9') break;
07294 if (c > '7') goto invalid_octal;
07295 nondigit = 0;
07296 tokadd(c);
07297 } while ((c = nextc()) != -1);
07298 if (toklen() > start) {
07299 pushback(c);
07300 tokfix();
07301 if (nondigit) goto trailing_uc;
07302 set_yylval_literal(rb_cstr_to_inum(tok(), 8, FALSE));
07303 return tINTEGER;
07304 }
07305 if (nondigit) {
07306 pushback(c);
07307 goto trailing_uc;
07308 }
07309 }
07310 if (c > '7' && c <= '9') {
07311 invalid_octal:
07312 yyerror("Invalid octal digit");
07313 }
07314 else if (c == '.' || c == 'e' || c == 'E') {
07315 tokadd('0');
07316 }
07317 else {
07318 pushback(c);
07319 set_yylval_literal(INT2FIX(0));
07320 return tINTEGER;
07321 }
07322 }
07323
07324 for (;;) {
07325 switch (c) {
07326 case '0': case '1': case '2': case '3': case '4':
07327 case '5': case '6': case '7': case '8': case '9':
07328 nondigit = 0;
07329 tokadd(c);
07330 break;
07331
07332 case '.':
07333 if (nondigit) goto trailing_uc;
07334 if (seen_point || seen_e) {
07335 goto decode_num;
07336 }
07337 else {
07338 int c0 = nextc();
07339 if (c0 == -1 || !ISDIGIT(c0)) {
07340 pushback(c0);
07341 goto decode_num;
07342 }
07343 c = c0;
07344 }
07345 tokadd('.');
07346 tokadd(c);
07347 is_float++;
07348 seen_point++;
07349 nondigit = 0;
07350 break;
07351
07352 case 'e':
07353 case 'E':
07354 if (nondigit) {
07355 pushback(c);
07356 c = nondigit;
07357 goto decode_num;
07358 }
07359 if (seen_e) {
07360 goto decode_num;
07361 }
07362 tokadd(c);
07363 seen_e++;
07364 is_float++;
07365 nondigit = c;
07366 c = nextc();
07367 if (c != '-' && c != '+') continue;
07368 tokadd(c);
07369 nondigit = c;
07370 break;
07371
07372 case '_':
07373 if (nondigit) goto decode_num;
07374 nondigit = c;
07375 break;
07376
07377 default:
07378 goto decode_num;
07379 }
07380 c = nextc();
07381 }
07382
07383 decode_num:
07384 pushback(c);
07385 if (nondigit) {
07386 char tmp[30];
07387 trailing_uc:
07388 snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit);
07389 yyerror(tmp);
07390 }
07391 tokfix();
07392 if (is_float) {
07393 double d = strtod(tok(), 0);
07394 if (errno == ERANGE) {
07395 rb_warningS("Float %s out of range", tok());
07396 errno = 0;
07397 }
07398 set_yylval_literal(DBL2NUM(d));
07399 return tFLOAT;
07400 }
07401 set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE));
07402 return tINTEGER;
07403 }
07404
07405 case ')':
07406 case ']':
07407 paren_nest--;
07408 case '}':
07409 COND_LEXPOP();
07410 CMDARG_LEXPOP();
07411 if (c == ')')
07412 lex_state = EXPR_ENDFN;
07413 else
07414 lex_state = EXPR_ENDARG;
07415 return c;
07416
07417 case ':':
07418 c = nextc();
07419 if (c == ':') {
07420 if (IS_BEG() || lex_state == EXPR_CLASS || IS_SPCARG(-1)) {
07421 lex_state = EXPR_BEG;
07422 return tCOLON3;
07423 }
07424 lex_state = EXPR_DOT;
07425 return tCOLON2;
07426 }
07427 if (IS_END() || ISSPACE(c)) {
07428 pushback(c);
07429 warn_balanced(":", "symbol literal");
07430 lex_state = EXPR_BEG;
07431 return ':';
07432 }
07433 switch (c) {
07434 case '\'':
07435 lex_strterm = NEW_STRTERM(str_ssym, c, 0);
07436 break;
07437 case '"':
07438 lex_strterm = NEW_STRTERM(str_dsym, c, 0);
07439 break;
07440 default:
07441 pushback(c);
07442 break;
07443 }
07444 lex_state = EXPR_FNAME;
07445 return tSYMBEG;
07446
07447 case '/':
07448 if (IS_BEG()) {
07449 lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
07450 return tREGEXP_BEG;
07451 }
07452 if ((c = nextc()) == '=') {
07453 set_yylval_id('/');
07454 lex_state = EXPR_BEG;
07455 return tOP_ASGN;
07456 }
07457 pushback(c);
07458 if (IS_SPCARG(c)) {
07459 (void)arg_ambiguous();
07460 lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
07461 return tREGEXP_BEG;
07462 }
07463 switch (lex_state) {
07464 case EXPR_FNAME: case EXPR_DOT:
07465 lex_state = EXPR_ARG; break;
07466 default:
07467 lex_state = EXPR_BEG; break;
07468 }
07469 warn_balanced("/", "regexp literal");
07470 return '/';
07471
07472 case '^':
07473 if ((c = nextc()) == '=') {
07474 set_yylval_id('^');
07475 lex_state = EXPR_BEG;
07476 return tOP_ASGN;
07477 }
07478 switch (lex_state) {
07479 case EXPR_FNAME: case EXPR_DOT:
07480 lex_state = EXPR_ARG; break;
07481 default:
07482 lex_state = EXPR_BEG; break;
07483 }
07484 pushback(c);
07485 return '^';
07486
07487 case ';':
07488 lex_state = EXPR_BEG;
07489 command_start = TRUE;
07490 return ';';
07491
07492 case ',':
07493 lex_state = EXPR_BEG;
07494 return ',';
07495
07496 case '~':
07497 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07498 if ((c = nextc()) != '@') {
07499 pushback(c);
07500 }
07501 lex_state = EXPR_ARG;
07502 }
07503 else {
07504 lex_state = EXPR_BEG;
07505 }
07506 return '~';
07507
07508 case '(':
07509 if (IS_BEG()) {
07510 c = tLPAREN;
07511 }
07512 else if (IS_SPCARG(-1)) {
07513 c = tLPAREN_ARG;
07514 }
07515 paren_nest++;
07516 COND_PUSH(0);
07517 CMDARG_PUSH(0);
07518 lex_state = EXPR_BEG;
07519 return c;
07520
07521 case '[':
07522 paren_nest++;
07523 if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
07524 lex_state = EXPR_ARG;
07525 if ((c = nextc()) == ']') {
07526 if ((c = nextc()) == '=') {
07527 return tASET;
07528 }
07529 pushback(c);
07530 return tAREF;
07531 }
07532 pushback(c);
07533 return '[';
07534 }
07535 else if (IS_BEG()) {
07536 c = tLBRACK;
07537 }
07538 else if (IS_ARG() && space_seen) {
07539 c = tLBRACK;
07540 }
07541 lex_state = EXPR_BEG;
07542 COND_PUSH(0);
07543 CMDARG_PUSH(0);
07544 return c;
07545
07546 case '{':
07547 if (lpar_beg && lpar_beg == paren_nest) {
07548 lex_state = EXPR_BEG;
07549 lpar_beg = 0;
07550 --paren_nest;
07551 COND_PUSH(0);
07552 CMDARG_PUSH(0);
07553 return tLAMBEG;
07554 }
07555 if (IS_ARG() || lex_state == EXPR_END || lex_state == EXPR_ENDFN)
07556 c = '{';
07557 else if (lex_state == EXPR_ENDARG)
07558 c = tLBRACE_ARG;
07559 else
07560 c = tLBRACE;
07561 COND_PUSH(0);
07562 CMDARG_PUSH(0);
07563 lex_state = EXPR_BEG;
07564 if (c != tLBRACE) command_start = TRUE;
07565 return c;
07566
07567 case '\\':
07568 c = nextc();
07569 if (c == '\n') {
07570 space_seen = 1;
07571 #ifdef RIPPER
07572 ripper_dispatch_scan_event(parser, tSP);
07573 #endif
07574 goto retry;
07575 }
07576 pushback(c);
07577 return '\\';
07578
07579 case '%':
07580 if (IS_BEG()) {
07581 int term;
07582 int paren;
07583
07584 c = nextc();
07585 quotation:
07586 if (c == -1 || !ISALNUM(c)) {
07587 term = c;
07588 c = 'Q';
07589 }
07590 else {
07591 term = nextc();
07592 if (rb_enc_isalnum(term, parser->enc) || !parser_isascii()) {
07593 yyerror("unknown type of %string");
07594 return 0;
07595 }
07596 }
07597 if (c == -1 || term == -1) {
07598 compile_error(PARSER_ARG "unterminated quoted string meets end of file");
07599 return 0;
07600 }
07601 paren = term;
07602 if (term == '(') term = ')';
07603 else if (term == '[') term = ']';
07604 else if (term == '{') term = '}';
07605 else if (term == '<') term = '>';
07606 else paren = 0;
07607
07608 switch (c) {
07609 case 'Q':
07610 lex_strterm = NEW_STRTERM(str_dquote, term, paren);
07611 return tSTRING_BEG;
07612
07613 case 'q':
07614 lex_strterm = NEW_STRTERM(str_squote, term, paren);
07615 return tSTRING_BEG;
07616
07617 case 'W':
07618 lex_strterm = NEW_STRTERM(str_dword, term, paren);
07619 do {c = nextc();} while (ISSPACE(c));
07620 pushback(c);
07621 return tWORDS_BEG;
07622
07623 case 'w':
07624 lex_strterm = NEW_STRTERM(str_sword, term, paren);
07625 do {c = nextc();} while (ISSPACE(c));
07626 pushback(c);
07627 return tQWORDS_BEG;
07628
07629 case 'x':
07630 lex_strterm = NEW_STRTERM(str_xquote, term, paren);
07631 return tXSTRING_BEG;
07632
07633 case 'r':
07634 lex_strterm = NEW_STRTERM(str_regexp, term, paren);
07635 return tREGEXP_BEG;
07636
07637 case 's':
07638 lex_strterm = NEW_STRTERM(str_ssym, term, paren);
07639 lex_state = EXPR_FNAME;
07640 return tSYMBEG;
07641
07642 default:
07643 yyerror("unknown type of %string");
07644 return 0;
07645 }
07646 }
07647 if ((c = nextc()) == '=') {
07648 set_yylval_id('%');
07649 lex_state = EXPR_BEG;
07650 return tOP_ASGN;
07651 }
07652 if (IS_SPCARG(c)) {
07653 goto quotation;
07654 }
07655 switch (lex_state) {
07656 case EXPR_FNAME: case EXPR_DOT:
07657 lex_state = EXPR_ARG; break;
07658 default:
07659 lex_state = EXPR_BEG; break;
07660 }
07661 pushback(c);
07662 warn_balanced("%%", "string literal");
07663 return '%';
07664
07665 case '$':
07666 lex_state = EXPR_END;
07667 newtok();
07668 c = nextc();
07669 switch (c) {
07670 case '_':
07671 c = nextc();
07672 if (parser_is_identchar()) {
07673 tokadd('$');
07674 tokadd('_');
07675 break;
07676 }
07677 pushback(c);
07678 c = '_';
07679
07680 case '~':
07681 case '*':
07682 case '$':
07683 case '?':
07684 case '!':
07685 case '@':
07686 case '/':
07687 case '\\':
07688 case ';':
07689 case ',':
07690 case '.':
07691 case '=':
07692 case ':':
07693 case '<':
07694 case '>':
07695 case '\"':
07696 tokadd('$');
07697 tokadd(c);
07698 tokfix();
07699 set_yylval_name(rb_intern(tok()));
07700 return tGVAR;
07701
07702 case '-':
07703 tokadd('$');
07704 tokadd(c);
07705 c = nextc();
07706 if (parser_is_identchar()) {
07707 if (tokadd_mbchar(c) == -1) return 0;
07708 }
07709 else {
07710 pushback(c);
07711 }
07712 gvar:
07713 tokfix();
07714 set_yylval_name(rb_intern(tok()));
07715 return tGVAR;
07716
07717 case '&':
07718 case '`':
07719 case '\'':
07720 case '+':
07721 if (last_state == EXPR_FNAME) {
07722 tokadd('$');
07723 tokadd(c);
07724 goto gvar;
07725 }
07726 set_yylval_node(NEW_BACK_REF(c));
07727 return tBACK_REF;
07728
07729 case '1': case '2': case '3':
07730 case '4': case '5': case '6':
07731 case '7': case '8': case '9':
07732 tokadd('$');
07733 do {
07734 tokadd(c);
07735 c = nextc();
07736 } while (c != -1 && ISDIGIT(c));
07737 pushback(c);
07738 if (last_state == EXPR_FNAME) goto gvar;
07739 tokfix();
07740 set_yylval_node(NEW_NTH_REF(atoi(tok()+1)));
07741 return tNTH_REF;
07742
07743 default:
07744 if (!parser_is_identchar()) {
07745 pushback(c);
07746 return '$';
07747 }
07748 case '0':
07749 tokadd('$');
07750 }
07751 break;
07752
07753 case '@':
07754 c = nextc();
07755 newtok();
07756 tokadd('@');
07757 if (c == '@') {
07758 tokadd('@');
07759 c = nextc();
07760 }
07761 if (c != -1 && ISDIGIT(c)) {
07762 if (tokidx == 1) {
07763 compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c);
07764 }
07765 else {
07766 compile_error(PARSER_ARG "`@@%c' is not allowed as a class variable name", c);
07767 }
07768 return 0;
07769 }
07770 if (!parser_is_identchar()) {
07771 pushback(c);
07772 return '@';
07773 }
07774 break;
07775
07776 case '_':
07777 if (was_bol() && whole_match_p("__END__", 7, 0)) {
07778 ruby__end__seen = 1;
07779 parser->eofp = Qtrue;
07780 #ifndef RIPPER
07781 return -1;
07782 #else
07783 lex_goto_eol(parser);
07784 ripper_dispatch_scan_event(parser, k__END__);
07785 return 0;
07786 #endif
07787 }
07788 newtok();
07789 break;
07790
07791 default:
07792 if (!parser_is_identchar()) {
07793 rb_compile_error(PARSER_ARG "Invalid char `\\x%02X' in expression", c);
07794 goto retry;
07795 }
07796
07797 newtok();
07798 break;
07799 }
07800
07801 mb = ENC_CODERANGE_7BIT;
07802 do {
07803 if (!ISASCII(c)) mb = ENC_CODERANGE_UNKNOWN;
07804 if (tokadd_mbchar(c) == -1) return 0;
07805 c = nextc();
07806 } while (parser_is_identchar());
07807 switch (tok()[0]) {
07808 case '@': case '$':
07809 pushback(c);
07810 break;
07811 default:
07812 if ((c == '!' || c == '?') && !peek('=')) {
07813 tokadd(c);
07814 }
07815 else {
07816 pushback(c);
07817 }
07818 }
07819 tokfix();
07820
07821 {
07822 int result = 0;
07823
07824 last_state = lex_state;
07825 switch (tok()[0]) {
07826 case '$':
07827 lex_state = EXPR_END;
07828 result = tGVAR;
07829 break;
07830 case '@':
07831 lex_state = EXPR_END;
07832 if (tok()[1] == '@')
07833 result = tCVAR;
07834 else
07835 result = tIVAR;
07836 break;
07837
07838 default:
07839 if (toklast() == '!' || toklast() == '?') {
07840 result = tFID;
07841 }
07842 else {
07843 if (lex_state == EXPR_FNAME) {
07844 if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
07845 (!peek('=') || (peek_n('>', 1)))) {
07846 result = tIDENTIFIER;
07847 tokadd(c);
07848 tokfix();
07849 }
07850 else {
07851 pushback(c);
07852 }
07853 }
07854 if (result == 0 && ISUPPER(tok()[0])) {
07855 result = tCONSTANT;
07856 }
07857 else {
07858 result = tIDENTIFIER;
07859 }
07860 }
07861
07862 if (IS_LABEL_POSSIBLE()) {
07863 if (IS_LABEL_SUFFIX(0)) {
07864 lex_state = EXPR_BEG;
07865 nextc();
07866 set_yylval_name(TOK_INTERN(!ENC_SINGLE(mb)));
07867 return tLABEL;
07868 }
07869 }
07870 if (mb == ENC_CODERANGE_7BIT && lex_state != EXPR_DOT) {
07871 const struct kwtable *kw;
07872
07873
07874 kw = rb_reserved_word(tok(), toklen());
07875 if (kw) {
07876 enum lex_state_e state = lex_state;
07877 lex_state = kw->state;
07878 if (state == EXPR_FNAME) {
07879 set_yylval_name(rb_intern(kw->name));
07880 return kw->id[0];
07881 }
07882 if (kw->id[0] == keyword_do) {
07883 command_start = TRUE;
07884 if (lpar_beg && lpar_beg == paren_nest) {
07885 lpar_beg = 0;
07886 --paren_nest;
07887 return keyword_do_LAMBDA;
07888 }
07889 if (COND_P()) return keyword_do_cond;
07890 if (CMDARG_P() && state != EXPR_CMDARG)
07891 return keyword_do_block;
07892 if (state == EXPR_ENDARG || state == EXPR_BEG)
07893 return keyword_do_block;
07894 return keyword_do;
07895 }
07896 if (state == EXPR_BEG || state == EXPR_VALUE)
07897 return kw->id[0];
07898 else {
07899 if (kw->id[0] != kw->id[1])
07900 lex_state = EXPR_BEG;
07901 return kw->id[1];
07902 }
07903 }
07904 }
07905
07906 if (IS_BEG() ||
07907 lex_state == EXPR_DOT ||
07908 IS_ARG()) {
07909 if (cmd_state) {
07910 lex_state = EXPR_CMDARG;
07911 }
07912 else {
07913 lex_state = EXPR_ARG;
07914 }
07915 }
07916 else if (lex_state == EXPR_FNAME) {
07917 lex_state = EXPR_ENDFN;
07918 }
07919 else {
07920 lex_state = EXPR_END;
07921 }
07922 }
07923 {
07924 ID ident = TOK_INTERN(!ENC_SINGLE(mb));
07925
07926 set_yylval_name(ident);
07927 if (last_state != EXPR_DOT && last_state != EXPR_FNAME &&
07928 is_local_id(ident) && lvar_defined(ident)) {
07929 lex_state = EXPR_END;
07930 }
07931 }
07932 return result;
07933 }
07934 }
07935
07936 #if YYPURE
07937 static int
07938 yylex(void *lval, void *p)
07939 #else
07940 yylex(void *p)
07941 #endif
07942 {
07943 struct parser_params *parser = (struct parser_params*)p;
07944 int t;
07945
07946 #if YYPURE
07947 parser->parser_yylval = lval;
07948 parser->parser_yylval->val = Qundef;
07949 #endif
07950 t = parser_yylex(parser);
07951 #ifdef RIPPER
07952 if (!NIL_P(parser->delayed)) {
07953 ripper_dispatch_delayed_token(parser, t);
07954 return t;
07955 }
07956 if (t != 0)
07957 ripper_dispatch_scan_event(parser, t);
07958 #endif
07959
07960 return t;
07961 }
07962
07963 #ifndef RIPPER
07964 static NODE*
07965 node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
07966 {
07967 NODE *n = (rb_node_newnode)(type, a0, a1, a2);
07968 nd_set_line(n, ruby_sourceline);
07969 return n;
07970 }
07971
07972 enum node_type
07973 nodetype(NODE *node)
07974 {
07975 return (enum node_type)nd_type(node);
07976 }
07977
07978 int
07979 nodeline(NODE *node)
07980 {
07981 return nd_line(node);
07982 }
07983
07984 static NODE*
07985 newline_node(NODE *node)
07986 {
07987 if (node) {
07988 node = remove_begin(node);
07989 node->flags |= NODE_FL_NEWLINE;
07990 }
07991 return node;
07992 }
07993
07994 static void
07995 fixpos(NODE *node, NODE *orig)
07996 {
07997 if (!node) return;
07998 if (!orig) return;
07999 if (orig == (NODE*)1) return;
08000 nd_set_line(node, nd_line(orig));
08001 }
08002
08003 static void
08004 parser_warning(struct parser_params *parser, NODE *node, const char *mesg)
08005 {
08006 rb_compile_warning(ruby_sourcefile, nd_line(node), "%s", mesg);
08007 }
08008 #define parser_warning(node, mesg) parser_warning(parser, (node), (mesg))
08009
08010 static void
08011 parser_warn(struct parser_params *parser, NODE *node, const char *mesg)
08012 {
08013 rb_compile_warn(ruby_sourcefile, nd_line(node), "%s", mesg);
08014 }
08015 #define parser_warn(node, mesg) parser_warn(parser, (node), (mesg))
08016
08017 static NODE*
08018 block_append_gen(struct parser_params *parser, NODE *head, NODE *tail)
08019 {
08020 NODE *end, *h = head, *nd;
08021
08022 if (tail == 0) return head;
08023
08024 if (h == 0) return tail;
08025 switch (nd_type(h)) {
08026 case NODE_LIT:
08027 case NODE_STR:
08028 case NODE_SELF:
08029 case NODE_TRUE:
08030 case NODE_FALSE:
08031 case NODE_NIL:
08032 parser_warning(h, "unused literal ignored");
08033 return tail;
08034 default:
08035 h = end = NEW_BLOCK(head);
08036 end->nd_end = end;
08037 fixpos(end, head);
08038 head = end;
08039 break;
08040 case NODE_BLOCK:
08041 end = h->nd_end;
08042 break;
08043 }
08044
08045 nd = end->nd_head;
08046 switch (nd_type(nd)) {
08047 case NODE_RETURN:
08048 case NODE_BREAK:
08049 case NODE_NEXT:
08050 case NODE_REDO:
08051 case NODE_RETRY:
08052 if (RTEST(ruby_verbose)) {
08053 parser_warning(nd, "statement not reached");
08054 }
08055 break;
08056
08057 default:
08058 break;
08059 }
08060
08061 if (nd_type(tail) != NODE_BLOCK) {
08062 tail = NEW_BLOCK(tail);
08063 tail->nd_end = tail;
08064 }
08065 end->nd_next = tail;
08066 h->nd_end = tail->nd_end;
08067 return head;
08068 }
08069
08070
08071 static NODE*
08072 list_append_gen(struct parser_params *parser, NODE *list, NODE *item)
08073 {
08074 NODE *last;
08075
08076 if (list == 0) return NEW_LIST(item);
08077 if (list->nd_next) {
08078 last = list->nd_next->nd_end;
08079 }
08080 else {
08081 last = list;
08082 }
08083
08084 list->nd_alen += 1;
08085 last->nd_next = NEW_LIST(item);
08086 list->nd_next->nd_end = last->nd_next;
08087 return list;
08088 }
08089
08090
08091 static NODE*
08092 list_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
08093 {
08094 NODE *last;
08095
08096 if (head->nd_next) {
08097 last = head->nd_next->nd_end;
08098 }
08099 else {
08100 last = head;
08101 }
08102
08103 head->nd_alen += tail->nd_alen;
08104 last->nd_next = tail;
08105 if (tail->nd_next) {
08106 head->nd_next->nd_end = tail->nd_next->nd_end;
08107 }
08108 else {
08109 head->nd_next->nd_end = tail;
08110 }
08111
08112 return head;
08113 }
08114
08115 static int
08116 literal_concat0(struct parser_params *parser, VALUE head, VALUE tail)
08117 {
08118 if (NIL_P(tail)) return 1;
08119 if (!rb_enc_compatible(head, tail)) {
08120 compile_error(PARSER_ARG "string literal encodings differ (%s / %s)",
08121 rb_enc_name(rb_enc_get(head)),
08122 rb_enc_name(rb_enc_get(tail)));
08123 rb_str_resize(head, 0);
08124 rb_str_resize(tail, 0);
08125 return 0;
08126 }
08127 rb_str_buf_append(head, tail);
08128 return 1;
08129 }
08130
08131
08132 static NODE *
08133 literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
08134 {
08135 enum node_type htype;
08136
08137 if (!head) return tail;
08138 if (!tail) return head;
08139
08140 htype = nd_type(head);
08141 if (htype == NODE_EVSTR) {
08142 NODE *node = NEW_DSTR(Qnil);
08143 head = list_append(node, head);
08144 }
08145 switch (nd_type(tail)) {
08146 case NODE_STR:
08147 if (htype == NODE_STR) {
08148 if (!literal_concat0(parser, head->nd_lit, tail->nd_lit)) {
08149 error:
08150 rb_gc_force_recycle((VALUE)head);
08151 rb_gc_force_recycle((VALUE)tail);
08152 return 0;
08153 }
08154 rb_gc_force_recycle((VALUE)tail);
08155 }
08156 else {
08157 list_append(head, tail);
08158 }
08159 break;
08160
08161 case NODE_DSTR:
08162 if (htype == NODE_STR) {
08163 if (!literal_concat0(parser, head->nd_lit, tail->nd_lit))
08164 goto error;
08165 tail->nd_lit = head->nd_lit;
08166 rb_gc_force_recycle((VALUE)head);
08167 head = tail;
08168 }
08169 else if (NIL_P(tail->nd_lit)) {
08170 head->nd_alen += tail->nd_alen - 1;
08171 head->nd_next->nd_end->nd_next = tail->nd_next;
08172 head->nd_next->nd_end = tail->nd_next->nd_end;
08173 rb_gc_force_recycle((VALUE)tail);
08174 }
08175 else {
08176 nd_set_type(tail, NODE_ARRAY);
08177 tail->nd_head = NEW_STR(tail->nd_lit);
08178 list_concat(head, tail);
08179 }
08180 break;
08181
08182 case NODE_EVSTR:
08183 if (htype == NODE_STR) {
08184 nd_set_type(head, NODE_DSTR);
08185 head->nd_alen = 1;
08186 }
08187 list_append(head, tail);
08188 break;
08189 }
08190 return head;
08191 }
08192
08193 static NODE *
08194 evstr2dstr_gen(struct parser_params *parser, NODE *node)
08195 {
08196 if (nd_type(node) == NODE_EVSTR) {
08197 node = list_append(NEW_DSTR(Qnil), node);
08198 }
08199 return node;
08200 }
08201
08202 static NODE *
08203 new_evstr_gen(struct parser_params *parser, NODE *node)
08204 {
08205 NODE *head = node;
08206
08207 if (node) {
08208 switch (nd_type(node)) {
08209 case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
08210 return node;
08211 }
08212 }
08213 return NEW_EVSTR(head);
08214 }
08215
08216 static NODE *
08217 call_bin_op_gen(struct parser_params *parser, NODE *recv, ID id, NODE *arg1)
08218 {
08219 value_expr(recv);
08220 value_expr(arg1);
08221 return NEW_CALL(recv, id, NEW_LIST(arg1));
08222 }
08223
08224 static NODE *
08225 call_uni_op_gen(struct parser_params *parser, NODE *recv, ID id)
08226 {
08227 value_expr(recv);
08228 return NEW_CALL(recv, id, 0);
08229 }
08230
08231 static NODE*
08232 match_op_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08233 {
08234 value_expr(node1);
08235 value_expr(node2);
08236 if (node1) {
08237 switch (nd_type(node1)) {
08238 case NODE_DREGX:
08239 case NODE_DREGX_ONCE:
08240 return NEW_MATCH2(node1, node2);
08241
08242 case NODE_LIT:
08243 if (TYPE(node1->nd_lit) == T_REGEXP) {
08244 return NEW_MATCH2(node1, node2);
08245 }
08246 }
08247 }
08248
08249 if (node2) {
08250 switch (nd_type(node2)) {
08251 case NODE_DREGX:
08252 case NODE_DREGX_ONCE:
08253 return NEW_MATCH3(node2, node1);
08254
08255 case NODE_LIT:
08256 if (TYPE(node2->nd_lit) == T_REGEXP) {
08257 return NEW_MATCH3(node2, node1);
08258 }
08259 }
08260 }
08261
08262 return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
08263 }
08264
08265 static NODE*
08266 gettable_gen(struct parser_params *parser, ID id)
08267 {
08268 if (id == keyword_self) {
08269 return NEW_SELF();
08270 }
08271 else if (id == keyword_nil) {
08272 return NEW_NIL();
08273 }
08274 else if (id == keyword_true) {
08275 return NEW_TRUE();
08276 }
08277 else if (id == keyword_false) {
08278 return NEW_FALSE();
08279 }
08280 else if (id == keyword__FILE__) {
08281 return NEW_STR(rb_external_str_new_with_enc(ruby_sourcefile, strlen(ruby_sourcefile),
08282 rb_filesystem_encoding()));
08283 }
08284 else if (id == keyword__LINE__) {
08285 return NEW_LIT(INT2FIX(ruby_sourceline));
08286 }
08287 else if (id == keyword__ENCODING__) {
08288 return NEW_LIT(rb_enc_from_encoding(parser->enc));
08289 }
08290 else if (is_local_id(id)) {
08291 if (dyna_in_block() && dvar_defined(id)) return NEW_DVAR(id);
08292 if (local_id(id)) return NEW_LVAR(id);
08293
08294 return NEW_VCALL(id);
08295 }
08296 else if (is_global_id(id)) {
08297 return NEW_GVAR(id);
08298 }
08299 else if (is_instance_id(id)) {
08300 return NEW_IVAR(id);
08301 }
08302 else if (is_const_id(id)) {
08303 return NEW_CONST(id);
08304 }
08305 else if (is_class_id(id)) {
08306 return NEW_CVAR(id);
08307 }
08308 compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id));
08309 return 0;
08310 }
08311 #else
08312 static int
08313 id_is_var_gen(struct parser_params *parser, ID id)
08314 {
08315 if (is_notop_id(id)) {
08316 switch (id & ID_SCOPE_MASK) {
08317 case ID_GLOBAL: case ID_INSTANCE: case ID_CONST: case ID_CLASS:
08318 return 1;
08319 case ID_LOCAL:
08320 if (dyna_in_block() && dvar_defined(id)) return 1;
08321 if (local_id(id)) return 1;
08322
08323 return 0;
08324 }
08325 }
08326 compile_error(PARSER_ARG "identifier %s is not valid to get", rb_id2name(id));
08327 return 0;
08328 }
08329 #endif
08330
08331 #ifdef RIPPER
08332 static VALUE
08333 assignable_gen(struct parser_params *parser, VALUE lhs)
08334 #else
08335 static NODE*
08336 assignable_gen(struct parser_params *parser, ID id, NODE *val)
08337 #endif
08338 {
08339 #ifdef RIPPER
08340 ID id = get_id(lhs);
08341 # define assignable_result(x) get_value(lhs)
08342 # define parser_yyerror(parser, x) dispatch1(assign_error, lhs)
08343 #else
08344 # define assignable_result(x) (x)
08345 #endif
08346 if (!id) return assignable_result(0);
08347 if (id == keyword_self) {
08348 yyerror("Can't change the value of self");
08349 }
08350 else if (id == keyword_nil) {
08351 yyerror("Can't assign to nil");
08352 }
08353 else if (id == keyword_true) {
08354 yyerror("Can't assign to true");
08355 }
08356 else if (id == keyword_false) {
08357 yyerror("Can't assign to false");
08358 }
08359 else if (id == keyword__FILE__) {
08360 yyerror("Can't assign to __FILE__");
08361 }
08362 else if (id == keyword__LINE__) {
08363 yyerror("Can't assign to __LINE__");
08364 }
08365 else if (id == keyword__ENCODING__) {
08366 yyerror("Can't assign to __ENCODING__");
08367 }
08368 else if (is_local_id(id)) {
08369 if (dyna_in_block()) {
08370 if (dvar_curr(id)) {
08371 return assignable_result(NEW_DASGN_CURR(id, val));
08372 }
08373 else if (dvar_defined(id)) {
08374 return assignable_result(NEW_DASGN(id, val));
08375 }
08376 else if (local_id(id)) {
08377 return assignable_result(NEW_LASGN(id, val));
08378 }
08379 else {
08380 dyna_var(id);
08381 return assignable_result(NEW_DASGN_CURR(id, val));
08382 }
08383 }
08384 else {
08385 if (!local_id(id)) {
08386 local_var(id);
08387 }
08388 return assignable_result(NEW_LASGN(id, val));
08389 }
08390 }
08391 else if (is_global_id(id)) {
08392 return assignable_result(NEW_GASGN(id, val));
08393 }
08394 else if (is_instance_id(id)) {
08395 return assignable_result(NEW_IASGN(id, val));
08396 }
08397 else if (is_const_id(id)) {
08398 if (!in_def && !in_single)
08399 return assignable_result(NEW_CDECL(id, val, 0));
08400 yyerror("dynamic constant assignment");
08401 }
08402 else if (is_class_id(id)) {
08403 return assignable_result(NEW_CVASGN(id, val));
08404 }
08405 else {
08406 compile_error(PARSER_ARG "identifier %s is not valid to set", rb_id2name(id));
08407 }
08408 return assignable_result(0);
08409 #undef assignable_result
08410 #undef parser_yyerror
08411 }
08412
08413 #define LVAR_USED ((int)1 << (sizeof(int) * CHAR_BIT - 1))
08414
08415 static ID
08416 shadowing_lvar_gen(struct parser_params *parser, ID name)
08417 {
08418 if (idUScore == name) return name;
08419 if (dyna_in_block()) {
08420 if (dvar_curr(name)) {
08421 yyerror("duplicated argument name");
08422 }
08423 else if (dvar_defined_get(name) || local_id(name)) {
08424 rb_warningS("shadowing outer local variable - %s", rb_id2name(name));
08425 vtable_add(lvtbl->vars, name);
08426 if (lvtbl->used) {
08427 vtable_add(lvtbl->used, (ID)ruby_sourceline | LVAR_USED);
08428 }
08429 }
08430 }
08431 else {
08432 if (local_id(name)) {
08433 yyerror("duplicated argument name");
08434 }
08435 }
08436 return name;
08437 }
08438
08439 static void
08440 new_bv_gen(struct parser_params *parser, ID name)
08441 {
08442 if (!name) return;
08443 if (!is_local_id(name)) {
08444 compile_error(PARSER_ARG "invalid local variable - %s",
08445 rb_id2name(name));
08446 return;
08447 }
08448 shadowing_lvar(name);
08449 dyna_var(name);
08450 }
08451
08452 #ifndef RIPPER
08453 static NODE *
08454 aryset_gen(struct parser_params *parser, NODE *recv, NODE *idx)
08455 {
08456 if (recv && nd_type(recv) == NODE_SELF)
08457 recv = (NODE *)1;
08458 return NEW_ATTRASGN(recv, tASET, idx);
08459 }
08460
08461 static void
08462 block_dup_check_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08463 {
08464 if (node2 && node1 && nd_type(node1) == NODE_BLOCK_PASS) {
08465 compile_error(PARSER_ARG "both block arg and actual block given");
08466 }
08467 }
08468
08469 ID
08470 rb_id_attrset(ID id)
08471 {
08472 id &= ~ID_SCOPE_MASK;
08473 id |= ID_ATTRSET;
08474 return id;
08475 }
08476
08477 static NODE *
08478 attrset_gen(struct parser_params *parser, NODE *recv, ID id)
08479 {
08480 if (recv && nd_type(recv) == NODE_SELF)
08481 recv = (NODE *)1;
08482 return NEW_ATTRASGN(recv, rb_id_attrset(id), 0);
08483 }
08484
08485 static void
08486 rb_backref_error_gen(struct parser_params *parser, NODE *node)
08487 {
08488 switch (nd_type(node)) {
08489 case NODE_NTH_REF:
08490 compile_error(PARSER_ARG "Can't set variable $%ld", node->nd_nth);
08491 break;
08492 case NODE_BACK_REF:
08493 compile_error(PARSER_ARG "Can't set variable $%c", (int)node->nd_nth);
08494 break;
08495 }
08496 }
08497
08498 static NODE *
08499 arg_concat_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08500 {
08501 if (!node2) return node1;
08502 switch (nd_type(node1)) {
08503 case NODE_BLOCK_PASS:
08504 if (node1->nd_head)
08505 node1->nd_head = arg_concat(node1->nd_head, node2);
08506 else
08507 node1->nd_head = NEW_LIST(node2);
08508 return node1;
08509 case NODE_ARGSPUSH:
08510 if (nd_type(node2) != NODE_ARRAY) break;
08511 node1->nd_body = list_concat(NEW_LIST(node1->nd_body), node2);
08512 nd_set_type(node1, NODE_ARGSCAT);
08513 return node1;
08514 case NODE_ARGSCAT:
08515 if (nd_type(node2) != NODE_ARRAY ||
08516 nd_type(node1->nd_body) != NODE_ARRAY) break;
08517 node1->nd_body = list_concat(node1->nd_body, node2);
08518 return node1;
08519 }
08520 return NEW_ARGSCAT(node1, node2);
08521 }
08522
08523 static NODE *
08524 arg_append_gen(struct parser_params *parser, NODE *node1, NODE *node2)
08525 {
08526 if (!node1) return NEW_LIST(node2);
08527 switch (nd_type(node1)) {
08528 case NODE_ARRAY:
08529 return list_append(node1, node2);
08530 case NODE_BLOCK_PASS:
08531 node1->nd_head = arg_append(node1->nd_head, node2);
08532 return node1;
08533 case NODE_ARGSPUSH:
08534 node1->nd_body = list_append(NEW_LIST(node1->nd_body), node2);
08535 nd_set_type(node1, NODE_ARGSCAT);
08536 return node1;
08537 }
08538 return NEW_ARGSPUSH(node1, node2);
08539 }
08540
08541 static NODE *
08542 splat_array(NODE* node)
08543 {
08544 if (nd_type(node) == NODE_SPLAT) node = node->nd_head;
08545 if (nd_type(node) == NODE_ARRAY) return node;
08546 return 0;
08547 }
08548
08549 static NODE *
08550 node_assign_gen(struct parser_params *parser, NODE *lhs, NODE *rhs)
08551 {
08552 if (!lhs) return 0;
08553
08554 switch (nd_type(lhs)) {
08555 case NODE_GASGN:
08556 case NODE_IASGN:
08557 case NODE_IASGN2:
08558 case NODE_LASGN:
08559 case NODE_DASGN:
08560 case NODE_DASGN_CURR:
08561 case NODE_MASGN:
08562 case NODE_CDECL:
08563 case NODE_CVASGN:
08564 lhs->nd_value = rhs;
08565 break;
08566
08567 case NODE_ATTRASGN:
08568 case NODE_CALL:
08569 lhs->nd_args = arg_append(lhs->nd_args, rhs);
08570 break;
08571
08572 default:
08573
08574 break;
08575 }
08576
08577 return lhs;
08578 }
08579
08580 static int
08581 value_expr_gen(struct parser_params *parser, NODE *node)
08582 {
08583 int cond = 0;
08584
08585 if (!node) {
08586 rb_warning0("empty expression");
08587 }
08588 while (node) {
08589 switch (nd_type(node)) {
08590 case NODE_DEFN:
08591 case NODE_DEFS:
08592 parser_warning(node, "void value expression");
08593 return FALSE;
08594
08595 case NODE_RETURN:
08596 case NODE_BREAK:
08597 case NODE_NEXT:
08598 case NODE_REDO:
08599 case NODE_RETRY:
08600 if (!cond) yyerror("void value expression");
08601
08602 return FALSE;
08603
08604 case NODE_BLOCK:
08605 while (node->nd_next) {
08606 node = node->nd_next;
08607 }
08608 node = node->nd_head;
08609 break;
08610
08611 case NODE_BEGIN:
08612 node = node->nd_body;
08613 break;
08614
08615 case NODE_IF:
08616 if (!node->nd_body) {
08617 node = node->nd_else;
08618 break;
08619 }
08620 else if (!node->nd_else) {
08621 node = node->nd_body;
08622 break;
08623 }
08624 if (!value_expr(node->nd_body)) return FALSE;
08625 node = node->nd_else;
08626 break;
08627
08628 case NODE_AND:
08629 case NODE_OR:
08630 cond = 1;
08631 node = node->nd_2nd;
08632 break;
08633
08634 default:
08635 return TRUE;
08636 }
08637 }
08638
08639 return TRUE;
08640 }
08641
08642 static void
08643 void_expr_gen(struct parser_params *parser, NODE *node)
08644 {
08645 const char *useless = 0;
08646
08647 if (!RTEST(ruby_verbose)) return;
08648
08649 if (!node) return;
08650 switch (nd_type(node)) {
08651 case NODE_CALL:
08652 switch (node->nd_mid) {
08653 case '+':
08654 case '-':
08655 case '*':
08656 case '/':
08657 case '%':
08658 case tPOW:
08659 case tUPLUS:
08660 case tUMINUS:
08661 case '|':
08662 case '^':
08663 case '&':
08664 case tCMP:
08665 case '>':
08666 case tGEQ:
08667 case '<':
08668 case tLEQ:
08669 case tEQ:
08670 case tNEQ:
08671 useless = rb_id2name(node->nd_mid);
08672 break;
08673 }
08674 break;
08675
08676 case NODE_LVAR:
08677 case NODE_DVAR:
08678 case NODE_GVAR:
08679 case NODE_IVAR:
08680 case NODE_CVAR:
08681 case NODE_NTH_REF:
08682 case NODE_BACK_REF:
08683 useless = "a variable";
08684 break;
08685 case NODE_CONST:
08686 useless = "a constant";
08687 break;
08688 case NODE_LIT:
08689 case NODE_STR:
08690 case NODE_DSTR:
08691 case NODE_DREGX:
08692 case NODE_DREGX_ONCE:
08693 useless = "a literal";
08694 break;
08695 case NODE_COLON2:
08696 case NODE_COLON3:
08697 useless = "::";
08698 break;
08699 case NODE_DOT2:
08700 useless = "..";
08701 break;
08702 case NODE_DOT3:
08703 useless = "...";
08704 break;
08705 case NODE_SELF:
08706 useless = "self";
08707 break;
08708 case NODE_NIL:
08709 useless = "nil";
08710 break;
08711 case NODE_TRUE:
08712 useless = "true";
08713 break;
08714 case NODE_FALSE:
08715 useless = "false";
08716 break;
08717 case NODE_DEFINED:
08718 useless = "defined?";
08719 break;
08720 }
08721
08722 if (useless) {
08723 int line = ruby_sourceline;
08724
08725 ruby_sourceline = nd_line(node);
08726 rb_warnS("possibly useless use of %s in void context", useless);
08727 ruby_sourceline = line;
08728 }
08729 }
08730
08731 static void
08732 void_stmts_gen(struct parser_params *parser, NODE *node)
08733 {
08734 if (!RTEST(ruby_verbose)) return;
08735 if (!node) return;
08736 if (nd_type(node) != NODE_BLOCK) return;
08737
08738 for (;;) {
08739 if (!node->nd_next) return;
08740 void_expr0(node->nd_head);
08741 node = node->nd_next;
08742 }
08743 }
08744
08745 static NODE *
08746 remove_begin(NODE *node)
08747 {
08748 NODE **n = &node, *n1 = node;
08749 while (n1 && nd_type(n1) == NODE_BEGIN && n1->nd_body) {
08750 *n = n1 = n1->nd_body;
08751 }
08752 return node;
08753 }
08754
08755 static void
08756 reduce_nodes_gen(struct parser_params *parser, NODE **body)
08757 {
08758 NODE *node = *body;
08759
08760 if (!node) {
08761 *body = NEW_NIL();
08762 return;
08763 }
08764 #define subnodes(n1, n2) \
08765 ((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
08766 (!node->n2) ? (body = &node->n1, 1) : \
08767 (reduce_nodes(&node->n1), body = &node->n2, 1))
08768
08769 while (node) {
08770 int newline = (int)(node->flags & NODE_FL_NEWLINE);
08771 switch (nd_type(node)) {
08772 end:
08773 case NODE_NIL:
08774 *body = 0;
08775 return;
08776 case NODE_RETURN:
08777 *body = node = node->nd_stts;
08778 if (newline && node) node->flags |= NODE_FL_NEWLINE;
08779 continue;
08780 case NODE_BEGIN:
08781 *body = node = node->nd_body;
08782 if (newline && node) node->flags |= NODE_FL_NEWLINE;
08783 continue;
08784 case NODE_BLOCK:
08785 body = &node->nd_end->nd_head;
08786 break;
08787 case NODE_IF:
08788 if (subnodes(nd_body, nd_else)) break;
08789 return;
08790 case NODE_CASE:
08791 body = &node->nd_body;
08792 break;
08793 case NODE_WHEN:
08794 if (!subnodes(nd_body, nd_next)) goto end;
08795 break;
08796 case NODE_ENSURE:
08797 if (!subnodes(nd_head, nd_resq)) goto end;
08798 break;
08799 case NODE_RESCUE:
08800 if (node->nd_else) {
08801 body = &node->nd_resq;
08802 break;
08803 }
08804 if (!subnodes(nd_head, nd_resq)) goto end;
08805 break;
08806 default:
08807 return;
08808 }
08809 node = *body;
08810 if (newline && node) node->flags |= NODE_FL_NEWLINE;
08811 }
08812
08813 #undef subnodes
08814 }
08815
08816 static int
08817 assign_in_cond(struct parser_params *parser, NODE *node)
08818 {
08819 switch (nd_type(node)) {
08820 case NODE_MASGN:
08821 yyerror("multiple assignment in conditional");
08822 return 1;
08823
08824 case NODE_LASGN:
08825 case NODE_DASGN:
08826 case NODE_DASGN_CURR:
08827 case NODE_GASGN:
08828 case NODE_IASGN:
08829 break;
08830
08831 default:
08832 return 0;
08833 }
08834
08835 if (!node->nd_value) return 1;
08836 switch (nd_type(node->nd_value)) {
08837 case NODE_LIT:
08838 case NODE_STR:
08839 case NODE_NIL:
08840 case NODE_TRUE:
08841 case NODE_FALSE:
08842
08843 parser_warn(node->nd_value, "found = in conditional, should be ==");
08844 return 1;
08845
08846 case NODE_DSTR:
08847 case NODE_XSTR:
08848 case NODE_DXSTR:
08849 case NODE_EVSTR:
08850 case NODE_DREGX:
08851 default:
08852 break;
08853 }
08854 return 1;
08855 }
08856
08857 static void
08858 warn_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
08859 {
08860 if (!e_option_supplied(parser)) parser_warn(node, str);
08861 }
08862
08863 static void
08864 warning_unless_e_option(struct parser_params *parser, NODE *node, const char *str)
08865 {
08866 if (!e_option_supplied(parser)) parser_warning(node, str);
08867 }
08868
08869 static void
08870 fixup_nodes(NODE **rootnode)
08871 {
08872 NODE *node, *next, *head;
08873
08874 for (node = *rootnode; node; node = next) {
08875 enum node_type type;
08876 VALUE val;
08877
08878 next = node->nd_next;
08879 head = node->nd_head;
08880 rb_gc_force_recycle((VALUE)node);
08881 *rootnode = next;
08882 switch (type = nd_type(head)) {
08883 case NODE_DOT2:
08884 case NODE_DOT3:
08885 val = rb_range_new(head->nd_beg->nd_lit, head->nd_end->nd_lit,
08886 type == NODE_DOT3);
08887 rb_gc_force_recycle((VALUE)head->nd_beg);
08888 rb_gc_force_recycle((VALUE)head->nd_end);
08889 nd_set_type(head, NODE_LIT);
08890 head->nd_lit = val;
08891 break;
08892 default:
08893 break;
08894 }
08895 }
08896 }
08897
08898 static NODE *cond0(struct parser_params*,NODE*);
08899
08900 static NODE*
08901 range_op(struct parser_params *parser, NODE *node)
08902 {
08903 enum node_type type;
08904
08905 if (node == 0) return 0;
08906
08907 type = nd_type(node);
08908 value_expr(node);
08909 if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
08910 warn_unless_e_option(parser, node, "integer literal in conditional range");
08911 return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(rb_intern("$."))));
08912 }
08913 return cond0(parser, node);
08914 }
08915
08916 static int
08917 literal_node(NODE *node)
08918 {
08919 if (!node) return 1;
08920 switch (nd_type(node)) {
08921 case NODE_LIT:
08922 case NODE_STR:
08923 case NODE_DSTR:
08924 case NODE_EVSTR:
08925 case NODE_DREGX:
08926 case NODE_DREGX_ONCE:
08927 case NODE_DSYM:
08928 return 2;
08929 case NODE_TRUE:
08930 case NODE_FALSE:
08931 case NODE_NIL:
08932 return 1;
08933 }
08934 return 0;
08935 }
08936
08937 static NODE*
08938 cond0(struct parser_params *parser, NODE *node)
08939 {
08940 if (node == 0) return 0;
08941 assign_in_cond(parser, node);
08942
08943 switch (nd_type(node)) {
08944 case NODE_DSTR:
08945 case NODE_EVSTR:
08946 case NODE_STR:
08947 rb_warn0("string literal in condition");
08948 break;
08949
08950 case NODE_DREGX:
08951 case NODE_DREGX_ONCE:
08952 warning_unless_e_option(parser, node, "regex literal in condition");
08953 return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
08954
08955 case NODE_AND:
08956 case NODE_OR:
08957 node->nd_1st = cond0(parser, node->nd_1st);
08958 node->nd_2nd = cond0(parser, node->nd_2nd);
08959 break;
08960
08961 case NODE_DOT2:
08962 case NODE_DOT3:
08963 node->nd_beg = range_op(parser, node->nd_beg);
08964 node->nd_end = range_op(parser, node->nd_end);
08965 if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
08966 else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
08967 if (!e_option_supplied(parser)) {
08968 int b = literal_node(node->nd_beg);
08969 int e = literal_node(node->nd_end);
08970 if ((b == 1 && e == 1) || (b + e >= 2 && RTEST(ruby_verbose))) {
08971 parser_warn(node, "range literal in condition");
08972 }
08973 }
08974 break;
08975
08976 case NODE_DSYM:
08977 parser_warning(node, "literal in condition");
08978 break;
08979
08980 case NODE_LIT:
08981 if (TYPE(node->nd_lit) == T_REGEXP) {
08982 warn_unless_e_option(parser, node, "regex literal in condition");
08983 nd_set_type(node, NODE_MATCH);
08984 }
08985 else {
08986 parser_warning(node, "literal in condition");
08987 }
08988 default:
08989 break;
08990 }
08991 return node;
08992 }
08993
08994 static NODE*
08995 cond_gen(struct parser_params *parser, NODE *node)
08996 {
08997 if (node == 0) return 0;
08998 return cond0(parser, node);
08999 }
09000
09001 static NODE*
09002 logop_gen(struct parser_params *parser, enum node_type type, NODE *left, NODE *right)
09003 {
09004 value_expr(left);
09005 if (left && (enum node_type)nd_type(left) == type) {
09006 NODE *node = left, *second;
09007 while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) {
09008 node = second;
09009 }
09010 node->nd_2nd = NEW_NODE(type, second, right, 0);
09011 return left;
09012 }
09013 return NEW_NODE(type, left, right, 0);
09014 }
09015
09016 static void
09017 no_blockarg(struct parser_params *parser, NODE *node)
09018 {
09019 if (node && nd_type(node) == NODE_BLOCK_PASS) {
09020 compile_error(PARSER_ARG "block argument should not be given");
09021 }
09022 }
09023
09024 static NODE *
09025 ret_args_gen(struct parser_params *parser, NODE *node)
09026 {
09027 if (node) {
09028 no_blockarg(parser, node);
09029 if (nd_type(node) == NODE_ARRAY) {
09030 if (node->nd_next == 0) {
09031 node = node->nd_head;
09032 }
09033 else {
09034 nd_set_type(node, NODE_VALUES);
09035 }
09036 }
09037 }
09038 return node;
09039 }
09040
09041 static NODE *
09042 new_yield_gen(struct parser_params *parser, NODE *node)
09043 {
09044 long state = Qtrue;
09045
09046 if (node) {
09047 no_blockarg(parser, node);
09048 if (node && nd_type(node) == NODE_SPLAT) {
09049 state = Qtrue;
09050 }
09051 }
09052 else {
09053 state = Qfalse;
09054 }
09055 return NEW_YIELD(node, state);
09056 }
09057
09058 static NODE*
09059 negate_lit(NODE *node)
09060 {
09061 switch (TYPE(node->nd_lit)) {
09062 case T_FIXNUM:
09063 node->nd_lit = LONG2FIX(-FIX2LONG(node->nd_lit));
09064 break;
09065 case T_BIGNUM:
09066 node->nd_lit = rb_funcall(node->nd_lit,tUMINUS,0,0);
09067 break;
09068 case T_FLOAT:
09069 RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit);
09070 break;
09071 default:
09072 break;
09073 }
09074 return node;
09075 }
09076
09077 static NODE *
09078 arg_blk_pass(NODE *node1, NODE *node2)
09079 {
09080 if (node2) {
09081 node2->nd_head = node1;
09082 return node2;
09083 }
09084 return node1;
09085 }
09086
09087 static NODE*
09088 new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b)
09089 {
09090 int saved_line = ruby_sourceline;
09091 NODE *node;
09092 NODE *i1, *i2 = 0;
09093
09094 node = NEW_ARGS(m ? m->nd_plen : 0, o);
09095 i1 = m ? m->nd_next : 0;
09096 node->nd_next = NEW_ARGS_AUX(r, b);
09097
09098 if (p) {
09099 i2 = p->nd_next;
09100 node->nd_next->nd_next = NEW_ARGS_AUX(p->nd_pid, p->nd_plen);
09101 }
09102 else if (i1) {
09103 node->nd_next->nd_next = NEW_ARGS_AUX(0, 0);
09104 }
09105 if (i1 || i2) {
09106 node->nd_next->nd_next->nd_next = NEW_NODE(NODE_AND, i1, i2, 0);
09107 }
09108 ruby_sourceline = saved_line;
09109 return node;
09110 }
09111 #endif
09112
09113 static void
09114 warn_unused_var(struct parser_params *parser, struct local_vars *local)
09115 {
09116 int i, cnt;
09117 ID *v, *u;
09118
09119 if (!local->used) return;
09120 v = local->vars->tbl;
09121 u = local->used->tbl;
09122 cnt = local->used->pos;
09123 if (cnt != local->vars->pos) {
09124 rb_bug("local->used->pos != local->vars->pos");
09125 }
09126 for (i = 0; i < cnt; ++i) {
09127 if (!v[i] || (u[i] & LVAR_USED)) continue;
09128 if (idUScore == v[i]) continue;
09129 rb_compile_warn(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i]));
09130 }
09131 }
09132
09133 static void
09134 local_push_gen(struct parser_params *parser, int inherit_dvars)
09135 {
09136 struct local_vars *local;
09137
09138 local = ALLOC(struct local_vars);
09139 local->prev = lvtbl;
09140 local->args = vtable_alloc(0);
09141 local->vars = vtable_alloc(inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE);
09142 local->used = !inherit_dvars && RTEST(ruby_verbose) ? vtable_alloc(0) : 0;
09143 lvtbl = local;
09144 }
09145
09146 static void
09147 local_pop_gen(struct parser_params *parser)
09148 {
09149 struct local_vars *local = lvtbl->prev;
09150 if (lvtbl->used) {
09151 warn_unused_var(parser, lvtbl);
09152 vtable_free(lvtbl->used);
09153 }
09154 vtable_free(lvtbl->args);
09155 vtable_free(lvtbl->vars);
09156 xfree(lvtbl);
09157 lvtbl = local;
09158 }
09159
09160 #ifndef RIPPER
09161 static ID*
09162 vtable_tblcpy(ID *buf, const struct vtable *src)
09163 {
09164 int i, cnt = vtable_size(src);
09165
09166 if (cnt > 0) {
09167 buf[0] = cnt;
09168 for (i = 0; i < cnt; i++) {
09169 buf[i] = src->tbl[i];
09170 }
09171 return buf;
09172 }
09173 return 0;
09174 }
09175
09176 static ID*
09177 local_tbl_gen(struct parser_params *parser)
09178 {
09179 int cnt = vtable_size(lvtbl->args) + vtable_size(lvtbl->vars);
09180 ID *buf;
09181
09182 if (cnt <= 0) return 0;
09183 buf = ALLOC_N(ID, cnt + 1);
09184 vtable_tblcpy(buf+1, lvtbl->args);
09185 vtable_tblcpy(buf+vtable_size(lvtbl->args)+1, lvtbl->vars);
09186 buf[0] = cnt;
09187 return buf;
09188 }
09189 #endif
09190
09191 static int
09192 arg_var_gen(struct parser_params *parser, ID id)
09193 {
09194 vtable_add(lvtbl->args, id);
09195 return vtable_size(lvtbl->args) - 1;
09196 }
09197
09198 static int
09199 local_var_gen(struct parser_params *parser, ID id)
09200 {
09201 vtable_add(lvtbl->vars, id);
09202 if (lvtbl->used) {
09203 vtable_add(lvtbl->used, (ID)ruby_sourceline);
09204 }
09205 return vtable_size(lvtbl->vars) - 1;
09206 }
09207
09208 static int
09209 local_id_gen(struct parser_params *parser, ID id)
09210 {
09211 struct vtable *vars, *args, *used;
09212
09213 vars = lvtbl->vars;
09214 args = lvtbl->args;
09215 used = lvtbl->used;
09216
09217 while (vars && POINTER_P(vars->prev)) {
09218 vars = vars->prev;
09219 args = args->prev;
09220 if (used) used = used->prev;
09221 }
09222
09223 if (vars && vars->prev == DVARS_INHERIT) {
09224 return rb_local_defined(id);
09225 }
09226 else if (vtable_included(args, id)) {
09227 return 1;
09228 }
09229 else {
09230 int i = vtable_included(vars, id);
09231 if (i && used) used->tbl[i-1] |= LVAR_USED;
09232 return i != 0;
09233 }
09234 }
09235
09236 static const struct vtable *
09237 dyna_push_gen(struct parser_params *parser)
09238 {
09239 lvtbl->args = vtable_alloc(lvtbl->args);
09240 lvtbl->vars = vtable_alloc(lvtbl->vars);
09241 if (lvtbl->used) {
09242 lvtbl->used = vtable_alloc(lvtbl->used);
09243 }
09244 return lvtbl->args;
09245 }
09246
09247 static void
09248 dyna_pop_1(struct parser_params *parser)
09249 {
09250 struct vtable *tmp;
09251
09252 if ((tmp = lvtbl->used) != 0) {
09253 warn_unused_var(parser, lvtbl);
09254 lvtbl->used = lvtbl->used->prev;
09255 vtable_free(tmp);
09256 }
09257 tmp = lvtbl->args;
09258 lvtbl->args = lvtbl->args->prev;
09259 vtable_free(tmp);
09260 tmp = lvtbl->vars;
09261 lvtbl->vars = lvtbl->vars->prev;
09262 vtable_free(tmp);
09263 }
09264
09265 static void
09266 dyna_pop_gen(struct parser_params *parser, const struct vtable *lvargs)
09267 {
09268 while (lvtbl->args != lvargs) {
09269 dyna_pop_1(parser);
09270 if (!lvtbl->args) {
09271 struct local_vars *local = lvtbl->prev;
09272 xfree(lvtbl);
09273 lvtbl = local;
09274 }
09275 }
09276 dyna_pop_1(parser);
09277 }
09278
09279 static int
09280 dyna_in_block_gen(struct parser_params *parser)
09281 {
09282 return POINTER_P(lvtbl->vars) && lvtbl->vars->prev != DVARS_TOPSCOPE;
09283 }
09284
09285 static int
09286 dvar_defined_gen(struct parser_params *parser, ID id, int get)
09287 {
09288 struct vtable *vars, *args, *used;
09289 int i;
09290
09291 args = lvtbl->args;
09292 vars = lvtbl->vars;
09293 used = lvtbl->used;
09294
09295 while (POINTER_P(vars)) {
09296 if (vtable_included(args, id)) {
09297 return 1;
09298 }
09299 if ((i = vtable_included(vars, id)) != 0) {
09300 if (used) used->tbl[i-1] |= LVAR_USED;
09301 return 1;
09302 }
09303 args = args->prev;
09304 vars = vars->prev;
09305 if (get) used = 0;
09306 if (used) used = used->prev;
09307 }
09308
09309 if (vars == DVARS_INHERIT) {
09310 return rb_dvar_defined(id);
09311 }
09312
09313 return 0;
09314 }
09315
09316 static int
09317 dvar_curr_gen(struct parser_params *parser, ID id)
09318 {
09319 return (vtable_included(lvtbl->args, id) ||
09320 vtable_included(lvtbl->vars, id));
09321 }
09322
09323 #ifndef RIPPER
09324 static void
09325 reg_fragment_setenc_gen(struct parser_params* parser, VALUE str, int options)
09326 {
09327 int c = RE_OPTION_ENCODING_IDX(options);
09328
09329 if (c) {
09330 int opt, idx;
09331 rb_char_to_option_kcode(c, &opt, &idx);
09332 if (idx != ENCODING_GET(str) &&
09333 rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09334 goto error;
09335 }
09336 ENCODING_SET(str, idx);
09337 }
09338 else if (RE_OPTION_ENCODING_NONE(options)) {
09339 if (!ENCODING_IS_ASCII8BIT(str) &&
09340 rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09341 c = 'n';
09342 goto error;
09343 }
09344 rb_enc_associate(str, rb_ascii8bit_encoding());
09345 }
09346 else if (parser->enc == rb_usascii_encoding()) {
09347 if (rb_enc_str_coderange(str) != ENC_CODERANGE_7BIT) {
09348
09349 rb_enc_associate(str, rb_usascii_encoding());
09350 }
09351 else {
09352 rb_enc_associate(str, rb_ascii8bit_encoding());
09353 }
09354 }
09355 return;
09356
09357 error:
09358 compile_error(PARSER_ARG
09359 "regexp encoding option '%c' differs from source encoding '%s'",
09360 c, rb_enc_name(rb_enc_get(str)));
09361 }
09362
09363 static int
09364 reg_fragment_check_gen(struct parser_params* parser, VALUE str, int options)
09365 {
09366 VALUE err;
09367 reg_fragment_setenc(str, options);
09368 err = rb_reg_check_preprocess(str);
09369 if (err != Qnil) {
09370 err = rb_obj_as_string(err);
09371 compile_error(PARSER_ARG "%s", RSTRING_PTR(err));
09372 RB_GC_GUARD(err);
09373 return 0;
09374 }
09375 return 1;
09376 }
09377
09378 typedef struct {
09379 struct parser_params* parser;
09380 rb_encoding *enc;
09381 NODE *succ_block;
09382 NODE *fail_block;
09383 int num;
09384 } reg_named_capture_assign_t;
09385
09386 static int
09387 reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
09388 int back_num, int *back_refs, OnigRegex regex, void *arg0)
09389 {
09390 reg_named_capture_assign_t *arg = (reg_named_capture_assign_t*)arg0;
09391 struct parser_params* parser = arg->parser;
09392 rb_encoding *enc = arg->enc;
09393 long len = name_end - name;
09394 const char *s = (const char *)name;
09395 ID var;
09396
09397 arg->num++;
09398
09399 if (arg->succ_block == 0) {
09400 arg->succ_block = NEW_BEGIN(0);
09401 arg->fail_block = NEW_BEGIN(0);
09402 }
09403
09404 if (!len || (*name != '_' && ISASCII(*name) && !rb_enc_islower(*name, enc)) ||
09405 (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) ||
09406 !rb_enc_symname2_p(s, len, enc)) {
09407 return ST_CONTINUE;
09408 }
09409 var = rb_intern3(s, len, enc);
09410 if (dvar_defined(var) || local_id(var)) {
09411 rb_warningS("named capture conflicts a local variable - %s",
09412 rb_id2name(var));
09413 }
09414 arg->succ_block = block_append(arg->succ_block,
09415 newline_node(node_assign(assignable(var,0),
09416 NEW_CALL(
09417 gettable(rb_intern("$~")),
09418 idAREF,
09419 NEW_LIST(NEW_LIT(ID2SYM(var))))
09420 )));
09421 arg->fail_block = block_append(arg->fail_block,
09422 newline_node(node_assign(assignable(var,0), NEW_LIT(Qnil))));
09423 return ST_CONTINUE;
09424 }
09425
09426 static NODE *
09427 reg_named_capture_assign_gen(struct parser_params* parser, VALUE regexp, NODE *match)
09428 {
09429 reg_named_capture_assign_t arg;
09430
09431 arg.parser = parser;
09432 arg.enc = rb_enc_get(regexp);
09433 arg.succ_block = 0;
09434 arg.fail_block = 0;
09435 arg.num = 0;
09436 onig_foreach_name(RREGEXP(regexp)->ptr, reg_named_capture_assign_iter, (void*)&arg);
09437
09438 if (arg.num == 0)
09439 return match;
09440
09441 return
09442 block_append(
09443 newline_node(match),
09444 NEW_IF(gettable(rb_intern("$~")),
09445 block_append(
09446 newline_node(arg.succ_block),
09447 newline_node(
09448 NEW_CALL(
09449 gettable(rb_intern("$~")),
09450 rb_intern("begin"),
09451 NEW_LIST(NEW_LIT(INT2FIX(0)))))),
09452 block_append(
09453 newline_node(arg.fail_block),
09454 newline_node(
09455 NEW_LIT(Qnil)))));
09456 }
09457
09458 static VALUE
09459 reg_compile_gen(struct parser_params* parser, VALUE str, int options)
09460 {
09461 VALUE re;
09462 VALUE err;
09463
09464 reg_fragment_setenc(str, options);
09465 err = rb_errinfo();
09466 re = rb_reg_compile(str, options & RE_OPTION_MASK, ruby_sourcefile, ruby_sourceline);
09467 if (NIL_P(re)) {
09468 ID mesg = rb_intern("mesg");
09469 VALUE m = rb_attr_get(rb_errinfo(), mesg);
09470 rb_set_errinfo(err);
09471 if (!NIL_P(err)) {
09472 rb_str_append(rb_str_cat(rb_attr_get(err, mesg), "\n", 1), m);
09473 }
09474 else {
09475 compile_error(PARSER_ARG "%s", RSTRING_PTR(m));
09476 }
09477 return Qnil;
09478 }
09479 return re;
09480 }
09481
09482 void
09483 rb_gc_mark_parser(void)
09484 {
09485 }
09486
09487 NODE*
09488 rb_parser_append_print(VALUE vparser, NODE *node)
09489 {
09490 NODE *prelude = 0;
09491 NODE *scope = node;
09492 struct parser_params *parser;
09493
09494 if (!node) return node;
09495
09496 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
09497
09498 node = node->nd_body;
09499
09500 if (nd_type(node) == NODE_PRELUDE) {
09501 prelude = node;
09502 node = node->nd_body;
09503 }
09504
09505 node = block_append(node,
09506 NEW_FCALL(rb_intern("print"),
09507 NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
09508 if (prelude) {
09509 prelude->nd_body = node;
09510 scope->nd_body = prelude;
09511 }
09512 else {
09513 scope->nd_body = node;
09514 }
09515
09516 return scope;
09517 }
09518
09519 NODE *
09520 rb_parser_while_loop(VALUE vparser, NODE *node, int chop, int split)
09521 {
09522 NODE *prelude = 0;
09523 NODE *scope = node;
09524 struct parser_params *parser;
09525
09526 if (!node) return node;
09527
09528 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
09529
09530 node = node->nd_body;
09531
09532 if (nd_type(node) == NODE_PRELUDE) {
09533 prelude = node;
09534 node = node->nd_body;
09535 }
09536 if (split) {
09537 node = block_append(NEW_GASGN(rb_intern("$F"),
09538 NEW_CALL(NEW_GVAR(rb_intern("$_")),
09539 rb_intern("split"), 0)),
09540 node);
09541 }
09542 if (chop) {
09543 node = block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
09544 rb_intern("chop!"), 0), node);
09545 }
09546
09547 node = NEW_OPT_N(node);
09548
09549 if (prelude) {
09550 prelude->nd_body = node;
09551 scope->nd_body = prelude;
09552 }
09553 else {
09554 scope->nd_body = node;
09555 }
09556
09557 return scope;
09558 }
09559
09560 static const struct {
09561 ID token;
09562 const char *name;
09563 } op_tbl[] = {
09564 {tDOT2, ".."},
09565 {tDOT3, "..."},
09566 {'+', "+(binary)"},
09567 {'-', "-(binary)"},
09568 {tPOW, "**"},
09569 {tUPLUS, "+@"},
09570 {tUMINUS, "-@"},
09571 {tCMP, "<=>"},
09572 {tGEQ, ">="},
09573 {tLEQ, "<="},
09574 {tEQ, "=="},
09575 {tEQQ, "==="},
09576 {tNEQ, "!="},
09577 {tMATCH, "=~"},
09578 {tNMATCH, "!~"},
09579 {tAREF, "[]"},
09580 {tASET, "[]="},
09581 {tLSHFT, "<<"},
09582 {tRSHFT, ">>"},
09583 {tCOLON2, "::"},
09584 };
09585
09586 #define op_tbl_count numberof(op_tbl)
09587
09588 #ifndef ENABLE_SELECTOR_NAMESPACE
09589 #define ENABLE_SELECTOR_NAMESPACE 0
09590 #endif
09591
09592 static struct symbols {
09593 ID last_id;
09594 st_table *sym_id;
09595 st_table *id_str;
09596 #if ENABLE_SELECTOR_NAMESPACE
09597 st_table *ivar2_id;
09598 st_table *id_ivar2;
09599 #endif
09600 VALUE op_sym[tLAST_TOKEN];
09601 } global_symbols = {tLAST_ID};
09602
09603 static const struct st_hash_type symhash = {
09604 rb_str_hash_cmp,
09605 rb_str_hash,
09606 };
09607
09608 #if ENABLE_SELECTOR_NAMESPACE
09609 struct ivar2_key {
09610 ID id;
09611 VALUE klass;
09612 };
09613
09614 static int
09615 ivar2_cmp(struct ivar2_key *key1, struct ivar2_key *key2)
09616 {
09617 if (key1->id == key2->id && key1->klass == key2->klass) {
09618 return 0;
09619 }
09620 return 1;
09621 }
09622
09623 static int
09624 ivar2_hash(struct ivar2_key *key)
09625 {
09626 return (key->id << 8) ^ (key->klass >> 2);
09627 }
09628
09629 static const struct st_hash_type ivar2_hash_type = {
09630 ivar2_cmp,
09631 ivar2_hash,
09632 };
09633 #endif
09634
09635 void
09636 Init_sym(void)
09637 {
09638 global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
09639 global_symbols.id_str = st_init_numtable_with_size(1000);
09640 #if ENABLE_SELECTOR_NAMESPACE
09641 global_symbols.ivar2_id = st_init_table_with_size(&ivar2_hash_type, 1000);
09642 global_symbols.id_ivar2 = st_init_numtable_with_size(1000);
09643 #endif
09644
09645 Init_id();
09646 }
09647
09648 void
09649 rb_gc_mark_symbols(void)
09650 {
09651 rb_mark_tbl(global_symbols.id_str);
09652 rb_gc_mark_locations(global_symbols.op_sym,
09653 global_symbols.op_sym + tLAST_TOKEN);
09654 }
09655 #endif
09656
09657 static ID
09658 internal_id_gen(struct parser_params *parser)
09659 {
09660 ID id = (ID)vtable_size(lvtbl->args) + (ID)vtable_size(lvtbl->vars);
09661 id += ((tLAST_TOKEN - ID_INTERNAL) >> ID_SCOPE_SHIFT) + 1;
09662 return ID_INTERNAL | (id << ID_SCOPE_SHIFT);
09663 }
09664
09665 #ifndef RIPPER
09666 static int
09667 is_special_global_name(const char *m, const char *e, rb_encoding *enc)
09668 {
09669 int mb = 0;
09670
09671 if (m >= e) return 0;
09672 switch (*m) {
09673 case '~': case '*': case '$': case '?': case '!': case '@':
09674 case '/': case '\\': case ';': case ',': case '.': case '=':
09675 case ':': case '<': case '>': case '\"':
09676 case '&': case '`': case '\'': case '+':
09677 case '0':
09678 ++m;
09679 break;
09680 case '-':
09681 ++m;
09682 if (m < e && is_identchar(m, e, enc)) {
09683 if (!ISASCII(*m)) mb = 1;
09684 m += rb_enc_mbclen(m, e, enc);
09685 }
09686 break;
09687 default:
09688 if (!rb_enc_isdigit(*m, enc)) return 0;
09689 do {
09690 if (!ISASCII(*m)) mb = 1;
09691 ++m;
09692 } while (m < e && rb_enc_isdigit(*m, enc));
09693 }
09694 return m == e ? mb + 1 : 0;
09695 }
09696
09697 int
09698 rb_symname_p(const char *name)
09699 {
09700 return rb_enc_symname_p(name, rb_ascii8bit_encoding());
09701 }
09702
09703 int
09704 rb_enc_symname_p(const char *name, rb_encoding *enc)
09705 {
09706 return rb_enc_symname2_p(name, strlen(name), enc);
09707 }
09708
09709 int
09710 rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
09711 {
09712 const char *m = name;
09713 const char *e = m + len;
09714 int localid = FALSE;
09715
09716 if (!m || len <= 0) return FALSE;
09717 switch (*m) {
09718 case '\0':
09719 return FALSE;
09720
09721 case '$':
09722 if (is_special_global_name(++m, e, enc)) return TRUE;
09723 goto id;
09724
09725 case '@':
09726 if (*++m == '@') ++m;
09727 goto id;
09728
09729 case '<':
09730 switch (*++m) {
09731 case '<': ++m; break;
09732 case '=': if (*++m == '>') ++m; break;
09733 default: break;
09734 }
09735 break;
09736
09737 case '>':
09738 switch (*++m) {
09739 case '>': case '=': ++m; break;
09740 }
09741 break;
09742
09743 case '=':
09744 switch (*++m) {
09745 case '~': ++m; break;
09746 case '=': if (*++m == '=') ++m; break;
09747 default: return FALSE;
09748 }
09749 break;
09750
09751 case '*':
09752 if (*++m == '*') ++m;
09753 break;
09754
09755 case '+': case '-':
09756 if (*++m == '@') ++m;
09757 break;
09758
09759 case '|': case '^': case '&': case '/': case '%': case '~': case '`':
09760 ++m;
09761 break;
09762
09763 case '[':
09764 if (*++m != ']') return FALSE;
09765 if (*++m == '=') ++m;
09766 break;
09767
09768 case '!':
09769 if (len == 1) return TRUE;
09770 switch (*++m) {
09771 case '=': case '~': ++m; break;
09772 default: return FALSE;
09773 }
09774 break;
09775
09776 default:
09777 localid = !rb_enc_isupper(*m, enc);
09778 id:
09779 if (m >= e || (*m != '_' && !rb_enc_isalpha(*m, enc) && ISASCII(*m)))
09780 return FALSE;
09781 while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
09782 if (localid) {
09783 switch (*m) {
09784 case '!': case '?': case '=': ++m;
09785 }
09786 }
09787 break;
09788 }
09789 return m == e;
09790 }
09791
09792 static ID
09793 register_symid(ID id, const char *name, long len, rb_encoding *enc)
09794 {
09795 VALUE str = rb_enc_str_new(name, len, enc);
09796 OBJ_FREEZE(str);
09797 st_add_direct(global_symbols.sym_id, (st_data_t)str, id);
09798 st_add_direct(global_symbols.id_str, id, (st_data_t)str);
09799 return id;
09800 }
09801
09802 ID
09803 rb_intern3(const char *name, long len, rb_encoding *enc)
09804 {
09805 const char *m = name;
09806 const char *e = m + len;
09807 unsigned char c;
09808 VALUE str;
09809 ID id;
09810 long last;
09811 int mb;
09812 st_data_t data;
09813 struct RString fake_str;
09814 fake_str.basic.flags = T_STRING|RSTRING_NOEMBED;
09815 fake_str.basic.klass = rb_cString;
09816 fake_str.as.heap.len = len;
09817 fake_str.as.heap.ptr = (char *)name;
09818 fake_str.as.heap.aux.capa = len;
09819 str = (VALUE)&fake_str;
09820 rb_enc_associate(str, enc);
09821 OBJ_FREEZE(str);
09822
09823 if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
09824 rb_raise(rb_eEncodingError, "invalid encoding symbol");
09825 }
09826
09827 if (st_lookup(global_symbols.sym_id, str, &data))
09828 return (ID)data;
09829
09830 if (rb_cString && !rb_enc_asciicompat(enc)) {
09831 id = ID_JUNK;
09832 goto new_id;
09833 }
09834 last = len-1;
09835 id = 0;
09836 switch (*m) {
09837 case '$':
09838 id |= ID_GLOBAL;
09839 if ((mb = is_special_global_name(++m, e, enc)) != 0) {
09840 if (!--mb) enc = rb_ascii8bit_encoding();
09841 goto new_id;
09842 }
09843 break;
09844 case '@':
09845 if (m[1] == '@') {
09846 m++;
09847 id |= ID_CLASS;
09848 }
09849 else {
09850 id |= ID_INSTANCE;
09851 }
09852 m++;
09853 break;
09854 default:
09855 c = m[0];
09856 if (c != '_' && rb_enc_isascii(c, enc) && rb_enc_ispunct(c, enc)) {
09857
09858 int i;
09859
09860 if (len == 1) {
09861 id = c;
09862 goto id_register;
09863 }
09864 for (i = 0; i < op_tbl_count; i++) {
09865 if (*op_tbl[i].name == *m &&
09866 strcmp(op_tbl[i].name, m) == 0) {
09867 id = op_tbl[i].token;
09868 goto id_register;
09869 }
09870 }
09871 }
09872
09873 if (m[last] == '=') {
09874
09875 id = rb_intern3(name, last, enc);
09876 if (id > tLAST_TOKEN && !is_attrset_id(id)) {
09877 enc = rb_enc_get(rb_id2str(id));
09878 id = rb_id_attrset(id);
09879 goto id_register;
09880 }
09881 id = ID_ATTRSET;
09882 }
09883 else if (rb_enc_isupper(m[0], enc)) {
09884 id = ID_CONST;
09885 }
09886 else {
09887 id = ID_LOCAL;
09888 }
09889 break;
09890 }
09891 mb = 0;
09892 if (!rb_enc_isdigit(*m, enc)) {
09893 while (m <= name + last && is_identchar(m, e, enc)) {
09894 if (ISASCII(*m)) {
09895 m++;
09896 }
09897 else {
09898 mb = 1;
09899 m += rb_enc_mbclen(m, e, enc);
09900 }
09901 }
09902 }
09903 if (m - name < len) id = ID_JUNK;
09904 if (enc != rb_usascii_encoding()) {
09905
09906
09907
09908
09909 if (!mb) {
09910 for (; m <= name + len; ++m) {
09911 if (!ISASCII(*m)) goto mbstr;
09912 }
09913 enc = rb_usascii_encoding();
09914 }
09915 mbstr:;
09916 }
09917 new_id:
09918 if (global_symbols.last_id >= ~(ID)0 >> (ID_SCOPE_SHIFT+RUBY_SPECIAL_SHIFT)) {
09919 if (len > 20) {
09920 rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %.20s...)",
09921 name);
09922 }
09923 else {
09924 rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %.*s)",
09925 (int)len, name);
09926 }
09927 }
09928 id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
09929 id_register:
09930 return register_symid(id, name, len, enc);
09931 }
09932
09933 ID
09934 rb_intern2(const char *name, long len)
09935 {
09936 return rb_intern3(name, len, rb_usascii_encoding());
09937 }
09938
09939 #undef rb_intern
09940 ID
09941 rb_intern(const char *name)
09942 {
09943 return rb_intern2(name, strlen(name));
09944 }
09945
09946 ID
09947 rb_intern_str(VALUE str)
09948 {
09949 rb_encoding *enc;
09950 ID id;
09951
09952 if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
09953 enc = rb_usascii_encoding();
09954 }
09955 else {
09956 enc = rb_enc_get(str);
09957 }
09958 id = rb_intern3(RSTRING_PTR(str), RSTRING_LEN(str), enc);
09959 RB_GC_GUARD(str);
09960 return id;
09961 }
09962
09963 VALUE
09964 rb_id2str(ID id)
09965 {
09966 st_data_t data;
09967
09968 if (id < tLAST_TOKEN) {
09969 int i = 0;
09970
09971 if (id < INT_MAX && rb_ispunct((int)id)) {
09972 VALUE str = global_symbols.op_sym[i = (int)id];
09973 if (!str) {
09974 char name[2];
09975 name[0] = (char)id;
09976 name[1] = 0;
09977 str = rb_usascii_str_new(name, 1);
09978 OBJ_FREEZE(str);
09979 global_symbols.op_sym[i] = str;
09980 }
09981 return str;
09982 }
09983 for (i = 0; i < op_tbl_count; i++) {
09984 if (op_tbl[i].token == id) {
09985 VALUE str = global_symbols.op_sym[i];
09986 if (!str) {
09987 str = rb_usascii_str_new2(op_tbl[i].name);
09988 OBJ_FREEZE(str);
09989 global_symbols.op_sym[i] = str;
09990 }
09991 return str;
09992 }
09993 }
09994 }
09995
09996 if (st_lookup(global_symbols.id_str, id, &data)) {
09997 VALUE str = (VALUE)data;
09998 if (RBASIC(str)->klass == 0)
09999 RBASIC(str)->klass = rb_cString;
10000 return str;
10001 }
10002
10003 if (is_attrset_id(id)) {
10004 ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
10005 VALUE str;
10006
10007 while (!(str = rb_id2str(id2))) {
10008 if (!is_local_id(id2)) return 0;
10009 id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
10010 }
10011 str = rb_str_dup(str);
10012 rb_str_cat(str, "=", 1);
10013 rb_intern_str(str);
10014 if (st_lookup(global_symbols.id_str, id, &data)) {
10015 VALUE str = (VALUE)data;
10016 if (RBASIC(str)->klass == 0)
10017 RBASIC(str)->klass = rb_cString;
10018 return str;
10019 }
10020 }
10021 return 0;
10022 }
10023
10024 const char *
10025 rb_id2name(ID id)
10026 {
10027 VALUE str = rb_id2str(id);
10028
10029 if (!str) return 0;
10030 return RSTRING_PTR(str);
10031 }
10032
10033 static int
10034 symbols_i(VALUE sym, ID value, VALUE ary)
10035 {
10036 rb_ary_push(ary, ID2SYM(value));
10037 return ST_CONTINUE;
10038 }
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056 VALUE
10057 rb_sym_all_symbols(void)
10058 {
10059 VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
10060
10061 st_foreach(global_symbols.sym_id, symbols_i, ary);
10062 return ary;
10063 }
10064
10065 int
10066 rb_is_const_id(ID id)
10067 {
10068 return is_const_id(id);
10069 }
10070
10071 int
10072 rb_is_class_id(ID id)
10073 {
10074 return is_class_id(id);
10075 }
10076
10077 int
10078 rb_is_instance_id(ID id)
10079 {
10080 return is_instance_id(id);
10081 }
10082
10083 int
10084 rb_is_local_id(ID id)
10085 {
10086 return is_local_id(id);
10087 }
10088
10089 int
10090 rb_is_junk_id(ID id)
10091 {
10092 return is_junk_id(id);
10093 }
10094
10095 #endif
10096
10097 static void
10098 parser_initialize(struct parser_params *parser)
10099 {
10100 parser->eofp = Qfalse;
10101
10102 parser->parser_lex_strterm = 0;
10103 parser->parser_cond_stack = 0;
10104 parser->parser_cmdarg_stack = 0;
10105 parser->parser_class_nest = 0;
10106 parser->parser_paren_nest = 0;
10107 parser->parser_lpar_beg = 0;
10108 parser->parser_in_single = 0;
10109 parser->parser_in_def = 0;
10110 parser->parser_in_defined = 0;
10111 parser->parser_compile_for_eval = 0;
10112 parser->parser_cur_mid = 0;
10113 parser->parser_tokenbuf = NULL;
10114 parser->parser_tokidx = 0;
10115 parser->parser_toksiz = 0;
10116 parser->parser_heredoc_end = 0;
10117 parser->parser_command_start = TRUE;
10118 parser->parser_deferred_nodes = 0;
10119 parser->parser_lex_pbeg = 0;
10120 parser->parser_lex_p = 0;
10121 parser->parser_lex_pend = 0;
10122 parser->parser_lvtbl = 0;
10123 parser->parser_ruby__end__seen = 0;
10124 parser->parser_ruby_sourcefile = 0;
10125 #ifndef RIPPER
10126 parser->is_ripper = 0;
10127 parser->parser_eval_tree_begin = 0;
10128 parser->parser_eval_tree = 0;
10129 #else
10130 parser->is_ripper = 1;
10131 parser->parser_ruby_sourcefile_string = Qnil;
10132 parser->delayed = Qnil;
10133
10134 parser->result = Qnil;
10135 parser->parsing_thread = Qnil;
10136 parser->toplevel_p = TRUE;
10137 #endif
10138 #ifdef YYMALLOC
10139 parser->heap = NULL;
10140 #endif
10141 parser->enc = rb_usascii_encoding();
10142 }
10143
10144 #ifdef RIPPER
10145 #define parser_mark ripper_parser_mark
10146 #define parser_free ripper_parser_free
10147 #endif
10148
10149 static void
10150 parser_mark(void *ptr)
10151 {
10152 struct parser_params *p = (struct parser_params*)ptr;
10153
10154 rb_gc_mark((VALUE)p->parser_lex_strterm);
10155 rb_gc_mark((VALUE)p->parser_deferred_nodes);
10156 rb_gc_mark(p->parser_lex_input);
10157 rb_gc_mark(p->parser_lex_lastline);
10158 rb_gc_mark(p->parser_lex_nextline);
10159 #ifndef RIPPER
10160 rb_gc_mark((VALUE)p->parser_eval_tree_begin) ;
10161 rb_gc_mark((VALUE)p->parser_eval_tree) ;
10162 rb_gc_mark(p->debug_lines);
10163 #else
10164 rb_gc_mark(p->parser_ruby_sourcefile_string);
10165 rb_gc_mark(p->delayed);
10166 rb_gc_mark(p->value);
10167 rb_gc_mark(p->result);
10168 rb_gc_mark(p->parsing_thread);
10169 #endif
10170 #ifdef YYMALLOC
10171 rb_gc_mark((VALUE)p->heap);
10172 #endif
10173 }
10174
10175 static void
10176 parser_free(void *ptr)
10177 {
10178 struct parser_params *p = (struct parser_params*)ptr;
10179 struct local_vars *local, *prev;
10180
10181 if (p->parser_tokenbuf) {
10182 xfree(p->parser_tokenbuf);
10183 }
10184 for (local = p->parser_lvtbl; local; local = prev) {
10185 if (local->vars) xfree(local->vars);
10186 prev = local->prev;
10187 xfree(local);
10188 }
10189 #ifndef RIPPER
10190 xfree(p->parser_ruby_sourcefile);
10191 #endif
10192 xfree(p);
10193 }
10194
10195 static size_t
10196 parser_memsize(const void *ptr)
10197 {
10198 struct parser_params *p = (struct parser_params*)ptr;
10199 struct local_vars *local;
10200 size_t size = sizeof(*p);
10201
10202 if (!ptr) return 0;
10203 size += p->parser_toksiz;
10204 for (local = p->parser_lvtbl; local; local = local->prev) {
10205 size += sizeof(*local);
10206 if (local->vars) size += local->vars->capa * sizeof(ID);
10207 }
10208 #ifndef RIPPER
10209 if (p->parser_ruby_sourcefile) {
10210 size += strlen(p->parser_ruby_sourcefile) + 1;
10211 }
10212 #endif
10213 return size;
10214 }
10215
10216 static
10217 #ifndef RIPPER
10218 const
10219 #endif
10220 rb_data_type_t parser_data_type = {
10221 "parser",
10222 {
10223 parser_mark,
10224 parser_free,
10225 parser_memsize,
10226 },
10227 };
10228
10229 #ifndef RIPPER
10230 #undef rb_reserved_word
10231
10232 const struct kwtable *
10233 rb_reserved_word(const char *str, unsigned int len)
10234 {
10235 return reserved_word(str, len);
10236 }
10237
10238 static struct parser_params *
10239 parser_new(void)
10240 {
10241 struct parser_params *p;
10242
10243 p = ALLOC_N(struct parser_params, 1);
10244 MEMZERO(p, struct parser_params, 1);
10245 parser_initialize(p);
10246 return p;
10247 }
10248
10249 VALUE
10250 rb_parser_new(void)
10251 {
10252 struct parser_params *p = parser_new();
10253
10254 return TypedData_Wrap_Struct(0, &parser_data_type, p);
10255 }
10256
10257
10258
10259
10260
10261
10262
10263 VALUE
10264 rb_parser_end_seen_p(VALUE vparser)
10265 {
10266 struct parser_params *parser;
10267
10268 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
10269 return ruby__end__seen ? Qtrue : Qfalse;
10270 }
10271
10272
10273
10274
10275
10276
10277
10278 VALUE
10279 rb_parser_encoding(VALUE vparser)
10280 {
10281 struct parser_params *parser;
10282
10283 TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
10284 return rb_enc_from_encoding(parser->enc);
10285 }
10286
10287
10288
10289
10290
10291
10292
10293 VALUE
10294 rb_parser_get_yydebug(VALUE self)
10295 {
10296 struct parser_params *parser;
10297
10298 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10299 return yydebug ? Qtrue : Qfalse;
10300 }
10301
10302
10303
10304
10305
10306
10307
10308 VALUE
10309 rb_parser_set_yydebug(VALUE self, VALUE flag)
10310 {
10311 struct parser_params *parser;
10312
10313 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10314 yydebug = RTEST(flag);
10315 return flag;
10316 }
10317
10318 #ifdef YYMALLOC
10319 #define HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE))
10320 #define NEWHEAP() rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)
10321 #define ADD2HEAP(n, c, p) ((parser->heap = (n))->u1.node = (p), \
10322 (n)->u3.cnt = (c), (p))
10323
10324 void *
10325 rb_parser_malloc(struct parser_params *parser, size_t size)
10326 {
10327 size_t cnt = HEAPCNT(1, size);
10328 NODE *n = NEWHEAP();
10329 void *ptr = xmalloc(size);
10330
10331 return ADD2HEAP(n, cnt, ptr);
10332 }
10333
10334 void *
10335 rb_parser_calloc(struct parser_params *parser, size_t nelem, size_t size)
10336 {
10337 size_t cnt = HEAPCNT(nelem, size);
10338 NODE *n = NEWHEAP();
10339 void *ptr = xcalloc(nelem, size);
10340
10341 return ADD2HEAP(n, cnt, ptr);
10342 }
10343
10344 void *
10345 rb_parser_realloc(struct parser_params *parser, void *ptr, size_t size)
10346 {
10347 NODE *n;
10348 size_t cnt = HEAPCNT(1, size);
10349
10350 if (ptr && (n = parser->heap) != NULL) {
10351 do {
10352 if (n->u1.node == ptr) {
10353 n->u1.node = ptr = xrealloc(ptr, size);
10354 if (n->u3.cnt) n->u3.cnt = cnt;
10355 return ptr;
10356 }
10357 } while ((n = n->u2.node) != NULL);
10358 }
10359 n = NEWHEAP();
10360 ptr = xrealloc(ptr, size);
10361 return ADD2HEAP(n, cnt, ptr);
10362 }
10363
10364 void
10365 rb_parser_free(struct parser_params *parser, void *ptr)
10366 {
10367 NODE **prev = &parser->heap, *n;
10368
10369 while ((n = *prev) != NULL) {
10370 if (n->u1.node == ptr) {
10371 *prev = n->u2.node;
10372 rb_gc_force_recycle((VALUE)n);
10373 break;
10374 }
10375 prev = &n->u2.node;
10376 }
10377 xfree(ptr);
10378 }
10379 #endif
10380 #endif
10381
10382 #ifdef RIPPER
10383 #ifdef RIPPER_DEBUG
10384 extern int rb_is_pointer_to_heap(VALUE);
10385
10386
10387 static VALUE
10388 ripper_validate_object(VALUE self, VALUE x)
10389 {
10390 if (x == Qfalse) return x;
10391 if (x == Qtrue) return x;
10392 if (x == Qnil) return x;
10393 if (x == Qundef)
10394 rb_raise(rb_eArgError, "Qundef given");
10395 if (FIXNUM_P(x)) return x;
10396 if (SYMBOL_P(x)) return x;
10397 if (!rb_is_pointer_to_heap(x))
10398 rb_raise(rb_eArgError, "invalid pointer: %p", x);
10399 switch (TYPE(x)) {
10400 case T_STRING:
10401 case T_OBJECT:
10402 case T_ARRAY:
10403 case T_BIGNUM:
10404 case T_FLOAT:
10405 return x;
10406 case T_NODE:
10407 if (nd_type(x) != NODE_LASGN) {
10408 rb_raise(rb_eArgError, "NODE given: %p", x);
10409 }
10410 return ((NODE *)x)->nd_rval;
10411 default:
10412 rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)",
10413 x, rb_obj_classname(x));
10414 }
10415 return x;
10416 }
10417 #endif
10418
10419 #define validate(x) ((x) = get_value(x))
10420
10421 static VALUE
10422 ripper_dispatch0(struct parser_params *parser, ID mid)
10423 {
10424 return rb_funcall(parser->value, mid, 0);
10425 }
10426
10427 static VALUE
10428 ripper_dispatch1(struct parser_params *parser, ID mid, VALUE a)
10429 {
10430 validate(a);
10431 return rb_funcall(parser->value, mid, 1, a);
10432 }
10433
10434 static VALUE
10435 ripper_dispatch2(struct parser_params *parser, ID mid, VALUE a, VALUE b)
10436 {
10437 validate(a);
10438 validate(b);
10439 return rb_funcall(parser->value, mid, 2, a, b);
10440 }
10441
10442 static VALUE
10443 ripper_dispatch3(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c)
10444 {
10445 validate(a);
10446 validate(b);
10447 validate(c);
10448 return rb_funcall(parser->value, mid, 3, a, b, c);
10449 }
10450
10451 static VALUE
10452 ripper_dispatch4(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d)
10453 {
10454 validate(a);
10455 validate(b);
10456 validate(c);
10457 validate(d);
10458 return rb_funcall(parser->value, mid, 4, a, b, c, d);
10459 }
10460
10461 static VALUE
10462 ripper_dispatch5(struct parser_params *parser, ID mid, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e)
10463 {
10464 validate(a);
10465 validate(b);
10466 validate(c);
10467 validate(d);
10468 validate(e);
10469 return rb_funcall(parser->value, mid, 5, a, b, c, d, e);
10470 }
10471
10472 static const struct kw_assoc {
10473 ID id;
10474 const char *name;
10475 } keyword_to_name[] = {
10476 {keyword_class, "class"},
10477 {keyword_module, "module"},
10478 {keyword_def, "def"},
10479 {keyword_undef, "undef"},
10480 {keyword_begin, "begin"},
10481 {keyword_rescue, "rescue"},
10482 {keyword_ensure, "ensure"},
10483 {keyword_end, "end"},
10484 {keyword_if, "if"},
10485 {keyword_unless, "unless"},
10486 {keyword_then, "then"},
10487 {keyword_elsif, "elsif"},
10488 {keyword_else, "else"},
10489 {keyword_case, "case"},
10490 {keyword_when, "when"},
10491 {keyword_while, "while"},
10492 {keyword_until, "until"},
10493 {keyword_for, "for"},
10494 {keyword_break, "break"},
10495 {keyword_next, "next"},
10496 {keyword_redo, "redo"},
10497 {keyword_retry, "retry"},
10498 {keyword_in, "in"},
10499 {keyword_do, "do"},
10500 {keyword_do_cond, "do"},
10501 {keyword_do_block, "do"},
10502 {keyword_return, "return"},
10503 {keyword_yield, "yield"},
10504 {keyword_super, "super"},
10505 {keyword_self, "self"},
10506 {keyword_nil, "nil"},
10507 {keyword_true, "true"},
10508 {keyword_false, "false"},
10509 {keyword_and, "and"},
10510 {keyword_or, "or"},
10511 {keyword_not, "not"},
10512 {modifier_if, "if"},
10513 {modifier_unless, "unless"},
10514 {modifier_while, "while"},
10515 {modifier_until, "until"},
10516 {modifier_rescue, "rescue"},
10517 {keyword_alias, "alias"},
10518 {keyword_defined, "defined?"},
10519 {keyword_BEGIN, "BEGIN"},
10520 {keyword_END, "END"},
10521 {keyword__LINE__, "__LINE__"},
10522 {keyword__FILE__, "__FILE__"},
10523 {keyword__ENCODING__, "__ENCODING__"},
10524 {0, NULL}
10525 };
10526
10527 static const char*
10528 keyword_id_to_str(ID id)
10529 {
10530 const struct kw_assoc *a;
10531
10532 for (a = keyword_to_name; a->id; a++) {
10533 if (a->id == id)
10534 return a->name;
10535 }
10536 return NULL;
10537 }
10538
10539 #undef ripper_id2sym
10540 static VALUE
10541 ripper_id2sym(ID id)
10542 {
10543 const char *name;
10544 char buf[8];
10545
10546 if (id <= 256) {
10547 buf[0] = (char)id;
10548 buf[1] = '\0';
10549 return ID2SYM(rb_intern2(buf, 1));
10550 }
10551 if ((name = keyword_id_to_str(id))) {
10552 return ID2SYM(rb_intern(name));
10553 }
10554 switch (id) {
10555 case tOROP:
10556 name = "||";
10557 break;
10558 case tANDOP:
10559 name = "&&";
10560 break;
10561 default:
10562 name = rb_id2name(id);
10563 if (!name) {
10564 rb_bug("cannot convert ID to string: %ld", (unsigned long)id);
10565 }
10566 return ID2SYM(id);
10567 }
10568 return ID2SYM(rb_intern(name));
10569 }
10570
10571 static ID
10572 ripper_get_id(VALUE v)
10573 {
10574 NODE *nd;
10575 if (!RB_TYPE_P(v, T_NODE)) return 0;
10576 nd = (NODE *)v;
10577 if (nd_type(nd) != NODE_LASGN) return 0;
10578 return nd->nd_vid;
10579 }
10580
10581 static VALUE
10582 ripper_get_value(VALUE v)
10583 {
10584 NODE *nd;
10585 if (v == Qundef) return Qnil;
10586 if (!RB_TYPE_P(v, T_NODE)) return v;
10587 nd = (NODE *)v;
10588 if (nd_type(nd) != NODE_LASGN) return Qnil;
10589 return nd->nd_rval;
10590 }
10591
10592 static void
10593 ripper_compile_error(struct parser_params *parser, const char *fmt, ...)
10594 {
10595 VALUE str;
10596 va_list args;
10597
10598 va_start(args, fmt);
10599 str = rb_vsprintf(fmt, args);
10600 va_end(args);
10601 rb_funcall(parser->value, rb_intern("compile_error"), 1, str);
10602 }
10603
10604 static void
10605 ripper_warn0(struct parser_params *parser, const char *fmt)
10606 {
10607 rb_funcall(parser->value, rb_intern("warn"), 1, STR_NEW2(fmt));
10608 }
10609
10610 static void
10611 ripper_warnI(struct parser_params *parser, const char *fmt, int a)
10612 {
10613 rb_funcall(parser->value, rb_intern("warn"), 2,
10614 STR_NEW2(fmt), INT2NUM(a));
10615 }
10616
10617 #if 0
10618 static void
10619 ripper_warnS(struct parser_params *parser, const char *fmt, const char *str)
10620 {
10621 rb_funcall(parser->value, rb_intern("warn"), 2,
10622 STR_NEW2(fmt), STR_NEW2(str));
10623 }
10624 #endif
10625
10626 static void
10627 ripper_warning0(struct parser_params *parser, const char *fmt)
10628 {
10629 rb_funcall(parser->value, rb_intern("warning"), 1, STR_NEW2(fmt));
10630 }
10631
10632 static void
10633 ripper_warningS(struct parser_params *parser, const char *fmt, const char *str)
10634 {
10635 rb_funcall(parser->value, rb_intern("warning"), 2,
10636 STR_NEW2(fmt), STR_NEW2(str));
10637 }
10638
10639 static VALUE
10640 ripper_lex_get_generic(struct parser_params *parser, VALUE src)
10641 {
10642 return rb_funcall(src, ripper_id_gets, 0);
10643 }
10644
10645 static VALUE
10646 ripper_s_allocate(VALUE klass)
10647 {
10648 struct parser_params *p;
10649 VALUE self;
10650
10651 p = ALLOC_N(struct parser_params, 1);
10652 MEMZERO(p, struct parser_params, 1);
10653 self = TypedData_Wrap_Struct(klass, &parser_data_type, p);
10654 p->value = self;
10655 return self;
10656 }
10657
10658 #define ripper_initialized_p(r) ((r)->parser_lex_input != 0)
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670 static VALUE
10671 ripper_initialize(int argc, VALUE *argv, VALUE self)
10672 {
10673 struct parser_params *parser;
10674 VALUE src, fname, lineno;
10675
10676 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10677 rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
10678 if (rb_obj_respond_to(src, ripper_id_gets, 0)) {
10679 parser->parser_lex_gets = ripper_lex_get_generic;
10680 }
10681 else {
10682 StringValue(src);
10683 parser->parser_lex_gets = lex_get_str;
10684 }
10685 parser->parser_lex_input = src;
10686 parser->eofp = Qfalse;
10687 if (NIL_P(fname)) {
10688 fname = STR_NEW2("(ripper)");
10689 }
10690 else {
10691 StringValue(fname);
10692 }
10693 parser_initialize(parser);
10694
10695 parser->parser_ruby_sourcefile_string = fname;
10696 parser->parser_ruby_sourcefile = RSTRING_PTR(fname);
10697 parser->parser_ruby_sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
10698
10699 return Qnil;
10700 }
10701
10702 struct ripper_args {
10703 struct parser_params *parser;
10704 int argc;
10705 VALUE *argv;
10706 };
10707
10708 static VALUE
10709 ripper_parse0(VALUE parser_v)
10710 {
10711 struct parser_params *parser;
10712
10713 TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, parser);
10714 parser_prepare(parser);
10715 ripper_yyparse((void*)parser);
10716 return parser->result;
10717 }
10718
10719 static VALUE
10720 ripper_ensure(VALUE parser_v)
10721 {
10722 struct parser_params *parser;
10723
10724 TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, parser);
10725 parser->parsing_thread = Qnil;
10726 return Qnil;
10727 }
10728
10729
10730
10731
10732
10733
10734
10735 static VALUE
10736 ripper_parse(VALUE self)
10737 {
10738 struct parser_params *parser;
10739
10740 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10741 if (!ripper_initialized_p(parser)) {
10742 rb_raise(rb_eArgError, "method called for uninitialized object");
10743 }
10744 if (!NIL_P(parser->parsing_thread)) {
10745 if (parser->parsing_thread == rb_thread_current())
10746 rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
10747 else
10748 rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
10749 }
10750 parser->parsing_thread = rb_thread_current();
10751 rb_ensure(ripper_parse0, self, ripper_ensure, self);
10752
10753 return parser->result;
10754 }
10755
10756
10757
10758
10759
10760
10761
10762
10763 static VALUE
10764 ripper_column(VALUE self)
10765 {
10766 struct parser_params *parser;
10767 long col;
10768
10769 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10770 if (!ripper_initialized_p(parser)) {
10771 rb_raise(rb_eArgError, "method called for uninitialized object");
10772 }
10773 if (NIL_P(parser->parsing_thread)) return Qnil;
10774 col = parser->tokp - parser->parser_lex_pbeg;
10775 return LONG2NUM(col);
10776 }
10777
10778
10779
10780
10781
10782
10783
10784 static VALUE
10785 ripper_filename(VALUE self)
10786 {
10787 struct parser_params *parser;
10788
10789 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10790 if (!ripper_initialized_p(parser)) {
10791 rb_raise(rb_eArgError, "method called for uninitialized object");
10792 }
10793 return parser->parser_ruby_sourcefile_string;
10794 }
10795
10796
10797
10798
10799
10800
10801
10802
10803 static VALUE
10804 ripper_lineno(VALUE self)
10805 {
10806 struct parser_params *parser;
10807
10808 TypedData_Get_Struct(self, struct parser_params, &parser_data_type, parser);
10809 if (!ripper_initialized_p(parser)) {
10810 rb_raise(rb_eArgError, "method called for uninitialized object");
10811 }
10812 if (NIL_P(parser->parsing_thread)) return Qnil;
10813 return INT2NUM(parser->parser_ruby_sourceline);
10814 }
10815
10816 #ifdef RIPPER_DEBUG
10817
10818 static VALUE
10819 ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
10820 {
10821 StringValue(msg);
10822 if (obj == Qundef) {
10823 rb_raise(rb_eArgError, "%s", RSTRING_PTR(msg));
10824 }
10825 return Qnil;
10826 }
10827
10828
10829 static VALUE
10830 ripper_value(VALUE self, VALUE obj)
10831 {
10832 return ULONG2NUM(obj);
10833 }
10834 #endif
10835
10836
10837 void
10838 InitVM_ripper(void)
10839 {
10840 parser_data_type.parent = RTYPEDDATA_TYPE(rb_parser_new());
10841 }
10842
10843 void
10844 Init_ripper(void)
10845 {
10846 VALUE Ripper;
10847
10848 InitVM(ripper);
10849 Ripper = rb_define_class("Ripper", rb_cObject);
10850 rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
10851 rb_define_alloc_func(Ripper, ripper_s_allocate);
10852 rb_define_method(Ripper, "initialize", ripper_initialize, -1);
10853 rb_define_method(Ripper, "parse", ripper_parse, 0);
10854 rb_define_method(Ripper, "column", ripper_column, 0);
10855 rb_define_method(Ripper, "filename", ripper_filename, 0);
10856 rb_define_method(Ripper, "lineno", ripper_lineno, 0);
10857 rb_define_method(Ripper, "end_seen?", rb_parser_end_seen_p, 0);
10858 rb_define_method(Ripper, "encoding", rb_parser_encoding, 0);
10859 rb_define_method(Ripper, "yydebug", rb_parser_get_yydebug, 0);
10860 rb_define_method(Ripper, "yydebug=", rb_parser_set_yydebug, 1);
10861 #ifdef RIPPER_DEBUG
10862 rb_define_method(rb_mKernel, "assert_Qundef", ripper_assert_Qundef, 2);
10863 rb_define_method(rb_mKernel, "rawVALUE", ripper_value, 1);
10864 rb_define_method(rb_mKernel, "validate_object", ripper_validate_object, 1);
10865 #endif
10866
10867 ripper_id_gets = rb_intern("gets");
10868 ripper_init_eventids1(Ripper);
10869 ripper_init_eventids2(Ripper);
10870
10871 (void)rb_intern("||");
10872 (void)rb_intern("&&");
10873
10874 # if 0
10875
10876
10877
10878
10879
10880
10881
10882 rb_define_global_const("SCRIPT_LINES__", Qnil);
10883 #endif
10884
10885 }
10886 #endif
10887