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