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