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