Ruby  2.0.0p451(2014-02-24revision45167)
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
parse.y File Reference
#include "ruby/ruby.h"
#include "ruby/st.h"
#include "ruby/encoding.h"
#include "internal.h"
#include "node.h"
#include "parse.h"
#include "id.h"
#include "regenc.h"
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include "probes.h"
#include "id.c"
#include "ruby/regex.h"
#include "ruby/util.h"
#include "lex.c"
Include dependency graph for parse.y:

Go to the source code of this file.

Data Structures

struct  vtable
 
struct  local_vars
 
struct  token_info
 
struct  parser_params
 

Macros

#define PARSER_DEBUG   0
 
#define YYDEBUG   1
 
#define YYERROR_VERBOSE   1
 
#define YYSTACK_USE_ALLOCA   0
 
#define numberof(array)   (int)(sizeof(array) / sizeof((array)[0]))
 
#define YYMALLOC(size)   rb_parser_malloc(parser, (size))
 
#define YYREALLOC(ptr, size)   rb_parser_realloc(parser, (ptr), (size))
 
#define YYCALLOC(nelem, size)   rb_parser_calloc(parser, (nelem), (size))
 
#define YYFREE(ptr)   rb_parser_free(parser, (ptr))
 
#define malloc   YYMALLOC
 
#define realloc   YYREALLOC
 
#define calloc   YYCALLOC
 
#define free   YYFREE
 
#define REGISTER_SYMID(id, name)   register_symid((id), (name), strlen(name), enc)
 
#define is_notop_id(id)   ((id)>tLAST_OP_ID)
 
#define is_local_id(id)   (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
 
#define is_global_id(id)   (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
 
#define is_instance_id(id)   (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
 
#define is_attrset_id(id)   (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
 
#define is_const_id(id)   (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
 
#define is_class_id(id)   (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
 
#define is_junk_id(id)   (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
 
#define id_type(id)   (is_notop_id(id) ? (int)((id)&ID_SCOPE_MASK) : -1)
 
#define is_asgn_or_id(id)
 
#define DEF_EXPR(n)   EXPR_##n = (1 << EXPR_##n##_bit)
 
#define IS_lex_state_for(x, ls)   ((x) & (ls))
 
#define IS_lex_state(ls)   IS_lex_state_for(lex_state, (ls))
 
#define BITSTACK_PUSH(stack, n)   ((stack) = ((stack)<<1)|((n)&1))
 
#define BITSTACK_POP(stack)   ((stack) = (stack) >> 1)
 
#define BITSTACK_LEXPOP(stack)   ((stack) = ((stack) >> 1) | ((stack) & 1))
 
#define BITSTACK_SET_P(stack)   ((stack)&1)
 
#define COND_PUSH(n)   BITSTACK_PUSH(cond_stack, (n))
 
#define COND_POP()   BITSTACK_POP(cond_stack)
 
#define COND_LEXPOP()   BITSTACK_LEXPOP(cond_stack)
 
#define COND_P()   BITSTACK_SET_P(cond_stack)
 
#define CMDARG_PUSH(n)   BITSTACK_PUSH(cmdarg_stack, (n))
 
#define CMDARG_POP()   BITSTACK_POP(cmdarg_stack)
 
#define CMDARG_LEXPOP()   BITSTACK_LEXPOP(cmdarg_stack)
 
#define CMDARG_P()   BITSTACK_SET_P(cmdarg_stack)
 
#define DVARS_INHERIT   ((void*)1)
 
#define DVARS_TOPSCOPE   NULL
 
#define DVARS_SPECIAL_P(tbl)   (!POINTER_P(tbl))
 
#define POINTER_P(val)   ((VALUE)(val) & ~(VALUE)3)
 
#define VTBL_DEBUG   0
 
#define STR_NEW(p, n)   rb_enc_str_new((p),(n),current_enc)
 
#define STR_NEW0()   rb_enc_str_new(0,0,current_enc)
 
#define STR_NEW2(p)   rb_enc_str_new((p),strlen(p),current_enc)
 
#define STR_NEW3(p, n, e, func)   parser_str_new((p),(n),(e),(func),current_enc)
 
#define ENC_SINGLE(cr)   ((cr)==ENC_CODERANGE_7BIT)
 
#define TOK_INTERN(mb)   rb_intern3(tok(), toklen(), current_enc)
 
#define yyerror(msg)   parser_yyerror(parser, (msg))
 
#define lex_strterm   (parser->parser_lex_strterm)
 
#define lex_state   (parser->parser_lex_state)
 
#define cond_stack   (parser->parser_cond_stack)
 
#define cmdarg_stack   (parser->parser_cmdarg_stack)
 
#define class_nest   (parser->parser_class_nest)
 
#define paren_nest   (parser->parser_paren_nest)
 
#define lpar_beg   (parser->parser_lpar_beg)
 
#define brace_nest   (parser->parser_brace_nest)
 
#define in_single   (parser->parser_in_single)
 
#define in_def   (parser->parser_in_def)
 
#define compile_for_eval   (parser->parser_compile_for_eval)
 
#define cur_mid   (parser->parser_cur_mid)
 
#define in_defined   (parser->parser_in_defined)
 
#define tokenbuf   (parser->parser_tokenbuf)
 
#define tokidx   (parser->parser_tokidx)
 
#define toksiz   (parser->parser_toksiz)
 
#define tokline   (parser->parser_tokline)
 
#define lex_input   (parser->parser_lex_input)
 
#define lex_lastline   (parser->parser_lex_lastline)
 
#define lex_nextline   (parser->parser_lex_nextline)
 
#define lex_pbeg   (parser->parser_lex_pbeg)
 
#define lex_p   (parser->parser_lex_p)
 
#define lex_pend   (parser->parser_lex_pend)
 
#define heredoc_end   (parser->parser_heredoc_end)
 
#define command_start   (parser->parser_command_start)
 
#define deferred_nodes   (parser->parser_deferred_nodes)
 
#define lex_gets_ptr   (parser->parser_lex_gets_ptr)
 
#define lex_gets   (parser->parser_lex_gets)
 
#define lvtbl   (parser->parser_lvtbl)
 
#define ruby__end__seen   (parser->parser_ruby__end__seen)
 
#define ruby_sourceline   (parser->parser_ruby_sourceline)
 
#define ruby_sourcefile   (parser->parser_ruby_sourcefile)
 
#define current_enc   (parser->enc)
 
#define yydebug   (parser->parser_yydebug)
 
#define ruby_eval_tree   (parser->parser_eval_tree)
 
#define ruby_eval_tree_begin   (parser->parser_eval_tree_begin)
 
#define ruby_debug_lines   (parser->debug_lines)
 
#define ruby_coverage   (parser->coverage)
 
#define yyparse   ruby_yyparse
 
#define rb_node_newnode(type, a1, a2, a3)   node_newnode(parser, (type), (a1), (a2), (a3))
 
#define cond(node)   cond_gen(parser, (node))
 
#define logop(type, node1, node2)   logop_gen(parser, (type), (node1), (node2))
 
#define value_expr(node)   value_expr_gen(parser, (node) = remove_begin(node))
 
#define void_expr0(node)   void_expr_gen(parser, (node))
 
#define void_expr(node)   void_expr0((node) = remove_begin(node))
 
#define void_stmts(node)   void_stmts_gen(parser, (node))
 
#define reduce_nodes(n)   reduce_nodes_gen(parser,(n))
 
#define block_dup_check(n1, n2)   block_dup_check_gen(parser,(n1),(n2))
 
#define block_append(h, t)   block_append_gen(parser,(h),(t))
 
#define list_append(l, i)   list_append_gen(parser,(l),(i))
 
#define list_concat(h, t)   list_concat_gen(parser,(h),(t))
 
#define arg_append(h, t)   arg_append_gen(parser,(h),(t))
 
#define arg_concat(h, t)   arg_concat_gen(parser,(h),(t))
 
#define literal_concat(h, t)   literal_concat_gen(parser,(h),(t))
 
#define new_evstr(n)   new_evstr_gen(parser,(n))
 
#define evstr2dstr(n)   evstr2dstr_gen(parser,(n))
 
#define call_bin_op(recv, id, arg1)   call_bin_op_gen(parser, (recv),(id),(arg1))
 
#define call_uni_op(recv, id)   call_uni_op_gen(parser, (recv),(id))
 
#define new_args(f, o, r, p, t)   new_args_gen(parser, (f),(o),(r),(p),(t))
 
#define new_args_tail(k, kr, b)   new_args_tail_gen(parser, (k),(kr),(b))
 
#define ret_args(node)   ret_args_gen(parser, (node))
 
#define new_yield(node)   new_yield_gen(parser, (node))
 
#define dsym_node(node)   dsym_node_gen(parser, (node))
 
#define gettable(id)   gettable_gen(parser,(id))
 
#define assignable(id, node)   assignable_gen(parser, (id), (node))
 
#define aryset(node1, node2)   aryset_gen(parser, (node1), (node2))
 
#define attrset(node, id)   attrset_gen(parser, (node), (id))
 
#define rb_backref_error(n)   rb_backref_error_gen(parser,(n))
 
#define node_assign(node1, node2)   node_assign_gen(parser, (node1), (node2))
 
#define new_attr_op_assign(lhs, type, attr, op, rhs)   new_attr_op_assign_gen(parser, (lhs), (attr), (op), (rhs))
 
#define new_const_op_assign(lhs, op, rhs)   new_const_op_assign_gen(parser, (lhs), (op), (rhs))
 
#define match_op(node1, node2)   match_op_gen(parser, (node1), (node2))
 
#define local_tbl()   local_tbl_gen(parser)
 
#define reg_compile(str, options)   reg_compile_gen(parser, (str), (options))
 
#define reg_fragment_setenc(str, options)   reg_fragment_setenc_gen(parser, (str), (options))
 
#define reg_fragment_check(str, options)   reg_fragment_check_gen(parser, (str), (options))
 
#define reg_named_capture_assign(regexp, match)   reg_named_capture_assign_gen(parser,(regexp),(match))
 
#define get_id(id)   (id)
 
#define get_value(val)   (val)
 
#define new_op_assign(lhs, op, rhs)   new_op_assign_gen(parser, (lhs), (op), (rhs))
 
#define formal_argument(id)   formal_argument_gen(parser, (id))
 
#define shadowing_lvar(name)   shadowing_lvar_gen(parser, (name))
 
#define new_bv(id)   new_bv_gen(parser, (id))
 
#define local_push(top)   local_push_gen(parser,(top))
 
#define local_pop()   local_pop_gen(parser)
 
#define local_var(id)   local_var_gen(parser, (id))
 
#define arg_var(id)   arg_var_gen(parser, (id))
 
#define local_id(id)   local_id_gen(parser, (id))
 
#define internal_id()   internal_id_gen(parser)
 
#define dyna_push()   dyna_push_gen(parser)
 
#define dyna_pop(node)   dyna_pop_gen(parser, (node))
 
#define dyna_in_block()   dyna_in_block_gen(parser)
 
#define dyna_var(id)   local_var(id)
 
#define dvar_defined(id)   dvar_defined_gen(parser, (id), 0)
 
#define dvar_defined_get(id)   dvar_defined_gen(parser, (id), 1)
 
#define dvar_curr(id)   dvar_curr_gen(parser, (id))
 
#define lvar_defined(id)   lvar_defined_gen(parser, (id))
 
#define RE_OPTION_ONCE   (1<<16)
 
#define RE_OPTION_ENCODING_SHIFT   8
 
#define RE_OPTION_ENCODING(e)   (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)
 
#define RE_OPTION_ENCODING_IDX(o)   (((o)>>RE_OPTION_ENCODING_SHIFT)&0xff)
 
#define RE_OPTION_ENCODING_NONE(o)   ((o)&RE_OPTION_ARG_ENCODING_NONE)
 
#define RE_OPTION_MASK   0xff
 
#define RE_OPTION_ARG_ENCODING_NONE   32
 
#define NODE_STRTERM   NODE_ZARRAY /* nothing to gc */
 
#define NODE_HEREDOC   NODE_ARRAY /* 1, 3 to gc */
 
#define SIGN_EXTEND(x, n)   (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))
 
#define nd_func   u1.id
 
#define nd_term(node)   SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)
 
#define nd_paren(node)   (char)((node)->u2.id >> CHAR_BIT*2)
 
#define nd_nest   u3.cnt
 
#define Qnone   0
 
#define ifndef_ripper(x)   (x)
 
#define rb_warn0(fmt)   rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt))
 
#define rb_warnI(fmt, a)   rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))
 
#define rb_warnS(fmt, a)   rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))
 
#define rb_warn4S(file, line, fmt, a)   rb_compile_warn((file), (line), (fmt), (a))
 
#define rb_warning0(fmt)   rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt))
 
#define rb_warningS(fmt, a)   rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt), (a))
 
#define rb_compile_error   rb_compile_error_with_enc
 
#define compile_error   parser->nerr++,rb_compile_error_with_enc
 
#define PARSER_ARG   ruby_sourcefile, ruby_sourceline, current_enc,
 
#define token_info_push(token)   (RTEST(ruby_verbose) ? token_info_push(parser, (token)) : (void)0)
 
#define token_info_pop(token)   (RTEST(ruby_verbose) ? token_info_pop(parser, (token)) : (void)0)
 
#define yylval   (*((YYSTYPE*)(parser->parser_yylval)))
 
#define nextc()   parser_nextc(parser)
 
#define pushback(c)   parser_pushback(parser, (c))
 
#define newtok()   parser_newtok(parser)
 
#define tokspace(n)   parser_tokspace(parser, (n))
 
#define tokadd(c)   parser_tokadd(parser, (c))
 
#define tok_hex(numlen)   parser_tok_hex(parser, (numlen))
 
#define read_escape(flags, e)   parser_read_escape(parser, (flags), (e))
 
#define tokadd_escape(e)   parser_tokadd_escape(parser, (e))
 
#define regx_options()   parser_regx_options(parser)
 
#define tokadd_string(f, t, p, n, e)   parser_tokadd_string(parser,(f),(t),(p),(n),(e))
 
#define parse_string(n)   parser_parse_string(parser,(n))
 
#define tokaddmbc(c, enc)   parser_tokaddmbc(parser, (c), (enc))
 
#define here_document(n)   parser_here_document(parser,(n))
 
#define heredoc_identifier()   parser_heredoc_identifier(parser)
 
#define heredoc_restore(n)   parser_heredoc_restore(parser,(n))
 
#define whole_match_p(e, l, i)   parser_whole_match_p(parser,(e),(l),(i))
 
#define set_yylval_str(x)   (yylval.node = NEW_STR(x))
 
#define set_yylval_num(x)   (yylval.num = (x))
 
#define set_yylval_id(x)   (yylval.id = (x))
 
#define set_yylval_name(x)   (yylval.id = (x))
 
#define set_yylval_literal(x)   (yylval.node = NEW_LIT(x))
 
#define set_yylval_node(x)   (yylval.node = (x))
 
#define yylval_id()   (yylval.id)
 
#define ripper_flush(p)   (void)(p)
 
#define SIGN_EXTEND_CHAR(c)   ((((unsigned char)(c)) ^ 128) - 128)
 
#define parser_encoding_name()   (current_enc->name)
 
#define parser_mbclen()   mbclen((lex_p-1),lex_pend,current_enc)
 
#define parser_precise_mbclen()   rb_enc_precise_mbclen((lex_p-1),lex_pend,current_enc)
 
#define is_identchar(p, e, enc)   (rb_enc_isalnum(*(p),(enc)) || (*(p)) == '_' || !ISASCII(*(p)))
 
#define parser_is_identchar()   (!parser->eofp && is_identchar((lex_p-1),lex_pend,current_enc))
 
#define parser_isascii()   ISASCII(*(lex_p-1))
 
#define STR_FUNC_ESCAPE   0x01
 
#define STR_FUNC_EXPAND   0x02
 
#define STR_FUNC_REGEXP   0x04
 
#define STR_FUNC_QWORDS   0x08
 
#define STR_FUNC_SYMBOL   0x10
 
#define STR_FUNC_INDENT   0x20
 
#define lex_goto_eol(parser)   ((parser)->parser_lex_p = (parser)->parser_lex_pend)
 
#define lex_eol_p()   (lex_p >= lex_pend)
 
#define peek(c)   peek_n((c), 0)
 
#define peek_n(c, n)   (lex_p+(n) < lex_pend && (c) == (unsigned char)lex_p[n])
 
#define was_bol()   (lex_p == lex_pbeg + 1)
 
#define tokfix()   (tokenbuf[tokidx]='\0')
 
#define tok()   tokenbuf
 
#define toklen()   tokidx
 
#define toklast()   (tokidx>0?tokenbuf[tokidx-1]:0)
 
#define tokcopy(n)   memcpy(tokspace(n), lex_p - (n), (n))
 
#define ESCAPE_CONTROL   1
 
#define ESCAPE_META   2
 
#define tokadd_mbchar(c)   parser_tokadd_mbchar(parser, (c))
 
#define mixed_error(enc1, enc2)
 
#define mixed_escape(beg, enc1, enc2)
 
#define NEW_STRTERM(func, term, paren)   rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
 
#define flush_string_content(enc)   ((void)(enc))
 
#define BIT(c, idx)   (((c) / 32 - 1 == idx) ? (1U << ((c) % 32)) : 0)
 
#define SPECIAL_PUNCT(idx)
 
#define dispatch_heredoc_end()   ((void)0)
 
#define arg_ambiguous()   (arg_ambiguous_gen(parser), 1)
 
#define str_copy(_s, _p, _n)
 
#define IS_ARG()   IS_lex_state(EXPR_ARG_ANY)
 
#define IS_END()   IS_lex_state(EXPR_END_ANY)
 
#define IS_BEG()   IS_lex_state(EXPR_BEG_ANY)
 
#define IS_SPCARG(c)   (IS_ARG() && space_seen && !ISSPACE(c))
 
#define IS_LABEL_POSSIBLE()   ((IS_lex_state(EXPR_BEG | EXPR_ENDFN) && !cmd_state) || IS_ARG())
 
#define IS_LABEL_SUFFIX(n)   (peek_n(':',(n)) && !peek_n(':', (n)+1))
 
#define IS_AFTER_OPERATOR()   IS_lex_state(EXPR_FNAME | EXPR_DOT)
 
#define ambiguous_operator(op, syn)
 
#define warn_balanced(op, syn)
 
#define no_digits()   do {yyerror("numeric literal without digits"); return 0;} while (0)
 
#define parser_warning(node, mesg)   parser_warning(parser, (node), (mesg))
 
#define parser_warn(node, mesg)   parser_warn(parser, (node), (mesg))
 
#define assignable_result(x)   (x)
 
#define LVAR_USED   ((ID)1 << (sizeof(ID) * CHAR_BIT - 1))
 
#define subnodes(n1, n2)
 
#define op_tbl_count   numberof(op_tbl)
 
#define ENABLE_SELECTOR_NAMESPACE   0
 
#define IDSET_ATTRSET_FOR_SYNTAX   ((1U<<ID_LOCAL)|(1U<<ID_CONST))
 
#define IDSET_ATTRSET_FOR_INTERN   (~(~0U<<(1<<ID_SCOPE_SHIFT)) & ~(1U<<ID_ATTRSET))
 
#define HEAPCNT(n, size)   ((n) * (size) / sizeof(YYSTYPE))
 
#define NEWHEAP()   rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)
 
#define ADD2HEAP(n, c, p)
 

Typedefs

typedef VALUE stack_type
 
typedef struct token_info token_info
 

Enumerations

enum  lex_state_bits {
  EXPR_BEG_bit, EXPR_END_bit, EXPR_ENDARG_bit, EXPR_ENDFN_bit,
  EXPR_ARG_bit, EXPR_CMDARG_bit, EXPR_MID_bit, EXPR_FNAME_bit,
  EXPR_DOT_bit, EXPR_CLASS_bit, EXPR_VALUE_bit, EXPR_MAX_STATE,
  EXPR_BEG_bit, EXPR_END_bit, EXPR_ENDARG_bit, EXPR_ENDFN_bit,
  EXPR_ARG_bit, EXPR_CMDARG_bit, EXPR_MID_bit, EXPR_FNAME_bit,
  EXPR_DOT_bit, EXPR_CLASS_bit, EXPR_VALUE_bit, EXPR_MAX_STATE,
  EXPR_BEG_bit, EXPR_END_bit, EXPR_ENDARG_bit, EXPR_ENDFN_bit,
  EXPR_ARG_bit, EXPR_CMDARG_bit, EXPR_MID_bit, EXPR_FNAME_bit,
  EXPR_DOT_bit, EXPR_CLASS_bit, EXPR_VALUE_bit, EXPR_MAX_STATE,
  EXPR_BEG_bit, EXPR_END_bit, EXPR_ENDARG_bit, EXPR_ENDFN_bit,
  EXPR_ARG_bit, EXPR_CMDARG_bit, EXPR_MID_bit, EXPR_FNAME_bit,
  EXPR_DOT_bit, EXPR_CLASS_bit, EXPR_VALUE_bit, EXPR_MAX_STATE
}
 
enum  lex_state_e {
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  EXPR_BEG_ANY = (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS), EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG), EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), EXPR_BEG_ANY = (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS),
  EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG), EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), EXPR_BEG_ANY = (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS), EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG),
  EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG), DEF_EXPR =(BEG),
  DEF_EXPR =(BEG), EXPR_BEG_ANY = (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS), EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG), EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN)
}
 

Functions

static ID register_symid_str (ID, VALUE)
 
static void Init_id (void)
 
static int vtable_size (const struct vtable *tbl)
 
static struct vtablevtable_alloc (struct vtable *prev)
 
static void vtable_free (struct vtable *tbl)
 
static void vtable_add (struct vtable *tbl, ID id)
 
static int vtable_included (const struct vtable *tbl, ID id)
 
static int parser_yyerror (struct parser_params *, const char *)
 
static int yylex (void *)
 
static NODEnode_newnode (struct parser_params *, enum node_type, VALUE, VALUE, VALUE)
 
static NODEcond_gen (struct parser_params *, NODE *)
 
static NODElogop_gen (struct parser_params *, enum node_type, NODE *, NODE *)
 
static NODEnewline_node (NODE *)
 
static void fixpos (NODE *, NODE *)
 
static int value_expr_gen (struct parser_params *, NODE *)
 
static void void_expr_gen (struct parser_params *, NODE *)
 
static NODEremove_begin (NODE *)
 
static void void_stmts_gen (struct parser_params *, NODE *)
 
static void reduce_nodes_gen (struct parser_params *, NODE **)
 
static void block_dup_check_gen (struct parser_params *, NODE *, NODE *)
 
static NODEblock_append_gen (struct parser_params *, NODE *, NODE *)
 
static NODElist_append_gen (struct parser_params *, NODE *, NODE *)
 
static NODElist_concat_gen (struct parser_params *, NODE *, NODE *)
 
static NODEarg_append_gen (struct parser_params *, NODE *, NODE *)
 
static NODEarg_concat_gen (struct parser_params *, NODE *, NODE *)
 
static NODEliteral_concat_gen (struct parser_params *, NODE *, NODE *)
 
static int literal_concat0 (struct parser_params *, VALUE, VALUE)
 
static NODEnew_evstr_gen (struct parser_params *, NODE *)
 
static NODEevstr2dstr_gen (struct parser_params *, NODE *)
 
static NODEsplat_array (NODE *)
 
static NODEcall_bin_op_gen (struct parser_params *, NODE *, ID, NODE *)
 
static NODEcall_uni_op_gen (struct parser_params *, NODE *, ID)
 
static NODEnew_args_gen (struct parser_params *, NODE *, NODE *, ID, NODE *, NODE *)
 
static NODEnew_args_tail_gen (struct parser_params *, NODE *, ID, ID)
 
static NODEnegate_lit (NODE *)
 
static NODEret_args_gen (struct parser_params *, NODE *)
 
static NODEarg_blk_pass (NODE *, NODE *)
 
static NODEnew_yield_gen (struct parser_params *, NODE *)
 
static NODEdsym_node_gen (struct parser_params *, NODE *)
 
static NODEgettable_gen (struct parser_params *, ID)
 
static NODEassignable_gen (struct parser_params *, ID, NODE *)
 
static NODEaryset_gen (struct parser_params *, NODE *, NODE *)
 
static NODEattrset_gen (struct parser_params *, NODE *, ID)
 
static void rb_backref_error_gen (struct parser_params *, NODE *)
 
static NODEnode_assign_gen (struct parser_params *, NODE *, NODE *)
 
static NODEnew_op_assign_gen (struct parser_params *parser, NODE *lhs, ID op, NODE *rhs)
 
static NODEnew_attr_op_assign_gen (struct parser_params *parser, NODE *lhs, ID attr, ID op, NODE *rhs)
 
static NODEnew_const_op_assign_gen (struct parser_params *parser, NODE *lhs, ID op, NODE *rhs)
 
static NODEmatch_op_gen (struct parser_params *, NODE *, NODE *)
 
static IDlocal_tbl_gen (struct parser_params *)
 
static void fixup_nodes (NODE **)
 
static VALUE reg_compile_gen (struct parser_params *, VALUE, int)
 
static void reg_fragment_setenc_gen (struct parser_params *, VALUE, int)
 
static int reg_fragment_check_gen (struct parser_params *, VALUE, int)
 
static NODEreg_named_capture_assign_gen (struct parser_params *parser, VALUE regexp, NODE *match)
 
static ID formal_argument_gen (struct parser_params *, ID)
 
static ID shadowing_lvar_gen (struct parser_params *, ID)
 
static void new_bv_gen (struct parser_params *, ID)
 
static void local_push_gen (struct parser_params *, int)
 
static void local_pop_gen (struct parser_params *)
 
static int local_var_gen (struct parser_params *, ID)
 
static int arg_var_gen (struct parser_params *, ID)
 
static int local_id_gen (struct parser_params *, ID)
 
static ID internal_id_gen (struct parser_params *)
 
static const struct vtabledyna_push_gen (struct parser_params *)
 
static void dyna_pop_gen (struct parser_params *, const struct vtable *)
 
static int dyna_in_block_gen (struct parser_params *)
 
static int dvar_defined_gen (struct parser_params *, ID, int)
 
static int dvar_curr_gen (struct parser_params *, ID)
 
static int lvar_defined_gen (struct parser_params *, ID)
 
static void token_info_push (struct parser_params *, const char *token)
 
static void token_info_pop (struct parser_params *, const char *token)
 
 if ($2)
 
 fixpos ($$, $1) = $3
 
 if (!$$)$$
 
 nd_set_line ($$,$< num >2)
 
 dyna_pop ($< vars >1)
 
fcall nd_set_line ($$, tokline)
 
 if (c== ')') lex_state
 
 if (IS_END()||ISSPACE(c))
 
 switch (c)
 
 if ((c=nextc())== '=')
 
 if (IS_SPCARG(c))
 
 warn_balanced ("/","regexp literal")
 

Variables

primary_value['opt_call_args
rbracket{$$=aryset($1,
$3);}|primary_value
'.'tIDENTIFIER{$$=attrset($1,
$3);}|primary_value tCOLON2
tIDENTIFIER{$$=attrset($1,
$3);}|primary_value
'.'tCONSTANT{$$=attrset($1,
$3);}|primary_value tCOLON2
tCONSTANT{if(in_def||in_single)
yyerror("dynamic constant
assignment");$$=NEW_CDECL(0,
0, NEW_COLON2($1,
$3));}|tCOLON3 tCONSTANT{if(in_def||in_single)
yyerror("dynamic constant
assignment");$$=NEW_CDECL(0,
0, NEW_COLON3($2));}|backref{rb_backref_error($1);$$=NEW_BEGIN(0);};lhs:user_variable{$$=assignable($1,
0);if(!$$)$$=NEW_BEGIN(0);}|keyword_variable{$$=assignable($1,
0);if(!$$)$$=NEW_BEGIN(0);}|primary_value
'['opt_call_args rbracket{$$=aryset($1,
$3);}|primary_value
'.'tIDENTIFIER{$$=attrset($1,
$3);}|primary_value tCOLON2
tIDENTIFIER{$$=attrset($1,
$3);}|primary_value
'.'tCONSTANT{$$=attrset($1,
$3);}|primary_value tCOLON2
tCONSTANT{if(in_def||in_single)
yyerror("dynamic constant
assignment");$$=NEW_CDECL(0,
0, NEW_COLON2($1,
$3));}|tCOLON3 tCONSTANT{if(in_def||in_single)
yyerror("dynamic constant
assignment");$$=NEW_CDECL(0,
0, NEW_COLON3($2));}|backref{rb_backref_error($1);$$=NEW_BEGIN(0);};cname:tIDENTIFIER{yyerror("class/module
name must be CONSTANT");}|tCONSTANT;cpath:tCOLON3
cname{$$=NEW_COLON3($2);}|cname{$$=NEW_COLON2(0,$$);}|primary_value
tCOLON2 cname{$$=NEW_COLON2($1,
$3);};fname:tIDENTIFIER|tCONSTANT|tFID|op{lex_state=EXPR_ENDFN;$$=$1;}|reswords{lex_state=EXPR_ENDFN;$$=$
< id >1;};fsym:fname|symbol;fitem:fsym{$$=NEW_LIT(ID2SYM($1));}|dsym;undef_list:fitem{$$=NEW_UNDEF($1);}|undef_list
','{lex_state=EXPR_FNAME;}fitem{$$=block_append($1,
NEW_UNDEF($4));};op:
'|'{ifndef_ripper($$=
'|');}| '^'{ifndef_ripper($$=
'^');}| '&'{ifndef_ripper($$=
'&');}|tCMP{ifndef_ripper($$=tCMP);}|tEQ{ifndef_ripper($$=tEQ);}|tEQQ{ifndef_ripper($$=tEQQ);}|tMATCH{ifndef_ripper($$=tMATCH);}|tNMATCH{ifndef_ripper($$=tNMATCH);}| '>
'{ifndef_ripper($$= '>
');}|tGEQ{ifndef_ripper($$=tGEQ);}| '
<'{ifndef_ripper($$= '
<');}|tLEQ{ifndef_ripper($$=tLEQ);}|tNEQ{ifndef_ripper($$=tNEQ);}|tLSHFT{ifndef_ripper($$=tLSHFT);}|tRSHFT{ifndef_ripper($$=tRSHFT);}|
'+'{ifndef_ripper($$=
'+');}| '-'{ifndef_ripper($$=
'-');}| '*'{ifndef_ripper($$=
'*');}|tSTAR{ifndef_ripper($$=
'*');}| '/'{ifndef_ripper($$=
'/');}| '%'{ifndef_ripper($$=
'%');}|tPOW{ifndef_ripper($$=tPOW);}|tDSTAR{ifndef_ripper($$=tDSTAR);}|
'!'{ifndef_ripper($$=
'!');}| '~'{ifndef_ripper($$=
'~');}|tUPLUS{ifndef_ripper($$=tUPLUS);}|tUMINUS{ifndef_ripper($$=tUMINUS);}|tAREF{ifndef_ripper($$=tAREF);}|tASET{ifndef_ripper($$=tASET);}|
'`'{ifndef_ripper($$=
'`');};reswords:keyword__LINE__|keyword__FILE__|keyword__ENCODING__|keyword_BEGIN|keyword_END|keyword_alias|keyword_and|keyword_begin|keyword_break|keyword_case|keyword_class|keyword_def|keyword_defined|keyword_do|keyword_else|keyword_elsif|keyword_end|keyword_ensure|keyword_false|keyword_for|keyword_in|keyword_module|keyword_next|keyword_nil|keyword_not|keyword_or|keyword_redo|keyword_rescue|keyword_retry|keyword_return|keyword_self|keyword_super|keyword_then|keyword_true|keyword_undef|keyword_when|keyword_yield|keyword_if|keyword_unless|keyword_while|keyword_until;arg:lhs
'='arg{value_expr($3);$$=node_assign($1,
$3);}|lhs '='arg
modifier_rescue arg{value_expr($3);$3=NEW_RESCUE($3,
NEW_RESBODY(0,
$5, 0), 0);$$=node_assign($1,
$3);}|var_lhs tOP_ASGN arg{value_expr($3);$$=new_op_assign($1,
$2, $3);}|var_lhs tOP_ASGN arg
modifier_rescue arg{value_expr($3);$3=NEW_RESCUE($3,
NEW_RESBODY(0,
$5, 0), 0);$$=new_op_assign($1,
$2, $3);}|primary_value
'['opt_call_args rbracket
tOP_ASGN arg{NODE *args;value_expr($6);if(!$3)
$3=NEW_ZARRAY();if(nd_type($3)==NODE_BLOCK_PASS){args=NEW_ARGSCAT($3,
$6);}else{args=arg_concat($3,
$6);}if($5==tOROP){$5=0;}else
if($5==tANDOP){$5=1;}$$=NEW_OP_ASGN1($1,
$5, args);fixpos($$,
$1);}|primary_value
'.'tIDENTIFIER tOP_ASGN arg{value_expr($5);$$=new_attr_op_assign($1,
ripper_id2sym('.'),
$3, $4, $5);}|primary_value
'.'tCONSTANT tOP_ASGN arg{value_expr($5);$$=new_attr_op_assign($1,
ripper_id2sym('.'),
$3, $4, $5);}|primary_value
tCOLON2 tIDENTIFIER tOP_ASGN
arg{value_expr($5);$$=new_attr_op_assign($1,
ripper_intern("::"),
$3, $4, $5);}|primary_value
tCOLON2 tCONSTANT tOP_ASGN arg{$$=NEW_COLON2($1,
$3);$$=new_const_op_assign($$,
$4, $5);}|tCOLON3 tCONSTANT
tOP_ASGN arg{$$=NEW_COLON3($2);$$=new_const_op_assign($$,
$3, $4);}|backref tOP_ASGN arg{rb_backref_error($1);$$=NEW_BEGIN(0);}|arg
tDOT2 arg{value_expr($1);value_expr($3);$$=NEW_DOT2($1,
$3);if(nd_type($1)==NODE_LIT
&&FIXNUM_P($1->nd_lit)&&nd_type($3)==NODE_LIT
&&FIXNUM_P($3->nd_lit)){deferred_nodes=list_append(deferred_nodes,$$);}}|arg
tDOT3 arg{value_expr($1);value_expr($3);$$=NEW_DOT3($1,
$3);if(nd_type($1)==NODE_LIT
&&FIXNUM_P($1->nd_lit)&&nd_type($3)==NODE_LIT
&&FIXNUM_P($3->nd_lit)){deferred_nodes=list_append(deferred_nodes,$$);}}|arg
'+'arg{$$=call_bin_op($1,
'+', $3);}|arg '-'arg{$$=call_bin_op($1,
'-', $3);}|arg '*'arg{$$=call_bin_op($1,
'*', $3);}|arg '/'arg{$$=call_bin_op($1,
'/', $3);}|arg '%'arg{$$=call_bin_op($1,
'%', $3);}|arg tPOW arg{$$=call_bin_op($1,
tPOW, $3);}|tUMINUS_NUM
tINTEGER tPOW arg{$$=NEW_CALL(call_bin_op($2,
tPOW, $4), tUMINUS,
0);}|tUMINUS_NUM tFLOAT tPOW
arg{$$=NEW_CALL(call_bin_op($2,
tPOW, $4), tUMINUS,
0);}|tUPLUS arg{$$=call_uni_op($2,
tUPLUS);}|tUMINUS arg{$$=call_uni_op($2,
tUMINUS);}|arg '|'arg{$$=call_bin_op($1,
'|', $3);}|arg '^'arg{$$=call_bin_op($1,
'^', $3);}|arg '&'arg{$$=call_bin_op($1,
'&', $3);}|arg tCMP arg{$$=call_bin_op($1,
tCMP, $3);}|arg '>'arg{$$=call_bin_op($1, '>
', $3);}|arg tGEQ arg{$$=call_bin_op($1,
tGEQ, $3);}|arg '<'arg{$$=call_bin_op($1, '
<', $3);}|arg tLEQ arg{$$=call_bin_op($1,
tLEQ, $3);}|arg tEQ arg{$$=call_bin_op($1,
tEQ, $3);}|arg tEQQ arg{$$=call_bin_op($1,
tEQQ, $3);}|arg tNEQ arg{$$=call_bin_op($1,
tNEQ, $3);}|arg tMATCH arg{$$=match_op($1,
$3);if(nd_type($1)==NODE_LIT
&&RB_TYPE_P($1->nd_lit,
T_REGEXP)){$$=reg_named_capture_assign($1->
nd_lit,$$);}}|arg tNMATCH arg{$$=call_bin_op($1,
tNMATCH, $3);}| '!'arg{$$=call_uni_op(cond($2),
'!');}| '~'arg{$$=call_uni_op($2,
'~');}|arg tLSHFT arg{$$=call_bin_op($1,
tLSHFT, $3);}|arg tRSHFT arg{$$=call_bin_op($1,
tRSHFT, $3);}|arg tANDOP arg{$$=logop(NODE_AND,
$1, $3);}|arg tOROP arg{$$=logop(NODE_OR,
$1, $3);}|keyword_defined
opt_nl{in_defined=1;}arg{in_defined=0;$$=NEW_DEFINED($4);}|arg
'?'arg opt_nl ':'arg{value_expr($1);$$=NEW_IF(cond($1),
$3, $6);fixpos($$,
$1);}|primary{$$=$1;};arg_value:arg{value_expr($1);$$=$1;if(!$$)$$=NEW_NIL();};aref_args:none|args
trailer{$$=$1;}|args ','assocs
trailer{$$=arg_append($1,
NEW_HASH($3));}|assocs trailer{$$=NEW_LIST(NEW_HASH($1));};paren_args:
'('opt_call_args rparen{$$=$2;};opt_paren_args:none|paren_args;opt_call_args:none|call_args|args
','{$$=$1;}|args ','assocs
','{$$=arg_append($1, NEW_HASH($3));}|assocs
','{$$=NEW_LIST(NEW_HASH($1));};call_args:command{value_expr($1);$$=NEW_LIST($1);}|args
opt_block_arg{$$=arg_blk_pass($1,
$2);}|assocs opt_block_arg{$$=NEW_LIST(NEW_HASH($1));$$=arg_blk_pass($$,
$2);}|args ','assocs
opt_block_arg{$$=arg_append($1,
NEW_HASH($3));$$=arg_blk_pass($$,
$4);}|block_arg;command_args:{$
< val > $=cmdarg_stack;CMDARG_PUSH(1);}call_args{cmdarg_stack=$
< val >
1;$$=$2;};block_arg:tAMPER
arg_value{$$=NEW_BLOCK_PASS($2);};opt_block_arg:
','block_arg{$$=$2;}|none{$$=0;};args:arg_value{$$=NEW_LIST($1);}|tSTAR
arg_value{$$=NEW_SPLAT($2);}|args
','arg_value{NODE *n1;if((n1=splat_array($1))!=0){$$=list_append(n1,
$3);}else{$$=arg_append($1,
$3);}}|args ','tSTAR arg_value{NODE
*n1;if((nd_type($4)==NODE_ARRAY)&&(n1=splat_array($1))!=0){$$=list_concat(n1,
$4);}else{$$=arg_concat($1,
$4);}};mrhs:args ','arg_value{NODE
*n1;if((n1=splat_array($1))!=0){$$=list_append(n1,
$3);}else{$$=arg_append($1,
$3);}}|args ','tSTAR arg_value{NODE
*n1;if(nd_type($4)==NODE_ARRAY
&&(n1=splat_array($1))!=0){$$=list_concat(n1,
$4);}else{$$=arg_concat($1,
$4);}}|tSTAR arg_value{$$=NEW_SPLAT($2);};primary:literal|strings|xstring|regexp|words|qwords|symbols|qsymbols|var_ref|backref|tFID{$$=NEW_FCALL($1,
0);}|k_begin{$< val >
1=cmdarg_stack;cmdarg_stack=0;$
< num > $=ruby_sourceline;}bodystmt
k_end{cmdarg_stack=$< val >
1;if($3==NULL){$$=NEW_NIL();}else{if(nd_type($3)==NODE_RESCUE||nd_type($3)==NODE_ENSURE)
nd_set_line($3,$< num >
2);$$=NEW_BEGIN($3);}nd_set_line($$,$
< num >2);}|tLPAREN_ARG{lex_state=EXPR_ENDARG;}rparen{$$=0;}|tLPAREN_ARG
expr{lex_state=EXPR_ENDARG;}rparen{$$=$2;}|tLPAREN
compstmt
')'{$$=$2;}|primary_value
tCOLON2 tCONSTANT{$$=NEW_COLON2($1,
$3);}|tCOLON3 tCONSTANT{$$=NEW_COLON3($2);}|tLBRACK
aref_args ']'{if($2==0){$$=NEW_ZARRAY();}else{$$=$2;}}|tLBRACE
assoc_list '}'{$$=NEW_HASH($2);}|keyword_return{$$=NEW_RETURN(0);}|keyword_yield
'('call_args rparen{$$=new_yield($3);}|keyword_yield
'('rparen{$$=NEW_YIELD(0);}|keyword_yield{$$=NEW_YIELD(0);}|keyword_defined
opt_nl '('{in_defined=1;}expr
rparen{in_defined=0;$$=NEW_DEFINED($5);}|keyword_not
'('expr rparen{$$=call_uni_op(cond($3),
'!');}|keyword_not '('rparen{$$=call_uni_op(cond(NEW_NIL()),
'!');}|fcall brace_block{$2->
nd_iter=$1;$$=$2;}|method_call|method_call
brace_block{block_dup_check($1->
nd_args, $2);$2->nd_iter=$1;$$=$2;}|tLAMBDA
lambda{$$=$2;}|k_if expr_value
then compstmt if_tail k_end{$$=NEW_IF(cond($2),
$4, $5);fixpos($$,
$2);}|k_unless expr_value then
compstmt opt_else k_end{$$=NEW_UNLESS(cond($2),
$4, $5);fixpos($$,
$2);}|k_while{COND_PUSH(1);}expr_value
do{COND_POP();}compstmt k_end{$$=NEW_WHILE(cond($3),
$6, 1);fixpos($$,
$3);}|k_until{COND_PUSH(1);}expr_value
do{COND_POP();}compstmt k_end{$$=NEW_UNTIL(cond($3),
$6, 1);fixpos($$, $3);}|k_case
expr_value opt_terms case_body
k_end{$$=NEW_CASE($2,
$4);fixpos($$, $2);}|k_case
opt_terms case_body k_end{$$=NEW_CASE(0,
$3);}|k_for for_var keyword_in{COND_PUSH(1);}expr_value
do{COND_POP();}compstmt k_end{ID
id=internal_id();ID *tbl=ALLOC_N(ID,
2);NODE *m=NEW_ARGS_AUX(0,
0);NODE *args,*scope;if(nd_type($2)==NODE_MASGN){NODE
*one=NEW_LIST(NEW_LIT(INT2FIX(1)));NODE
*zero=NEW_LIST(NEW_LIT(INT2FIX(0)));m->
nd_next=block_append(NEW_IF(NEW_NODE(NODE_AND,
NEW_CALL(NEW_CALL(NEW_DVAR(id),
idLength, 0), idEq, one),
NEW_CALL(NEW_CALL(NEW_DVAR(id),
idAREF, zero), rb_intern("kind_of?"),
NEW_LIST(NEW_LIT(rb_cArray))),
0), NEW_DASGN_CURR(id,
NEW_CALL(NEW_DVAR(id), idAREF,
zero)), 0), node_assign($2,
NEW_DVAR(id)));args=new_args(m,
0, id, 0, new_args_tail(0,
0, 0));}else{if(nd_type($2)==NODE_LASGN||nd_type($2)==NODE_DASGN||nd_type($2)==NODE_DASGN_CURR){$2->
nd_value=NEW_DVAR(id);m->
nd_plen=1;m->nd_next=$2;args=new_args(m,
0, 0, 0, new_args_tail(0,
0, 0));}else{m->nd_next=node_assign(NEW_MASGN(NEW_LIST($2),
0), NEW_DVAR(id));args=new_args(m,
0, id, 0, new_args_tail(0,
0, 0));}}scope=NEW_NODE(NODE_SCOPE,
tbl, $8, args);tbl[0]=1;tbl[1]=id;$$=NEW_FOR(0,
$5, scope);fixpos($$,
$2);}|k_class cpath superclass{if(in_def||in_single)
yyerror("class definition in
method body");local_push(0);$
< num > $=ruby_sourceline;}bodystmt
k_end{$$=NEW_CLASS($2,
$5, $3);nd_set_line($$,$< num >
4);local_pop();}|k_class
tLSHFT expr{$< num > $=in_def;in_def=0;}term{$
< num > $=in_single;in_single=0;local_push(0);}bodystmt
k_end{$$=NEW_SCLASS($3,
$7);fixpos($$, $3);local_pop();in_def=$
< num >4;in_single=$< num >
6;}|k_module cpath{if(in_def||in_single)
yyerror("module definition in
method body");local_push(0);$
< num > $=ruby_sourceline;}bodystmt
k_end{$$=NEW_MODULE($2,
$4);nd_set_line($$,$< num >
3);local_pop();}|k_def fname{$
< id > $=cur_mid;cur_mid=$2;in_def++;local_push(0);}f_arglist
bodystmt k_end{NODE *body=remove_begin($5);reduce_nodes(&body);$$=NEW_DEFN($2,
$4, body, NOEX_PRIVATE);nd_set_line($$,$
< num >1);local_pop();in_def--;cur_mid=$
< id >3;}|k_def singleton
dot_or_colon{lex_state=EXPR_FNAME;}fname{in_single++;lex_state=EXPR_ENDFN;local_push(0);}f_arglist
bodystmt k_end{NODE *body=remove_begin($8);reduce_nodes(&body);$$=NEW_DEFS($2,
$5, $7, body);nd_set_line($$,$
< num >1);local_pop();in_single--;}|keyword_break{$$=NEW_BREAK(0);}|keyword_next{$$=NEW_NEXT(0);}|keyword_redo{$$=NEW_REDO();}|keyword_retry{$$=NEW_RETRY();};primary_value:primary{value_expr($1);$$=$1;if(!$$)$$=NEW_NIL();};k_begin:keyword_begin{token_info_push("begin");};k_if:keyword_if{token_info_push("if");};k_unless:keyword_unless{token_info_push("unless");};k_while:keyword_while{token_info_push("while");};k_until:keyword_until{token_info_push("until");};k_case:keyword_case{token_info_push("case");};k_for:keyword_for{token_info_push("for");};k_class:keyword_class{token_info_push("class");};k_module:keyword_module{token_info_push("module");};k_def:keyword_def{token_info_push("def");$
< num > $=ruby_sourceline;};k_end:keyword_end{token_info_pop("end");};then:term|keyword_then|term
keyword_then;do:term|keyword_do_cond;if_tail:opt_else|keyword_elsif
expr_value then compstmt
if_tail{$$=NEW_IF(cond($2),
$4, $5);fixpos($$,
$2);};opt_else:none|keyword_else
compstmt{$$=$2;};for_var:lhs|mlhs;f_marg:f_norm_arg{$$=assignable($1,
0);}|tLPAREN f_margs rparen{$$=$2;};f_marg_list:f_marg{$$=NEW_LIST($1);}|f_marg_list
','f_marg{$$=list_append($1,
$3);};f_margs:f_marg_list{$$=NEW_MASGN($1,
0);}|f_marg_list ','tSTAR
f_norm_arg{$$=assignable($4,
0);$$=NEW_MASGN($1,$$);}|f_marg_list
','tSTAR f_norm_arg
','f_marg_list{$$=assignable($4,
0);$$=NEW_MASGN($1,
NEW_POSTARG($$,
$6));}|f_marg_list ','tSTAR{$$=NEW_MASGN($1,-1);}|f_marg_list
','tSTAR ','f_marg_list{$$=NEW_MASGN($1,
NEW_POSTARG(-1, $5));}|tSTAR
f_norm_arg{$$=assignable($2,
0);$$=NEW_MASGN(0,$$);}|tSTAR
f_norm_arg ','f_marg_list{$$=assignable($2,
0);$$=NEW_MASGN(0, NEW_POSTARG($$,
$4));}|tSTAR{$$=NEW_MASGN(0,-1);}|tSTAR
','f_marg_list{$$=NEW_MASGN(0,
NEW_POSTARG(-1,
$3));};block_args_tail:f_block_kwarg
','f_kwrest opt_f_block_arg{$$=new_args_tail($1,
$3, $4);}|f_block_kwarg
opt_f_block_arg{$$=new_args_tail($1,
Qnone, $2);}|f_kwrest
opt_f_block_arg{$$=new_args_tail(Qnone,
$1, $2);}|f_block_arg{$$=new_args_tail(Qnone,
Qnone,
$1);};opt_block_args_tail:
','block_args_tail{$$=$2;}|{$$=new_args_tail(Qnone,
Qnone, Qnone);};block_param:f_arg
','f_block_optarg
','f_rest_arg
opt_block_args_tail{$$=new_args($1,
$3, $5, Qnone, $6);}|f_arg
','f_block_optarg
','f_rest_arg ','f_arg
opt_block_args_tail{$$=new_args($1,
$3, $5, $7, $8);}|f_arg
','f_block_optarg
opt_block_args_tail{$$=new_args($1,
$3, Qnone, Qnone, $4);}|f_arg
','f_block_optarg ','f_arg
opt_block_args_tail{$$=new_args($1,
$3, Qnone, $5, $6);}|f_arg
','f_rest_arg
opt_block_args_tail{$$=new_args($1,
Qnone, $3, Qnone, $4);}|f_arg
','{$$=new_args($1, Qnone,
1, Qnone, new_args_tail(Qnone,
Qnone, Qnone));}|f_arg
','f_rest_arg ','f_arg
opt_block_args_tail{$$=new_args($1,
Qnone, $3, $5, $6);}|f_arg
opt_block_args_tail{$$=new_args($1,
Qnone, Qnone, Qnone,
$2);}|f_block_optarg
','f_rest_arg
opt_block_args_tail{$$=new_args(Qnone,
$1, $3, Qnone,
$4);}|f_block_optarg
','f_rest_arg ','f_arg
opt_block_args_tail{$$=new_args(Qnone,
$1, $3, $5, $6);}|f_block_optarg
opt_block_args_tail{$$=new_args(Qnone,
$1, Qnone, Qnone,
$2);}|f_block_optarg ','f_arg
opt_block_args_tail{$$=new_args(Qnone,
$1, Qnone,
$3, $4);}|f_rest_arg
opt_block_args_tail{$$=new_args(Qnone,
Qnone, $1, Qnone,
$2);}|f_rest_arg ','f_arg
opt_block_args_tail{$$=new_args(Qnone,
Qnone,
$1, $3, $4);}|block_args_tail{$$=new_args(Qnone,
Qnone, Qnone, Qnone,
$1);};opt_block_param:none|block_param_def{command_start=TRUE;};block_param_def:
'|'opt_bv_decl
'|'{$$=0;}|tOROP{$$=0;}|
'|'block_param opt_bv_decl
'|'{$$=$2;};opt_bv_decl:opt_nl{$$=0;}|opt_nl
';'bv_decls opt_nl{$$=0;};bv_decls:bvar|bv_decls
','bvar;bvar:tIDENTIFIER{new_bv(get_id($1));}|f_bad_arg{$$=0;};lambda:{$
< vars > $=dyna_push();}{$
< num > $=lpar_beg;lpar_beg=++paren_nest;}f_larglist{$
< num > $=ruby_sourceline;}lambda_body{lpar_beg=$
< num >2;$$=NEW_LAMBDA($3,
$5);nd_set_line($$,$< num >
4);dyna_pop($< vars >
1);};f_larglist: '('f_args
opt_bv_decl ')'{$$=$2;}|f_args{$$=$1;};lambda_body:tLAMBEG
compstmt
'}'{$$=$2;}|keyword_do_LAMBDA
compstmt keyword_end{$$=$2;};do_block:keyword_do_block{$
< vars >1=dyna_push();$< num >
$=ruby_sourceline;}opt_block_param
compstmt keyword_end{$$=NEW_ITER($3,
$4);nd_set_line($$,$< num >
2);dyna_pop($< vars >
1);};block_call:command
do_block{if(nd_type($1)==NODE_YIELD){compile_error(PARSER_ARG"block
given to yield");}else{block_dup_check($1->
nd_args, $2);}$2->nd_iter=$1;$$=$2;fixpos($$,
$1);}|block_call dot_or_colon
operation2 opt_paren_args{$$=NEW_CALL($1,
$3, $4);}|block_call
dot_or_colon operation2
opt_paren_args brace_block{block_dup_check($4, $5);$5->
nd_iter=NEW_CALL($1,
$3, $4);$$=$5;fixpos($$,
$1);}|block_call dot_or_colon
operation2 command_args
do_block{block_dup_check($4, $5);$5->
nd_iter=NEW_CALL($1,
$3, $4);$$=$5;fixpos($$,
$1);};method_call:fcall
paren_args{$$=$1;$$->nd_args=$2;}|primary_value
'.'operation2{$< num >
$=ruby_sourceline;}opt_paren_args{$$=NEW_CALL($1,
$3, $5);nd_set_line($$,$< num >
4);}|primary_value tCOLON2
operation2{$< num >
$=ruby_sourceline;}paren_args{$$=NEW_CALL($1,
$3, $5);nd_set_line($$,$< num >
4);}|primary_value tCOLON2
operation3{$$=NEW_CALL($1,
$3, 0);}|primary_value '.'{$
< num > $=ruby_sourceline;}paren_args{$$=NEW_CALL($1,
rb_intern("call"),
$4);nd_set_line($$,$< num >
3);}|primary_value tCOLON2{$
< num > $=ruby_sourceline;}paren_args{$$=NEW_CALL($1,
rb_intern("call"),
$4);nd_set_line($$,$< num >
3);}|keyword_super paren_args{$$=NEW_SUPER($2);}|keyword_super{$$=NEW_ZSUPER();}|primary_value
'['opt_call_args rbracket{if($1
&&nd_type($1)==NODE_SELF)$$=NEW_FCALL(tAREF,
$3);else $$=NEW_CALL($1, tAREF,
$3);fixpos($$,
$1);};brace_block: '{'{$< vars >
1=dyna_push();$< num >
$=ruby_sourceline;}opt_block_param
compstmt '}'{$$=NEW_ITER($3,
$4);nd_set_line($$,$< num >
2);dyna_pop($< vars >
1);}|keyword_do{$< vars >
1=dyna_push();$< num >
$=ruby_sourceline;}opt_block_param
compstmt keyword_end{$$=NEW_ITER($3,
$4);nd_set_line($$,$< num >
2);dyna_pop($< vars >
1);};case_body:keyword_when
args then compstmt cases{$$=NEW_WHEN($2,
$4, $5);};cases:opt_else|case_body;opt_rescue:keyword_rescue
exc_list exc_var then compstmt
opt_rescue{if($3){$3=node_assign($3,
NEW_ERRINFO());$5=block_append($3,
$5);}$$=NEW_RESBODY($2,
$5, $6);fixpos($$,
$2?$2:$5);}|none;exc_list:arg_value{$$=NEW_LIST($1);}|mrhs{if(!($$=splat_array($1)))$$=$1;}|none;exc_var:tASSOC
lhs{$$=$2;}|none;opt_ensure:keyword_ensure
compstmt{$$=$2;}|none;literal:numeric|symbol{$$=NEW_LIT(ID2SYM($1));}|dsym;strings:string{NODE
*node=$1;if(!node){node=NEW_STR(STR_NEW0());}else{node=evstr2dstr(node);}$$=node;};string:tCHAR|string1|string
string1{$$=literal_concat($1,
$2);};string1:tSTRING_BEG
string_contents tSTRING_END{$$=$2;};xstring:tXSTRING_BEG
xstring_contents tSTRING_END{NODE
*node=$2;if(!node){node=NEW_XSTR(STR_NEW0());}else{switch(nd_type(node)){case
NODE_STR:nd_set_type(node,
NODE_XSTR);break;case
NODE_DSTR:nd_set_type(node,
NODE_DXSTR);break;default:node=NEW_NODE(NODE_DXSTR,
Qnil, 1, NEW_LIST(node));break;}}$$=node;};regexp:tREGEXP_BEG
regexp_contents tREGEXP_END{int
options=$3;NODE *node=$2;NODE
*list,*prev;if(!node){node=NEW_LIT(reg_compile(STR_NEW0(),
options));}else switch(nd_type(node)){case
NODE_STR:{VALUE src=node->
nd_lit;nd_set_type(node,
NODE_LIT);node->nd_lit=reg_compile(src,
options);}break;default:node=NEW_NODE(NODE_DSTR,
STR_NEW0(), 1, NEW_LIST(node));case
NODE_DSTR:if(options
&RE_OPTION_ONCE){nd_set_type(node,
NODE_DREGX_ONCE);}else{nd_set_type(node,
NODE_DREGX);}node->nd_cflag=options
&RE_OPTION_MASK;if(!NIL_P(node->
nd_lit)) reg_fragment_check(node->
nd_lit, options);for(list=(prev=node) ->
nd_next;list;list=list->
nd_next){if(nd_type(list->
nd_head)==NODE_STR){VALUE tail=list->
nd_head->nd_lit;if(reg_fragment_check(tail,
options)&&prev &&!NIL_P(prev->
nd_lit)){VALUE lit=prev==node?prev->
nd_lit:prev->nd_head->nd_lit;if(!literal_concat0(parser,
lit, tail)){node=0;break;}rb_str_resize(tail,
0);prev->nd_next=list->nd_next;rb_gc_force_recycle((VALUE)
list->nd_head);rb_gc_force_recycle((VALUE)
list);list=prev;}else{prev=list;}}else{prev=0;}}if(!node->
nd_next){VALUE src=node->
nd_lit;nd_set_type(node,
NODE_LIT);node->nd_lit=reg_compile(src,
options);}break;}$$=node;};words:tWORDS_BEG
' 'tSTRING_END{$$=NEW_ZARRAY();}|tWORDS_BEG
word_list tSTRING_END{$$=$2;};word_list:{$$=0;}|word_list
word ' '{$$=list_append($1,
evstr2dstr($2));};word:string_content|word
string_content{$$=literal_concat($1,
$2);};symbols:tSYMBOLS_BEG
' 'tSTRING_END{$$=NEW_ZARRAY();}|tSYMBOLS_BEG
symbol_list tSTRING_END{$$=$2;};symbol_list:{$$=0;}|symbol_list
word ' '{$2=evstr2dstr($2);nd_set_type($2,
NODE_DSYM);$$=list_append($1,
$2);};qwords:tQWORDS_BEG
' 'tSTRING_END{$$=NEW_ZARRAY();}|tQWORDS_BEG
qword_list tSTRING_END{$$=$2;};qsymbols:tQSYMBOLS_BEG
' 'tSTRING_END{$$=NEW_ZARRAY();}|tQSYMBOLS_BEG
qsym_list tSTRING_END{$$=$2;};qword_list:{$$=0;}|qword_list
tSTRING_CONTENT
' '{$$=list_append($1,
$2);};qsym_list:{$$=0;}|qsym_list
tSTRING_CONTENT ' '{VALUE lit;lit=$2->
nd_lit;$2->nd_lit=ID2SYM(rb_intern_str(lit));nd_set_type($2,
NODE_LIT);$$=list_append($1,
$2);};string_contents:{$$=0;}|string_contents
string_content{$$=literal_concat($1,
$2);};xstring_contents:{$$=0;}|xstring_contents
string_content{$$=literal_concat($1,
$2);};regexp_contents:{$$=0;}|regexp_contents
string_content{NODE *head=$1,*tail=$2;if(!head){$$=tail;}else
if(!tail){$$=head;}else{switch(nd_type(head)){case
NODE_STR:nd_set_type(head,
NODE_DSTR);break;case
NODE_DSTR:break;default:head=list_append(NEW_DSTR(Qnil),
head);break;}$$=list_append(head,
tail);}};string_content:tSTRING_CONTENT|tSTRING_DVAR{$
< node > $=lex_strterm;lex_strterm=0;lex_state=EXPR_BEG;}string_dvar{lex_strterm=$
< node >2;$$=NEW_EVSTR($3);}|tSTRING_DBEG{$
< val >1=cond_stack;$< val >
$=cmdarg_stack;cond_stack=0;cmdarg_stack=0;}{$
< node > $=lex_strterm;lex_strterm=0;lex_state=EXPR_BEG;}{$
< num > $=brace_nest;brace_nest=0;}compstmt
tSTRING_DEND{cond_stack=$< val >
1;cmdarg_stack=$< val >
2;lex_strterm=$< node >
3;brace_nest=$< num >4;if($5) $5->
flags &=~NODE_FL_NEWLINE;$$=new_evstr($5);};string_dvar:tGVAR{$$=NEW_GVAR($1);}|tIVAR{$$=NEW_IVAR($1);}|tCVAR{$$=NEW_CVAR($1);}|backref;symbol:tSYMBEG
sym{lex_state=EXPR_END;$$=$2;};sym:fname|tIVAR|tGVAR|tCVAR;dsym:tSYMBEG
xstring_contents tSTRING_END{lex_state=EXPR_END;$$=dsym_node($2);};numeric:tINTEGER|tFLOAT|tUMINUS_NUM
tINTEGER%prec tLOWEST{$$=negate_lit($2);}|tUMINUS_NUM
tFLOAT%prec tLOWEST{$$=negate_lit($2);};user_variable:tIDENTIFIER|tIVAR|tGVAR|tCONSTANT|tCVAR;keyword_variable:keyword_nil{ifndef_ripper($$=keyword_nil);}|keyword_self{ifndef_ripper($$=keyword_self);}|keyword_true{ifndef_ripper($$=keyword_true);}|keyword_false{ifndef_ripper($$=keyword_false);}|keyword__FILE__{ifndef_ripper($$=keyword__FILE__);}|keyword__LINE__{ifndef_ripper($$=keyword__LINE__);}|keyword__ENCODING__{ifndef_ripper($$=keyword__ENCODING__);};var_ref:user_variable{if(!($$=gettable($1)))$$=NEW_BEGIN(0);}|keyword_variable{if(!($$=gettable($1)))$$=NEW_BEGIN(0);};var_lhs:user_variable{$$=assignable($1,
0);}|keyword_variable{$$=assignable($1,
0);};backref:tNTH_REF|tBACK_REF;superclass:term{$$=0;}| '
<'{lex_state=EXPR_BEG;command_start=TRUE;}expr_value
term{$$=$3;}|error term{yyerrok;$$=0;};f_arglist:
'('f_args rparen{$$=$2;lex_state=EXPR_BEG;command_start=TRUE;}|f_args
term{$$=$1;lex_state=EXPR_BEG;command_start=TRUE;};args_tail:f_kwarg
','f_kwrest opt_f_block_arg{$$=new_args_tail($1,
$3, $4);}|f_kwarg
opt_f_block_arg{$$=new_args_tail($1,
Qnone, $2);}|f_kwrest
opt_f_block_arg{$$=new_args_tail(Qnone,
$1, $2);}|f_block_arg{$$=new_args_tail(Qnone,
Qnone, $1);};opt_args_tail:
','args_tail{$$=$2;}|{$$=new_args_tail(Qnone,
Qnone, Qnone);};f_args:f_arg
','f_optarg ','f_rest_arg
opt_args_tail{$$=new_args($1,
$3, $5, Qnone, $6);}|f_arg
','f_optarg ','f_rest_arg
','f_arg opt_args_tail{$$=new_args($1,
$3, $5, $7, $8);}|f_arg
','f_optarg opt_args_tail{$$=new_args($1,
$3, Qnone, Qnone, $4);}|f_arg
','f_optarg ','f_arg
opt_args_tail{$$=new_args($1,
$3, Qnone, $5, $6);}|f_arg
','f_rest_arg opt_args_tail{$$=new_args($1,
Qnone, $3, Qnone, $4);}|f_arg
','f_rest_arg ','f_arg
opt_args_tail{$$=new_args($1,
Qnone, $3, $5, $6);}|f_arg
opt_args_tail{$$=new_args($1,
Qnone, Qnone, Qnone,
$2);}|f_optarg ','f_rest_arg
opt_args_tail{$$=new_args(Qnone,
$1, $3, Qnone, $4);}|f_optarg
','f_rest_arg ','f_arg
opt_args_tail{$$=new_args(Qnone,
$1, $3, $5, $6);}|f_optarg
opt_args_tail{$$=new_args(Qnone,
$1, Qnone, Qnone,
$2);}|f_optarg ','f_arg
opt_args_tail{$$=new_args(Qnone,
$1, Qnone,
$3, $4);}|f_rest_arg
opt_args_tail{$$=new_args(Qnone,
Qnone, $1, Qnone,
$2);}|f_rest_arg ','f_arg
opt_args_tail{$$=new_args(Qnone,
Qnone, $1, $3, $4);}|args_tail{$$=new_args(Qnone,
Qnone, Qnone, Qnone,
$1);}|{$$=new_args_tail(Qnone,
Qnone, Qnone);$$=new_args(Qnone,
Qnone, Qnone, Qnone,$$);};f_bad_arg:tCONSTANT{yyerror("formal
argument cannot be a constant");$$=0;}|tIVAR{yyerror("formal
argument cannot be an instance
variable");$$=0;}|tGVAR{yyerror("formal
argument cannot be a global
variable");$$=0;}|tCVAR{yyerror("formal
argument cannot be a class
variable");$$=0;};f_norm_arg:f_bad_arg|tIDENTIFIER{formal_argument(get_id($1));$$=$1;};f_arg_item:f_norm_arg{arg_var(get_id($1));$$=NEW_ARGS_AUX($1,
1);}|tLPAREN f_margs rparen{ID
tid=internal_id();arg_var(tid);if(dyna_in_block()){$2->
nd_value=NEW_DVAR(tid);}else{$2->
nd_value=NEW_LVAR(tid);}$$=NEW_ARGS_AUX(tid, 1);$$->
nd_next=$2;};f_arg:f_arg_item|f_arg
','f_arg_item{$$=$1;$$->
nd_plen++;$$->nd_next=block_append($$->
nd_next, $3->nd_next);rb_gc_force_recycle((VALUE)$3);};f_kw:tLABEL
arg_value{arg_var(formal_argument(get_id($1)));$$=assignable($1,
$2);$$=NEW_KW_ARG(0,$$);};f_block_kw:tLABEL
primary_value{arg_var(formal_argument(get_id($1)));$$=assignable($1,
$2);$$=NEW_KW_ARG(0,$$);};f_block_kwarg:f_block_kw{$$=$1;}|f_block_kwarg
','f_block_kw{NODE *kws=$1;while(kws->
nd_next){kws=kws->nd_next;}kws->
nd_next=$3;$$=$1;};f_kwarg:f_kw{$$=$1;}|f_kwarg
','f_kw{NODE *kws=$1;while(kws->
nd_next){kws=kws->nd_next;}kws->
nd_next=$3;$$=$1;};kwrest_mark:tPOW|tDSTAR;f_kwrest:kwrest_mark
tIDENTIFIER{shadowing_lvar(get_id($2));$$=$2;}|kwrest_mark{$$=internal_id();};f_opt:tIDENTIFIER
'='arg_value{arg_var(formal_argument(get_id($1)));$$=assignable($1,
$3);$$=NEW_OPT_ARG(0,$$);};f_block_opt:tIDENTIFIER
'='primary_value{arg_var(formal_argument(get_id($1)));$$=assignable($1,
$3);$$=NEW_OPT_ARG(0,$$);};f_block_optarg:f_block_opt{$$=$1;}|f_block_optarg
','f_block_opt{NODE *opts=$1;while(opts->
nd_next){opts=opts->nd_next;}opts->
nd_next=$3;$$=$1;};f_optarg:f_opt{$$=$1;}|f_optarg
','f_opt{NODE *opts=$1;while(opts->
nd_next){opts=opts->nd_next;}opts->
nd_next=$3;$$=$1;};restarg_mark:
'*'|tSTAR;f_rest_arg:restarg_mark
tIDENTIFIER{if(!is_local_id($2))
yyerror("rest argument must be
local variable");arg_var(shadowing_lvar(get_id($2)));$$=$2;}|restarg_mark{$$=internal_id();arg_var($$);};blkarg_mark:
'&'|tAMPER;f_block_arg:blkarg_mark
tIDENTIFIER{if(!is_local_id($2))
yyerror("block argument must
be local variable");else if(!dyna_in_block()&&local_id($2))
yyerror("duplicated block
argument name");arg_var(shadowing_lvar(get_id($2)));$$=$2;};opt_f_block_arg:
','f_block_arg{$$=$2;}|none{$$=0;};singleton:var_ref{value_expr($1);$$=$1;if(!$$)$$=NEW_NIL();}|
'('{lex_state=EXPR_BEG;}expr
rparen{if($3==0){yyerror("can't
define singleton method for
().");}else{switch(nd_type($3)){case
NODE_STR:case NODE_DSTR:case
NODE_XSTR:case NODE_DXSTR:case
NODE_DREGX:case NODE_LIT:case
NODE_ARRAY:case
NODE_ZARRAY:yyerror("can't
define singleton method for
literals");default:value_expr($3);break;}}$$=$3;};assoc_list:none|assocs
trailer{$$=$1;};assocs:assoc|assocs
','assoc{$$=list_concat($1,
$3);};assoc:arg_value tASSOC
arg_value{$$=list_append(NEW_LIST($1),
$3);}|tLABEL arg_value{$$=list_append(NEW_LIST(NEW_LIT(ID2SYM($1))),
$2);}|tDSTAR arg_value{$$=list_append(NEW_LIST(0),
$2);};;operation:tIDENTIFIER|tCONSTANT|tFID;operation2:tIDENTIFIER|tCONSTANT|tFID|op;operation3:tIDENTIFIER|tFID|op;dot_or_colon:
'.'|tCOLON2;opt_terms:|terms;opt_nl:|
'\n';rparen:opt_nl
')';rbracket:opt_nl
']';trailer:| '\n'| ',';term:
';'{yyerrok;}| '\n';terms:term|terms
';'{yyerrok;};none:{$$=0;};%%#define
yylvalstatic int
parser_regx_options(struct
parser_params *);static int
parser_tokadd_string(struct
parser_params *, int, int, int,
long *, rb_encoding **);static
void parser_tokaddmbc(struct
parser_params *parser, int c,
rb_encoding *enc);static int
parser_parse_string(struct
parser_params *, NODE
*);static int
parser_here_document(struct
parser_params *, NODE
*);#define nextc()#define
pushback(c)#define newtok()#define
tokspace(n)#define tokadd(c)#define
tok_hex(numlen)#define
read_escape(flags, e)#define
tokadd_escape(e)#define
regx_options()#define
tokadd_string(f, t, p, n, e)#define
parse_string(n)#define
tokaddmbc(c, enc)#define
here_document(n)#define
heredoc_identifier()#define
heredoc_restore(n)#define
whole_match_p(e, l, i)#define
set_yylval_str(x)#define
set_yylval_num(x)#define
set_yylval_id(x)#define
set_yylval_name(x)#define
set_yylval_literal(x)#define
set_yylval_node(x)#define
yylval_id()#define
ripper_flush(p)#define
SIGN_EXTEND_CHAR(c)#define
parser_encoding_name()#define
parser_mbclen()#define
parser_precise_mbclen()#define
is_identchar(p, e, enc)#define
parser_is_identchar()#define
parser_isascii() static
inttoken_info_get_column(struct
parser_params *parser, const
char *token){int column=1;const
char *p,*pend=lex_p-strlen(token);for(p=lex_pbeg;p
< pend;p++){if(*p== '\t'){column=(((column-1)/8)+1)*8;}column++;}return
column;}static
inttoken_info_has_nonspaces(struct
parser_params *parser, const
char *token){const char *p,*pend=lex_p-strlen(token);for(p=lex_pbeg;p
< pend;p++){if(*p!= ' '&&*p!=
'\t'){return 1;}}return
0;}static voidtoken_info_push(struct
parser_params *parser, const
char *token){token_info
*ptinfo;if(!parser->
parser_token_info_enabled)
return;ptinfo=ALLOC(token_info);ptinfo->
token=token;ptinfo->linenum=ruby_sourceline;ptinfo->
column=token_info_get_column(parser,
token);ptinfo->nonspc=token_info_has_nonspaces(parser,
token);ptinfo->next=parser->
parser_token_info;parser->
parser_token_info=ptinfo;}static
voidtoken_info_pop(struct
parser_params *parser, const
char *token){int linenum;token_info
*ptinfo=parser->
parser_token_info;if(!ptinfo)
return;parser->
parser_token_info=ptinfo->next;if(token_info_get_column(parser,
token)==ptinfo->column){goto
finish;}linenum=ruby_sourceline;if(linenum==ptinfo->
linenum){goto finish;}if(token_info_has_nonspaces(parser,
token)||ptinfo->nonspc){goto
finish;}if(parser->
parser_token_info_enabled){rb_compile_warn(ruby_sourcefile,
linenum,"mismatched
indentations at '%s' with '%s'
at %d", token, ptinfo->token,
ptinfo->linenum);}finish:xfree(ptinfo);}static
intparser_yyerror(struct
parser_params *parser, const
char *msg){const int
max_line_margin=30;const char
*p,*pe;char *buf;long len;int
i;compile_error(PARSER_ARG"%s",
msg);p=lex_p;while(lex_pbeg<=p){if(*p==
'\n') break;p--;}p++;pe=lex_p;while(pe
< lex_pend){if(*pe== '\n')
break;pe++;}len=pe-p;if(len >
4){char *p2;const char *pre="",*post="";if(len >
max_line_margin *2+10){if(lex_p-p >
max_line_margin){p=rb_enc_prev_char(p,
lex_p-max_line_margin, pe,
rb_enc_get(lex_lastline));pre="...";}if(pe-lex_p >
max_line_margin){pe=rb_enc_prev_char(lex_p,
lex_p+max_line_margin, pe,
rb_enc_get(lex_lastline));post="...";}len=pe-p;}buf=ALLOCA_N(char,
len+2);MEMCPY(buf, p, char,
len);buf[len]=
'\0';rb_compile_error_append("%s%s%s",
pre, buf, post);i=(int)(lex_p-p);p2=buf;pe=buf+len;while(p2
< pe){if(*p2!= '\t')*p2=
' ';p2++;}buf[i]= '^';buf[i+1]=
'\0';rb_compile_error_append("%s%s",
pre, buf);}return 0;}static
void parser_prepare(struct
parser_params *parser);static
VALUEdebug_lines(const char *f){ID
script_lines;CONST_ID(script_lines,"SCRIPT_LINES__");if(rb_const_defined_at(rb_cObject,
script_lines)){VALUE hash=rb_const_get_at(rb_cObject,
script_lines);if(RB_TYPE_P(hash,
T_HASH)){VALUE fname=rb_external_str_new_with_enc(f,
strlen(f),
rb_filesystem_encoding());VALUE
lines=rb_ary_new();rb_hash_aset(hash,
fname, lines);return lines;}}return
0;}static VALUEcoverage(const
char *f, int n){VALUE
coverages=rb_get_coverages();if(RTEST(coverages)&&RBASIC(coverages) ->
klass==0){VALUE fname=rb_external_str_new_with_enc(f,
strlen(f),
rb_filesystem_encoding());VALUE
lines=rb_ary_new2(n);int i;RBASIC(lines) ->
klass=0;for(i=0;i< n;i++)
RARRAY_PTR(lines)[i]=Qnil;RARRAY(lines) ->
as.heap.len=n;rb_hash_aset(coverages,
fname, lines);return lines;}return
0;}static inte_option_supplied(struct
parser_params *parser){return
strcmp(ruby_sourcefile,"-e")==0;}static
VALUEyycompile0(VALUE arg){int
n;NODE *tree;struct
parser_params *parser=(struct
parser_params *) arg;if(!compile_for_eval
&&rb_safe_level()==0){ruby_debug_lines=debug_lines(ruby_sourcefile);if(ruby_debug_lines
&&ruby_sourceline > 0){VALUE
str=STR_NEW0();n=ruby_sourceline;do{rb_ary_push(ruby_debug_lines,
str);}while(--n);}if(!e_option_supplied(parser)){ruby_coverage=coverage(ruby_sourcefile,
ruby_sourceline);}}parser_prepare(parser);deferred_nodes=0;parser->
parser_token_info_enabled=!compile_for_eval
&&RTEST(ruby_verbose);if(RUBY_DTRACE_PARSE_BEGIN_ENABLED()){RUBY_DTRACE_PARSE_BEGIN(parser->
parser_ruby_sourcefile, parser->
parser_ruby_sourceline);}n=yyparse((void
*) parser);if(RUBY_DTRACE_PARSE_END_ENABLED()){RUBY_DTRACE_PARSE_END(parser->
parser_ruby_sourcefile, parser->
parser_ruby_sourceline);}ruby_debug_lines=0;ruby_coverage=0;compile_for_eval=0;lex_strterm=0;lex_p=lex_pbeg=lex_pend=0;lex_lastline=lex_nextline=0;if(parser->
nerr){return 0;}tree=ruby_eval_tree;if(!tree){tree=NEW_NIL();}else
if(ruby_eval_tree_begin){tree->
nd_body=NEW_PRELUDE(ruby_eval_tree_begin,
tree->nd_body);}return(VALUE)
tree;}static NODE *yycompile(struct
parser_params *parser, const
char *f, int line){ruby_sourcefile=ruby_strdup(f);ruby_sourceline=line-1;return(NODE
*) rb_suppress_tracing(yycompile0,(VALUE)
parser);}static rb_encoding
*must_be_ascii_compatible(VALUE
s){rb_encoding *enc=rb_enc_get(s);if(!rb_enc_asciicompat(enc)){rb_raise(rb_eArgError,"invalid
source encoding");}return enc;}static
VALUElex_get_str(struct
parser_params *parser, VALUE s){char
*beg,*end,*pend;rb_encoding
*enc=must_be_ascii_compatible(s);beg=RSTRING_PTR(s);if(lex_gets_ptr){if(RSTRING_LEN(s)==lex_gets_ptr)
return Qnil;beg+=lex_gets_ptr;}pend=RSTRING_PTR(s)+RSTRING_LEN(s);end=beg;while(end
< pend){if(*end++== '\n')
break;}lex_gets_ptr=end-RSTRING_PTR(s);return
rb_enc_str_new(beg, end-beg,
enc);}static VALUElex_getline(struct
parser_params *parser){VALUE
line=(*parser->parser_lex_gets)(parser,
parser->parser_lex_input);if(NIL_P(line))
return line;must_be_ascii_compatible(line);if(ruby_debug_lines){rb_enc_associate(line,
current_enc);rb_ary_push(ruby_debug_lines,
line);}if(ruby_coverage){rb_ary_push(ruby_coverage,
Qnil);}return line;}static
const rb_data_type_t
parser_data_type;static NODE
*parser_compile_string(volatile
VALUE vparser, const char *f,
VALUE s, int line){struct
parser_params *parser;NODE
*node;TypedData_Get_Struct(vparser,
struct parser_params,&parser_data_type,
parser);lex_gets=lex_get_str;lex_gets_ptr=0;lex_input=s;lex_pbeg=lex_p=lex_pend=0;compile_for_eval=rb_parse_in_eval();node=yycompile(parser,
f, line);RB_GC_GUARD(vparser);return
node;}NODE *rb_compile_string(const
char *f, VALUE s, int line){must_be_ascii_compatible(s);return
parser_compile_string(rb_parser_new(),
f, s, line);}NODE
*rb_parser_compile_string(volatile
VALUE vparser, const char *f,
VALUE s, int line){must_be_ascii_compatible(s);return
parser_compile_string(vparser,
f, s, line);}NODE
*rb_compile_cstr(const char *f,
const char *s, int len, int
line){VALUE str=rb_str_new(s,
len);return
parser_compile_string(rb_parser_new(),
f, str, line);}NODE
*rb_parser_compile_cstr(volatile
VALUE vparser, const char *f,
const char *s, int len, int
line){VALUE str=rb_str_new(s,
len);return
parser_compile_string(vparser,
f, str, line);}static
VALUElex_io_gets(struct
parser_params *parser, VALUE
io){return rb_io_gets(io);}NODE
*rb_compile_file(const char *f,
VALUE file, int start){VALUE
volatile vparser=rb_parser_new();return
rb_parser_compile_file(vparser,
f, file, start);}NODE
*rb_parser_compile_file(volatile
VALUE vparser, const char *f,
VALUE file, int start){struct
parser_params *parser;NODE
*node;TypedData_Get_Struct(vparser,
struct parser_params,&parser_data_type,
parser);lex_gets=lex_io_gets;lex_input=file;lex_pbeg=lex_p=lex_pend=0;compile_for_eval=rb_parse_in_eval();node=yycompile(parser,
f, start);RB_GC_GUARD(vparser);return
node;}#define STR_FUNC_ESCAPE#define
STR_FUNC_EXPAND#define
STR_FUNC_REGEXP#define
STR_FUNC_QWORDS#define
STR_FUNC_SYMBOL#define
STR_FUNC_INDENTenum
string_type{str_squote=(0),
str_dquote=(STR_FUNC_EXPAND),
str_xquote=(STR_FUNC_EXPAND),
str_regexp=(STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
str_sword=(STR_FUNC_QWORDS),
str_dword=(STR_FUNC_QWORDS|STR_FUNC_EXPAND),
str_ssym=(STR_FUNC_SYMBOL),
str_dsym=(STR_FUNC_SYMBOL|STR_FUNC_EXPAND)};static
VALUEparser_str_new(const char
*p, long n, rb_encoding *enc,
int func, rb_encoding *enc0){VALUE
str;str=rb_enc_str_new(p, n,
enc);if(!(func
&STR_FUNC_REGEXP)&&rb_enc_asciicompat(enc)){if(rb_enc_str_coderange(str)==ENC_CODERANGE_7BIT){}else
if(enc0==rb_usascii_encoding()&&enc!=rb_utf8_encoding()){rb_enc_associate(str,
rb_ascii8bit_encoding());}}return
str;}#define lex_goto_eol(parser)#define
lex_eol_p()#define peek(c)#define
peek_n(c, n) static inline
intparser_nextc(struct
parser_params *parser){int c;if(lex_p==lex_pend){VALUE
v=lex_nextline;lex_nextline=0;if(!v){if(parser->
eofp) return-1;if(!lex_input||NIL_P(v=lex_getline(parser))){parser->
eofp=Qtrue;lex_goto_eol(parser);return-1;}}{if(heredoc_end >
0){ruby_sourceline=heredoc_end;heredoc_end=0;}ruby_sourceline++;parser->
line_count++;lex_pbeg=lex_p=RSTRING_PTR(v);lex_pend=lex_p+RSTRING_LEN(v);ripper_flush(parser);lex_lastline=v;}}c=(unsigned
char)*lex_p++;if(c== '\r'&&peek('\n')){lex_p++;c=
'\n';}return c;}static
voidparser_pushback(struct
parser_params *parser, int c){if(c==-1)
return;lex_p--;if(lex_p >
lex_pbeg &&lex_p[0]== '\n'&&lex_p[-1]==
'\r'){lex_p--;}}#define
was_bol()#define tokfix()#define
tok()#define toklen()#define
toklast() static char
*parser_newtok(struct
parser_params *parser){tokidx=0;tokline=ruby_sourceline;if(!tokenbuf){toksiz=60;tokenbuf=ALLOC_N(char,
60);}if(toksiz > 4096){toksiz=60;REALLOC_N(tokenbuf,
char, 60);}return tokenbuf;}static
char *parser_tokspace(struct
parser_params *parser, int n){tokidx+=n;if(tokidx >
=toksiz){do{toksiz *=2;}while(toksiz
< tokidx);REALLOC_N(tokenbuf,
char, toksiz);}return
&tokenbuf[tokidx-n];}static
voidparser_tokadd(struct
parser_params *parser, int c){tokenbuf[tokidx++]=(char)
c;if(tokidx >=toksiz){toksiz
*=2;REALLOC_N(tokenbuf, char,
toksiz);}}static
intparser_tok_hex(struct
parser_params *parser, size_t
*numlen){int c;c=scan_hex(lex_p,
2, numlen);if(!*numlen){yyerror("invalid
hex escape");return 0;}lex_p+=*numlen;return
c;}#define tokcopy(n) static
intparser_tokadd_utf8(struct
parser_params *parser,
rb_encoding **encp, int
string_literal, int
symbol_literal, int
regexp_literal){int codepoint;size_t
numlen;if(regexp_literal){tokadd('\\');tokadd('u');}if(peek('{')){do{if(regexp_literal){tokadd(*lex_p);}nextc();codepoint=scan_hex(lex_p,
6,&numlen);if(numlen==0){yyerror("invalid
Unicode escape");return 0;}if(codepoint > 0x10ffff){yyerror("invalid Unicode codepoint (too large)");return 0;}lex_p+=numlen;if(regexp_literal){tokcopy((int) numlen);}else if(codepoint >=0x80){*encp=rb_utf8_encoding();if(string_literal) tokaddmbc(codepoint,*encp);}else if(string_literal){tokadd(codepoint);}}while(string_literal &&(peek(' ')||peek('\t')));if(!peek('}')){yyerror("unterminated Unicode escape");return 0;}if(regexp_literal){tokadd('}');}nextc();}else{codepoint=scan_hex(lex_p, 4,&numlen);if(numlen< 4){yyerror("invalid Unicode escape");return 0;}lex_p+=4;if(regexp_literal){tokcopy(4);}else if(codepoint >=0x80){*encp=rb_utf8_encoding();if(string_literal) tokaddmbc(codepoint,*encp);}else if(string_literal){tokadd(codepoint);}}return codepoint;}#define ESCAPE_CONTROL#define ESCAPE_METAstatic intparser_read_escape(struct parser_params *parser, int flags, rb_encoding **encp){int c;size_t numlen;switch(c=nextc()){case '\\':return c;case 'n':return '\n';case 't':return '\t';case 'r':return '\r';case 'f':return '\f';case 'v':return '\13';case 'a':return '\007';case 'e':return 033;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':pushback(c);c=scan_oct(lex_p, 3,&numlen);lex_p+=numlen;return c;case 'x':c=tok_hex(&numlen);if(numlen==0) return 0;return c;case 'b':return '\010';case 's':return ' ';case 'M':if(flags &ESCAPE_META) goto eof;if((c=nextc())!= '-'){pushback(c);goto eof;}if((c=nextc())== '\\'){if(peek('u')) goto eof;return read_escape(flags|ESCAPE_META, encp)|0x80;}else if(c==-1||!ISASCII(c)) goto eof;else{return((c &0xff)|0x80);}case 'C':if((c=nextc())!= '-'){pushback(c);goto eof;}case 'c':if(flags &ESCAPE_CONTROL) goto eof;if((c=nextc())== '\\'){if(peek('u')) goto eof;c=read_escape(flags|ESCAPE_CONTROL, encp);}else if(c== '?') return 0177;else if(c==-1||!ISASCII(c)) goto eof;return c &0x9f;eof:case-1:yyerror("Invalid escape character syntax");return '\0';default:return c;}}static voidparser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc){int len=rb_enc_codelen(c, enc);rb_enc_mbcput(c, tokspace(len), enc);}static intparser_tokadd_escape(struct parser_params *parser, rb_encoding **encp){int c;int flags=0;size_t numlen;first:switch(c=nextc()){case '\n':return 0;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':{ruby_scan_oct(--lex_p, 3,&numlen);if(numlen==0) goto eof;lex_p+=numlen;tokcopy((int) numlen+1);}return 0;case 'x':{tok_hex(&numlen);if(numlen==0) return-1;tokcopy((int) numlen+2);}return 0;case 'M':if(flags &ESCAPE_META) goto eof;if((c=nextc())!= '-'){pushback(c);goto eof;}tokcopy(3);flags|=ESCAPE_META;goto escaped;case 'C':if(flags &ESCAPE_CONTROL) goto eof;if((c=nextc())!= '-'){pushback(c);goto eof;}tokcopy(3);goto escaped;case 'c':if(flags &ESCAPE_CONTROL) goto eof;tokcopy(2);flags|=ESCAPE_CONTROL;escaped:if((c=nextc())== '\\'){goto first;}else if(c==-1) goto eof;tokadd(c);return 0;eof:case-1:yyerror("Invalid escape character syntax");return-1;default:tokadd('\\');tokadd(c);}return 0;}static intparser_regx_options(struct parser_params *parser){int kcode=0;int kopt=0;int options=0;int c, opt, kc;newtok();while(c=nextc(), ISALPHA(c)){if(c== 'o'){options|=RE_OPTION_ONCE;}else if(rb_char_to_option_kcode(c,&opt,&kc)){if(kc >=0){if(kc!=rb_ascii8bit_encindex()) kcode=c;kopt=opt;}else{options|=opt;}}else{tokadd(c);}}options|=kopt;pushback(c);if(toklen()){tokfix();compile_error(PARSER_ARG"unknown regexp option%s - %s", toklen() > 1?"s":"", tok());}return options|RE_OPTION_ENCODING(kcode);}static voiddispose_string(VALUE str){rb_str_free(str);rb_gc_force_recycle(str);}static intparser_tokadd_mbchar(struct parser_params *parser, int c){int len=parser_precise_mbclen();if(!MBCLEN_CHARFOUND_P(len)){compile_error(PARSER_ARG"invalid multibyte char (%s)", parser_encoding_name());return-1;}tokadd(c);lex_p+=--len;if(len > 0) tokcopy(len);return c;}#define tokadd_mbchar(c) static inline intsimple_re_meta(int c){switch(c){case '$':case '*':case '+':case '.':case '?':case '^':case '|':case ')':case ']':case '}':case '>':return TRUE;default:return FALSE;}}static intparser_tokadd_string(struct parser_params *parser, int func, int term, int paren, long *nest, rb_encoding **encp){int c;int has_nonascii=0;rb_encoding *enc=*encp;char *errbuf=0;static const char mixed_msg[]="%s mixed within %s source";#define mixed_error(enc1, enc2)#define mixed_escape(beg, enc1, enc2) while((c=nextc())!=-1){if(paren &&c==paren){++*nest;}else if(c==term){if(!nest||!*nest){pushback(c);break;}--*nest;}else if((func &STR_FUNC_EXPAND)&&c== '#'&&lex_p< lex_pend){int c2=*lex_p;if(c2== '$'||c2== '@'||c2== '{'){pushback(c);break;}}else if(c== '\\'){const char *beg=lex_p-1;c=nextc();switch(c){case '\n':if(func &STR_FUNC_QWORDS) break;if(func &STR_FUNC_EXPAND) continue;tokadd('\\');break;case '\\':if(func &STR_FUNC_ESCAPE) tokadd(c);break;case 'u':if((func &STR_FUNC_EXPAND)==0){tokadd('\\');break;}parser_tokadd_utf8(parser,&enc, 1, func &STR_FUNC_SYMBOL, func &STR_FUNC_REGEXP);if(has_nonascii &&enc!=*encp){mixed_escape(beg, enc,*encp);}continue;default:if(c==-1) return-1;if(!ISASCII(c)){if((func &STR_FUNC_EXPAND)==0) tokadd('\\');goto non_ascii;}if(func &STR_FUNC_REGEXP){if(c==term &&!simple_re_meta(c)){tokadd(c);continue;}pushback(c);if((c=tokadd_escape(&enc))< 0) return-1;if(has_nonascii &&enc!=*encp){mixed_escape(beg, enc,*encp);}continue;}else if(func &STR_FUNC_EXPAND){pushback(c);if(func &STR_FUNC_ESCAPE) tokadd('\\');c=read_escape(0,&enc);}else if((func &STR_FUNC_QWORDS)&&ISSPACE(c)){}else if(c!=term &&!(paren &&c==paren)){tokadd('\\');pushback(c);continue;}}}else if(!parser_isascii()){non_ascii:has_nonascii=1;if(enc!=*encp){mixed_error(enc,*encp);continue;}if(tokadd_mbchar(c)==-1) return-1;continue;}else if((func &STR_FUNC_QWORDS)&&ISSPACE(c)){pushback(c);break;}if(c &0x80){has_nonascii=1;if(enc!=*encp){mixed_error(enc,*encp);continue;}}tokadd(c);}*encp=enc;return c;}#define NEW_STRTERM(func, term, paren)#define flush_string_content(enc) RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e-0x20+31)/32];#define BIT(c, idx)#define SPECIAL_PUNCT(idx) const unsigned int ruby_global_name_punct_bits[]={SPECIAL_PUNCT(0), SPECIAL_PUNCT(1), SPECIAL_PUNCT(2),};static inline intis_global_name_punct(const char c){if(c<=0x20||0x7e< c) return 0;return(ruby_global_name_punct_bits[(c-0x20)/32] >>(c%32))&1;}static intparser_peek_variable_name(struct parser_params *parser){int c;const char *p=lex_p;if(p+1 >=lex_pend) return 0;c=*p++;switch(c){case '$':if((c=*p)== '-'){if(++p >=lex_pend) return 0;c=*p;}else if(is_global_name_punct(c)||ISDIGIT(c)){return tSTRING_DVAR;}break;case '@':if((c=*p)== '@'){if(++p >=lex_pend) return 0;c=*p;}break;case '{':lex_p=p;command_start=TRUE;return tSTRING_DBEG;default:return 0;}if(!ISASCII(c)||c== '_'||ISALPHA(c)) return tSTRING_DVAR;return 0;}static intparser_parse_string(struct parser_params *parser, NODE *quote){int func=(int) quote->nd_func;int term=nd_term(quote);int paren=nd_paren(quote);int c, space=0;rb_encoding *enc=current_enc;if(func==-1) return tSTRING_END;c=nextc();if((func &STR_FUNC_QWORDS)&&ISSPACE(c)){do{c=nextc();}while(ISSPACE(c));space=1;}if(c==term &&!quote->nd_nest){if(func &STR_FUNC_QWORDS){quote->nd_func=-1;return ' ';}if(!(func &STR_FUNC_REGEXP)) return tSTRING_END;set_yylval_num(regx_options());return tREGEXP_END;}if(space){pushback(c);return ' ';}newtok();if((func &STR_FUNC_EXPAND)&&c== '#'){int t=parser_peek_variable_name(parser);if(t) return t;tokadd('#');c=nextc();}pushback(c);if(tokadd_string(func, term, paren,&quote->nd_nest,&enc)==-1){ruby_sourceline=nd_line(quote);if(func &STR_FUNC_REGEXP){if(parser->eofp) compile_error(PARSER_ARG"unterminated regexp meets end of file");return tREGEXP_END;}else{if(parser->eofp) compile_error(PARSER_ARG"unterminated string meets end of file");return tSTRING_END;}}tokfix();set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));flush_string_content(enc);return tSTRING_CONTENT;}static intparser_heredoc_identifier(struct parser_params *parser){int c=nextc(), term, func=0;long len;if(c== '-'){c=nextc();func=STR_FUNC_INDENT;}switch(c){case '\'':func|=str_squote;goto quoted;case '"': func |= str_dquote; goto quoted; case '`': func |= str_xquote; quoted: newtok(); tokadd(func); term = c; while ((c = nextc()) != -1 && c != term) { if (tokadd_mbchar(c) == -1) return 0; } if (c == -1) { compile_error(PARSER_ARG "unterminated here document identifier"); return 0; } break; default: if (!parser_is_identchar()) { pushback(c); if (func & STR_FUNC_INDENT) { pushback('-'); } return 0; } newtok(); term = '"';tokadd(func|=str_dquote);do{if(tokadd_mbchar(c)==-1) return 0;}while((c=nextc())!=-1 &&parser_is_identchar());pushback(c);break;}tokfix();len=lex_p-lex_pbeg;lex_goto_eol(parser);lex_strterm=rb_node_newnode(NODE_HEREDOC, STR_NEW(tok(), toklen()), len, lex_lastline);nd_set_line(lex_strterm, ruby_sourceline);ripper_flush(parser);return term== '`'?tXSTRING_BEG:tSTRING_BEG;}static voidparser_heredoc_restore(struct parser_params *parser, NODE *here){VALUE line;line=here->nd_orig;lex_lastline=line;lex_pbeg=RSTRING_PTR(line);lex_pend=lex_pbeg+RSTRING_LEN(line);lex_p=lex_pbeg+here->nd_nth;heredoc_end=ruby_sourceline;ruby_sourceline=nd_line(here);dispose_string(here->nd_lit);rb_gc_force_recycle((VALUE) here);ripper_flush(parser);}static intparser_whole_match_p(struct parser_params *parser, const char *eos, long len, int indent){const char *p=lex_pbeg;long n;if(indent){while(*p &&ISSPACE(*p)) p++;}n=lex_pend-(p+len);if(n< 0||(n > 0 &&p[len]!= '\n'&&p[len]!= '\r')) return FALSE;return strncmp(eos, p, len)==0;}#define dispatch_heredoc_end() static intparser_here_document(struct parser_params *parser, NODE *here){int c, func, indent=0;const char *eos,*p,*pend;long len;VALUE str=0;rb_encoding *enc=current_enc;eos=RSTRING_PTR(here->nd_lit);len=RSTRING_LEN(here->nd_lit)-1;indent=(func=*eos++)&STR_FUNC_INDENT;if((c=nextc())==-1){error:compile_error(PARSER_ARG"can't find string \"%s\" anywhere before EOF", eos);restore:heredoc_restore(lex_strterm);lex_strterm=0;return 0;}if(was_bol()&&whole_match_p(eos, len, indent)){dispatch_heredoc_end();heredoc_restore(lex_strterm);return tSTRING_END;}if(!(func &STR_FUNC_EXPAND)){do{p=RSTRING_PTR(lex_lastline);pend=lex_pend;if(pend > p){switch(pend[-1]){case '\n':if(--pend==p||pend[-1]!= '\r'){pend++;break;}case '\r':--pend;}}if(str) rb_str_cat(str, p, pend-p);else str=STR_NEW(p, pend-p);if(pend< lex_pend) rb_str_cat(str,"\n", 1);lex_goto_eol(parser);if(nextc()==-1){if(str) dispose_string(str);goto error;}}while(!whole_match_p(eos, len, indent));}else{newtok();if(c== '#'){int t=parser_peek_variable_name(parser);if(t) return t;tokadd('#');c=nextc();}do{pushback(c);if((c=tokadd_string(func, '\n', 0, NULL,&enc))==-1){if(parser->eofp) goto error;goto restore;}if(c!= '\n'){set_yylval_str(STR_NEW3(tok(), toklen(), enc, func));flush_string_content(enc);return tSTRING_CONTENT;}tokadd(nextc());if((c=nextc())==-1) goto error;}while(!whole_match_p(eos, len, indent));str=STR_NEW3(tok(), toklen(), enc, func);}dispatch_heredoc_end();heredoc_restore(lex_strterm);lex_strterm=NEW_STRTERM(-1, 0, 0);set_yylval_str(str);return tSTRING_CONTENT;}static voidarg_ambiguous_gen(struct parser_params *parser){rb_warning0("ambiguous first argument; put parentheses or even spaces");}#define arg_ambiguous() static IDformal_argument_gen(struct parser_params *parser, ID lhs){if(!is_local_id(lhs)) yyerror("formal argument must be local variable");shadowing_lvar(lhs);return lhs;}static intlvar_defined_gen(struct parser_params *parser, ID id){return(dyna_in_block()&&dvar_defined_get(id))||local_id(id);}static longparser_encode_length(struct parser_params *parser, const char *name, long len){long nlen;if(len > 5 &&name[nlen=len-5]== '-'){if(rb_memcicmp(name+nlen+1,"unix", 4)==0) return nlen;}if(len > 4 &&name[nlen=len-4]== '-'){if(rb_memcicmp(name+nlen+1,"dos", 3)==0) return nlen;if(rb_memcicmp(name+nlen+1,"mac", 3)==0 &&!(len==8 &&rb_memcicmp(name,"utf8-mac", len)==0)) return nlen;}return len;}static voidparser_set_encode(struct parser_params *parser, const char *name){int idx=rb_enc_find_index(name);rb_encoding *enc;VALUE excargs[3];if(idx< 0){excargs[1]=rb_sprintf("unknown encoding name: %s", name);error:excargs[0]=rb_eArgError;excargs[2]=rb_make_backtrace();rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline));rb_exc_raise(rb_make_exception(3, excargs));}enc=rb_enc_from_index(idx);if(!rb_enc_asciicompat(enc)){excargs[1]=rb_sprintf("%s is not ASCII compatible", rb_enc_name(enc));goto error;}parser->enc=enc;if(ruby_debug_lines){long i, n=RARRAY_LEN(ruby_debug_lines);const VALUE *p=RARRAY_PTR(ruby_debug_lines);for(i=0;i< n;++i){rb_enc_associate_index(*p, idx);}}}static intcomment_at_top(struct parser_params *parser){const char *p=lex_pbeg,*pend=lex_p-1;if(parser->line_count!=(parser->has_shebang?2:1)) return 0;while(p< pend){if(!ISSPACE(*p)) return 0;p++;}return 1;}typedef long(*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, long len);typedef void(*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);static voidmagic_comment_encoding(struct parser_params *parser, const char *name, const char *val){if(!comment_at_top(parser)){return;}parser_set_encode(parser, val);}static voidparser_set_token_info(struct parser_params *parser, const char *name, const char *val){int *p=&parser->parser_token_info_enabled;switch(*val){case 't':case 'T':if(strcasecmp(val,"true")==0){*p=TRUE;return;}break;case 'f':case 'F':if(strcasecmp(val,"false")==0){*p=FALSE;return;}break;}rb_compile_warning(ruby_sourcefile, ruby_sourceline,"invalid value for %s: %s", name, val);}struct magic_comment{const char *name;rb_magic_comment_setter_t func;rb_magic_comment_length_t length;};static const struct magic_comment magic_comments[]={{"coding", magic_comment_encoding, parser_encode_length},{"encoding", magic_comment_encoding, parser_encode_length},{"warn_indent", parser_set_token_info},};static const char *magic_comment_marker(const char *str, long len){long i=2;while(i< len){switch(str[i]){case '-':if(str[i-1]== '*'&&str[i-2]== '-'){return str+i+1;}i+=2;break;case '*':if(i+1 >=len) return 0;if(str[i+1]!= '-'){i+=4;}else if(str[i-1]!= '-'){i+=2;}else{return str+i+2;}break;default:i+=3;break;}}return 0;}static intparser_magic_comment(struct parser_params *parser, const char *str, long len){VALUE name=0, val=0;const char *beg,*end,*vbeg,*vend;#define str_copy(_s, _p, _n) if(len<=7) return FALSE;if(!(beg=magic_comment_marker(str, len))) return FALSE;if(!(end=magic_comment_marker(beg, str+len-beg))) return FALSE;str=beg;len=end-beg-3;while(len > 0){const struct magic_comment *p=magic_comments;char *s;int i;long n=0;for(;len > 0 &&*str;str++,--len){switch(*str){case '\'':case '"': case ':': case ';': continue; } if (!ISSPACE(*str)) break; } for (beg = str; len > 0; str++, --len) { switch (*str) { case '\'': case '"':case ':':case ';':break;default:if(ISSPACE(*str)) break;continue;}break;}for(end=str;len > 0 &&ISSPACE(*str);str++,--len);if(!len) break;if(*str!= ':') continue;do str++;while(--len > 0 &&ISSPACE(*str));if(!len) break;if(*str== '"') { for (vbeg = ++str; --len > 0 && *str != '"';str++){if(*str== '\\'){--len;++str;}}vend=str;if(len){--len;++str;}}else{for(vbeg=str;len > 0 &&*str!= '"' && *str != ';' && !ISSPACE(*str); --len, str++); vend = str; } while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++; n = end - beg; str_copy(name, beg, n); s = RSTRING_PTR(name); for (i = 0; i < n; ++i) { if (s[i] == '-') s[i] = '_'; } do { if (STRNCASECMP(p->name, s, n) == 0) { n = vend - vbeg; if (p->length) { n = (*p->length)(parser, vbeg, n); } str_copy(val, vbeg, n); (*p->func)(parser, s, RSTRING_PTR(val)); break; } } while (++p < magic_comments + numberof(magic_comments)); } return TRUE;}static voidset_file_encoding(struct parser_params *parser, const char *str, const char *send){ int sep = 0; const char *beg = str; VALUE s; for (;;) { if (send - str <= 6) return; switch (str[6]) { case 'C': case 'c': str += 6; continue; case 'O': case 'o': str += 5; continue; case 'D': case 'd': str += 4; continue; case 'I': case 'i': str += 3; continue; case 'N': case 'n': str += 2; continue; case 'G': case 'g': str += 1; continue; case '=': case ':': sep = 1; str += 6; break; default: str += 6; if (ISSPACE(*str)) break; continue; } if (STRNCASECMP(str-6, "coding", 6) == 0) break; } for (;;) { do { if (++str >= send) return; } while (ISSPACE(*str)); if (sep) break; if (*str != '=' && *str != ':') return; sep = 1; str++; } beg = str; while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send); s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg)); parser_set_encode(parser, RSTRING_PTR(s)); rb_str_resize(s, 0);}static voidparser_prepare(struct parser_params *parser){ int c = nextc(); switch (c) { case '#': if (peek('!')) parser->has_shebang = 1; break; case 0xef: if (lex_pend - lex_p >= 2 && (unsigned char)lex_p[0] == 0xbb && (unsigned char)lex_p[1] == 0xbf) { parser->enc = rb_utf8_encoding(); lex_p += 2; lex_pbeg = lex_p; return; } break; case EOF: return; } pushback(c); parser->enc = rb_enc_get(lex_lastline);}#define IS_ARG() #define IS_END() #define IS_BEG() #define IS_SPCARG(c) #define IS_LABEL_POSSIBLE() #define IS_LABEL_SUFFIX(n) #define IS_AFTER_OPERATOR() #define ambiguous_operator(op, syn) #define warn_balanced(op, syn) static intparser_yylex(struct parser_params *parser){ register int c; int space_seen = 0; int cmd_state; enum lex_state_e last_state; rb_encoding *enc; int mb; if (lex_strterm) { int token; if (nd_type(lex_strterm) == NODE_HEREDOC) { token = here_document(lex_strterm); if (token == tSTRING_END) { lex_strterm = 0; lex_state = EXPR_END; } } else { token = parse_string(lex_strterm); if (token == tSTRING_END || token == tREGEXP_END) { rb_gc_force_recycle((VALUE)lex_strterm); lex_strterm = 0; lex_state = EXPR_END; } } return token; } cmd_state = command_start; command_start = FALSE; retry: last_state = lex_state; switch (c = nextc()) { case '\0': case '\004': case '\032': case -1: return 0; case ' ': case '\t': case '\f': case '\r': case '\13': space_seen = 1; goto retry; case '#': if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) { if (comment_at_top(parser)) { set_file_encoding(parser, lex_p, lex_pend); } } lex_p = lex_pend; case '\n': if (IS_lex_state(EXPR_BEG | EXPR_VALUE | EXPR_CLASS | EXPR_FNAME | EXPR_DOT)) { goto retry; } while ((c = nextc())) { switch (c) { case ' ': case '\t': case '\f': case '\r': case '\13': space_seen = 1; break; case '.': { if ((c = nextc()) != '.') { pushback(c); pushback('.'); goto retry; } } default: --ruby_sourceline; lex_nextline = lex_lastline; case -1: lex_goto_eol(parser); goto normal_newline; } } normal_newline: command_start = TRUE; lex_state = EXPR_BEG; return '\n'; case '*': if ((c = nextc()) == '*') { if ((c = nextc()) == '=') { set_yylval_id(tPOW); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`**'interpreted as argument prefix"); c = tDSTAR; } else if (IS_BEG()) { c = tDSTAR; } else { warn_balanced("**", "argument prefix"); c = tPOW; } } else { if (c == '=') { set_yylval_id('*'); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`*'interpreted as argument prefix"); c = tSTAR; } else if (IS_BEG()) { c = tSTAR; } else { warn_balanced("*", "argument prefix"); c = '*'; } } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; return c; case '!': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return '!'; } } else { lex_state = EXPR_BEG; } if (c == '=') { return tNEQ; } if (c == '~') { return tNMATCH; } pushback(c); return '!'; case '=': if (was_bol()) { if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) { for (;;) { lex_goto_eol(parser); c = nextc(); if (c == -1) { compile_error(PARSER_ARG "embedded document meets end of file"); return 0; } if (c != '=') continue; if (strncmp(lex_p, "end", 3) == 0 && (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) { break; } } lex_goto_eol(parser); goto retry; } } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; if ((c = nextc()) == '=') { if ((c = nextc()) == '=') { return tEQQ; } pushback(c); return tEQ; } if (c == '~') { return tMATCH; } else if (c == '>') { return tASSOC; } pushback(c); return '='; case '<': last_state = lex_state; c = nextc(); if (c == '<' && !IS_lex_state(EXPR_DOT | EXPR_CLASS) && !IS_END() && (!IS_ARG() || space_seen)) { int token = heredoc_identifier(); if (token) return token; } if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; } else { if (IS_lex_state(EXPR_CLASS)) command_start = TRUE; lex_state = EXPR_BEG; } if (c == '=') { if ((c = nextc()) == '>') { return tCMP; } pushback(c); return tLEQ; } if (c == '<') { if ((c = nextc()) == '=') { set_yylval_id(tLSHFT); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); warn_balanced("<<", "here document"); return tLSHFT; } pushback(c); return '<'; case '>': lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; if ((c = nextc()) == '=') { return tGEQ; } if (c == '>') { if ((c = nextc()) == '=') { set_yylval_id(tRSHFT); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tRSHFT; } pushback(c); return '>'; case '"':lex_strterm=NEW_STRTERM(str_dquote, '"', 0); return tSTRING_BEG; case '`': if (IS_lex_state(EXPR_FNAME)) { lex_state = EXPR_ENDFN; return c; } if (IS_lex_state(EXPR_DOT)) { if (cmd_state) lex_state = EXPR_CMDARG; else lex_state = EXPR_ARG; return c; } lex_strterm = NEW_STRTERM(str_xquote, '`', 0); return tXSTRING_BEG; case '\'': lex_strterm = NEW_STRTERM(str_squote, '\'', 0); return tSTRING_BEG; case '?': if (IS_END()) { lex_state = EXPR_VALUE; return '?'; } c = nextc(); if (c == -1) { compile_error(PARSER_ARG "incomplete character syntax"); return 0; } if (rb_enc_isspace(c, current_enc)) { if (!IS_ARG()) { int c2 = 0; switch (c) { case ' ': c2 = 's'; break; case '\n': c2 = 'n'; break; case '\t': c2 = 't'; break; case '\v': c2 = 'v'; break; case '\r': c2 = 'r'; break; case '\f': c2 = 'f'; break; } if (c2) { rb_warnI("invalid character syntax;use?\\%c", c2); } } ternary: pushback(c); lex_state = EXPR_VALUE; return '?'; } newtok(); enc = current_enc; if (!parser_isascii()) { if (tokadd_mbchar(c) == -1) return 0; } else if ((rb_enc_isalnum(c, current_enc) || c == '_') && lex_p < lex_pend && is_identchar(lex_p, lex_pend, current_enc)) { goto ternary; } else if (c == '\\') { if (peek('u')) { nextc(); c = parser_tokadd_utf8(parser, &enc, 0, 0, 0); if (0x80 <= c) { tokaddmbc(c, enc); } else { tokadd(c); } } else if (!lex_eol_p() && !(c = *lex_p, ISASCII(c))) { nextc(); if (tokadd_mbchar(c) == -1) return 0; } else { c = read_escape(0, &enc); tokadd(c); } } else { tokadd(c); } tokfix(); set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0)); lex_state = EXPR_END; return tCHAR; case '&': if ((c = nextc()) == '&') { lex_state = EXPR_BEG; if ((c = nextc()) == '=') { set_yylval_id(tANDOP); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tANDOP; } else if (c == '=') { set_yylval_id('&'); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`&'interpreted as argument prefix"); c = tAMPER; } else if (IS_BEG()) { c = tAMPER; } else { warn_balanced("&", "argument prefix"); c = '&'; } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; return c; case '|': if ((c = nextc()) == '|') { lex_state = EXPR_BEG; if ((c = nextc()) == '=') { set_yylval_id(tOROP); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tOROP; } if (c == '=') { set_yylval_id('|'); lex_state = EXPR_BEG; return tOP_ASGN; } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; pushback(c); return '|'; case '+': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return tUPLUS; } pushback(c); return '+'; } if (c == '=') { set_yylval_id('+'); lex_state = EXPR_BEG; return tOP_ASGN; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) { lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { c = '+'; goto start_num; } return tUPLUS; } lex_state = EXPR_BEG; pushback(c); warn_balanced("+", "unary operator"); return '+'; case '-': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return tUMINUS; } pushback(c); return '-'; } if (c == '=') { set_yylval_id('-'); lex_state = EXPR_BEG; return tOP_ASGN; } if (c == '>') { lex_state = EXPR_ENDFN; return tLAMBDA; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) { lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { return tUMINUS_NUM; } return tUMINUS; } lex_state = EXPR_BEG; pushback(c); warn_balanced("-", "unary operator"); return '-'; case '.': lex_state = EXPR_BEG; if ((c = nextc()) == '.') { if ((c = nextc()) == '.') { return tDOT3; } pushback(c); return tDOT2; } pushback(c); if (c != -1 && ISDIGIT(c)) { yyerror("no.< digit > floating literal anymore;put 0 before dot"); } lex_state = EXPR_DOT; return '.'; start_num: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int is_float, seen_point, seen_e, nondigit; is_float = seen_point = seen_e = nondigit = 0; lex_state = EXPR_END; newtok(); if (c == '-' || c == '+') { tokadd(c); c = nextc(); } if (c == '0') {#define no_digits() int start = toklen(); c = nextc(); if (c == 'x' || c == 'X') { c = nextc(); if (c != -1 && ISXDIGIT(c)) { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (!ISXDIGIT(c)) break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 16, FALSE)); return tINTEGER; } if (c == 'b' || c == 'B') { c = nextc(); if (c == '0' || c == '1') { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (c != '0' && c != '1') break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 2, FALSE)); return tINTEGER; } if (c == 'd' || c == 'D') { c = nextc(); if (c != -1 && ISDIGIT(c)) { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (!ISDIGIT(c)) break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE)); return tINTEGER; } if (c == '_') { goto octal_number; } if (c == 'o' || c == 'O') { c = nextc(); if (c == -1 || c == '_' || !ISDIGIT(c)) { no_digits(); } } if (c >= '0' && c <= '7') { octal_number: do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (c < '0' || c > '9') break; if (c > '7') goto invalid_octal; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); if (toklen() > start) { pushback(c); tokfix(); if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 8, FALSE)); return tINTEGER; } if (nondigit) { pushback(c); goto trailing_uc; } } if (c > '7' && c <= '9') { invalid_octal: yyerror("Invalid octal digit"); } else if (c == '.' || c == 'e' || c == 'E') { tokadd('0'); } else { pushback(c); set_yylval_literal(INT2FIX(0)); return tINTEGER; } } for (;;) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': nondigit = 0; tokadd(c); break; case '.': if (nondigit) goto trailing_uc; if (seen_point || seen_e) { goto decode_num; } else { int c0 = nextc(); if (c0 == -1 || !ISDIGIT(c0)) { pushback(c0); goto decode_num; } c = c0; } tokadd('.'); tokadd(c); is_float++; seen_point++; nondigit = 0; break; case 'e': case 'E': if (nondigit) { pushback(c); c = nondigit; goto decode_num; } if (seen_e) { goto decode_num; } tokadd(c); seen_e++; is_float++; nondigit = c; c = nextc(); if (c != '-' && c != '+') continue; tokadd(c); nondigit = c; break; case '_': if (nondigit) goto decode_num; nondigit = c; break; default: goto decode_num; } c = nextc(); } decode_num: pushback(c); if (nondigit) { char tmp[30]; trailing_uc: snprintf(tmp, sizeof(tmp), "trailing`%c'in number", nondigit); yyerror(tmp); } tokfix(); if (is_float) { double d = strtod(tok(), 0); if (errno == ERANGE) { rb_warningS("Float%s out of range", tok()); errno = 0; } set_yylval_literal(DBL2NUM(d)); return tFLOAT; } set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE)); return tINTEGER; } case ')': case '] 
__pad18__
 
pure parser lex param
 
top_compstmt __pad0__
 
fixup_nodesdeferred_nodes
 
top_stmts __pad1__ = $1
 
 top_stmt
 
top_stmt __pad2__
 
top_stmt bodystmt = NEW_BEGIN(0)
 
compstmt __pad3__
 
stmts __pad4__ = $1
 
 stmt_or_begin
 
error stmt
 
stmt_or_begin __pad5__
 
 keyword_BEGIN
 
command_asgn __pad6__
 
 lhs
 
expr __pad7__
 
expr expr keyword_or expr
 
 command_call
 
 arg
 
expr_value __pad8__
 
command_call __pad9__
 
block_command __pad10__
 
block_command cmd_brace_block
 
< num > opt_block_param compstmt
 
fcall __pad11__
 
command __pad12__
 
 nd_args = $2
 
 nd_iter = $1
 
primary_value operation2
command_args prec 
tLOWEST
 
keyword_super command_args
 
keyword_return call_args
 
mlhs __pad13__
 
mlhs_inner __pad14__
 
mlhs_inner mlhs_basic
 
mlhs_inner mlhs_head mlhs_item
 
mlhs_head tSTAR mlhs_node
 
mlhs_head tSTAR mlhs_post
 
mlhs_head tSTAR
 
mlhs_item __pad15__
 
mlhs_head __pad16__
 
mlhs_node __pad17__
 
mlhs_node keyword_variable
 
case __pad19__
 
else lex_state = EXPR_ENDARG
 
return c
 
case __pad20__
 
return tSYMBEG
 
case __pad21__
 
case return tREGEXP_BEG
 
 return
 
case __pad22__
 
return tOP_ASGN
 
 case
 
 __pad23__
 
 command_start = TRUE
 
 __pad24__
 
case __pad25__
 
 else
 

Macro Definition Documentation

#define ADD2HEAP (   n,
  c,
  p 
)
Value:
((parser->heap = (n))->u1.node = (p), \
(n)->u3.cnt = (c), (p))
return c
Definition: parse.y:7591
Win32OLEIDispatch * p
Definition: win32ole.c:786
#define ambiguous_operator (   op,
  syn 
)
Value:
( \
rb_warning0("`"op"' after local variable is interpreted as binary operator"), \
rb_warning0("even though it seems like "syn""))
#define rb_warning0(fmt)
Definition: parse.y:639
#define arg_ambiguous ( )    (arg_ambiguous_gen(parser), 1)

Referenced by if().

#define arg_append (   h,
 
)    arg_append_gen(parser,(h),(t))

Definition at line 392 of file parse.y.

#define arg_concat (   h,
 
)    arg_concat_gen(parser,(h),(t))

Definition at line 394 of file parse.y.

#define arg_var (   id)    arg_var_gen(parser, (id))

Definition at line 501 of file parse.y.

#define aryset (   node1,
  node2 
)    aryset_gen(parser, (node1), (node2))

Definition at line 429 of file parse.y.

#define assignable (   id,
  node 
)    assignable_gen(parser, (id), (node))

Definition at line 426 of file parse.y.

#define assignable_result (   x)    (x)
#define attrset (   node,
  id 
)    attrset_gen(parser, (node), (id))

Definition at line 431 of file parse.y.

#define BIT (   c,
  idx 
)    (((c) / 32 - 1 == idx) ? (1U << ((c) % 32)) : 0)
#define BITSTACK_LEXPOP (   stack)    ((stack) = ((stack) >> 1) | ((stack) & 1))

Definition at line 110 of file parse.y.

#define BITSTACK_POP (   stack)    ((stack) = (stack) >> 1)

Definition at line 109 of file parse.y.

#define BITSTACK_PUSH (   stack,
 
)    ((stack) = ((stack)<<1)|((n)&1))

Definition at line 108 of file parse.y.

#define BITSTACK_SET_P (   stack)    ((stack)&1)

Definition at line 111 of file parse.y.

#define block_append (   h,
 
)    block_append_gen(parser,(h),(t))

Definition at line 386 of file parse.y.

#define block_dup_check (   n1,
  n2 
)    block_dup_check_gen(parser,(n1),(n2))

Definition at line 383 of file parse.y.

#define brace_nest   (parser->parser_brace_nest)

Definition at line 317 of file parse.y.

Referenced by if().

#define call_bin_op (   recv,
  id,
  arg1 
)    call_bin_op_gen(parser, (recv),(id),(arg1))

Definition at line 405 of file parse.y.

#define call_uni_op (   recv,
  id 
)    call_uni_op_gen(parser, (recv),(id))

Definition at line 407 of file parse.y.

#define calloc   YYCALLOC
#define class_nest   (parser->parser_class_nest)

Definition at line 314 of file parse.y.

#define CMDARG_LEXPOP ( )    BITSTACK_LEXPOP(cmdarg_stack)

Definition at line 120 of file parse.y.

#define CMDARG_P ( )    BITSTACK_SET_P(cmdarg_stack)

Definition at line 121 of file parse.y.

#define CMDARG_POP ( )    BITSTACK_POP(cmdarg_stack)

Definition at line 119 of file parse.y.

#define CMDARG_PUSH (   n)    BITSTACK_PUSH(cmdarg_stack, (n))

Definition at line 118 of file parse.y.

#define cmdarg_stack   (parser->parser_cmdarg_stack)

Definition at line 313 of file parse.y.

#define command_start   (parser->parser_command_start)

Definition at line 334 of file parse.y.

#define compile_error   parser->nerr++,rb_compile_error_with_enc

Definition at line 662 of file parse.y.

#define compile_for_eval   (parser->parser_compile_for_eval)

Definition at line 320 of file parse.y.

#define cond (   node)    cond_gen(parser, (node))

Definition at line 365 of file parse.y.

#define COND_LEXPOP ( )    BITSTACK_LEXPOP(cond_stack)

Definition at line 115 of file parse.y.

#define COND_P ( )    BITSTACK_SET_P(cond_stack)

Definition at line 116 of file parse.y.

#define COND_POP ( )    BITSTACK_POP(cond_stack)

Definition at line 114 of file parse.y.

#define COND_PUSH (   n)    BITSTACK_PUSH(cond_stack, (n))

Definition at line 113 of file parse.y.

#define cond_stack   (parser->parser_cond_stack)

Definition at line 312 of file parse.y.

#define cur_mid   (parser->parser_cur_mid)

Definition at line 321 of file parse.y.

#define current_enc   (parser->enc)

Definition at line 342 of file parse.y.

#define DEF_EXPR (   n)    EXPR_##n = (1 << EXPR_##n##_bit)

Definition at line 83 of file parse.y.

#define deferred_nodes   (parser->parser_deferred_nodes)

Definition at line 335 of file parse.y.

#define dispatch_heredoc_end ( )    ((void)0)
#define dsym_node (   node)    dsym_node_gen(parser, (node))

Definition at line 421 of file parse.y.

#define dvar_curr (   id)    dvar_curr_gen(parser, (id))

Definition at line 518 of file parse.y.

#define dvar_defined (   id)    dvar_defined_gen(parser, (id), 0)

Definition at line 515 of file parse.y.

#define dvar_defined_get (   id)    dvar_defined_gen(parser, (id), 1)

Definition at line 516 of file parse.y.

#define DVARS_INHERIT   ((void*)1)

Definition at line 138 of file parse.y.

#define DVARS_SPECIAL_P (   tbl)    (!POINTER_P(tbl))

Definition at line 140 of file parse.y.

#define DVARS_TOPSCOPE   NULL

Definition at line 139 of file parse.y.

#define dyna_in_block ( )    dyna_in_block_gen(parser)

Definition at line 512 of file parse.y.

#define dyna_pop (   node)    dyna_pop_gen(parser, (node))

Definition at line 510 of file parse.y.

#define dyna_push ( )    dyna_push_gen(parser)

Definition at line 508 of file parse.y.

#define dyna_var (   id)    local_var(id)

Definition at line 513 of file parse.y.

#define ENABLE_SELECTOR_NAMESPACE   0
#define ENC_SINGLE (   cr)    ((cr)==ENC_CODERANGE_7BIT)

Definition at line 304 of file parse.y.

#define ESCAPE_CONTROL   1
#define ESCAPE_META   2
#define evstr2dstr (   n)    evstr2dstr_gen(parser,(n))

Definition at line 401 of file parse.y.

#define flush_string_content (   enc)    ((void)(enc))
#define formal_argument (   id)    formal_argument_gen(parser, (id))

Definition at line 488 of file parse.y.

#define free   YYFREE
#define get_id (   id)    (id)

Definition at line 461 of file parse.y.

#define get_value (   val)    (val)

Definition at line 462 of file parse.y.

#define gettable (   id)    gettable_gen(parser,(id))

Definition at line 424 of file parse.y.

#define HEAPCNT (   n,
  size 
)    ((n) * (size) / sizeof(YYSTYPE))
#define here_document (   n)    parser_here_document(parser,(n))
#define heredoc_end   (parser->parser_heredoc_end)

Definition at line 333 of file parse.y.

#define heredoc_identifier ( )    parser_heredoc_identifier(parser)
#define heredoc_restore (   n)    parser_heredoc_restore(parser,(n))
#define id_type (   id)    (is_notop_id(id) ? (int)((id)&ID_SCOPE_MASK) : -1)

Definition at line 60 of file parse.y.

#define IDSET_ATTRSET_FOR_INTERN   (~(~0U<<(1<<ID_SCOPE_SHIFT)) & ~(1U<<ID_ATTRSET))
#define IDSET_ATTRSET_FOR_SYNTAX   ((1U<<ID_LOCAL)|(1U<<ID_CONST))
#define ifndef_ripper (   x)    (x)

Definition at line 628 of file parse.y.

#define in_def   (parser->parser_in_def)

Definition at line 319 of file parse.y.

#define in_defined   (parser->parser_in_defined)

Definition at line 322 of file parse.y.

#define in_single   (parser->parser_in_single)

Definition at line 318 of file parse.y.

#define internal_id ( )    internal_id_gen(parser)

Definition at line 505 of file parse.y.

#define IS_AFTER_OPERATOR ( )    IS_lex_state(EXPR_FNAME | EXPR_DOT)
#define IS_ARG ( )    IS_lex_state(EXPR_ARG_ANY)
#define is_asgn_or_id (   id)
Value:
((is_notop_id(id)) && \
(((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
((id)&ID_SCOPE_MASK) == ID_CLASS))
const int id
Definition: nkf.c:209
#define ID_INSTANCE
#define ID_GLOBAL
#define ID_CLASS
#define ID_SCOPE_MASK
#define is_notop_id(id)
Definition: parse.y:52

Definition at line 62 of file parse.y.

#define is_attrset_id (   id)    (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)

Definition at line 56 of file parse.y.

#define IS_BEG ( )    IS_lex_state(EXPR_BEG_ANY)
#define is_class_id (   id)    (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)

Definition at line 58 of file parse.y.

#define is_const_id (   id)    (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)

Definition at line 57 of file parse.y.

#define IS_END ( )    IS_lex_state(EXPR_END_ANY)
#define is_global_id (   id)    (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)

Definition at line 54 of file parse.y.

#define is_identchar (   p,
  e,
  enc 
)    (rb_enc_isalnum(*(p),(enc)) || (*(p)) == '_' || !ISASCII(*(p)))
#define is_instance_id (   id)    (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)

Definition at line 55 of file parse.y.

#define is_junk_id (   id)    (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)

Definition at line 59 of file parse.y.

#define IS_LABEL_POSSIBLE ( )    ((IS_lex_state(EXPR_BEG | EXPR_ENDFN) && !cmd_state) || IS_ARG())
#define IS_LABEL_SUFFIX (   n)    (peek_n(':',(n)) && !peek_n(':', (n)+1))
#define IS_lex_state (   ls)    IS_lex_state_for(lex_state, (ls))

Definition at line 100 of file parse.y.

#define IS_lex_state_for (   x,
  ls 
)    ((x) & (ls))

Definition at line 99 of file parse.y.

#define is_local_id (   id)    (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)

Definition at line 53 of file parse.y.

#define is_notop_id (   id)    ((id)>tLAST_OP_ID)

Definition at line 52 of file parse.y.

#define IS_SPCARG (   c)    (IS_ARG() && space_seen && !ISSPACE(c))
#define lex_eol_p ( )    (lex_p >= lex_pend)
#define lex_gets   (parser->parser_lex_gets)

Definition at line 337 of file parse.y.

#define lex_gets_ptr   (parser->parser_lex_gets_ptr)

Definition at line 336 of file parse.y.

#define lex_goto_eol (   parser)    ((parser)->parser_lex_p = (parser)->parser_lex_pend)
#define lex_input   (parser->parser_lex_input)

Definition at line 327 of file parse.y.

#define lex_lastline   (parser->parser_lex_lastline)

Definition at line 328 of file parse.y.

#define lex_nextline   (parser->parser_lex_nextline)

Definition at line 329 of file parse.y.

#define lex_p   (parser->parser_lex_p)

Definition at line 331 of file parse.y.

#define lex_pbeg   (parser->parser_lex_pbeg)

Definition at line 330 of file parse.y.

#define lex_pend   (parser->parser_lex_pend)

Definition at line 332 of file parse.y.

#define lex_state   (parser->parser_lex_state)

Definition at line 311 of file parse.y.

Referenced by if().

#define lex_strterm   (parser->parser_lex_strterm)

Definition at line 310 of file parse.y.

Referenced by if(), and switch().

#define list_append (   l,
  i 
)    list_append_gen(parser,(l),(i))

Definition at line 388 of file parse.y.

#define list_concat (   h,
 
)    list_concat_gen(parser,(h),(t))

Definition at line 390 of file parse.y.

#define literal_concat (   h,
 
)    literal_concat_gen(parser,(h),(t))

Definition at line 396 of file parse.y.

#define local_id (   id)    local_id_gen(parser, (id))

Definition at line 503 of file parse.y.

#define local_pop ( )    local_pop_gen(parser)

Definition at line 497 of file parse.y.

#define local_push (   top)    local_push_gen(parser,(top))

Definition at line 495 of file parse.y.

#define local_tbl ( )    local_tbl_gen(parser)

Definition at line 448 of file parse.y.

#define local_var (   id)    local_var_gen(parser, (id))

Definition at line 499 of file parse.y.

#define logop (   type,
  node1,
  node2 
)    logop_gen(parser, (type), (node1), (node2))

Definition at line 367 of file parse.y.

#define lpar_beg   (parser->parser_lpar_beg)

Definition at line 316 of file parse.y.

#define lvar_defined (   id)    lvar_defined_gen(parser, (id))

Definition at line 521 of file parse.y.

#define LVAR_USED   ((ID)1 << (sizeof(ID) * CHAR_BIT - 1))
#define lvtbl   (parser->parser_lvtbl)

Definition at line 338 of file parse.y.

#define malloc   YYMALLOC
#define match_op (   node1,
  node2 
)    match_op_gen(parser, (node1), (node2))

Definition at line 445 of file parse.y.

#define mixed_error (   enc1,
  enc2 
)
Value:
if (!errbuf) { \
size_t len = sizeof(mixed_msg) - 4; \
len += strlen(rb_enc_name(enc1)); \
len += strlen(rb_enc_name(enc2)); \
errbuf = ALLOCA_N(char, len); \
snprintf(errbuf, len, mixed_msg, \
rb_enc_name(enc1), \
rb_enc_name(enc2)); \
yyerror(errbuf); \
}
size_t strlen(const char *)
#define rb_enc_name(enc)
#define ALLOCA_N(type, n)
#define snprintf
#define yyerror(msg)
Definition: parse.y:308
#define mixed_escape (   beg,
  enc1,
  enc2 
)
Value:
do { \
const char *pos = lex_p; \
lex_p = (beg); \
mixed_error((enc1), (enc2)); \
lex_p = pos; \
} while (0)
#define lex_p
Definition: parse.y:331
#define mixed_error(enc1, enc2)
#define const
Definition: strftime.c:102
#define nd_func   u1.id

Definition at line 534 of file parse.y.

#define nd_nest   u3.cnt

Definition at line 541 of file parse.y.

#define nd_paren (   node)    (char)((node)->u2.id >> CHAR_BIT*2)

Definition at line 540 of file parse.y.

#define nd_term (   node)    SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)

Definition at line 538 of file parse.y.

#define new_args (   f,
  o,
  r,
  p,
 
)    new_args_gen(parser, (f),(o),(r),(p),(t))

Definition at line 410 of file parse.y.

#define new_args_tail (   k,
  kr,
 
)    new_args_tail_gen(parser, (k),(kr),(b))

Definition at line 412 of file parse.y.

#define new_attr_op_assign (   lhs,
  type,
  attr,
  op,
  rhs 
)    new_attr_op_assign_gen(parser, (lhs), (attr), (op), (rhs))

Definition at line 440 of file parse.y.

#define new_bv (   id)    new_bv_gen(parser, (id))

Definition at line 492 of file parse.y.

#define new_const_op_assign (   lhs,
  op,
  rhs 
)    new_const_op_assign_gen(parser, (lhs), (op), (rhs))

Definition at line 442 of file parse.y.

#define new_evstr (   n)    new_evstr_gen(parser,(n))

Definition at line 399 of file parse.y.

#define new_op_assign (   lhs,
  op,
  rhs 
)    new_op_assign_gen(parser, (lhs), (op), (rhs))

Definition at line 485 of file parse.y.

#define NEW_STRTERM (   func,
  term,
  paren 
)    rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)

Referenced by if(), and switch().

#define new_yield (   node)    new_yield_gen(parser, (node))

Definition at line 419 of file parse.y.

#define NEWHEAP ( )    rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0)
#define newtok ( )    parser_newtok(parser)
#define nextc ( )    parser_nextc(parser)
#define no_digits ( )    do {yyerror("numeric literal without digits"); return 0;} while (0)
#define node_assign (   node1,
  node2 
)    node_assign_gen(parser, (node1), (node2))

Definition at line 436 of file parse.y.

#define NODE_HEREDOC   NODE_ARRAY /* 1, 3 to gc */

Definition at line 532 of file parse.y.

#define NODE_STRTERM   NODE_ZARRAY /* nothing to gc */

Definition at line 531 of file parse.y.

#define numberof (   array)    (int)(sizeof(array) / sizeof((array)[0]))
#define op_tbl_count   numberof(op_tbl)
#define paren_nest   (parser->parser_paren_nest)

Definition at line 315 of file parse.y.

#define parse_string (   n)    parser_parse_string(parser,(n))
#define PARSER_ARG   ruby_sourcefile, ruby_sourceline, current_enc,

Definition at line 663 of file parse.y.

#define PARSER_DEBUG   0
#define parser_encoding_name ( )    (current_enc->name)
#define parser_is_identchar ( )    (!parser->eofp && is_identchar((lex_p-1),lex_pend,current_enc))
#define parser_isascii ( )    ISASCII(*(lex_p-1))
#define parser_mbclen ( )    mbclen((lex_p-1),lex_pend,current_enc)
#define parser_precise_mbclen ( )    rb_enc_precise_mbclen((lex_p-1),lex_pend,current_enc)
#define parser_warn (   node,
  mesg 
)    parser_warn(parser, (node), (mesg))
#define parser_warning (   node,
  mesg 
)    parser_warning(parser, (node), (mesg))
#define peek (   c)    peek_n((c), 0)
#define peek_n (   c,
 
)    (lex_p+(n) < lex_pend && (c) == (unsigned char)lex_p[n])
#define POINTER_P (   val)    ((VALUE)(val) & ~(VALUE)3)

Definition at line 141 of file parse.y.

Referenced by vtable_add(), vtable_free(), vtable_included(), and vtable_size().

#define pushback (   c)    parser_pushback(parser, (c))

Referenced by if(), and switch().

#define Qnone   0

Definition at line 627 of file parse.y.

#define rb_backref_error (   n)    rb_backref_error_gen(parser,(n))

Definition at line 434 of file parse.y.

#define rb_compile_error   rb_compile_error_with_enc

Definition at line 661 of file parse.y.

#define rb_node_newnode (   type,
  a1,
  a2,
  a3 
)    node_newnode(parser, (type), (a1), (a2), (a3))

Definition at line 362 of file parse.y.

#define rb_warn0 (   fmt)    rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt))

Definition at line 635 of file parse.y.

#define rb_warn4S (   file,
  line,
  fmt,
 
)    rb_compile_warn((file), (line), (fmt), (a))

Definition at line 638 of file parse.y.

#define rb_warnI (   fmt,
 
)    rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))

Definition at line 636 of file parse.y.

#define rb_warning0 (   fmt)    rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt))

Definition at line 639 of file parse.y.

#define rb_warningS (   fmt,
 
)    rb_compile_warning(ruby_sourcefile, ruby_sourceline, (fmt), (a))

Definition at line 640 of file parse.y.

#define rb_warnS (   fmt,
 
)    rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a))

Definition at line 637 of file parse.y.

#define RE_OPTION_ARG_ENCODING_NONE   32

Definition at line 529 of file parse.y.

#define RE_OPTION_ENCODING (   e)    (((e)&0xff)<<RE_OPTION_ENCODING_SHIFT)

Definition at line 525 of file parse.y.

#define RE_OPTION_ENCODING_IDX (   o)    (((o)>>RE_OPTION_ENCODING_SHIFT)&0xff)

Definition at line 526 of file parse.y.

#define RE_OPTION_ENCODING_NONE (   o)    ((o)&RE_OPTION_ARG_ENCODING_NONE)

Definition at line 527 of file parse.y.

#define RE_OPTION_ENCODING_SHIFT   8

Definition at line 524 of file parse.y.

#define RE_OPTION_MASK   0xff

Definition at line 528 of file parse.y.

#define RE_OPTION_ONCE   (1<<16)

Definition at line 523 of file parse.y.

#define read_escape (   flags,
 
)    parser_read_escape(parser, (flags), (e))
#define realloc   YYREALLOC
#define reduce_nodes (   n)    reduce_nodes_gen(parser,(n))

Definition at line 381 of file parse.y.

#define reg_compile (   str,
  options 
)    reg_compile_gen(parser, (str), (options))

Definition at line 453 of file parse.y.

#define reg_fragment_check (   str,
  options 
)    reg_fragment_check_gen(parser, (str), (options))

Definition at line 457 of file parse.y.

#define reg_fragment_setenc (   str,
  options 
)    reg_fragment_setenc_gen(parser, (str), (options))

Definition at line 455 of file parse.y.

#define reg_named_capture_assign (   regexp,
  match 
)    reg_named_capture_assign_gen(parser,(regexp),(match))

Definition at line 459 of file parse.y.

#define REGISTER_SYMID (   id,
  name 
)    register_symid((id), (name), strlen(name), enc)

Definition at line 3937 of file parse.y.

#define regx_options ( )    parser_regx_options(parser)
#define ret_args (   node)    ret_args_gen(parser, (node))

Definition at line 416 of file parse.y.

#define ripper_flush (   p)    (void)(p)
#define ruby__end__seen   (parser->parser_ruby__end__seen)

Definition at line 339 of file parse.y.

#define ruby_coverage   (parser->coverage)

Definition at line 349 of file parse.y.

#define ruby_debug_lines   (parser->debug_lines)

Definition at line 348 of file parse.y.

#define ruby_eval_tree   (parser->parser_eval_tree)

Definition at line 346 of file parse.y.

#define ruby_eval_tree_begin   (parser->parser_eval_tree_begin)

Definition at line 347 of file parse.y.

#define ruby_sourcefile   (parser->parser_ruby_sourcefile)

Definition at line 341 of file parse.y.

#define ruby_sourceline   (parser->parser_ruby_sourceline)

Definition at line 340 of file parse.y.

#define set_yylval_id (   x)    (yylval.id = (x))

Referenced by if().

#define set_yylval_literal (   x)    (yylval.node = NEW_LIT(x))
#define set_yylval_name (   x)    (yylval.id = (x))
#define set_yylval_node (   x)    (yylval.node = (x))
#define set_yylval_num (   x)    (yylval.num = (x))
#define set_yylval_str (   x)    (yylval.node = NEW_STR(x))
#define shadowing_lvar (   name)    shadowing_lvar_gen(parser, (name))

Definition at line 490 of file parse.y.

#define SIGN_EXTEND (   x,
 
)    (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))

Definition at line 533 of file parse.y.

#define SIGN_EXTEND_CHAR (   c)    ((((unsigned char)(c)) ^ 128) - 128)
#define SPECIAL_PUNCT (   idx)
Value:
( \
BIT('~', idx) | BIT('*', idx) | BIT('$', idx) | BIT('?', idx) | \
BIT('!', idx) | BIT('@', idx) | BIT('/', idx) | BIT('\\', idx) | \
BIT(';', idx) | BIT(',', idx) | BIT('.', idx) | BIT('=', idx) | \
BIT(':', idx) | BIT('<', idx) | BIT('>', idx) | BIT('\"', idx) | \
BIT('&', idx) | BIT('`', idx) | BIT('\'', idx) | BIT('+', idx) | \
BIT('0', idx))
#define BIT(c, idx)
#define str_copy (   _s,
  _p,
  _n 
)
Value:
((_s) \
? (void)(rb_str_resize((_s), (_n)), \
MEMCPY(RSTRING_PTR(_s), (_p), char, (_n)), (_s)) \
: (void)((_s) = STR_NEW((_p), (_n))))
#define RSTRING_PTR(str)
VALUE rb_str_resize(VALUE, long)
Definition: string.c:1854
#define MEMCPY(p1, p2, type, n)
#define STR_NEW(p, n)
Definition: parse.y:300
#define STR_FUNC_ESCAPE   0x01
#define STR_FUNC_EXPAND   0x02
#define STR_FUNC_INDENT   0x20
#define STR_FUNC_QWORDS   0x08
#define STR_FUNC_REGEXP   0x04
#define STR_FUNC_SYMBOL   0x10
#define STR_NEW (   p,
 
)    rb_enc_str_new((p),(n),current_enc)

Definition at line 300 of file parse.y.

#define STR_NEW0 ( )    rb_enc_str_new(0,0,current_enc)

Definition at line 301 of file parse.y.

#define STR_NEW2 (   p)    rb_enc_str_new((p),strlen(p),current_enc)

Definition at line 302 of file parse.y.

#define STR_NEW3 (   p,
  n,
  e,
  func 
)    parser_str_new((p),(n),(e),(func),current_enc)

Definition at line 303 of file parse.y.

#define subnodes (   n1,
  n2 
)
Value:
((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
(!node->n2) ? (body = &node->n1, 1) : \
(reduce_nodes(&node->n1), body = &node->n2, 1))
#define reduce_nodes(n)
Definition: parse.y:381
#define tok ( )    tokenbuf
#define tok_hex (   numlen)    parser_tok_hex(parser, (numlen))
#define TOK_INTERN (   mb)    rb_intern3(tok(), toklen(), current_enc)

Definition at line 305 of file parse.y.

#define tokadd (   c)    parser_tokadd(parser, (c))
#define tokadd_escape (   e)    parser_tokadd_escape(parser, (e))
#define tokadd_mbchar (   c)    parser_tokadd_mbchar(parser, (c))
#define tokadd_string (   f,
  t,
  p,
  n,
 
)    parser_tokadd_string(parser,(f),(t),(p),(n),(e))
#define tokaddmbc (   c,
  enc 
)    parser_tokaddmbc(parser, (c), (enc))
#define tokcopy (   n)    memcpy(tokspace(n), lex_p - (n), (n))
#define token_info_pop (   token)    (RTEST(ruby_verbose) ? token_info_pop(parser, (token)) : (void)0)

Definition at line 679 of file parse.y.

#define token_info_push (   token)    (RTEST(ruby_verbose) ? token_info_push(parser, (token)) : (void)0)

Definition at line 678 of file parse.y.

#define tokenbuf   (parser->parser_tokenbuf)

Definition at line 323 of file parse.y.

#define tokfix ( )    (tokenbuf[tokidx]='\0')
#define tokidx   (parser->parser_tokidx)

Definition at line 324 of file parse.y.

#define toklast ( )    (tokidx>0?tokenbuf[tokidx-1]:0)
#define toklen ( )    tokidx
#define tokline   (parser->parser_tokline)

Definition at line 326 of file parse.y.

#define toksiz   (parser->parser_toksiz)

Definition at line 325 of file parse.y.

#define tokspace (   n)    parser_tokspace(parser, (n))
#define value_expr (   node)    value_expr_gen(parser, (node) = remove_begin(node))

Definition at line 375 of file parse.y.

#define void_expr (   node)    void_expr0((node) = remove_begin(node))

Definition at line 377 of file parse.y.

#define void_expr0 (   node)    void_expr_gen(parser, (node))

Definition at line 376 of file parse.y.

#define void_stmts (   node)    void_stmts_gen(parser, (node))

Definition at line 379 of file parse.y.

#define VTBL_DEBUG   0

Definition at line 154 of file parse.y.

Referenced by vtable_add(), vtable_alloc(), and vtable_free().

#define warn_balanced (   op,
  syn 
)
Value:
((void) \
(!IS_lex_state_for(last_state, EXPR_CLASS|EXPR_DOT|EXPR_FNAME|EXPR_ENDFN|EXPR_ENDARG) && \
space_seen && !ISSPACE(c) && \
(ambiguous_operator(op, syn), 0)))
return c
Definition: parse.y:7591
#define IS_lex_state_for(x, ls)
Definition: parse.y:99
#define ambiguous_operator(op, syn)
#define ISSPACE(c)
Definition: ruby.h:1632

Referenced by if().

#define was_bol ( )    (lex_p == lex_pbeg + 1)
#define whole_match_p (   e,
  l,
  i 
)    parser_whole_match_p(parser,(e),(l),(i))
#define YYCALLOC (   nelem,
  size 
)    rb_parser_calloc(parser, (nelem), (size))
#define YYDEBUG   1
#define yydebug   (parser->parser_yydebug)

Definition at line 343 of file parse.y.

#define yyerror (   msg)    parser_yyerror(parser, (msg))

Definition at line 308 of file parse.y.

#define YYERROR_VERBOSE   1
#define YYFREE (   ptr)    rb_parser_free(parser, (ptr))
#define yylval   (*((YYSTYPE*)(parser->parser_yylval)))
#define yylval_id ( )    (yylval.id)
#define YYMALLOC (   size)    rb_parser_malloc(parser, (size))
#define yyparse   ruby_yyparse

Definition at line 359 of file parse.y.

#define YYREALLOC (   ptr,
  size 
)    rb_parser_realloc(parser, (ptr), (size))
#define YYSTACK_USE_ALLOCA   0

Typedef Documentation

typedef VALUE stack_type

Definition at line 106 of file parse.y.

typedef struct token_info token_info

Enumeration Type Documentation

Enumerator
EXPR_BEG_bit 
EXPR_END_bit 
EXPR_ENDARG_bit 
EXPR_ENDFN_bit 
EXPR_ARG_bit 
EXPR_CMDARG_bit 
EXPR_MID_bit 
EXPR_FNAME_bit 
EXPR_DOT_bit 
EXPR_CLASS_bit 
EXPR_VALUE_bit 
EXPR_MAX_STATE 
EXPR_BEG_bit 
EXPR_END_bit 
EXPR_ENDARG_bit 
EXPR_ENDFN_bit 
EXPR_ARG_bit 
EXPR_CMDARG_bit 
EXPR_MID_bit 
EXPR_FNAME_bit 
EXPR_DOT_bit 
EXPR_CLASS_bit 
EXPR_VALUE_bit 
EXPR_MAX_STATE 
EXPR_BEG_bit 
EXPR_END_bit 
EXPR_ENDARG_bit 
EXPR_ENDFN_bit 
EXPR_ARG_bit 
EXPR_CMDARG_bit 
EXPR_MID_bit 
EXPR_FNAME_bit 
EXPR_DOT_bit 
EXPR_CLASS_bit 
EXPR_VALUE_bit 
EXPR_MAX_STATE 
EXPR_BEG_bit 
EXPR_END_bit 
EXPR_ENDARG_bit 
EXPR_ENDFN_bit 
EXPR_ARG_bit 
EXPR_CMDARG_bit 
EXPR_MID_bit 
EXPR_FNAME_bit 
EXPR_DOT_bit 
EXPR_CLASS_bit 
EXPR_VALUE_bit 
EXPR_MAX_STATE 

Definition at line 67 of file parse.y.

Enumerator
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
EXPR_BEG_ANY 
EXPR_ARG_ANY 
EXPR_END_ANY 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
EXPR_BEG_ANY 
EXPR_ARG_ANY 
EXPR_END_ANY 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
EXPR_BEG_ANY 
EXPR_ARG_ANY 
EXPR_END_ANY 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
DEF_EXPR 
EXPR_BEG_ANY 
EXPR_ARG_ANY 
EXPR_END_ANY 

Definition at line 82 of file parse.y.

Function Documentation

static NODE* arg_append_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static NODE* arg_blk_pass ( NODE ,
NODE  
)
static
static NODE* arg_concat_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static int arg_var_gen ( struct parser_params ,
ID   
)
static
static NODE* aryset_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static NODE* assignable_gen ( struct parser_params ,
ID  ,
NODE  
)
static
static NODE* attrset_gen ( struct parser_params ,
NODE ,
ID   
)
static
static NODE* block_append_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static void block_dup_check_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static NODE* call_bin_op_gen ( struct parser_params ,
NODE ,
ID  ,
NODE  
)
static
static NODE* call_uni_op_gen ( struct parser_params ,
NODE ,
ID   
)
static
static NODE* cond_gen ( struct parser_params ,
NODE  
)
static
static NODE* dsym_node_gen ( struct parser_params ,
NODE  
)
static
static int dvar_curr_gen ( struct parser_params ,
ID   
)
static
static int dvar_defined_gen ( struct parser_params ,
ID  ,
int   
)
static
static int dyna_in_block_gen ( struct parser_params )
static
dyna_pop (   $< vars >)
static void dyna_pop_gen ( struct parser_params ,
const struct vtable  
)
static
static const struct vtable* dyna_push_gen ( struct parser_params )
static
static NODE* evstr2dstr_gen ( struct parser_params ,
NODE  
)
static
static void fixpos ( NODE ,
NODE  
)
static
fixpos (   $$,
  $1 
) = $3
static void fixup_nodes ( NODE **  )
static
static ID formal_argument_gen ( struct parser_params ,
ID   
)
static
static NODE* gettable_gen ( struct parser_params ,
ID   
)
static
if (   $2)

Definition at line 956 of file parse.y.

References NEW_RESCUE.

if ( $$)
if ( c  = = ')')

Definition at line 7588 of file parse.y.

References brace_nest, and tSTRING_DEND.

if ( IS_END()||ISSPACE(c )

Definition at line 7603 of file parse.y.

References lex_state, pushback, and warn_balanced.

if ( (c=nextc())  = = '=')

Definition at line 7628 of file parse.y.

References lex_state, set_yylval_id, and tOP_ASGN.

if ( IS_SPCARG(c )

Definition at line 7634 of file parse.y.

References arg_ambiguous, lex_strterm, NEW_STRTERM, str_regexp, and tREGEXP_BEG.

static void Init_id ( void  )
static
static ID internal_id_gen ( struct parser_params )
static
static NODE* list_append_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static NODE* list_concat_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static int literal_concat0 ( struct parser_params ,
VALUE  ,
VALUE   
)
static
static NODE* literal_concat_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static int local_id_gen ( struct parser_params ,
ID   
)
static
static void local_pop_gen ( struct parser_params )
static
static void local_push_gen ( struct parser_params ,
int   
)
static
static ID* local_tbl_gen ( struct parser_params )
static
static int local_var_gen ( struct parser_params ,
ID   
)
static
static NODE* logop_gen ( struct parser_params ,
enum  node_type,
NODE ,
NODE  
)
static
static int lvar_defined_gen ( struct parser_params ,
ID   
)
static
static NODE* match_op_gen ( struct parser_params ,
NODE ,
NODE  
)
static
nd_set_line (   $$,
  $< num > 
)
fcall nd_set_line (   $$,
tokline   
)
static NODE* negate_lit ( NODE )
static
static NODE* new_args_gen ( struct parser_params ,
NODE ,
NODE ,
ID  ,
NODE ,
NODE  
)
static
static NODE* new_args_tail_gen ( struct parser_params ,
NODE ,
ID  ,
ID   
)
static
static NODE* new_attr_op_assign_gen ( struct parser_params parser,
NODE lhs,
ID  attr,
ID  op,
NODE rhs 
)
static
static void new_bv_gen ( struct parser_params ,
ID   
)
static
static NODE* new_const_op_assign_gen ( struct parser_params parser,
NODE lhs,
ID  op,
NODE rhs 
)
static
static NODE* new_evstr_gen ( struct parser_params ,
NODE  
)
static
static NODE* new_op_assign_gen ( struct parser_params parser,
NODE lhs,
ID  op,
NODE rhs 
)
static
static NODE* new_yield_gen ( struct parser_params ,
NODE  
)
static
static NODE* newline_node ( NODE )
static
static NODE* node_assign_gen ( struct parser_params ,
NODE ,
NODE  
)
static
static NODE* node_newnode ( struct parser_params ,
enum  node_type,
VALUE  ,
VALUE  ,
VALUE   
)
static
static int parser_yyerror ( struct parser_params ,
const char *   
)
static
static void rb_backref_error_gen ( struct parser_params ,
NODE  
)
static
static void reduce_nodes_gen ( struct parser_params ,
NODE **   
)
static
static VALUE reg_compile_gen ( struct parser_params ,
VALUE  ,
int   
)
static
static int reg_fragment_check_gen ( struct parser_params ,
VALUE  ,
int   
)
static
static void reg_fragment_setenc_gen ( struct parser_params ,
VALUE  ,
int   
)
static
static NODE* reg_named_capture_assign_gen ( struct parser_params parser,
VALUE  regexp,
NODE match 
)
static
static ID register_symid_str ( ID  ,
VALUE   
)
static
static NODE* remove_begin ( NODE )
static
static NODE* ret_args_gen ( struct parser_params ,
NODE  
)
static
static ID shadowing_lvar_gen ( struct parser_params ,
ID   
)
static
static NODE* splat_array ( NODE )
static
switch ( c  )

Definition at line 7609 of file parse.y.

References lex_strterm, NEW_STRTERM, pushback, str_dsym, and str_ssym.

static void token_info_pop ( struct parser_params ,
const char *  token 
)
static
static void token_info_push ( struct parser_params ,
const char *  token 
)
static
static int value_expr_gen ( struct parser_params ,
NODE  
)
static
static void void_expr_gen ( struct parser_params ,
NODE  
)
static
static void void_stmts_gen ( struct parser_params ,
NODE  
)
static
static void vtable_add ( struct vtable tbl,
ID  id 
)
static

Definition at line 181 of file parse.y.

References vtable::capa, id, POINTER_P, vtable::pos, rb_bug(), rb_id2name(), REALLOC_N, vtable::tbl, and VTBL_DEBUG.

static struct vtable* vtable_alloc ( struct vtable prev)
static

Definition at line 157 of file parse.y.

References ALLOC, ALLOC_N, vtable::capa, vtable::pos, vtable::prev, vtable::tbl, and VTBL_DEBUG.

static void vtable_free ( struct vtable tbl)
static

Definition at line 169 of file parse.y.

References POINTER_P, vtable::tbl, VTBL_DEBUG, and xfree.

static int vtable_included ( const struct vtable tbl,
ID  id 
)
static

Definition at line 196 of file parse.y.

References i, POINTER_P, vtable::pos, and vtable::tbl.

static int vtable_size ( const struct vtable tbl)
static

Definition at line 144 of file parse.y.

References POINTER_P, and vtable::pos.

warn_balanced ( "/"  ,
"regexp literal"   
)
static int yylex ( void *  )
static

Variable Documentation

top_compstmt __pad0__

Definition at line 888 of file parse.y.

block_command __pad10__

Definition at line 1338 of file parse.y.

fcall __pad11__

Definition at line 1366 of file parse.y.

command __pad12__

Definition at line 1376 of file parse.y.

mlhs __pad13__

Definition at line 1484 of file parse.y.

mlhs_inner __pad14__

Definition at line 1495 of file parse.y.

mlhs_item __pad15__

Definition at line 1592 of file parse.y.

mlhs_head __pad16__

Definition at line 1603 of file parse.y.

mlhs_node __pad17__

Definition at line 1639 of file parse.y.

primary_value [' opt_call_args rbracket { $$ = aryset($1, $3); } | primary_value '.' tIDENTIFIER { $$ = attrset($1, $3); } | primary_value tCOLON2 tIDENTIFIER { $$ = attrset($1, $3); } | primary_value '.' tCONSTANT { $$ = attrset($1, $3); } | primary_value tCOLON2 tCONSTANT { if (in_def || in_single) yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3)); } | tCOLON3 tCONSTANT { if (in_def || in_single) yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON3($2)); } | backref { rb_backref_error($1); $$ = NEW_BEGIN(0); } ;lhs : user_variable { $$ = assignable($1, 0); if (!$$) $$ = NEW_BEGIN(0); } | keyword_variable { $$ = assignable($1, 0); if (!$$) $$ = NEW_BEGIN(0); } | primary_value '[' opt_call_args rbracket { $$ = aryset($1, $3); } | primary_value '.' tIDENTIFIER { $$ = attrset($1, $3); } | primary_value tCOLON2 tIDENTIFIER { $$ = attrset($1, $3); } | primary_value '.' tCONSTANT { $$ = attrset($1, $3); } | primary_value tCOLON2 tCONSTANT { if (in_def || in_single) yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3)); } | tCOLON3 tCONSTANT { if (in_def || in_single) yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON3($2)); } | backref { rb_backref_error($1); $$ = NEW_BEGIN(0); } ;cname : tIDENTIFIER { yyerror("class/module name must be CONSTANT"); } | tCONSTANT ;cpath : tCOLON3 cname { $$ = NEW_COLON3($2); } | cname { $$ = NEW_COLON2(0, $$); } | primary_value tCOLON2 cname { $$ = NEW_COLON2($1, $3); } ;fname : tIDENTIFIER | tCONSTANT | tFID | op { lex_state = EXPR_ENDFN; $$ = $1; } | reswords { lex_state = EXPR_ENDFN; $$ = $<id>1; } ;fsym : fname | symbol ;fitem : fsym { $$ = NEW_LIT(ID2SYM($1)); } | dsym ;undef_list : fitem { $$ = NEW_UNDEF($1); } | undef_list ',' {lex_state = EXPR_FNAME;} fitem { $$ = block_append($1, NEW_UNDEF($4)); } ;op : '|' { ifndef_ripper($$ = '|'); } | '^' { ifndef_ripper($$ = '^'); } | '&' { ifndef_ripper($$ = '&'); } | tCMP { ifndef_ripper($$ = tCMP); } | tEQ { ifndef_ripper($$ = tEQ); } | tEQQ { ifndef_ripper($$ = tEQQ); } | tMATCH { ifndef_ripper($$ = tMATCH); } | tNMATCH { ifndef_ripper($$ = tNMATCH); } | '>' { ifndef_ripper($$ = '>'); } | tGEQ { ifndef_ripper($$ = tGEQ); } | '<' { ifndef_ripper($$ = '<'); } | tLEQ { ifndef_ripper($$ = tLEQ); } | tNEQ { ifndef_ripper($$ = tNEQ); } | tLSHFT { ifndef_ripper($$ = tLSHFT); } | tRSHFT { ifndef_ripper($$ = tRSHFT); } | '+' { ifndef_ripper($$ = '+'); } | '-' { ifndef_ripper($$ = '-'); } | '*' { ifndef_ripper($$ = '*'); } | tSTAR { ifndef_ripper($$ = '*'); } | '/' { ifndef_ripper($$ = '/'); } | '%' { ifndef_ripper($$ = '%'); } | tPOW { ifndef_ripper($$ = tPOW); } | tDSTAR { ifndef_ripper($$ = tDSTAR); } | '!' { ifndef_ripper($$ = '!'); } | '~' { ifndef_ripper($$ = '~'); } | tUPLUS { ifndef_ripper($$ = tUPLUS); } | tUMINUS { ifndef_ripper($$ = tUMINUS); } | tAREF { ifndef_ripper($$ = tAREF); } | tASET { ifndef_ripper($$ = tASET); } | '`' { ifndef_ripper($$ = '`'); } ;reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ | keyword_BEGIN | keyword_END | keyword_alias | keyword_and | keyword_begin | keyword_break | keyword_case | keyword_class | keyword_def | keyword_defined | keyword_do | keyword_else | keyword_elsif | keyword_end | keyword_ensure | keyword_false | keyword_for | keyword_in | keyword_module | keyword_next | keyword_nil | keyword_not | keyword_or | keyword_redo | keyword_rescue | keyword_retry | keyword_return | keyword_self | keyword_super | keyword_then | keyword_true | keyword_undef | keyword_when | keyword_yield | keyword_if | keyword_unless | keyword_while | keyword_until ;arg : lhs '=' arg { value_expr($3); $$ = node_assign($1, $3); } | lhs '=' arg modifier_rescue arg { value_expr($3); $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0); $$ = node_assign($1, $3); } | var_lhs tOP_ASGN arg { value_expr($3); $$ = new_op_assign($1, $2, $3); } | var_lhs tOP_ASGN arg modifier_rescue arg { value_expr($3); $3 = NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0); $$ = new_op_assign($1, $2, $3); } | primary_value '[' opt_call_args rbracket tOP_ASGN arg { NODE *args; value_expr($6); if (!$3) $3 = NEW_ZARRAY(); if (nd_type($3) == NODE_BLOCK_PASS) { args = NEW_ARGSCAT($3, $6); } else { args = arg_concat($3, $6); } if ($5 == tOROP) { $5 = 0; } else if ($5 == tANDOP) { $5 = 1; } $$ = NEW_OP_ASGN1($1, $5, args); fixpos($$, $1); } | primary_value '.' tIDENTIFIER tOP_ASGN arg { value_expr($5); $$ = new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5); } | primary_value '.' tCONSTANT tOP_ASGN arg { value_expr($5); $$ = new_attr_op_assign($1, ripper_id2sym('.'), $3, $4, $5); } | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg { value_expr($5); $$ = new_attr_op_assign($1, ripper_intern("::"), $3, $4, $5); } | primary_value tCOLON2 tCONSTANT tOP_ASGN arg { $$ = NEW_COLON2($1, $3); $$ = new_const_op_assign($$, $4, $5); } | tCOLON3 tCONSTANT tOP_ASGN arg { $$ = NEW_COLON3($2); $$ = new_const_op_assign($$, $3, $4); } | backref tOP_ASGN arg { rb_backref_error($1); $$ = NEW_BEGIN(0); } | arg tDOT2 arg { value_expr($1); value_expr($3); $$ = NEW_DOT2($1, $3); if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) && nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) { deferred_nodes = list_append(deferred_nodes, $$); } } | arg tDOT3 arg { value_expr($1); value_expr($3); $$ = NEW_DOT3($1, $3); if (nd_type($1) == NODE_LIT && FIXNUM_P($1->nd_lit) && nd_type($3) == NODE_LIT && FIXNUM_P($3->nd_lit)) { deferred_nodes = list_append(deferred_nodes, $$); } } | arg '+' arg { $$ = call_bin_op($1, '+', $3); } | arg '-' arg { $$ = call_bin_op($1, '-', $3); } | arg '*' arg { $$ = call_bin_op($1, '*', $3); } | arg '/' arg { $$ = call_bin_op($1, '/', $3); } | arg '%' arg { $$ = call_bin_op($1, '%', $3); } | arg tPOW arg { $$ = call_bin_op($1, tPOW, $3); } | tUMINUS_NUM tINTEGER tPOW arg { $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0); } | tUMINUS_NUM tFLOAT tPOW arg { $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0); } | tUPLUS arg { $$ = call_uni_op($2, tUPLUS); } | tUMINUS arg { $$ = call_uni_op($2, tUMINUS); } | arg '|' arg { $$ = call_bin_op($1, '|', $3); } | arg '^' arg { $$ = call_bin_op($1, '^', $3); } | arg '&' arg { $$ = call_bin_op($1, '&', $3); } | arg tCMP arg { $$ = call_bin_op($1, tCMP, $3); } | arg '>' arg { $$ = call_bin_op($1, '>', $3); } | arg tGEQ arg { $$ = call_bin_op($1, tGEQ, $3); } | arg '<' arg { $$ = call_bin_op($1, '<', $3); } | arg tLEQ arg { $$ = call_bin_op($1, tLEQ, $3); } | arg tEQ arg { $$ = call_bin_op($1, tEQ, $3); } | arg tEQQ arg { $$ = call_bin_op($1, tEQQ, $3); } | arg tNEQ arg { $$ = call_bin_op($1, tNEQ, $3); } | arg tMATCH arg { $$ = match_op($1, $3); if (nd_type($1) == NODE_LIT && RB_TYPE_P($1->nd_lit, T_REGEXP)) { $$ = reg_named_capture_assign($1->nd_lit, $$); } } | arg tNMATCH arg { $$ = call_bin_op($1, tNMATCH, $3); } | '!' arg { $$ = call_uni_op(cond($2), '!'); } | '~' arg { $$ = call_uni_op($2, '~'); } | arg tLSHFT arg { $$ = call_bin_op($1, tLSHFT, $3); } | arg tRSHFT arg { $$ = call_bin_op($1, tRSHFT, $3); } | arg tANDOP arg { $$ = logop(NODE_AND, $1, $3); } | arg tOROP arg { $$ = logop(NODE_OR, $1, $3); } | keyword_defined opt_nl {in_defined = 1;} arg { in_defined = 0; $$ = NEW_DEFINED($4); } | arg '?' arg opt_nl ':' arg { value_expr($1); $$ = NEW_IF(cond($1), $3, $6); fixpos($$, $1); } | primary { $$ = $1; } ;arg_value : arg { value_expr($1); $$ = $1; if (!$$) $$ = NEW_NIL(); } ;aref_args : none | args trailer { $$ = $1; } | args ',' assocs trailer { $$ = arg_append($1, NEW_HASH($3)); } | assocs trailer { $$ = NEW_LIST(NEW_HASH($1)); } ;paren_args : '(' opt_call_args rparen { $$ = $2; } ;opt_paren_args : none | paren_args ;opt_call_args : none | call_args | args ',' { $$ = $1; } | args ',' assocs ',' { $$ = arg_append($1, NEW_HASH($3)); } | assocs ',' { $$ = NEW_LIST(NEW_HASH($1)); } ;call_args : command { value_expr($1); $$ = NEW_LIST($1); } | args opt_block_arg { $$ = arg_blk_pass($1, $2); } | assocs opt_block_arg { $$ = NEW_LIST(NEW_HASH($1)); $$ = arg_blk_pass($$, $2); } | args ',' assocs opt_block_arg { $$ = arg_append($1, NEW_HASH($3)); $$ = arg_blk_pass($$, $4); } | block_arg ;command_args : { $<val>$ = cmdarg_stack; CMDARG_PUSH(1); } call_args { cmdarg_stack = $<val>1; $$ = $2; } ;block_arg : tAMPER arg_value { $$ = NEW_BLOCK_PASS($2); } ;opt_block_arg : ',' block_arg { $$ = $2; } | none { $$ = 0; } ;args : arg_value { $$ = NEW_LIST($1); } | tSTAR arg_value { $$ = NEW_SPLAT($2); } | args ',' arg_value { NODE *n1; if ((n1 = splat_array($1)) != 0) { $$ = list_append(n1, $3); } else { $$ = arg_append($1, $3); } } | args ',' tSTAR arg_value { NODE *n1; if ((nd_type($4) == NODE_ARRAY) && (n1 = splat_array($1)) != 0) { $$ = list_concat(n1, $4); } else { $$ = arg_concat($1, $4); } } ;mrhs : args ',' arg_value { NODE *n1; if ((n1 = splat_array($1)) != 0) { $$ = list_append(n1, $3); } else { $$ = arg_append($1, $3); } } | args ',' tSTAR arg_value { NODE *n1; if (nd_type($4) == NODE_ARRAY && (n1 = splat_array($1)) != 0) { $$ = list_concat(n1, $4); } else { $$ = arg_concat($1, $4); } } | tSTAR arg_value { $$ = NEW_SPLAT($2); } ;primary : literal | strings | xstring | regexp | words | qwords | symbols | qsymbols | var_ref | backref | tFID { $$ = NEW_FCALL($1, 0); } | k_begin { $<val>1 = cmdarg_stack; cmdarg_stack = 0; $<num>$ = ruby_sourceline; } bodystmt k_end { cmdarg_stack = $<val>1; if ($3 == NULL) { $$ = NEW_NIL(); } else { if (nd_type($3) == NODE_RESCUE || nd_type($3) == NODE_ENSURE) nd_set_line($3, $<num>2); $$ = NEW_BEGIN($3); } nd_set_line($$, $<num>2); } | tLPAREN_ARG {lex_state = EXPR_ENDARG;} rparen { $$ = 0; } | tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} rparen { $$ = $2; } | tLPAREN compstmt ')' { $$ = $2; } | primary_value tCOLON2 tCONSTANT { $$ = NEW_COLON2($1, $3); } | tCOLON3 tCONSTANT { $$ = NEW_COLON3($2); } | tLBRACK aref_args ']' { if ($2 == 0) { $$ = NEW_ZARRAY(); } else { $$ = $2; } } | tLBRACE assoc_list '}' { $$ = NEW_HASH($2); } | keyword_return { $$ = NEW_RETURN(0); } | keyword_yield '(' call_args rparen { $$ = new_yield($3); } | keyword_yield '(' rparen { $$ = NEW_YIELD(0); } | keyword_yield { $$ = NEW_YIELD(0); } | keyword_defined opt_nl '(' {in_defined = 1;} expr rparen { in_defined = 0; $$ = NEW_DEFINED($5); } | keyword_not '(' expr rparen { $$ = call_uni_op(cond($3), '!'); } | keyword_not '(' rparen { $$ = call_uni_op(cond(NEW_NIL()), '!'); } | fcall brace_block { $2->nd_iter = $1; $$ = $2; } | method_call | method_call brace_block { block_dup_check($1->nd_args, $2); $2->nd_iter = $1; $$ = $2; } | tLAMBDA lambda { $$ = $2; } | k_if expr_value then compstmt if_tail k_end { $$ = NEW_IF(cond($2), $4, $5); fixpos($$, $2); } | k_unless expr_value then compstmt opt_else k_end { $$ = NEW_UNLESS(cond($2), $4, $5); fixpos($$, $2); } | k_while {COND_PUSH(1);} expr_value do {COND_POP();} compstmt k_end { $$ = NEW_WHILE(cond($3), $6, 1); fixpos($$, $3); } | k_until {COND_PUSH(1);} expr_value do {COND_POP();} compstmt k_end { $$ = NEW_UNTIL(cond($3), $6, 1); fixpos($$, $3); } | k_case expr_value opt_terms case_body k_end { $$ = NEW_CASE($2, $4); fixpos($$, $2); } | k_case opt_terms case_body k_end { $$ = NEW_CASE(0, $3); } | k_for for_var keyword_in {COND_PUSH(1);} expr_value do {COND_POP();} compstmt k_end { ID id = internal_id(); ID *tbl = ALLOC_N(ID, 2); NODE *m = NEW_ARGS_AUX(0, 0); NODE *args, *scope; if (nd_type($2) == NODE_MASGN) { NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1))); NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0))); m->nd_next = block_append( NEW_IF( NEW_NODE(NODE_AND, NEW_CALL(NEW_CALL(NEW_DVAR(id), idLength, 0), idEq, one), NEW_CALL(NEW_CALL(NEW_DVAR(id), idAREF, zero), rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))), 0), NEW_DASGN_CURR(id, NEW_CALL(NEW_DVAR(id), idAREF, zero)), 0), node_assign($2, NEW_DVAR(id))); args = new_args(m, 0, id, 0, new_args_tail(0, 0, 0)); } else { if (nd_type($2) == NODE_LASGN || nd_type($2) == NODE_DASGN || nd_type($2) == NODE_DASGN_CURR) { $2->nd_value = NEW_DVAR(id); m->nd_plen = 1; m->nd_next = $2; args = new_args(m, 0, 0, 0, new_args_tail(0, 0, 0)); } else { m->nd_next = node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id)); args = new_args(m, 0, id, 0, new_args_tail(0, 0, 0)); } } scope = NEW_NODE(NODE_SCOPE, tbl, $8, args); tbl[0] = 1; tbl[1] = id; $$ = NEW_FOR(0, $5, scope); fixpos($$, $2); } | k_class cpath superclass { if (in_def || in_single) yyerror("class definition in method body"); local_push(0); $<num>$ = ruby_sourceline; } bodystmt k_end { $$ = NEW_CLASS($2, $5, $3); nd_set_line($$, $<num>4); local_pop(); } | k_class tLSHFT expr { $<num>$ = in_def; in_def = 0; } term { $<num>$ = in_single; in_single = 0; local_push(0); } bodystmt k_end { $$ = NEW_SCLASS($3, $7); fixpos($$, $3); local_pop(); in_def = $<num>4; in_single = $<num>6; } | k_module cpath { if (in_def || in_single) yyerror("module definition in method body"); local_push(0); $<num>$ = ruby_sourceline; } bodystmt k_end { $$ = NEW_MODULE($2, $4); nd_set_line($$, $<num>3); local_pop(); } | k_def fname { $<id>$ = cur_mid; cur_mid = $2; in_def++; local_push(0); } f_arglist bodystmt k_end { NODE *body = remove_begin($5); reduce_nodes(&body); $$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE); nd_set_line($$, $<num>1); local_pop(); in_def--; cur_mid = $<id>3; } | k_def singleton dot_or_colon {lex_state = EXPR_FNAME;} fname { in_single++; lex_state = EXPR_ENDFN; local_push(0); } f_arglist bodystmt k_end { NODE *body = remove_begin($8); reduce_nodes(&body); $$ = NEW_DEFS($2, $5, $7, body); nd_set_line($$, $<num>1); local_pop(); in_single--; } | keyword_break { $$ = NEW_BREAK(0); } | keyword_next { $$ = NEW_NEXT(0); } | keyword_redo { $$ = NEW_REDO(); } | keyword_retry { $$ = NEW_RETRY(); } ;primary_value : primary { value_expr($1); $$ = $1; if (!$$) $$ = NEW_NIL(); } ;k_begin : keyword_begin { token_info_push("begin"); } ;k_if : keyword_if { token_info_push("if"); } ;k_unless : keyword_unless { token_info_push("unless"); } ;k_while : keyword_while { token_info_push("while"); } ;k_until : keyword_until { token_info_push("until"); } ;k_case : keyword_case { token_info_push("case"); } ;k_for : keyword_for { token_info_push("for"); } ;k_class : keyword_class { token_info_push("class"); } ;k_module : keyword_module { token_info_push("module"); } ;k_def : keyword_def { token_info_push("def"); $<num>$ = ruby_sourceline; } ;k_end : keyword_end { token_info_pop("end"); } ;then : term | keyword_then | term keyword_then ;do : term | keyword_do_cond ;if_tail : opt_else | keyword_elsif expr_value then compstmt if_tail { $$ = NEW_IF(cond($2), $4, $5); fixpos($$, $2); } ;opt_else : none | keyword_else compstmt { $$ = $2; } ;for_var : lhs | mlhs ;f_marg : f_norm_arg { $$ = assignable($1, 0); } | tLPAREN f_margs rparen { $$ = $2; } ;f_marg_list : f_marg { $$ = NEW_LIST($1); } | f_marg_list ',' f_marg { $$ = list_append($1, $3); } ;f_margs : f_marg_list { $$ = NEW_MASGN($1, 0); } | f_marg_list ',' tSTAR f_norm_arg { $$ = assignable($4, 0); $$ = NEW_MASGN($1, $$); } | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list { $$ = assignable($4, 0); $$ = NEW_MASGN($1, NEW_POSTARG($$, $6)); } | f_marg_list ',' tSTAR { $$ = NEW_MASGN($1, -1); } | f_marg_list ',' tSTAR ',' f_marg_list { $$ = NEW_MASGN($1, NEW_POSTARG(-1, $5)); } | tSTAR f_norm_arg { $$ = assignable($2, 0); $$ = NEW_MASGN(0, $$); } | tSTAR f_norm_arg ',' f_marg_list { $$ = assignable($2, 0); $$ = NEW_MASGN(0, NEW_POSTARG($$, $4)); } | tSTAR { $$ = NEW_MASGN(0, -1); } | tSTAR ',' f_marg_list { $$ = NEW_MASGN(0, NEW_POSTARG(-1, $3)); } ;block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg { $$ = new_args_tail($1, $3, $4); } | f_block_kwarg opt_f_block_arg { $$ = new_args_tail($1, Qnone, $2); } | f_kwrest opt_f_block_arg { $$ = new_args_tail(Qnone, $1, $2); } | f_block_arg { $$ = new_args_tail(Qnone, Qnone, $1); } ;opt_block_args_tail : ',' block_args_tail { $$ = $2; } | { $$ = new_args_tail(Qnone, Qnone, Qnone); } ;block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail { $$ = new_args($1, $3, $5, Qnone, $6); } | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail { $$ = new_args($1, $3, $5, $7, $8); } | f_arg ',' f_block_optarg opt_block_args_tail { $$ = new_args($1, $3, Qnone, Qnone, $4); } | f_arg ',' f_block_optarg ',' f_arg opt_block_args_tail { $$ = new_args($1, $3, Qnone, $5, $6); } | f_arg ',' f_rest_arg opt_block_args_tail { $$ = new_args($1, Qnone, $3, Qnone, $4); } | f_arg ',' { $$ = new_args($1, Qnone, 1, Qnone, new_args_tail(Qnone, Qnone, Qnone)); } | f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail { $$ = new_args($1, Qnone, $3, $5, $6); } | f_arg opt_block_args_tail { $$ = new_args($1, Qnone, Qnone, Qnone, $2); } | f_block_optarg ',' f_rest_arg opt_block_args_tail { $$ = new_args(Qnone, $1, $3, Qnone, $4); } | f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail { $$ = new_args(Qnone, $1, $3, $5, $6); } | f_block_optarg opt_block_args_tail { $$ = new_args(Qnone, $1, Qnone, Qnone, $2); } | f_block_optarg ',' f_arg opt_block_args_tail { $$ = new_args(Qnone, $1, Qnone, $3, $4); } | f_rest_arg opt_block_args_tail { $$ = new_args(Qnone, Qnone, $1, Qnone, $2); } | f_rest_arg ',' f_arg opt_block_args_tail { $$ = new_args(Qnone, Qnone, $1, $3, $4); } | block_args_tail { $$ = new_args(Qnone, Qnone, Qnone, Qnone, $1); } ;opt_block_param : none | block_param_def { command_start = TRUE; } ;block_param_def : '|' opt_bv_decl '|' { $$ = 0; } | tOROP { $$ = 0; } | '|' block_param opt_bv_decl '|' { $$ = $2; } ;opt_bv_decl : opt_nl { $$ = 0; } | opt_nl ';' bv_decls opt_nl { $$ = 0; } ;bv_decls : bvar | bv_decls ',' bvar ;bvar : tIDENTIFIER { new_bv(get_id($1)); } | f_bad_arg { $$ = 0; } ;lambda : { $<vars>$ = dyna_push(); } { $<num>$ = lpar_beg; lpar_beg = ++paren_nest; } f_larglist { $<num>$ = ruby_sourceline; } lambda_body { lpar_beg = $<num>2; $$ = NEW_LAMBDA($3, $5); nd_set_line($$, $<num>4); dyna_pop($<vars>1); } ;f_larglist : '(' f_args opt_bv_decl ')' { $$ = $2; } | f_args { $$ = $1; } ;lambda_body : tLAMBEG compstmt '}' { $$ = $2; } | keyword_do_LAMBDA compstmt keyword_end { $$ = $2; } ;do_block : keyword_do_block { $<vars>1 = dyna_push(); $<num>$ = ruby_sourceline; } opt_block_param compstmt keyword_end { $$ = NEW_ITER($3,$4); nd_set_line($$, $<num>2); dyna_pop($<vars>1); } ;block_call : command do_block { if (nd_type($1) == NODE_YIELD) { compile_error(PARSER_ARG "block given to yield"); } else { block_dup_check($1->nd_args, $2); } $2->nd_iter = $1; $$ = $2; fixpos($$, $1); } | block_call dot_or_colon operation2 opt_paren_args { $$ = NEW_CALL($1, $3, $4); } | block_call dot_or_colon operation2 opt_paren_args brace_block { block_dup_check($4, $5); $5->nd_iter = NEW_CALL($1, $3, $4); $$ = $5; fixpos($$, $1); } | block_call dot_or_colon operation2 command_args do_block { block_dup_check($4, $5); $5->nd_iter = NEW_CALL($1, $3, $4); $$ = $5; fixpos($$, $1); } ;method_call : fcall paren_args { $$ = $1; $$->nd_args = $2; } | primary_value '.' operation2 { $<num>$ = ruby_sourceline; } opt_paren_args { $$ = NEW_CALL($1, $3, $5); nd_set_line($$, $<num>4); } | primary_value tCOLON2 operation2 { $<num>$ = ruby_sourceline; } paren_args { $$ = NEW_CALL($1, $3, $5); nd_set_line($$, $<num>4); } | primary_value tCOLON2 operation3 { $$ = NEW_CALL($1, $3, 0); } | primary_value '.' { $<num>$ = ruby_sourceline; } paren_args { $$ = NEW_CALL($1, rb_intern("call"), $4); nd_set_line($$, $<num>3); } | primary_value tCOLON2 { $<num>$ = ruby_sourceline; } paren_args { $$ = NEW_CALL($1, rb_intern("call"), $4); nd_set_line($$, $<num>3); } | keyword_super paren_args { $$ = NEW_SUPER($2); } | keyword_super { $$ = NEW_ZSUPER(); } | primary_value '[' opt_call_args rbracket { if ($1 && nd_type($1) == NODE_SELF) $$ = NEW_FCALL(tAREF, $3); else $$ = NEW_CALL($1, tAREF, $3); fixpos($$, $1); } ;brace_block : '{' { $<vars>1 = dyna_push(); $<num>$ = ruby_sourceline; } opt_block_param compstmt '}' { $$ = NEW_ITER($3,$4); nd_set_line($$, $<num>2); dyna_pop($<vars>1); } | keyword_do { $<vars>1 = dyna_push(); $<num>$ = ruby_sourceline; } opt_block_param compstmt keyword_end { $$ = NEW_ITER($3,$4); nd_set_line($$, $<num>2); dyna_pop($<vars>1); } ;case_body : keyword_when args then compstmt cases { $$ = NEW_WHEN($2, $4, $5); } ;cases : opt_else | case_body ;opt_rescue : keyword_rescue exc_list exc_var then compstmt opt_rescue { if ($3) { $3 = node_assign($3, NEW_ERRINFO()); $5 = block_append($3, $5); } $$ = NEW_RESBODY($2, $5, $6); fixpos($$, $2?$2:$5); } | none ;exc_list : arg_value { $$ = NEW_LIST($1); } | mrhs { if (!($$ = splat_array($1))) $$ = $1; } | none ;exc_var : tASSOC lhs { $$ = $2; } | none ;opt_ensure : keyword_ensure compstmt { $$ = $2; } | none ;literal : numeric | symbol { $$ = NEW_LIT(ID2SYM($1)); } | dsym ;strings : string { NODE *node = $1; if (!node) { node = NEW_STR(STR_NEW0()); } else { node = evstr2dstr(node); } $$ = node; } ;string : tCHAR | string1 | string string1 { $$ = literal_concat($1, $2); } ;string1 : tSTRING_BEG string_contents tSTRING_END { $$ = $2; } ;xstring : tXSTRING_BEG xstring_contents tSTRING_END { NODE *node = $2; if (!node) { node = NEW_XSTR(STR_NEW0()); } else { switch (nd_type(node)) { case NODE_STR: nd_set_type(node, NODE_XSTR); break; case NODE_DSTR: nd_set_type(node, NODE_DXSTR); break; default: node = NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node)); break; } } $$ = node; } ;regexp : tREGEXP_BEG regexp_contents tREGEXP_END { int options = $3; NODE *node = $2; NODE *list, *prev; if (!node) { node = NEW_LIT(reg_compile(STR_NEW0(), options)); } else switch (nd_type(node)) { case NODE_STR: { VALUE src = node->nd_lit; nd_set_type(node, NODE_LIT); node->nd_lit = reg_compile(src, options); } break; default: node = NEW_NODE(NODE_DSTR, STR_NEW0(), 1, NEW_LIST(node)); case NODE_DSTR: if (options & RE_OPTION_ONCE) { nd_set_type(node, NODE_DREGX_ONCE); } else { nd_set_type(node, NODE_DREGX); } node->nd_cflag = options & RE_OPTION_MASK; if (!NIL_P(node->nd_lit)) reg_fragment_check(node->nd_lit, options); for (list = (prev = node)->nd_next; list; list = list->nd_next) { if (nd_type(list->nd_head) == NODE_STR) { VALUE tail = list->nd_head->nd_lit; if (reg_fragment_check(tail, options) && prev && !NIL_P(prev->nd_lit)) { VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit; if (!literal_concat0(parser, lit, tail)) { node = 0; break; } rb_str_resize(tail, 0); prev->nd_next = list->nd_next; rb_gc_force_recycle((VALUE)list->nd_head); rb_gc_force_recycle((VALUE)list); list = prev; } else { prev = list; } } else { prev = 0; } } if (!node->nd_next) { VALUE src = node->nd_lit; nd_set_type(node, NODE_LIT); node->nd_lit = reg_compile(src, options); } break; } $$ = node; } ;words : tWORDS_BEG ' ' tSTRING_END { $$ = NEW_ZARRAY(); } | tWORDS_BEG word_list tSTRING_END { $$ = $2; } ;word_list : { $$ = 0; } | word_list word ' ' { $$ = list_append($1, evstr2dstr($2)); } ;word : string_content | word string_content { $$ = literal_concat($1, $2); } ;symbols : tSYMBOLS_BEG ' ' tSTRING_END { $$ = NEW_ZARRAY(); } | tSYMBOLS_BEG symbol_list tSTRING_END { $$ = $2; } ;symbol_list : { $$ = 0; } | symbol_list word ' ' { $2 = evstr2dstr($2); nd_set_type($2, NODE_DSYM); $$ = list_append($1, $2); } ;qwords : tQWORDS_BEG ' ' tSTRING_END { $$ = NEW_ZARRAY(); } | tQWORDS_BEG qword_list tSTRING_END { $$ = $2; } ;qsymbols : tQSYMBOLS_BEG ' ' tSTRING_END { $$ = NEW_ZARRAY(); } | tQSYMBOLS_BEG qsym_list tSTRING_END { $$ = $2; } ;qword_list : { $$ = 0; } | qword_list tSTRING_CONTENT ' ' { $$ = list_append($1, $2); } ;qsym_list : { $$ = 0; } | qsym_list tSTRING_CONTENT ' ' { VALUE lit; lit = $2->nd_lit; $2->nd_lit = ID2SYM(rb_intern_str(lit)); nd_set_type($2, NODE_LIT); $$ = list_append($1, $2); } ;string_contents : { $$ = 0; } | string_contents string_content { $$ = literal_concat($1, $2); } ;xstring_contents: { $$ = 0; } | xstring_contents string_content { $$ = literal_concat($1, $2); } ;regexp_contents: { $$ = 0; } | regexp_contents string_content { NODE *head = $1, *tail = $2; if (!head) { $$ = tail; } else if (!tail) { $$ = head; } else { switch (nd_type(head)) { case NODE_STR: nd_set_type(head, NODE_DSTR); break; case NODE_DSTR: break; default: head = list_append(NEW_DSTR(Qnil), head); break; } $$ = list_append(head, tail); } } ;string_content : tSTRING_CONTENT | tSTRING_DVAR { $<node>$ = lex_strterm; lex_strterm = 0; lex_state = EXPR_BEG; } string_dvar { lex_strterm = $<node>2; $$ = NEW_EVSTR($3); } | tSTRING_DBEG { $<val>1 = cond_stack; $<val>$ = cmdarg_stack; cond_stack = 0; cmdarg_stack = 0; } { $<node>$ = lex_strterm; lex_strterm = 0; lex_state = EXPR_BEG; } { $<num>$ = brace_nest; brace_nest = 0; } compstmt tSTRING_DEND { cond_stack = $<val>1; cmdarg_stack = $<val>2; lex_strterm = $<node>3; brace_nest = $<num>4; if ($5) $5->flags &= ~NODE_FL_NEWLINE; $$ = new_evstr($5); } ;string_dvar : tGVAR { $$ = NEW_GVAR($1); } | tIVAR { $$ = NEW_IVAR($1); } | tCVAR { $$ = NEW_CVAR($1); } | backref ;symbol : tSYMBEG sym { lex_state = EXPR_END; $$ = $2; } ;sym : fname | tIVAR | tGVAR | tCVAR ;dsym : tSYMBEG xstring_contents tSTRING_END { lex_state = EXPR_END; $$ = dsym_node($2); } ;numeric : tINTEGER | tFLOAT | tUMINUS_NUM tINTEGER %prec tLOWEST { $$ = negate_lit($2); } | tUMINUS_NUM tFLOAT %prec tLOWEST { $$ = negate_lit($2); } ;user_variable : tIDENTIFIER | tIVAR | tGVAR | tCONSTANT | tCVAR ;keyword_variable: keyword_nil {ifndef_ripper($$ = keyword_nil);} | keyword_self {ifndef_ripper($$ = keyword_self);} | keyword_true {ifndef_ripper($$ = keyword_true);} | keyword_false {ifndef_ripper($$ = keyword_false);} | keyword__FILE__ {ifndef_ripper($$ = keyword__FILE__);} | keyword__LINE__ {ifndef_ripper($$ = keyword__LINE__);} | keyword__ENCODING__ {ifndef_ripper($$ = keyword__ENCODING__);} ;var_ref : user_variable { if (!($$ = gettable($1))) $$ = NEW_BEGIN(0); } | keyword_variable { if (!($$ = gettable($1))) $$ = NEW_BEGIN(0); } ;var_lhs : user_variable { $$ = assignable($1, 0); } | keyword_variable { $$ = assignable($1, 0); } ;backref : tNTH_REF | tBACK_REF ;superclass : term { $$ = 0; } | '<' { lex_state = EXPR_BEG; command_start = TRUE; } expr_value term { $$ = $3; } | error term { yyerrok; $$ = 0; } ;f_arglist : '(' f_args rparen { $$ = $2; lex_state = EXPR_BEG; command_start = TRUE; } | f_args term { $$ = $1; lex_state = EXPR_BEG; command_start = TRUE; } ;args_tail : f_kwarg ',' f_kwrest opt_f_block_arg { $$ = new_args_tail($1, $3, $4); } | f_kwarg opt_f_block_arg { $$ = new_args_tail($1, Qnone, $2); } | f_kwrest opt_f_block_arg { $$ = new_args_tail(Qnone, $1, $2); } | f_block_arg { $$ = new_args_tail(Qnone, Qnone, $1); } ;opt_args_tail : ',' args_tail { $$ = $2; } | { $$ = new_args_tail(Qnone, Qnone, Qnone); } ;f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail { $$ = new_args($1, $3, $5, Qnone, $6); } | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_args_tail { $$ = new_args($1, $3, $5, $7, $8); } | f_arg ',' f_optarg opt_args_tail { $$ = new_args($1, $3, Qnone, Qnone, $4); } | f_arg ',' f_optarg ',' f_arg opt_args_tail { $$ = new_args($1, $3, Qnone, $5, $6); } | f_arg ',' f_rest_arg opt_args_tail { $$ = new_args($1, Qnone, $3, Qnone, $4); } | f_arg ',' f_rest_arg ',' f_arg opt_args_tail { $$ = new_args($1, Qnone, $3, $5, $6); } | f_arg opt_args_tail { $$ = new_args($1, Qnone, Qnone, Qnone, $2); } | f_optarg ',' f_rest_arg opt_args_tail { $$ = new_args(Qnone, $1, $3, Qnone, $4); } | f_optarg ',' f_rest_arg ',' f_arg opt_args_tail { $$ = new_args(Qnone, $1, $3, $5, $6); } | f_optarg opt_args_tail { $$ = new_args(Qnone, $1, Qnone, Qnone, $2); } | f_optarg ',' f_arg opt_args_tail { $$ = new_args(Qnone, $1, Qnone, $3, $4); } | f_rest_arg opt_args_tail { $$ = new_args(Qnone, Qnone, $1, Qnone, $2); } | f_rest_arg ',' f_arg opt_args_tail { $$ = new_args(Qnone, Qnone, $1, $3, $4); } | args_tail { $$ = new_args(Qnone, Qnone, Qnone, Qnone, $1); } | { $$ = new_args_tail(Qnone, Qnone, Qnone); $$ = new_args(Qnone, Qnone, Qnone, Qnone, $$); } ;f_bad_arg : tCONSTANT { yyerror("formal argument cannot be a constant"); $$ = 0; } | tIVAR { yyerror("formal argument cannot be an instance variable"); $$ = 0; } | tGVAR { yyerror("formal argument cannot be a global variable"); $$ = 0; } | tCVAR { yyerror("formal argument cannot be a class variable"); $$ = 0; } ;f_norm_arg : f_bad_arg | tIDENTIFIER { formal_argument(get_id($1)); $$ = $1; } ;f_arg_item : f_norm_arg { arg_var(get_id($1)); $$ = NEW_ARGS_AUX($1, 1); } | tLPAREN f_margs rparen { ID tid = internal_id(); arg_var(tid); if (dyna_in_block()) { $2->nd_value = NEW_DVAR(tid); } else { $2->nd_value = NEW_LVAR(tid); } $$ = NEW_ARGS_AUX(tid, 1); $$->nd_next = $2; } ;f_arg : f_arg_item | f_arg ',' f_arg_item { $$ = $1; $$->nd_plen++; $$->nd_next = block_append($$->nd_next, $3->nd_next); rb_gc_force_recycle((VALUE)$3); } ;f_kw : tLABEL arg_value { arg_var(formal_argument(get_id($1))); $$ = assignable($1, $2); $$ = NEW_KW_ARG(0, $$); } ;f_block_kw : tLABEL primary_value { arg_var(formal_argument(get_id($1))); $$ = assignable($1, $2); $$ = NEW_KW_ARG(0, $$); } ;f_block_kwarg : f_block_kw { $$ = $1; } | f_block_kwarg ',' f_block_kw { NODE *kws = $1; while (kws->nd_next) { kws = kws->nd_next; } kws->nd_next = $3; $$ = $1; } ;f_kwarg : f_kw { $$ = $1; } | f_kwarg ',' f_kw { NODE *kws = $1; while (kws->nd_next) { kws = kws->nd_next; } kws->nd_next = $3; $$ = $1; } ;kwrest_mark : tPOW | tDSTAR ;f_kwrest : kwrest_mark tIDENTIFIER { shadowing_lvar(get_id($2)); $$ = $2; } | kwrest_mark { $$ = internal_id(); } ;f_opt : tIDENTIFIER '=' arg_value { arg_var(formal_argument(get_id($1))); $$ = assignable($1, $3); $$ = NEW_OPT_ARG(0, $$); } ;f_block_opt : tIDENTIFIER '=' primary_value { arg_var(formal_argument(get_id($1))); $$ = assignable($1, $3); $$ = NEW_OPT_ARG(0, $$); } ;f_block_optarg : f_block_opt { $$ = $1; } | f_block_optarg ',' f_block_opt { NODE *opts = $1; while (opts->nd_next) { opts = opts->nd_next; } opts->nd_next = $3; $$ = $1; } ;f_optarg : f_opt { $$ = $1; } | f_optarg ',' f_opt { NODE *opts = $1; while (opts->nd_next) { opts = opts->nd_next; } opts->nd_next = $3; $$ = $1; } ;restarg_mark : '*' | tSTAR ;f_rest_arg : restarg_mark tIDENTIFIER { if (!is_local_id($2)) yyerror("rest argument must be local variable"); arg_var(shadowing_lvar(get_id($2))); $$ = $2; } | restarg_mark { $$ = internal_id(); arg_var($$); } ;blkarg_mark : '&' | tAMPER ;f_block_arg : blkarg_mark tIDENTIFIER { if (!is_local_id($2)) yyerror("block argument must be local variable"); else if (!dyna_in_block() && local_id($2)) yyerror("duplicated block argument name"); arg_var(shadowing_lvar(get_id($2))); $$ = $2; } ;opt_f_block_arg : ',' f_block_arg { $$ = $2; } | none { $$ = 0; } ;singleton : var_ref { value_expr($1); $$ = $1; if (!$$) $$ = NEW_NIL(); } | '(' {lex_state = EXPR_BEG;} expr rparen { if ($3 == 0) { yyerror("can't define singleton method for ()."); } else { switch (nd_type($3)) { case NODE_STR: case NODE_DSTR: case NODE_XSTR: case NODE_DXSTR: case NODE_DREGX: case NODE_LIT: case NODE_ARRAY: case NODE_ZARRAY: yyerror("can't define singleton method for literals"); default: value_expr($3); break; } } $$ = $3; } ;assoc_list : none | assocs trailer { $$ = $1; } ;assocs : assoc | assocs ',' assoc { $$ = list_concat($1, $3); } ;assoc : arg_value tASSOC arg_value { $$ = list_append(NEW_LIST($1), $3); } | tLABEL arg_value { $$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2); } | tDSTAR arg_value { $$ = list_append(NEW_LIST(0), $2); } ; ;operation : tIDENTIFIER | tCONSTANT | tFID ;operation2 : tIDENTIFIER | tCONSTANT | tFID | op ;operation3 : tIDENTIFIER | tFID | op ;dot_or_colon : '.' | tCOLON2 ;opt_terms : | terms ;opt_nl : | '\n' ;rparen : opt_nl ')' ;rbracket : opt_nl ']' ;trailer : | '\n' | ',' ;term : ';' {yyerrok;} | '\n' ;terms : term | terms ';' {yyerrok;} ;none : { $$ = 0; } ;%%#define yylvalstatic int parser_regx_options(struct parser_params*);static int parser_tokadd_string(struct parser_params*,int,int,int,long*,rb_encoding**);static void parser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc);static int parser_parse_string(struct parser_params*,NODE*);static int parser_here_document(struct parser_params*,NODE*);#define nextc() #define pushback(c) #define newtok() #define tokspace(n) #define tokadd(c) #define tok_hex(numlen) #define read_escape(flags,e) #define tokadd_escape(e) #define regx_options() #define tokadd_string(f,t,p,n,e) #define parse_string(n) #define tokaddmbc(c, enc) #define here_document(n) #define heredoc_identifier() #define heredoc_restore(n) #define whole_match_p(e,l,i) #define set_yylval_str(x) #define set_yylval_num(x) #define set_yylval_id(x) #define set_yylval_name(x) #define set_yylval_literal(x) #define set_yylval_node(x) #define yylval_id() #define ripper_flush(p) #define SIGN_EXTEND_CHAR(c) #define parser_encoding_name() #define parser_mbclen() #define parser_precise_mbclen() #define is_identchar(p,e,enc) #define parser_is_identchar() #define parser_isascii() static inttoken_info_get_column(struct parser_params *parser, const char *token){ int column = 1; const char *p, *pend = lex_p - strlen(token); for (p = lex_pbeg; p < pend; p++) { if (*p == '\t') { column = (((column - 1) / 8) + 1) * 8; } column++; } return column;}static inttoken_info_has_nonspaces(struct parser_params *parser, const char *token){ const char *p, *pend = lex_p - strlen(token); for (p = lex_pbeg; p < pend; p++) { if (*p != ' ' && *p != '\t') { return 1; } } return 0;}static voidtoken_info_push(struct parser_params *parser, const char *token){ token_info *ptinfo; if (!parser->parser_token_info_enabled) return; ptinfo = ALLOC(token_info); ptinfo->token = token; ptinfo->linenum = ruby_sourceline; ptinfo->column = token_info_get_column(parser, token); ptinfo->nonspc = token_info_has_nonspaces(parser, token); ptinfo->next = parser->parser_token_info; parser->parser_token_info = ptinfo;}static voidtoken_info_pop(struct parser_params *parser, const char *token){ int linenum; token_info *ptinfo = parser->parser_token_info; if (!ptinfo) return; parser->parser_token_info = ptinfo->next; if (token_info_get_column(parser, token) == ptinfo->column) { goto finish; } linenum = ruby_sourceline; if (linenum == ptinfo->linenum) { goto finish; } if (token_info_has_nonspaces(parser, token) || ptinfo->nonspc) { goto finish; } if (parser->parser_token_info_enabled) { rb_compile_warn(ruby_sourcefile, linenum, "mismatched indentations at '%s' with '%s' at %d", token, ptinfo->token, ptinfo->linenum); } finish: xfree(ptinfo);}static intparser_yyerror(struct parser_params *parser, const char *msg){ const int max_line_margin = 30; const char *p, *pe; char *buf; long len; int i; compile_error(PARSER_ARG "%s", msg); p = lex_p; while (lex_pbeg <= p) { if (*p == '\n') break; p--; } p++; pe = lex_p; while (pe < lex_pend) { if (*pe == '\n') break; pe++; } len = pe - p; if (len > 4) { char *p2; const char *pre = "", *post = ""; if (len > max_line_margin * 2 + 10) { if (lex_p - p > max_line_margin) { p = rb_enc_prev_char(p, lex_p - max_line_margin, pe, rb_enc_get(lex_lastline)); pre = "..."; } if (pe - lex_p > max_line_margin) { pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, pe, rb_enc_get(lex_lastline)); post = "..."; } len = pe - p; } buf = ALLOCA_N(char, len+2); MEMCPY(buf, p, char, len); buf[len] = '\0'; rb_compile_error_append("%s%s%s", pre, buf, post); i = (int)(lex_p - p); p2 = buf; pe = buf + len; while (p2 < pe) { if (*p2 != '\t') *p2 = ' '; p2++; } buf[i] = '^'; buf[i+1] = '\0'; rb_compile_error_append("%s%s", pre, buf); } return 0;}static void parser_prepare(struct parser_params *parser);static VALUEdebug_lines(const char *f){ ID script_lines; CONST_ID(script_lines, "SCRIPT_LINES__"); if (rb_const_defined_at(rb_cObject, script_lines)) { VALUE hash = rb_const_get_at(rb_cObject, script_lines); if (RB_TYPE_P(hash, T_HASH)) { VALUE fname = rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding()); VALUE lines = rb_ary_new(); rb_hash_aset(hash, fname, lines); return lines; } } return 0;}static VALUEcoverage(const char *f, int n){ VALUE coverages = rb_get_coverages(); if (RTEST(coverages) && RBASIC(coverages)->klass == 0) { VALUE fname = rb_external_str_new_with_enc(f, strlen(f), rb_filesystem_encoding()); VALUE lines = rb_ary_new2(n); int i; RBASIC(lines)->klass = 0; for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil; RARRAY(lines)->as.heap.len = n; rb_hash_aset(coverages, fname, lines); return lines; } return 0;}static inte_option_supplied(struct parser_params *parser){ return strcmp(ruby_sourcefile, "-e") == 0;}static VALUEyycompile0(VALUE arg){ int n; NODE *tree; struct parser_params *parser = (struct parser_params *)arg; if (!compile_for_eval && rb_safe_level() == 0) { ruby_debug_lines = debug_lines(ruby_sourcefile); if (ruby_debug_lines && ruby_sourceline > 0) { VALUE str = STR_NEW0(); n = ruby_sourceline; do { rb_ary_push(ruby_debug_lines, str); } while (--n); } if (!e_option_supplied(parser)) { ruby_coverage = coverage(ruby_sourcefile, ruby_sourceline); } } parser_prepare(parser); deferred_nodes = 0; parser->parser_token_info_enabled = !compile_for_eval && RTEST(ruby_verbose); if (RUBY_DTRACE_PARSE_BEGIN_ENABLED()) { RUBY_DTRACE_PARSE_BEGIN(parser->parser_ruby_sourcefile, parser->parser_ruby_sourceline); } n = yyparse((void*)parser); if (RUBY_DTRACE_PARSE_END_ENABLED()) { RUBY_DTRACE_PARSE_END(parser->parser_ruby_sourcefile, parser->parser_ruby_sourceline); } ruby_debug_lines = 0; ruby_coverage = 0; compile_for_eval = 0; lex_strterm = 0; lex_p = lex_pbeg = lex_pend = 0; lex_lastline = lex_nextline = 0; if (parser->nerr) { return 0; } tree = ruby_eval_tree; if (!tree) { tree = NEW_NIL(); } else if (ruby_eval_tree_begin) { tree->nd_body = NEW_PRELUDE(ruby_eval_tree_begin, tree->nd_body); } return (VALUE)tree;}static NODE*yycompile(struct parser_params *parser, const char *f, int line){ ruby_sourcefile = ruby_strdup(f); ruby_sourceline = line - 1; return (NODE *)rb_suppress_tracing(yycompile0, (VALUE)parser);}static rb_encoding *must_be_ascii_compatible(VALUE s){ rb_encoding *enc = rb_enc_get(s); if (!rb_enc_asciicompat(enc)) { rb_raise(rb_eArgError, "invalid source encoding"); } return enc;}static VALUElex_get_str(struct parser_params *parser, VALUE s){ char *beg, *end, *pend; rb_encoding *enc = must_be_ascii_compatible(s); beg = RSTRING_PTR(s); if (lex_gets_ptr) { if (RSTRING_LEN(s) == lex_gets_ptr) return Qnil; beg += lex_gets_ptr; } pend = RSTRING_PTR(s) + RSTRING_LEN(s); end = beg; while (end < pend) { if (*end++ == '\n') break; } lex_gets_ptr = end - RSTRING_PTR(s); return rb_enc_str_new(beg, end - beg, enc);}static VALUElex_getline(struct parser_params *parser){ VALUE line = (*parser->parser_lex_gets)(parser, parser->parser_lex_input); if (NIL_P(line)) return line; must_be_ascii_compatible(line); if (ruby_debug_lines) { rb_enc_associate(line, current_enc); rb_ary_push(ruby_debug_lines, line); } if (ruby_coverage) { rb_ary_push(ruby_coverage, Qnil); } return line;}static const rb_data_type_t parser_data_type;static NODE*parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line){ struct parser_params *parser; NODE *node; TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser); lex_gets = lex_get_str; lex_gets_ptr = 0; lex_input = s; lex_pbeg = lex_p = lex_pend = 0; compile_for_eval = rb_parse_in_eval(); node = yycompile(parser, f, line); RB_GC_GUARD(vparser); return node;}NODE*rb_compile_string(const char *f, VALUE s, int line){ must_be_ascii_compatible(s); return parser_compile_string(rb_parser_new(), f, s, line);}NODE*rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line){ must_be_ascii_compatible(s); return parser_compile_string(vparser, f, s, line);}NODE*rb_compile_cstr(const char *f, const char *s, int len, int line){ VALUE str = rb_str_new(s, len); return parser_compile_string(rb_parser_new(), f, str, line);}NODE*rb_parser_compile_cstr(volatile VALUE vparser, const char *f, const char *s, int len, int line){ VALUE str = rb_str_new(s, len); return parser_compile_string(vparser, f, str, line);}static VALUElex_io_gets(struct parser_params *parser, VALUE io){ return rb_io_gets(io);}NODE*rb_compile_file(const char *f, VALUE file, int start){ VALUE volatile vparser = rb_parser_new(); return rb_parser_compile_file(vparser, f, file, start);}NODE*rb_parser_compile_file(volatile VALUE vparser, const char *f, VALUE file, int start){ struct parser_params *parser; NODE *node; TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser); lex_gets = lex_io_gets; lex_input = file; lex_pbeg = lex_p = lex_pend = 0; compile_for_eval = rb_parse_in_eval(); node = yycompile(parser, f, start); RB_GC_GUARD(vparser); return node;}#define STR_FUNC_ESCAPE#define STR_FUNC_EXPAND#define STR_FUNC_REGEXP#define STR_FUNC_QWORDS#define STR_FUNC_SYMBOL#define STR_FUNC_INDENTenum string_type { str_squote = (0), str_dquote = (STR_FUNC_EXPAND), str_xquote = (STR_FUNC_EXPAND), str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND), str_sword = (STR_FUNC_QWORDS), str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND), str_ssym = (STR_FUNC_SYMBOL), str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND)};static VALUEparser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *enc0){ VALUE str; str = rb_enc_str_new(p, n, enc); if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) { if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) { } else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) { rb_enc_associate(str, rb_ascii8bit_encoding()); } } return str;}#define lex_goto_eol(parser) #define lex_eol_p() #define peek(c) #define peek_n(c,n) static inline intparser_nextc(struct parser_params *parser){ int c; if (lex_p == lex_pend) { VALUE v = lex_nextline; lex_nextline = 0; if (!v) { if (parser->eofp) return -1; if (!lex_input || NIL_P(v = lex_getline(parser))) { parser->eofp = Qtrue; lex_goto_eol(parser); return -1; } } { if (heredoc_end > 0) { ruby_sourceline = heredoc_end; heredoc_end = 0; } ruby_sourceline++; parser->line_count++; lex_pbeg = lex_p = RSTRING_PTR(v); lex_pend = lex_p + RSTRING_LEN(v); ripper_flush(parser); lex_lastline = v; } } c = (unsigned char)*lex_p++; if (c == '\r' && peek('\n')) { lex_p++; c = '\n'; } return c;}static voidparser_pushback(struct parser_params *parser, int c){ if (c == -1) return; lex_p--; if (lex_p > lex_pbeg && lex_p[0] == '\n' && lex_p[-1] == '\r') { lex_p--; }}#define was_bol() #define tokfix() #define tok() #define toklen() #define toklast() static char*parser_newtok(struct parser_params *parser){ tokidx = 0; tokline = ruby_sourceline; if (!tokenbuf) { toksiz = 60; tokenbuf = ALLOC_N(char, 60); } if (toksiz > 4096) { toksiz = 60; REALLOC_N(tokenbuf, char, 60); } return tokenbuf;}static char *parser_tokspace(struct parser_params *parser, int n){ tokidx += n; if (tokidx >= toksiz) { do {toksiz *= 2;} while (toksiz < tokidx); REALLOC_N(tokenbuf, char, toksiz); } return &tokenbuf[tokidx-n];}static voidparser_tokadd(struct parser_params *parser, int c){ tokenbuf[tokidx++] = (char)c; if (tokidx >= toksiz) { toksiz *= 2; REALLOC_N(tokenbuf, char, toksiz); }}static intparser_tok_hex(struct parser_params *parser, size_t *numlen){ int c; c = scan_hex(lex_p, 2, numlen); if (!*numlen) { yyerror("invalid hex escape"); return 0; } lex_p += *numlen; return c;}#define tokcopy(n) static intparser_tokadd_utf8(struct parser_params *parser, rb_encoding **encp, int string_literal, int symbol_literal, int regexp_literal){ int codepoint; size_t numlen; if (regexp_literal) { tokadd('\\'); tokadd('u'); } if (peek('{')) { do { if (regexp_literal) { tokadd(*lex_p); } nextc(); codepoint = scan_hex(lex_p, 6, &numlen); if (numlen == 0) { yyerror("invalid Unicode escape"); return 0; } if (codepoint > 0x10ffff) { yyerror("invalid Unicode codepoint (too large)"); return 0; } lex_p += numlen; if (regexp_literal) { tokcopy((int)numlen); } else if (codepoint >= 0x80) { *encp = rb_utf8_encoding(); if (string_literal) tokaddmbc(codepoint, *encp); } else if (string_literal) { tokadd(codepoint); } } while (string_literal && (peek(' ') || peek('\t'))); if (!peek('}')) { yyerror("unterminated Unicode escape"); return 0; } if (regexp_literal) { tokadd('}'); } nextc(); } else { codepoint = scan_hex(lex_p, 4, &numlen); if (numlen < 4) { yyerror("invalid Unicode escape"); return 0; } lex_p += 4; if (regexp_literal) { tokcopy(4); } else if (codepoint >= 0x80) { *encp = rb_utf8_encoding(); if (string_literal) tokaddmbc(codepoint, *encp); } else if (string_literal) { tokadd(codepoint); } } return codepoint;}#define ESCAPE_CONTROL#define ESCAPE_METAstatic intparser_read_escape(struct parser_params *parser, int flags, rb_encoding **encp){ int c; size_t numlen; switch (c = nextc()) { case '\\': return c; case 'n': return '\n'; case 't': return '\t'; case 'r': return '\r'; case 'f': return '\f'; case 'v': return '\13'; case 'a': return '\007'; case 'e': return 033; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': pushback(c); c = scan_oct(lex_p, 3, &numlen); lex_p += numlen; return c; case 'x': c = tok_hex(&numlen); if (numlen == 0) return 0; return c; case 'b': return '\010'; case 's': return ' '; case 'M': if (flags & ESCAPE_META) goto eof; if ((c = nextc()) != '-') { pushback(c); goto eof; } if ((c = nextc()) == '\\') { if (peek('u')) goto eof; return read_escape(flags|ESCAPE_META, encp) | 0x80; } else if (c == -1 || !ISASCII(c)) goto eof; else { return ((c & 0xff) | 0x80); } case 'C': if ((c = nextc()) != '-') { pushback(c); goto eof; } case 'c': if (flags & ESCAPE_CONTROL) goto eof; if ((c = nextc())== '\\') { if (peek('u')) goto eof; c = read_escape(flags|ESCAPE_CONTROL, encp); } else if (c == '?') return 0177; else if (c == -1 || !ISASCII(c)) goto eof; return c & 0x9f; eof: case -1: yyerror("Invalid escape character syntax"); return '\0'; default: return c; }}static voidparser_tokaddmbc(struct parser_params *parser, int c, rb_encoding *enc){ int len = rb_enc_codelen(c, enc); rb_enc_mbcput(c, tokspace(len), enc);}static intparser_tokadd_escape(struct parser_params *parser, rb_encoding **encp){ int c; int flags = 0; size_t numlen; first: switch (c = nextc()) { case '\n': return 0; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { ruby_scan_oct(--lex_p, 3, &numlen); if (numlen == 0) goto eof; lex_p += numlen; tokcopy((int)numlen + 1); } return 0; case 'x': { tok_hex(&numlen); if (numlen == 0) return -1; tokcopy((int)numlen + 2); } return 0; case 'M': if (flags & ESCAPE_META) goto eof; if ((c = nextc()) != '-') { pushback(c); goto eof; } tokcopy(3); flags |= ESCAPE_META; goto escaped; case 'C': if (flags & ESCAPE_CONTROL) goto eof; if ((c = nextc()) != '-') { pushback(c); goto eof; } tokcopy(3); goto escaped; case 'c': if (flags & ESCAPE_CONTROL) goto eof; tokcopy(2); flags |= ESCAPE_CONTROL; escaped: if ((c = nextc()) == '\\') { goto first; } else if (c == -1) goto eof; tokadd(c); return 0; eof: case -1: yyerror("Invalid escape character syntax"); return -1; default: tokadd('\\'); tokadd(c); } return 0;}static intparser_regx_options(struct parser_params *parser){ int kcode = 0; int kopt = 0; int options = 0; int c, opt, kc; newtok(); while (c = nextc(), ISALPHA(c)) { if (c == 'o') { options |= RE_OPTION_ONCE; } else if (rb_char_to_option_kcode(c, &opt, &kc)) { if (kc >= 0) { if (kc != rb_ascii8bit_encindex()) kcode = c; kopt = opt; } else { options |= opt; } } else { tokadd(c); } } options |= kopt; pushback(c); if (toklen()) { tokfix(); compile_error(PARSER_ARG "unknown regexp option%s - %s", toklen() > 1 ? "s" : "", tok()); } return options | RE_OPTION_ENCODING(kcode);}static voiddispose_string(VALUE str){ rb_str_free(str); rb_gc_force_recycle(str);}static intparser_tokadd_mbchar(struct parser_params *parser, int c){ int len = parser_precise_mbclen(); if (!MBCLEN_CHARFOUND_P(len)) { compile_error(PARSER_ARG "invalid multibyte char (%s)", parser_encoding_name()); return -1; } tokadd(c); lex_p += --len; if (len > 0) tokcopy(len); return c;}#define tokadd_mbchar(c) static inline intsimple_re_meta(int c){ switch (c) { case '$': case '*': case '+': case '.': case '?': case '^': case '|': case ')': case ']': case '}': case '>': return TRUE; default: return FALSE; }}static intparser_tokadd_string(struct parser_params *parser, int func, int term, int paren, long *nest, rb_encoding **encp){ int c; int has_nonascii = 0; rb_encoding *enc = *encp; char *errbuf = 0; static const char mixed_msg[] = "%s mixed within %s source";#define mixed_error(enc1, enc2) #define mixed_escape(beg, enc1, enc2) while ((c = nextc()) != -1) { if (paren && c == paren) { ++*nest; } else if (c == term) { if (!nest || !*nest) { pushback(c); break; } --*nest; } else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) { int c2 = *lex_p; if (c2 == '$' || c2 == '@' || c2 == '{') { pushback(c); break; } } else if (c == '\\') { const char *beg = lex_p - 1; c = nextc(); switch (c) { case '\n': if (func & STR_FUNC_QWORDS) break; if (func & STR_FUNC_EXPAND) continue; tokadd('\\'); break; case '\\': if (func & STR_FUNC_ESCAPE) tokadd(c); break; case 'u': if ((func & STR_FUNC_EXPAND) == 0) { tokadd('\\'); break; } parser_tokadd_utf8(parser, &enc, 1, func & STR_FUNC_SYMBOL, func & STR_FUNC_REGEXP); if (has_nonascii && enc != *encp) { mixed_escape(beg, enc, *encp); } continue; default: if (c == -1) return -1; if (!ISASCII(c)) { if ((func & STR_FUNC_EXPAND) == 0) tokadd('\\'); goto non_ascii; } if (func & STR_FUNC_REGEXP) { if (c == term && !simple_re_meta(c)) { tokadd(c); continue; } pushback(c); if ((c = tokadd_escape(&enc)) < 0) return -1; if (has_nonascii && enc != *encp) { mixed_escape(beg, enc, *encp); } continue; } else if (func & STR_FUNC_EXPAND) { pushback(c); if (func & STR_FUNC_ESCAPE) tokadd('\\'); c = read_escape(0, &enc); } else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) { } else if (c != term && !(paren && c == paren)) { tokadd('\\'); pushback(c); continue; } } } else if (!parser_isascii()) { non_ascii: has_nonascii = 1; if (enc != *encp) { mixed_error(enc, *encp); continue; } if (tokadd_mbchar(c) == -1) return -1; continue; } else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) { pushback(c); break; } if (c & 0x80) { has_nonascii = 1; if (enc != *encp) { mixed_error(enc, *encp); continue; } } tokadd(c); } *encp = enc; return c;}#define NEW_STRTERM(func, term, paren) #define flush_string_content(enc) RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32];#define BIT(c, idx) #define SPECIAL_PUNCT(idx) const unsigned int ruby_global_name_punct_bits[] = { SPECIAL_PUNCT(0), SPECIAL_PUNCT(1), SPECIAL_PUNCT(2),};static inline intis_global_name_punct(const char c){ if (c <= 0x20 || 0x7e < c) return 0; return (ruby_global_name_punct_bits[(c - 0x20) / 32] >> (c % 32)) & 1;}static intparser_peek_variable_name(struct parser_params *parser){ int c; const char *p = lex_p; if (p + 1 >= lex_pend) return 0; c = *p++; switch (c) { case '$': if ((c = *p) == '-') { if (++p >= lex_pend) return 0; c = *p; } else if (is_global_name_punct(c) || ISDIGIT(c)) { return tSTRING_DVAR; } break; case '@': if ((c = *p) == '@') { if (++p >= lex_pend) return 0; c = *p; } break; case '{': lex_p = p; command_start = TRUE; return tSTRING_DBEG; default: return 0; } if (!ISASCII(c) || c == '_' || ISALPHA(c)) return tSTRING_DVAR; return 0;}static intparser_parse_string(struct parser_params *parser, NODE *quote){ int func = (int)quote->nd_func; int term = nd_term(quote); int paren = nd_paren(quote); int c, space = 0; rb_encoding *enc = current_enc; if (func == -1) return tSTRING_END; c = nextc(); if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) { do {c = nextc();} while (ISSPACE(c)); space = 1; } if (c == term && !quote->nd_nest) { if (func & STR_FUNC_QWORDS) { quote->nd_func = -1; return ' '; } if (!(func & STR_FUNC_REGEXP)) return tSTRING_END; set_yylval_num(regx_options()); return tREGEXP_END; } if (space) { pushback(c); return ' '; } newtok(); if ((func & STR_FUNC_EXPAND) && c == '#') { int t = parser_peek_variable_name(parser); if (t) return t; tokadd('#'); c = nextc(); } pushback(c); if (tokadd_string(func, term, paren, &quote->nd_nest, &enc) == -1) { ruby_sourceline = nd_line(quote); if (func & STR_FUNC_REGEXP) { if (parser->eofp) compile_error(PARSER_ARG "unterminated regexp meets end of file"); return tREGEXP_END; } else { if (parser->eofp) compile_error(PARSER_ARG "unterminated string meets end of file"); return tSTRING_END; } } tokfix(); set_yylval_str(STR_NEW3(tok(), toklen(), enc, func)); flush_string_content(enc); return tSTRING_CONTENT;}static intparser_heredoc_identifier(struct parser_params *parser){ int c = nextc(), term, func = 0; long len; if (c == '-') { c = nextc(); func = STR_FUNC_INDENT; } switch (c) { case '\'': func |= str_squote; goto quoted; case '"': func |= str_dquote; goto quoted; case '`': func |= str_xquote; quoted: newtok(); tokadd(func); term = c; while ((c = nextc()) != -1 && c != term) { if (tokadd_mbchar(c) == -1) return 0; } if (c == -1) { compile_error(PARSER_ARG "unterminated here document identifier"); return 0; } break; default: if (!parser_is_identchar()) { pushback(c); if (func & STR_FUNC_INDENT) { pushback('-'); } return 0; } newtok(); term = '"'; tokadd(func |= str_dquote); do { if (tokadd_mbchar(c) == -1) return 0; } while ((c = nextc()) != -1 && parser_is_identchar()); pushback(c); break; } tokfix(); len = lex_p - lex_pbeg; lex_goto_eol(parser); lex_strterm = rb_node_newnode(NODE_HEREDOC, STR_NEW(tok(), toklen()), len, lex_lastline); nd_set_line(lex_strterm, ruby_sourceline); ripper_flush(parser); return term == '`' ? tXSTRING_BEG : tSTRING_BEG;}static voidparser_heredoc_restore(struct parser_params *parser, NODE *here){ VALUE line; line = here->nd_orig; lex_lastline = line; lex_pbeg = RSTRING_PTR(line); lex_pend = lex_pbeg + RSTRING_LEN(line); lex_p = lex_pbeg + here->nd_nth; heredoc_end = ruby_sourceline; ruby_sourceline = nd_line(here); dispose_string(here->nd_lit); rb_gc_force_recycle((VALUE)here); ripper_flush(parser);}static intparser_whole_match_p(struct parser_params *parser, const char *eos, long len, int indent){ const char *p = lex_pbeg; long n; if (indent) { while (*p && ISSPACE(*p)) p++; } n = lex_pend - (p + len); if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return FALSE; return strncmp(eos, p, len) == 0;}#define dispatch_heredoc_end() static intparser_here_document(struct parser_params *parser, NODE *here){ int c, func, indent = 0; const char *eos, *p, *pend; long len; VALUE str = 0; rb_encoding *enc = current_enc; eos = RSTRING_PTR(here->nd_lit); len = RSTRING_LEN(here->nd_lit) - 1; indent = (func = *eos++) & STR_FUNC_INDENT; if ((c = nextc()) == -1) { error: compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos); restore: heredoc_restore(lex_strterm); lex_strterm = 0; return 0; } if (was_bol() && whole_match_p(eos, len, indent)) { dispatch_heredoc_end(); heredoc_restore(lex_strterm); return tSTRING_END; } if (!(func & STR_FUNC_EXPAND)) { do { p = RSTRING_PTR(lex_lastline); pend = lex_pend; if (pend > p) { switch (pend[-1]) { case '\n': if (--pend == p || pend[-1] != '\r') { pend++; break; } case '\r': --pend; } } if (str) rb_str_cat(str, p, pend - p); else str = STR_NEW(p, pend - p); if (pend < lex_pend) rb_str_cat(str, "\n", 1); lex_goto_eol(parser); if (nextc() == -1) { if (str) dispose_string(str); goto error; } } while (!whole_match_p(eos, len, indent)); } else { newtok(); if (c == '#') { int t = parser_peek_variable_name(parser); if (t) return t; tokadd('#'); c = nextc(); } do { pushback(c); if ((c = tokadd_string(func, '\n', 0, NULL, &enc)) == -1) { if (parser->eofp) goto error; goto restore; } if (c != '\n') { set_yylval_str(STR_NEW3(tok(), toklen(), enc, func)); flush_string_content(enc); return tSTRING_CONTENT; } tokadd(nextc()); if ((c = nextc()) == -1) goto error; } while (!whole_match_p(eos, len, indent)); str = STR_NEW3(tok(), toklen(), enc, func); } dispatch_heredoc_end(); heredoc_restore(lex_strterm); lex_strterm = NEW_STRTERM(-1, 0, 0); set_yylval_str(str); return tSTRING_CONTENT;}static voidarg_ambiguous_gen(struct parser_params *parser){ rb_warning0("ambiguous first argument; put parentheses or even spaces");}#define arg_ambiguous() static IDformal_argument_gen(struct parser_params *parser, ID lhs){ if (!is_local_id(lhs)) yyerror("formal argument must be local variable"); shadowing_lvar(lhs); return lhs;}static intlvar_defined_gen(struct parser_params *parser, ID id){ return (dyna_in_block() && dvar_defined_get(id)) || local_id(id);}static longparser_encode_length(struct parser_params *parser, const char *name, long len){ long nlen; if (len > 5 && name[nlen = len - 5] == '-') { if (rb_memcicmp(name + nlen + 1, "unix", 4) == 0) return nlen; } if (len > 4 && name[nlen = len - 4] == '-') { if (rb_memcicmp(name + nlen + 1, "dos", 3) == 0) return nlen; if (rb_memcicmp(name + nlen + 1, "mac", 3) == 0 && !(len == 8 && rb_memcicmp(name, "utf8-mac", len) == 0)) return nlen; } return len;}static voidparser_set_encode(struct parser_params *parser, const char *name){ int idx = rb_enc_find_index(name); rb_encoding *enc; VALUE excargs[3]; if (idx < 0) { excargs[1] = rb_sprintf("unknown encoding name: %s", name); error: excargs[0] = rb_eArgError; excargs[2] = rb_make_backtrace(); rb_ary_unshift(excargs[2], rb_sprintf("%s:%d", ruby_sourcefile, ruby_sourceline)); rb_exc_raise(rb_make_exception(3, excargs)); } enc = rb_enc_from_index(idx); if (!rb_enc_asciicompat(enc)) { excargs[1] = rb_sprintf("%s is not ASCII compatible", rb_enc_name(enc)); goto error; } parser->enc = enc; if (ruby_debug_lines) { long i, n = RARRAY_LEN(ruby_debug_lines); const VALUE *p = RARRAY_PTR(ruby_debug_lines); for (i = 0; i < n; ++i) { rb_enc_associate_index(*p, idx); } }}static intcomment_at_top(struct parser_params *parser){ const char *p = lex_pbeg, *pend = lex_p - 1; if (parser->line_count != (parser->has_shebang ? 2 : 1)) return 0; while (p < pend) { if (!ISSPACE(*p)) return 0; p++; } return 1;}typedef long (*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, long len);typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);static voidmagic_comment_encoding(struct parser_params *parser, const char *name, const char *val){ if (!comment_at_top(parser)) { return; } parser_set_encode(parser, val);}static voidparser_set_token_info(struct parser_params *parser, const char *name, const char *val){ int *p = &parser->parser_token_info_enabled; switch (*val) { case 't': case 'T': if (strcasecmp(val, "true") == 0) { *p = TRUE; return; } break; case 'f': case 'F': if (strcasecmp(val, "false") == 0) { *p = FALSE; return; } break; } rb_compile_warning(ruby_sourcefile, ruby_sourceline, "invalid value for %s: %s", name, val);}struct magic_comment { const char *name; rb_magic_comment_setter_t func; rb_magic_comment_length_t length;};static const struct magic_comment magic_comments[] = { {"coding", magic_comment_encoding, parser_encode_length}, {"encoding", magic_comment_encoding, parser_encode_length}, {"warn_indent", parser_set_token_info},};static const char *magic_comment_marker(const char *str, long len){ long i = 2; while (i < len) { switch (str[i]) { case '-': if (str[i-1] == '*' && str[i-2] == '-') { return str + i + 1; } i += 2; break; case '*': if (i + 1 >= len) return 0; if (str[i+1] != '-') { i += 4; } else if (str[i-1] != '-') { i += 2; } else { return str + i + 2; } break; default: i += 3; break; } } return 0;}static intparser_magic_comment(struct parser_params *parser, const char *str, long len){ VALUE name = 0, val = 0; const char *beg, *end, *vbeg, *vend;#define str_copy(_s, _p, _n) if (len <= 7) return FALSE; if (!(beg = magic_comment_marker(str, len))) return FALSE; if (!(end = magic_comment_marker(beg, str + len - beg))) return FALSE; str = beg; len = end - beg - 3; while (len > 0) { const struct magic_comment *p = magic_comments; char *s; int i; long n = 0; for (; len > 0 && *str; str++, --len) { switch (*str) { case '\'': case '"': case ':': case ';': continue; } if (!ISSPACE(*str)) break; } for (beg = str; len > 0; str++, --len) { switch (*str) { case '\'': case '"': case ':': case ';': break; default: if (ISSPACE(*str)) break; continue; } break; } for (end = str; len > 0 && ISSPACE(*str); str++, --len); if (!len) break; if (*str != ':') continue; do str++; while (--len > 0 && ISSPACE(*str)); if (!len) break; if (*str == '"') { for (vbeg = ++str; --len > 0 && *str != '"'; str++) { if (*str == '\\') { --len; ++str; } } vend = str; if (len) { --len; ++str; } } else { for (vbeg = str; len > 0 && *str != '"' && *str != ';' && !ISSPACE(*str); --len, str++); vend = str; } while (len > 0 && (*str == ';' || ISSPACE(*str))) --len, str++; n = end - beg; str_copy(name, beg, n); s = RSTRING_PTR(name); for (i = 0; i < n; ++i) { if (s[i] == '-') s[i] = '_'; } do { if (STRNCASECMP(p->name, s, n) == 0) { n = vend - vbeg; if (p->length) { n = (*p->length)(parser, vbeg, n); } str_copy(val, vbeg, n); (*p->func)(parser, s, RSTRING_PTR(val)); break; } } while (++p < magic_comments + numberof(magic_comments)); } return TRUE;}static voidset_file_encoding(struct parser_params *parser, const char *str, const char *send){ int sep = 0; const char *beg = str; VALUE s; for (;;) { if (send - str <= 6) return; switch (str[6]) { case 'C': case 'c': str += 6; continue; case 'O': case 'o': str += 5; continue; case 'D': case 'd': str += 4; continue; case 'I': case 'i': str += 3; continue; case 'N': case 'n': str += 2; continue; case 'G': case 'g': str += 1; continue; case '=': case ':': sep = 1; str += 6; break; default: str += 6; if (ISSPACE(*str)) break; continue; } if (STRNCASECMP(str-6, "coding", 6) == 0) break; } for (;;) { do { if (++str >= send) return; } while (ISSPACE(*str)); if (sep) break; if (*str != '=' && *str != ':') return; sep = 1; str++; } beg = str; while ((*str == '-' || *str == '_' || ISALNUM(*str)) && ++str < send); s = rb_str_new(beg, parser_encode_length(parser, beg, str - beg)); parser_set_encode(parser, RSTRING_PTR(s)); rb_str_resize(s, 0);}static voidparser_prepare(struct parser_params *parser){ int c = nextc(); switch (c) { case '#': if (peek('!')) parser->has_shebang = 1; break; case 0xef: if (lex_pend - lex_p >= 2 && (unsigned char)lex_p[0] == 0xbb && (unsigned char)lex_p[1] == 0xbf) { parser->enc = rb_utf8_encoding(); lex_p += 2; lex_pbeg = lex_p; return; } break; case EOF: return; } pushback(c); parser->enc = rb_enc_get(lex_lastline);}#define IS_ARG() #define IS_END() #define IS_BEG() #define IS_SPCARG(c) #define IS_LABEL_POSSIBLE() #define IS_LABEL_SUFFIX(n) #define IS_AFTER_OPERATOR() #define ambiguous_operator(op, syn) #define warn_balanced(op, syn) static intparser_yylex(struct parser_params *parser){ register int c; int space_seen = 0; int cmd_state; enum lex_state_e last_state; rb_encoding *enc; int mb; if (lex_strterm) { int token; if (nd_type(lex_strterm) == NODE_HEREDOC) { token = here_document(lex_strterm); if (token == tSTRING_END) { lex_strterm = 0; lex_state = EXPR_END; } } else { token = parse_string(lex_strterm); if (token == tSTRING_END || token == tREGEXP_END) { rb_gc_force_recycle((VALUE)lex_strterm); lex_strterm = 0; lex_state = EXPR_END; } } return token; } cmd_state = command_start; command_start = FALSE; retry: last_state = lex_state; switch (c = nextc()) { case '\0': case '\004': case '\032': case -1: return 0; case ' ': case '\t': case '\f': case '\r': case '\13': space_seen = 1; goto retry; case '#': if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) { if (comment_at_top(parser)) { set_file_encoding(parser, lex_p, lex_pend); } } lex_p = lex_pend; case '\n': if (IS_lex_state(EXPR_BEG | EXPR_VALUE | EXPR_CLASS | EXPR_FNAME | EXPR_DOT)) { goto retry; } while ((c = nextc())) { switch (c) { case ' ': case '\t': case '\f': case '\r': case '\13': space_seen = 1; break; case '.': { if ((c = nextc()) != '.') { pushback(c); pushback('.'); goto retry; } } default: --ruby_sourceline; lex_nextline = lex_lastline; case -1: lex_goto_eol(parser); goto normal_newline; } } normal_newline: command_start = TRUE; lex_state = EXPR_BEG; return '\n'; case '*': if ((c = nextc()) == '*') { if ((c = nextc()) == '=') { set_yylval_id(tPOW); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`**' interpreted as argument prefix"); c = tDSTAR; } else if (IS_BEG()) { c = tDSTAR; } else { warn_balanced("**", "argument prefix"); c = tPOW; } } else { if (c == '=') { set_yylval_id('*'); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`*' interpreted as argument prefix"); c = tSTAR; } else if (IS_BEG()) { c = tSTAR; } else { warn_balanced("*", "argument prefix"); c = '*'; } } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; return c; case '!': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return '!'; } } else { lex_state = EXPR_BEG; } if (c == '=') { return tNEQ; } if (c == '~') { return tNMATCH; } pushback(c); return '!'; case '=': if (was_bol()) { if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) { for (;;) { lex_goto_eol(parser); c = nextc(); if (c == -1) { compile_error(PARSER_ARG "embedded document meets end of file"); return 0; } if (c != '=') continue; if (strncmp(lex_p, "end", 3) == 0 && (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) { break; } } lex_goto_eol(parser); goto retry; } } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; if ((c = nextc()) == '=') { if ((c = nextc()) == '=') { return tEQQ; } pushback(c); return tEQ; } if (c == '~') { return tMATCH; } else if (c == '>') { return tASSOC; } pushback(c); return '='; case '<': last_state = lex_state; c = nextc(); if (c == '<' && !IS_lex_state(EXPR_DOT | EXPR_CLASS) && !IS_END() && (!IS_ARG() || space_seen)) { int token = heredoc_identifier(); if (token) return token; } if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; } else { if (IS_lex_state(EXPR_CLASS)) command_start = TRUE; lex_state = EXPR_BEG; } if (c == '=') { if ((c = nextc()) == '>') { return tCMP; } pushback(c); return tLEQ; } if (c == '<') { if ((c = nextc()) == '=') { set_yylval_id(tLSHFT); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); warn_balanced("<<", "here document"); return tLSHFT; } pushback(c); return '<'; case '>': lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; if ((c = nextc()) == '=') { return tGEQ; } if (c == '>') { if ((c = nextc()) == '=') { set_yylval_id(tRSHFT); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tRSHFT; } pushback(c); return '>'; case '"': lex_strterm = NEW_STRTERM(str_dquote, '"', 0); return tSTRING_BEG; case '`': if (IS_lex_state(EXPR_FNAME)) { lex_state = EXPR_ENDFN; return c; } if (IS_lex_state(EXPR_DOT)) { if (cmd_state) lex_state = EXPR_CMDARG; else lex_state = EXPR_ARG; return c; } lex_strterm = NEW_STRTERM(str_xquote, '`', 0); return tXSTRING_BEG; case '\'': lex_strterm = NEW_STRTERM(str_squote, '\'', 0); return tSTRING_BEG; case '?': if (IS_END()) { lex_state = EXPR_VALUE; return '?'; } c = nextc(); if (c == -1) { compile_error(PARSER_ARG "incomplete character syntax"); return 0; } if (rb_enc_isspace(c, current_enc)) { if (!IS_ARG()) { int c2 = 0; switch (c) { case ' ': c2 = 's'; break; case '\n': c2 = 'n'; break; case '\t': c2 = 't'; break; case '\v': c2 = 'v'; break; case '\r': c2 = 'r'; break; case '\f': c2 = 'f'; break; } if (c2) { rb_warnI("invalid character syntax; use ?\\%c", c2); } } ternary: pushback(c); lex_state = EXPR_VALUE; return '?'; } newtok(); enc = current_enc; if (!parser_isascii()) { if (tokadd_mbchar(c) == -1) return 0; } else if ((rb_enc_isalnum(c, current_enc) || c == '_') && lex_p < lex_pend && is_identchar(lex_p, lex_pend, current_enc)) { goto ternary; } else if (c == '\\') { if (peek('u')) { nextc(); c = parser_tokadd_utf8(parser, &enc, 0, 0, 0); if (0x80 <= c) { tokaddmbc(c, enc); } else { tokadd(c); } } else if (!lex_eol_p() && !(c = *lex_p, ISASCII(c))) { nextc(); if (tokadd_mbchar(c) == -1) return 0; } else { c = read_escape(0, &enc); tokadd(c); } } else { tokadd(c); } tokfix(); set_yylval_str(STR_NEW3(tok(), toklen(), enc, 0)); lex_state = EXPR_END; return tCHAR; case '&': if ((c = nextc()) == '&') { lex_state = EXPR_BEG; if ((c = nextc()) == '=') { set_yylval_id(tANDOP); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tANDOP; } else if (c == '=') { set_yylval_id('&'); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); if (IS_SPCARG(c)) { rb_warning0("`&' interpreted as argument prefix"); c = tAMPER; } else if (IS_BEG()) { c = tAMPER; } else { warn_balanced("&", "argument prefix"); c = '&'; } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; return c; case '|': if ((c = nextc()) == '|') { lex_state = EXPR_BEG; if ((c = nextc()) == '=') { set_yylval_id(tOROP); lex_state = EXPR_BEG; return tOP_ASGN; } pushback(c); return tOROP; } if (c == '=') { set_yylval_id('|'); lex_state = EXPR_BEG; return tOP_ASGN; } lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG; pushback(c); return '|'; case '+': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return tUPLUS; } pushback(c); return '+'; } if (c == '=') { set_yylval_id('+'); lex_state = EXPR_BEG; return tOP_ASGN; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) { lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { c = '+'; goto start_num; } return tUPLUS; } lex_state = EXPR_BEG; pushback(c); warn_balanced("+", "unary operator"); return '+'; case '-': c = nextc(); if (IS_AFTER_OPERATOR()) { lex_state = EXPR_ARG; if (c == '@') { return tUMINUS; } pushback(c); return '-'; } if (c == '=') { set_yylval_id('-'); lex_state = EXPR_BEG; return tOP_ASGN; } if (c == '>') { lex_state = EXPR_ENDFN; return tLAMBDA; } if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous())) { lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { return tUMINUS_NUM; } return tUMINUS; } lex_state = EXPR_BEG; pushback(c); warn_balanced("-", "unary operator"); return '-'; case '.': lex_state = EXPR_BEG; if ((c = nextc()) == '.') { if ((c = nextc()) == '.') { return tDOT3; } pushback(c); return tDOT2; } pushback(c); if (c != -1 && ISDIGIT(c)) { yyerror("no .<digit> floating literal anymore; put 0 before dot"); } lex_state = EXPR_DOT; return '.'; start_num: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int is_float, seen_point, seen_e, nondigit; is_float = seen_point = seen_e = nondigit = 0; lex_state = EXPR_END; newtok(); if (c == '-' || c == '+') { tokadd(c); c = nextc(); } if (c == '0') {#define no_digits() int start = toklen(); c = nextc(); if (c == 'x' || c == 'X') { c = nextc(); if (c != -1 && ISXDIGIT(c)) { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (!ISXDIGIT(c)) break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 16, FALSE)); return tINTEGER; } if (c == 'b' || c == 'B') { c = nextc(); if (c == '0' || c == '1') { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (c != '0' && c != '1') break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 2, FALSE)); return tINTEGER; } if (c == 'd' || c == 'D') { c = nextc(); if (c != -1 && ISDIGIT(c)) { do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (!ISDIGIT(c)) break; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); } pushback(c); tokfix(); if (toklen() == start) { no_digits(); } else if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE)); return tINTEGER; } if (c == '_') { goto octal_number; } if (c == 'o' || c == 'O') { c = nextc(); if (c == -1 || c == '_' || !ISDIGIT(c)) { no_digits(); } } if (c >= '0' && c <= '7') { octal_number: do { if (c == '_') { if (nondigit) break; nondigit = c; continue; } if (c < '0' || c > '9') break; if (c > '7') goto invalid_octal; nondigit = 0; tokadd(c); } while ((c = nextc()) != -1); if (toklen() > start) { pushback(c); tokfix(); if (nondigit) goto trailing_uc; set_yylval_literal(rb_cstr_to_inum(tok(), 8, FALSE)); return tINTEGER; } if (nondigit) { pushback(c); goto trailing_uc; } } if (c > '7' && c <= '9') { invalid_octal: yyerror("Invalid octal digit"); } else if (c == '.' || c == 'e' || c == 'E') { tokadd('0'); } else { pushback(c); set_yylval_literal(INT2FIX(0)); return tINTEGER; } } for (;;) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': nondigit = 0; tokadd(c); break; case '.': if (nondigit) goto trailing_uc; if (seen_point || seen_e) { goto decode_num; } else { int c0 = nextc(); if (c0 == -1 || !ISDIGIT(c0)) { pushback(c0); goto decode_num; } c = c0; } tokadd('.'); tokadd(c); is_float++; seen_point++; nondigit = 0; break; case 'e': case 'E': if (nondigit) { pushback(c); c = nondigit; goto decode_num; } if (seen_e) { goto decode_num; } tokadd(c); seen_e++; is_float++; nondigit = c; c = nextc(); if (c != '-' && c != '+') continue; tokadd(c); nondigit = c; break; case '_': if (nondigit) goto decode_num; nondigit = c; break; default: goto decode_num; } c = nextc(); } decode_num: pushback(c); if (nondigit) { char tmp[30]; trailing_uc: snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit); yyerror(tmp); } tokfix(); if (is_float) { double d = strtod(tok(), 0); if (errno == ERANGE) { rb_warningS("Float %s out of range", tok()); errno = 0; } set_yylval_literal(DBL2NUM(d)); return tFLOAT; } set_yylval_literal(rb_cstr_to_inum(tok(), 10, FALSE)); return tINTEGER; } case ')': case '] __pad18__

Definition at line 7580 of file parse.y.

case __pad19__

Definition at line 7582 of file parse.y.

top_stmts __pad1__ = $1

Definition at line 892 of file parse.y.

case __pad20__

Definition at line 7594 of file parse.y.

case __pad21__

Definition at line 7625 of file parse.y.

case __pad22__

Definition at line 7645 of file parse.y.

__pad23__

Definition at line 7654 of file parse.y.

__pad24__

Definition at line 7656 of file parse.y.

case __pad25__

Definition at line 7660 of file parse.y.

top_stmt __pad2__

Definition at line 925 of file parse.y.

compstmt __pad3__

Definition at line 980 of file parse.y.

stmts __pad4__ = $1

Definition at line 989 of file parse.y.

stmt_or_begin __pad5__

Definition at line 1022 of file parse.y.

command_asgn __pad6__

Definition at line 1036 of file parse.y.

expr __pad7__

Definition at line 1286 of file parse.y.

expr_value __pad8__

Definition at line 1321 of file parse.y.

command_call __pad9__

Definition at line 1328 of file parse.y.

arg

Definition at line 1316 of file parse.y.

top_stmt bodystmt = NEW_BEGIN(0)

Definition at line 942 of file parse.y.

return c

Definition at line 7591 of file parse.y.

keyword_next call_args
Initial value:
{
$$ = NEW_RETURN(ret_args($2))
#define ret_args(node)
Definition: parse.y:416
#define NEW_RETURN(s)

Definition at line 1461 of file parse.y.

case

Definition at line 7653 of file parse.y.

primary_value tCOLON2 operation2 command_args cmd_brace_block
Initial value:
{
#define block_dup_check(n1, n2)
Definition: parse.y:383

Definition at line 1338 of file parse.y.

keyword_yield command_args
Initial value:
{
$$ = NEW_SUPER($2)
#define NEW_SUPER(a)

Definition at line 1443 of file parse.y.

command_call
Initial value:
{
$$ = call_uni_op(cond($2), '!')
#define call_uni_op(recv, id)
Definition: parse.y:407
#define cond(node)
Definition: parse.y:365

Definition at line 1308 of file parse.y.

command_start = TRUE

Definition at line 7655 of file parse.y.

<num> opt_block_param compstmt
Initial value:
{
$$ = NEW_ITER($3,$4)
#define NEW_ITER(a, b)

Definition at line 1357 of file parse.y.

fixup_nodes& deferred_nodes

Definition at line 889 of file parse.y.

else
Initial value:
{
lex_state = EXPR_BEG
#define lex_state
Definition: parse.y:311

Definition at line 7669 of file parse.y.

keyword_not opt_nl expr
Initial value:
{
$$ = logop(NODE_OR, $1, $3)
#define NODE_OR
#define logop(type, node1, node2)
Definition: parse.y:367

Definition at line 1292 of file parse.y.

keyword_BEGIN
Initial value:
{
yyerror("BEGIN is permitted only at toplevel")
#define yyerror(msg)
Definition: parse.y:308

Definition at line 1029 of file parse.y.

mlhs_node keyword_variable
Initial value:
{
$$ = assignable($1, 0)
#define assignable(id, node)
Definition: parse.y:426

Definition at line 1646 of file parse.y.

lex_state = EXPR_ENDARG

Definition at line 7587 of file parse.y.

lhs
Initial value:
=' command_asgn
{
value_expr($3);
$$ = node_assign($1, $3);
}

Definition at line 1270 of file parse.y.

mlhs_inner mlhs_basic

Definition at line 1495 of file parse.y.

mlhs_item
Initial value:
{
$$ = NEW_MASGN(list_append($1,$2), 0)
#define NEW_MASGN(l, r)
#define list_append(l, i)
Definition: parse.y:388

Definition at line 1517 of file parse.y.

tSTAR mlhs_node
Initial value:
{
$$ = NEW_MASGN($1, $3)
#define NEW_MASGN(l, r)

Definition at line 1525 of file parse.y.

mlhs_post
Initial value:
{
$$ = NEW_MASGN($1, NEW_POSTARG($3,$5))
#define NEW_MASGN(l, r)
#define NEW_POSTARG(i, v)

Definition at line 1533 of file parse.y.

nd_args = $2

Definition at line 1382 of file parse.y.

Referenced by dump_node(), and yyparse().

nd_iter = $1

Definition at line 1392 of file parse.y.

Referenced by dump_node(), and yyparse().

pure parser lex param

Definition at line 687 of file parse.y.

return

Definition at line 7641 of file parse.y.

error stmt
Initial value:
{
$$ = remove_begin($2)
static NODE * remove_begin(NODE *)

Definition at line 1019 of file parse.y.

stmts terms stmt_or_begin
Initial value:
{
$$ = newline_node($1)
static NODE * newline_node(NODE *)

Definition at line 1003 of file parse.y.

primary_value tCOLON2 operation2 command_args prec tLOWEST
Initial value:
{
$$ = NEW_CALL($1, $3, $4)
#define NEW_CALL(r, m, a)

Definition at line 1401 of file parse.y.

return tOP_ASGN

Definition at line 7647 of file parse.y.

Referenced by if().

error top_stmt
Initial value:
{
$$ = newline_node($1)
static NODE * newline_node(NODE *)

Definition at line 906 of file parse.y.

case return tREGEXP_BEG

Definition at line 7625 of file parse.y.

Referenced by if().

tSTAR
Initial value:
{
$$ = NEW_MASGN($1, -1)
#define NEW_MASGN(l, r)

Definition at line 1542 of file parse.y.

return tSYMBEG

Definition at line 7621 of file parse.y.