Ruby
2.0.0p594(2014-10-27revision48167)
|
#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"
Go to the source code of this file.
Data Structures | |
struct | vtable |
struct | local_vars |
struct | token_info |
struct | parser_params |
Typedefs | |
typedef VALUE | stack_type |
typedef struct token_info | token_info |
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{yyerror("dynamic constant assignment");$$=NEW_CDECL(0, 0, NEW_COLON2($1, $3));}|tCOLON3 tCONSTANT{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{yyerror("dynamic constant assignment");$$=NEW_CDECL(0, 0, NEW_COLON2($1, $3));}|tCOLON3 tCONSTANT{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{$ < val >1=cmdarg_stack;cmdarg_stack=0;}expr{lex_state=EXPR_ENDARG;}rparen{cmdarg_stack=$ < val >1;$$=$3;}|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{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{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{$$=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{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{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_with_enc(NULL, 0,(void *) current_enc,"%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(VALUE fname){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 lines=rb_ary_new();rb_hash_aset(hash, fname, lines);return lines;}}return 0;}static VALUEcoverage(VALUE fname, int n){VALUE coverages=rb_get_coverages();if(RTEST(coverages)&&RBASIC(coverages) -> klass==0){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_string);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_string, 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, VALUE fname, int line){ruby_sourcefile_string=rb_str_new_frozen(fname);ruby_sourcefile=RSTRING_PTR(fname);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, VALUE fname, 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, fname, 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(), rb_filesystem_str_new_cstr(f), s, line);}NODE *rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line){return rb_parser_compile_string_path(vparser, rb_filesystem_str_new_cstr(f), s, line);}NODE *rb_parser_compile_string_path(volatile VALUE vparser, VALUE 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(), rb_filesystem_str_new_cstr(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, rb_filesystem_str_new_cstr(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){return rb_parser_compile_file_path(vparser, rb_filesystem_str_new_cstr(f), file, start);}NODE *rb_parser_compile_file_path(volatile VALUE vparser, VALUE fname, 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, fname, 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){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,"e->nd_nest,&enc)==-1){ruby_sourceline=nd_line(quote);if(func &STR_FUNC_REGEXP){compile_error(PARSER_ARG"unterminated regexp meets end of file");return tREGEXP_END;}else{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;}}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);str=0;}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){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]== '-'){return nlen;}if(len > 4 &&name[nlen=len-4]== '-'){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 { 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)) { 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_nodes & | deferred_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 | |
#define ambiguous_operator | ( | op, | |
syn | |||
) |
#define arg_ambiguous | ( | ) | (arg_ambiguous_gen(parser), 1) |
Referenced by if().
#define aryset | ( | node1, | |
node2 | |||
) | aryset_gen(parser, (node1), (node2)) |
#define assignable | ( | id, | |
node | |||
) | assignable_gen(parser, (id), (node)) |
#define assignable_result | ( | x | ) | (x) |
#define attrset | ( | node, | |
id | |||
) | attrset_gen(parser, (node), (id)) |
#define BITSTACK_LEXPOP | ( | stack | ) | ((stack) = ((stack) >> 1) | ((stack) & 1)) |
#define block_append | ( | h, | |
t | |||
) | block_append_gen(parser,(h),(t)) |
#define block_dup_check | ( | n1, | |
n2 | |||
) | block_dup_check_gen(parser,(n1),(n2)) |
#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 calloc YYCALLOC |
#define CMDARG_LEXPOP | ( | ) | BITSTACK_LEXPOP(cmdarg_stack) |
#define CMDARG_P | ( | ) | BITSTACK_SET_P(cmdarg_stack) |
#define CMDARG_POP | ( | ) | BITSTACK_POP(cmdarg_stack) |
#define CMDARG_PUSH | ( | n | ) | BITSTACK_PUSH(cmdarg_stack, (n)) |
#define compile_error parser->nerr++,rb_compile_error_with_enc |
#define COND_LEXPOP | ( | ) | BITSTACK_LEXPOP(cond_stack) |
#define COND_P | ( | ) | BITSTACK_SET_P(cond_stack) |
#define COND_POP | ( | ) | BITSTACK_POP(cond_stack) |
#define COND_PUSH | ( | n | ) | BITSTACK_PUSH(cond_stack, (n)) |
#define dispatch_heredoc_end | ( | ) | ((void)0) |
#define dsym_node | ( | node | ) | dsym_node_gen(parser, (node)) |
#define dvar_defined | ( | id | ) | dvar_defined_gen(parser, (id), 0) |
#define dvar_defined_get | ( | id | ) | dvar_defined_gen(parser, (id), 1) |
#define dyna_in_block | ( | ) | dyna_in_block_gen(parser) |
#define dyna_pop | ( | node | ) | dyna_pop_gen(parser, (node)) |
#define dyna_push | ( | ) | dyna_push_gen(parser) |
#define ENABLE_SELECTOR_NAMESPACE 0 |
#define ENC_SINGLE | ( | cr | ) | ((cr)==ENC_CODERANGE_7BIT) |
#define ESCAPE_CONTROL 1 |
#define ESCAPE_META 2 |
#define formal_argument | ( | id | ) | formal_argument_gen(parser, (id)) |
#define free YYFREE |
#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 id_type | ( | id | ) | (is_notop_id(id) ? (int)((id)&ID_SCOPE_MASK) : -1) |
#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 internal_id | ( | ) | internal_id_gen(parser) |
#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 | ) |
#define is_attrset_id | ( | id | ) | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET) |
#define IS_BEG | ( | ) | IS_lex_state(EXPR_BEG_ANY) |
#define is_class_id | ( | id | ) | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS) |
#define is_const_id | ( | id | ) | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST) |
#define IS_END | ( | ) | IS_lex_state(EXPR_END_ANY) |
#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_junk_id | ( | id | ) | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK) |
#define IS_LABEL_POSSIBLE | ( | ) | ((IS_lex_state(EXPR_BEG | EXPR_ENDFN) && !cmd_state) || IS_ARG()) |
#define IS_lex_state | ( | ls | ) | IS_lex_state_for(lex_state, (ls)) |
#define is_local_id | ( | id | ) | (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL) |
#define is_notop_id | ( | id | ) | ((id)>tLAST_OP_ID) |
#define lex_strterm (parser->parser_lex_strterm) |
#define list_append | ( | l, | |
i | |||
) | list_append_gen(parser,(l),(i)) |
#define list_concat | ( | h, | |
t | |||
) | list_concat_gen(parser,(h),(t)) |
#define literal_concat | ( | h, | |
t | |||
) | literal_concat_gen(parser,(h),(t)) |
#define local_pop | ( | ) | local_pop_gen(parser) |
#define local_tbl | ( | ) | local_tbl_gen(parser) |
#define malloc YYMALLOC |
#define match_op | ( | node1, | |
node2 | |||
) | match_op_gen(parser, (node1), (node2)) |
#define mixed_error | ( | enc1, | |
enc2 | |||
) |
#define mixed_escape | ( | beg, | |
enc1, | |||
enc2 | |||
) |
#define nd_term | ( | node | ) | SIGN_EXTEND((node)->u2.id, CHAR_BIT*2) |
#define new_args_tail | ( | k, | |
kr, | |||
b | |||
) | new_args_tail_gen(parser, (k),(kr),(b)) |
#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 new_op_assign | ( | lhs, | |
op, | |||
rhs | |||
) | new_op_assign_gen(parser, (lhs), (op), (rhs)) |
#define NEW_STRTERM | ( | func, | |
term, | |||
paren | |||
) | rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0) |
#define new_yield | ( | node | ) | new_yield_gen(parser, (node)) |
#define NEWHEAP | ( | ) | rb_node_newnode(NODE_ALLOCA, 0, (VALUE)parser->heap, 0) |
#define newtok | ( | ) | parser_newtok(parser) |
#define nextc | ( | ) | parser_nextc(parser) |
#define node_assign | ( | node1, | |
node2 | |||
) | node_assign_gen(parser, (node1), (node2)) |
#define NODE_HEREDOC NODE_ARRAY /* 1, 3 to gc */ |
#define NODE_STRTERM NODE_ZARRAY /* nothing to gc */ |
#define parse_string | ( | n | ) | parser_parse_string(parser,(n)) |
#define PARSER_ARG ruby_sourcefile, ruby_sourceline, current_enc, |
#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_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)) |
Definition at line 141 of file parse.y.
Referenced by vtable_add(), vtable_free(), vtable_included(), and vtable_size().
#define rb_backref_error | ( | n | ) | rb_backref_error_gen(parser,(n)) |
#define rb_compile_error rb_compile_error_with_enc |
#define rb_node_newnode | ( | type, | |
a1, | |||
a2, | |||
a3 | |||
) | node_newnode(parser, (type), (a1), (a2), (a3)) |
#define rb_warn0 | ( | fmt | ) | rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt)) |
#define rb_warn4S | ( | file, | |
line, | |||
fmt, | |||
a | |||
) | rb_compile_warn((file), (line), (fmt), (a)) |
#define rb_warnI | ( | fmt, | |
a | |||
) | rb_compile_warn(ruby_sourcefile, ruby_sourceline, (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_warnS | ( | fmt, | |
a | |||
) | rb_compile_warn(ruby_sourcefile, ruby_sourceline, (fmt), (a)) |
#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 realloc YYREALLOC |
#define reg_named_capture_assign | ( | regexp, | |
match | |||
) | reg_named_capture_assign_gen(parser,(regexp),(match)) |
#define regx_options | ( | ) | parser_regx_options(parser) |
#define ret_args | ( | node | ) | ret_args_gen(parser, (node)) |
#define ruby_debug_lines (parser->debug_lines) |
#define ruby_eval_tree_begin (parser->parser_eval_tree_begin) |
#define ruby_sourcefile_string (parser->parser_ruby_sourcefile_string) |
#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)) |
#define str_copy | ( | _s, | |
_p, | |||
_n | |||
) |
#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, | |
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 subnodes | ( | n1, | |
n2 | |||
) |
#define tok | ( | ) | tokenbuf |
#define tok_hex | ( | numlen | ) | parser_tok_hex(parser, (numlen)) |
#define TOK_INTERN | ( | mb | ) | rb_intern3(tok(), toklen(), current_enc) |
#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 toklen | ( | ) | tokidx |
#define tokspace | ( | n | ) | parser_tokspace(parser, (n)) |
#define value_expr | ( | node | ) | value_expr_gen(parser, (node) = remove_begin(node)) |
#define void_expr | ( | node | ) | void_expr0((node) = remove_begin(node)) |
#define void_expr0 | ( | node | ) | void_expr_gen(parser, (node)) |
#define void_stmts | ( | node | ) | void_stmts_gen(parser, (node)) |
#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 | |||
) |
#define YYCALLOC | ( | nelem, | |
size | |||
) | rb_parser_calloc(parser, (nelem), (size)) |
#define YYDEBUG 1 |
#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 YYSTACK_USE_ALLOCA 0 |
typedef VALUE stack_type |
typedef struct token_info token_info |
enum lex_state_bits |
enum lex_state_e |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
dyna_pop | ( | $< vars > | ) |
|
static |
|
static |
|
static |
fixpos | ( | $$, | |
$1 | |||
) | = $3 |
|
static |
|
static |
if | ( | $2 | ) |
Definition at line 957 of file parse.y.
References NEW_RESCUE.
if | ( | ! | $$ | ) |
Definition at line 547 of file stubs.c.
References parser_yyerror(), rb_argv0, RSTRING_PTR, ruby_open_tcl_dll(), YY_, yymsg, yymsgbuf, yynerrs, YYSTACK_ALLOC, YYSTACK_FREE, and YYSYNTAX_ERROR.
if | ( | c | = = ')' | ) |
Definition at line 7624 of file parse.y.
References lex_state, pushback, and warn_balanced.
Definition at line 7649 of file parse.y.
References lex_state, set_yylval_id, and tOP_ASGN.
Definition at line 7655 of file parse.y.
References arg_ambiguous, lex_strterm, NEW_STRTERM, str_regexp, tREGEXP_BEG, and void.
Definition at line 14 of file id.c.
References enc, id_core_define_method, id_core_define_singleton_method, id_core_hash_from_ary, id_core_hash_merge_ary, id_core_hash_merge_kwd, id_core_hash_merge_ptr, id_core_set_method_alias, id_core_set_postexe, id_core_set_variable_alias, id_core_undef_method, idCFUNC, idEmptyP, idIFUNC, idNULL, idRespond_to, idRespond_to_missing, rb_usascii_encoding(), and REGISTER_SYMID.
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
nd_set_line | ( | $$, | |
$< num > | |||
) |
fcall nd_set_line | ( | $$, | |
tokline | |||
) |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
switch | ( | c | ) |
Definition at line 7630 of file parse.y.
References lex_strterm, NEW_STRTERM, pushback, str_dsym, and str_ssym.
|
static |
|
static |
|
static |
|
static |
|
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.
Definition at line 157 of file parse.y.
References ALLOC, ALLOC_N, vtable::capa, vtable::pos, vtable::prev, vtable::tbl, tbl, and VTBL_DEBUG.
Definition at line 169 of file parse.y.
References POINTER_P, vtable::tbl, VTBL_DEBUG, and xfree.
Definition at line 196 of file parse.y.
References i, POINTER_P, vtable::pos, and vtable::tbl.
Definition at line 144 of file parse.y.
References POINTER_P, and vtable::pos.
warn_balanced | ( | "/" | , |
"regexp literal" | |||
) |
mlhs_inner __pad14__ |
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 { yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3)); } | tCOLON3 tCONSTANT { 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 { yyerror("dynamic constant assignment"); $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3)); } | tCOLON3 tCONSTANT { 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 { $<val>1 = cmdarg_stack; cmdarg_stack = 0; } expr {lex_state = EXPR_ENDARG;} rparen { cmdarg_stack = $<val>1; $$ = $3; } | 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 { 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 { 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 { $$ = 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 { 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 { 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_with_enc(NULL, 0, (void *)current_enc, "%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(VALUE fname){ 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 lines = rb_ary_new(); rb_hash_aset(hash, fname, lines); return lines; } } return 0;}static VALUEcoverage(VALUE fname, int n){ VALUE coverages = rb_get_coverages(); if (RTEST(coverages) && RBASIC(coverages)->klass == 0) { 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_string); 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_string, 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, VALUE fname, int line){ ruby_sourcefile_string = rb_str_new_frozen(fname); ruby_sourcefile = RSTRING_PTR(fname); 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, VALUE fname, 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, fname, 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(), rb_filesystem_str_new_cstr(f), s, line);}NODE*rb_parser_compile_string(volatile VALUE vparser, const char *f, VALUE s, int line){ return rb_parser_compile_string_path(vparser, rb_filesystem_str_new_cstr(f), s, line);}NODE*rb_parser_compile_string_path(volatile VALUE vparser, VALUE 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(), rb_filesystem_str_new_cstr(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, rb_filesystem_str_new_cstr(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){ return rb_parser_compile_file_path(vparser, rb_filesystem_str_new_cstr(f), file, start);}NODE*rb_parser_compile_file_path(volatile VALUE vparser, VALUE fname, 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, fname, 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) { 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, "e->nd_nest, &enc) == -1) { ruby_sourceline = nd_line(quote); if (func & STR_FUNC_REGEXP) { compile_error(PARSER_ARG "unterminated regexp meets end of file"); return tREGEXP_END; } else { 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; } } 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); str = 0; } 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){ 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] == '-') { return nlen; } if (len > 4 && name[nlen = len - 4] == '-') { 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 { 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)) { 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__ |
stmt_or_begin __pad5__ |
command_call __pad9__ |
keyword_next call_args |
primary_value tCOLON2 operation2 command_args cmd_brace_block |
keyword_yield command_args |
command_call |
<num> opt_block_param compstmt |
fixup_nodes& deferred_nodes |
else |
keyword_not opt_nl expr |
keyword_BEGIN |
mlhs_node keyword_variable |
lhs |
mlhs_inner mlhs_basic |
mlhs_item |
tSTAR mlhs_node |
mlhs_post |
nd_args = $2 |
Definition at line 1383 of file parse.y.
Referenced by dump_node(), and switch().
nd_iter = $1 |
Definition at line 1393 of file parse.y.
Referenced by dump_node(), and switch().
error stmt |
stmts terms stmt_or_begin |
primary_value tCOLON2 operation2 command_args prec tLOWEST |
error top_stmt |
tSTAR |