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