2000-05-01 05:42:38 -04:00
|
|
|
/**********************************************************************
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
parse.y -
|
|
|
|
|
2004-09-12 11:23:41 -04:00
|
|
|
$Author$
|
|
|
|
$Date$
|
1998-01-16 07:13:05 -05:00
|
|
|
created at: Fri May 28 18:02:42 JST 1993
|
|
|
|
|
2004-09-12 11:23:41 -04:00
|
|
|
Copyright (C) 1993-2004 Yukihiro Matsumoto
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-05-01 05:42:38 -04:00
|
|
|
**********************************************************************/
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
%{
|
|
|
|
|
|
|
|
#define YYDEBUG 1
|
2002-05-29 01:20:39 -04:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
#include "ruby.h"
|
|
|
|
#include "env.h"
|
2002-05-29 01:20:39 -04:00
|
|
|
#include "intern.h"
|
1998-01-16 07:13:05 -05:00
|
|
|
#include "node.h"
|
|
|
|
#include "st.h"
|
|
|
|
#include <stdio.h>
|
1999-08-13 01:45:20 -04:00
|
|
|
#include <errno.h>
|
2001-05-16 05:05:54 -04:00
|
|
|
#include <ctype.h>
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
#define ID_SCOPE_SHIFT 3
|
|
|
|
#define ID_SCOPE_MASK 0x07
|
|
|
|
#define ID_LOCAL 0x01
|
|
|
|
#define ID_INSTANCE 0x02
|
|
|
|
#define ID_GLOBAL 0x03
|
|
|
|
#define ID_ATTRSET 0x04
|
1999-12-14 01:50:43 -05:00
|
|
|
#define ID_CONST 0x05
|
2000-03-23 03:37:35 -05:00
|
|
|
#define ID_CLASS 0x06
|
2001-06-05 03:50:59 -04:00
|
|
|
#define ID_JUNK 0x07
|
2001-09-20 02:23:50 -04:00
|
|
|
#define ID_INTERNAL ID_JUNK
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-12-24 03:53:56 -05:00
|
|
|
#define is_notop_id(id) ((id)>tLAST_TOKEN)
|
1999-11-17 02:30:37 -05:00
|
|
|
#define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
|
|
|
|
#define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
|
|
|
|
#define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
|
|
|
|
#define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
|
1999-12-14 01:50:43 -05:00
|
|
|
#define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
|
2000-03-23 03:37:35 -05:00
|
|
|
#define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
|
2002-10-23 06:17:30 -04:00
|
|
|
#define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-09-13 05:36:28 -04:00
|
|
|
#define is_asgn_or_id(id) ((is_notop_id(id)) && \
|
|
|
|
(((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
|
|
|
|
((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
|
|
|
|
((id)&ID_SCOPE_MASK) == ID_CLASS))
|
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifndef RIPPER
|
1999-01-19 23:59:39 -05:00
|
|
|
char *ruby_sourcefile; /* current source file */
|
|
|
|
int ruby_sourceline; /* current line no. */
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
enum lex_state_e {
|
1998-01-16 07:13:05 -05:00
|
|
|
EXPR_BEG, /* ignore newline, +/- is a sign. */
|
|
|
|
EXPR_END, /* newline significant, +/- is a operator. */
|
1999-01-19 23:59:39 -05:00
|
|
|
EXPR_ARG, /* newline significant, +/- is a operator. */
|
2003-01-30 23:00:17 -05:00
|
|
|
EXPR_CMDARG, /* newline significant, +/- is a operator. */
|
2001-06-01 02:47:32 -04:00
|
|
|
EXPR_ENDARG, /* newline significant, +/- is a operator. */
|
2000-05-30 00:24:17 -04:00
|
|
|
EXPR_MID, /* newline significant, +/- is a operator. */
|
1999-08-13 01:45:20 -04:00
|
|
|
EXPR_FNAME, /* ignore newline, no reserved words. */
|
|
|
|
EXPR_DOT, /* right after `.' or `::', no reserved words. */
|
1999-01-19 23:59:39 -05:00
|
|
|
EXPR_CLASS, /* immediate after `class', no here document. */
|
2004-03-20 11:45:41 -05:00
|
|
|
EXPR_TERNARY, /* alike EXPR_BEG but immediate after ternary op. */
|
2004-09-12 11:21:49 -04:00
|
|
|
};
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
# ifdef HAVE_LONG_LONG
|
2001-05-02 00:22:21 -04:00
|
|
|
typedef unsigned LONG_LONG stack_type;
|
2004-09-17 05:24:13 -04:00
|
|
|
# else
|
2001-01-29 00:10:42 -05:00
|
|
|
typedef unsigned long stack_type;
|
2004-09-17 05:24:13 -04:00
|
|
|
# endif
|
2001-01-29 00:10:42 -05:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
# define BITSTACK_PUSH(stack, n) (stack = (stack<<1)|((n)&1))
|
|
|
|
# define BITSTACK_POP(stack) (stack >>= 1)
|
|
|
|
# define BITSTACK_LEXPOP(stack) (stack = (stack >> 1) | (stack & 1))
|
|
|
|
# define BITSTACK_SET_P(stack) (stack&1)
|
2003-10-23 00:44:04 -04:00
|
|
|
|
|
|
|
#define COND_PUSH(n) BITSTACK_PUSH(cond_stack, n)
|
|
|
|
#define COND_POP() BITSTACK_POP(cond_stack)
|
|
|
|
#define COND_LEXPOP() BITSTACK_LEXPOP(cond_stack)
|
|
|
|
#define COND_P() BITSTACK_SET_P(cond_stack)
|
2000-09-04 04:24:09 -04:00
|
|
|
|
2003-10-23 00:44:04 -04:00
|
|
|
#define CMDARG_PUSH(n) BITSTACK_PUSH(cmdarg_stack, n)
|
|
|
|
#define CMDARG_POP() BITSTACK_POP(cmdarg_stack)
|
|
|
|
#define CMDARG_LEXPOP() BITSTACK_LEXPOP(cmdarg_stack)
|
|
|
|
#define CMDARG_P() BITSTACK_SET_P(cmdarg_stack)
|
2001-01-26 00:02:19 -05:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
/* must sync with real YYSTYPE */
|
|
|
|
union tmpyystype {
|
|
|
|
VALUE val;
|
|
|
|
NODE *node;
|
|
|
|
unsigned long id;
|
|
|
|
int num;
|
|
|
|
struct RVarmap *vars;
|
|
|
|
};
|
|
|
|
|
2004-10-02 07:34:13 -04:00
|
|
|
struct local_vars {
|
|
|
|
ID *tbl;
|
|
|
|
int nofree;
|
|
|
|
int cnt;
|
|
|
|
int dlev;
|
|
|
|
struct RVarmap* dyna_vars;
|
|
|
|
struct local_vars *prev;
|
|
|
|
};
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
/*
|
|
|
|
Structure of Lexer Buffer:
|
|
|
|
|
2004-09-19 23:03:12 -04:00
|
|
|
lex_pbeg tokp lex_p lex_pend
|
|
|
|
| | | |
|
|
|
|
|-----------+--------------+------------|
|
|
|
|
|<------------>|
|
|
|
|
token
|
2004-09-17 05:24:13 -04:00
|
|
|
*/
|
|
|
|
struct parser_params {
|
|
|
|
VALUE value;
|
|
|
|
VALUE result;
|
|
|
|
VALUE parsing_thread;
|
|
|
|
int toplevel_p;
|
|
|
|
union tmpyystype *parser_yylval; /* YYSTYPE not defined yet */
|
|
|
|
VALUE eofp;
|
|
|
|
|
2004-09-21 20:19:15 -04:00
|
|
|
#ifndef RIPPER
|
|
|
|
NODE *parser_eval_tree_begin;
|
|
|
|
NODE *parser_eval_tree;
|
|
|
|
#endif
|
2004-09-17 05:24:13 -04:00
|
|
|
NODE *parser_lex_strterm;
|
|
|
|
enum lex_state_e parser_lex_state;
|
|
|
|
stack_type parser_cond_stack;
|
|
|
|
stack_type parser_cmdarg_stack;
|
|
|
|
int parser_class_nest;
|
|
|
|
int parser_in_single;
|
|
|
|
int parser_in_def;
|
|
|
|
int parser_compile_for_eval;
|
|
|
|
VALUE parser_cur_mid;
|
|
|
|
int parser_in_defined;
|
|
|
|
char *parser_tokenbuf;
|
|
|
|
int parser_tokidx;
|
|
|
|
int parser_toksiz;
|
|
|
|
VALUE parser_lex_input;
|
|
|
|
VALUE parser_lex_lastline;
|
|
|
|
char *parser_lex_pbeg;
|
|
|
|
char *parser_lex_p;
|
|
|
|
char *parser_lex_pend;
|
|
|
|
int parser_heredoc_end;
|
|
|
|
int parser_command_start;
|
|
|
|
int parser_lex_gets_ptr;
|
|
|
|
VALUE (*parser_lex_gets) _((struct parser_params*,VALUE));
|
2004-10-02 07:34:13 -04:00
|
|
|
struct local_vars *parser_lvtbl;
|
2004-09-17 05:24:13 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
int parser_ruby__end__seen;
|
|
|
|
int parser_ruby_sourceline;
|
|
|
|
VALUE parser_ruby_sourcefile;
|
2004-09-19 23:03:12 -04:00
|
|
|
char *tokp;
|
2004-09-20 01:40:23 -04:00
|
|
|
VALUE delayed;
|
2004-09-20 03:59:30 -04:00
|
|
|
int delayed_line;
|
|
|
|
int delayed_col;
|
2004-09-17 05:24:13 -04:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
static int parser_yyerror _((struct parser_params*, const char*));
|
|
|
|
#define yyerror(msg) parser_yyerror(parser, msg)
|
|
|
|
|
|
|
|
#define YYPARSE_PARAM parser_v
|
|
|
|
#define YYLEX_PARAM parser_v
|
|
|
|
#define parser ((struct parser_params*)parser_v)
|
|
|
|
|
2004-09-21 20:19:15 -04:00
|
|
|
#define ruby_eval_tree (parser->parser_eval_tree)
|
|
|
|
#define ruby_eval_tree_begin (parser->parser_eval_tree_begin)
|
2004-09-17 05:24:13 -04:00
|
|
|
#define lex_strterm (parser->parser_lex_strterm)
|
|
|
|
#define lex_state (parser->parser_lex_state)
|
|
|
|
#define cond_stack (parser->parser_cond_stack)
|
|
|
|
#define cmdarg_stack (parser->parser_cmdarg_stack)
|
|
|
|
#define class_nest (parser->parser_class_nest)
|
|
|
|
#define in_single (parser->parser_in_single)
|
|
|
|
#define in_def (parser->parser_in_def)
|
|
|
|
#define compile_for_eval (parser->parser_compile_for_eval)
|
|
|
|
#define cur_mid (parser->parser_cur_mid)
|
|
|
|
#define in_defined (parser->parser_in_defined)
|
|
|
|
#define tokenbuf (parser->parser_tokenbuf)
|
|
|
|
#define tokidx (parser->parser_tokidx)
|
|
|
|
#define toksiz (parser->parser_toksiz)
|
|
|
|
#define lex_input (parser->parser_lex_input)
|
|
|
|
#define lex_lastline (parser->parser_lex_lastline)
|
|
|
|
#define lex_pbeg (parser->parser_lex_pbeg)
|
|
|
|
#define lex_p (parser->parser_lex_p)
|
|
|
|
#define lex_pend (parser->parser_lex_pend)
|
|
|
|
#define heredoc_end (parser->parser_heredoc_end)
|
|
|
|
#define command_start (parser->parser_command_start)
|
|
|
|
#define lex_gets_ptr (parser->parser_lex_gets_ptr)
|
|
|
|
#define lex_gets (parser->parser_lex_gets)
|
2004-10-02 07:34:13 -04:00
|
|
|
#define lvtbl (parser->parser_lvtbl)
|
2004-09-17 05:24:13 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
#define ruby__end__seen (parser->parser_ruby__end__seen)
|
|
|
|
#define ruby_sourceline (parser->parser_ruby_sourceline)
|
|
|
|
#define ruby_sourcefile (parser->parser_ruby_sourcefile)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int yylex _((void*, void*));
|
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifndef RIPPER
|
2004-09-17 05:24:13 -04:00
|
|
|
#define yyparse parser_yyparse
|
|
|
|
#define yydebug ruby_yydebug
|
|
|
|
|
|
|
|
static NODE *cond_gen _((struct parser_params*,NODE*));
|
|
|
|
#define cond(node) cond_gen(parser, node)
|
|
|
|
static NODE *logop_gen _((struct parser_params*,enum node_type,NODE*,NODE*));
|
|
|
|
#define logop(type,node1,node2) logop_gen(parser, type, node1, node2)
|
|
|
|
|
2003-03-20 02:03:22 -05:00
|
|
|
static int cond_negative();
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
static NODE *newline_node();
|
|
|
|
static void fixpos();
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
static int value_expr_gen _((struct parser_params*,NODE*));
|
|
|
|
static void void_expr_gen _((struct parser_params*,NODE*));
|
|
|
|
static NODE *remove_begin _((NODE*));
|
|
|
|
#define value_expr(node) value_expr_gen(parser, (node) = remove_begin(node))
|
|
|
|
#define void_expr(node) void_expr_gen(parser, (node) = remove_begin(node))
|
|
|
|
static void void_stmts_gen _((struct parser_params*,NODE*));
|
|
|
|
#define void_stmts(node) void_stmts_gen(parser, node)
|
|
|
|
static void reduce_nodes _((NODE**));
|
1999-08-13 01:45:20 -04:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static NODE *block_append();
|
|
|
|
static NODE *list_append();
|
|
|
|
static NODE *list_concat();
|
1999-08-13 01:45:20 -04:00
|
|
|
static NODE *arg_concat();
|
2001-05-30 05:12:34 -04:00
|
|
|
static NODE *arg_prepend();
|
2002-06-24 03:20:42 -04:00
|
|
|
static NODE *literal_concat();
|
2002-09-20 10:03:45 -04:00
|
|
|
static NODE *new_evstr();
|
2003-05-21 12:01:49 -04:00
|
|
|
static NODE *evstr2dstr();
|
2004-09-17 05:24:13 -04:00
|
|
|
|
|
|
|
static NODE *call_op_gen _((struct parser_params*,NODE*,ID,int,NODE*));
|
|
|
|
#define call_op(recv,id,narg,arg1) call_op_gen(parser, recv,id,narg,arg1)
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2003-01-22 22:39:25 -05:00
|
|
|
static NODE *negate_lit();
|
2001-05-30 05:12:34 -04:00
|
|
|
static NODE *ret_args();
|
1999-01-19 23:59:39 -05:00
|
|
|
static NODE *arg_blk_pass();
|
|
|
|
static NODE *new_call();
|
|
|
|
static NODE *new_fcall();
|
2000-06-23 03:05:59 -04:00
|
|
|
static NODE *new_super();
|
2003-06-20 03:11:44 -04:00
|
|
|
static NODE *new_yield();
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-10-02 07:34:13 -04:00
|
|
|
static NODE *gettable_gen _((struct parser_params*,ID));
|
|
|
|
#define gettable(id) gettable_gen(parser,id)
|
2004-09-17 05:24:13 -04:00
|
|
|
static NODE *assignable_gen _((struct parser_params*,ID,NODE*));
|
|
|
|
#define assignable(id,node) assignable_gen(parser, id, node)
|
|
|
|
static NODE *aryset_gen _((struct parser_params*,NODE*,NODE*));
|
|
|
|
#define aryset(node1,node2) aryset_gen(parser, node1, node2)
|
|
|
|
static NODE *attrset_gen _((struct parser_params*,NODE*,ID));
|
|
|
|
#define attrset(node,id) attrset_gen(parser, node, id)
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static void rb_backref_error();
|
2004-09-17 05:24:13 -04:00
|
|
|
static NODE *node_assign_gen _((struct parser_params*,NODE*,NODE*));
|
|
|
|
#define node_assign(node1, node2) node_assign_gen(parser, node1, node2)
|
|
|
|
|
|
|
|
static NODE *match_op_gen _((struct parser_params*,NODE*,NODE*));
|
|
|
|
#define match_op(node1,node2) match_op_gen(parser, node1, node2)
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-10-02 07:34:13 -04:00
|
|
|
static void local_push_gen _((struct parser_params*,int));
|
|
|
|
#define local_push(top) local_push_gen(parser,top)
|
|
|
|
static void local_pop_gen _((struct parser_params*));
|
|
|
|
#define local_pop() local_pop_gen(parser)
|
|
|
|
static int local_append_gen _((struct parser_params*, ID));
|
|
|
|
#define local_append(id) local_append_gen(parser, id)
|
|
|
|
static int local_cnt_gen _((struct parser_params*, ID));
|
|
|
|
#define local_cnt(id) local_cnt_gen(parser, id)
|
|
|
|
static int local_id_gen _((struct parser_params*, ID));
|
|
|
|
#define local_id(id) local_id_gen(parser, id)
|
|
|
|
static ID *local_tbl_gen _((struct parser_params*));
|
|
|
|
#define local_tbl() local_tbl_gen(parser)
|
|
|
|
static ID internal_id _((void));
|
|
|
|
|
|
|
|
static struct RVarmap *dyna_push_gen _((struct parser_params*));
|
|
|
|
#define dyna_push() dyna_push_gen(parser)
|
|
|
|
static void dyna_pop_gen _((struct parser_params*, struct RVarmap*));
|
|
|
|
#define dyna_pop(vars) dyna_pop_gen(parser, vars)
|
|
|
|
static int dyna_in_block_gen _((struct parser_params*));
|
|
|
|
#define dyna_in_block() dyna_in_block_gen(parser)
|
|
|
|
static NODE *dyna_init_gen _((struct parser_params*, NODE*, struct RVarmap *));
|
|
|
|
#define dyna_init(node, pre) dyna_init_gen(parser, node, pre)
|
|
|
|
|
|
|
|
static void top_local_init_gen _((struct parser_params*));
|
|
|
|
#define top_local_init() top_local_init_gen(parser)
|
|
|
|
static void top_local_setup_gen _((struct parser_params*));
|
|
|
|
#define top_local_setup() top_local_setup_gen(parser)
|
|
|
|
#else
|
|
|
|
#define remove_begin(node) (node)
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif /* !RIPPER */
|
2004-10-02 07:34:13 -04:00
|
|
|
static int lvar_defined_gen _((struct parser_params*, ID));
|
|
|
|
#define lvar_defined(id) lvar_defined_gen(parser, id)
|
2001-05-30 05:12:34 -04:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
#define RE_OPTION_ONCE 0x80
|
|
|
|
|
|
|
|
#define NODE_STRTERM NODE_ZARRAY /* nothing to gc */
|
|
|
|
#define NODE_HEREDOC NODE_ARRAY /* 1, 3 to gc */
|
2004-04-23 01:52:18 -04:00
|
|
|
#define SIGN_EXTEND(x,n) (((1<<(n)-1)^((x)&~(~0<<(n))))-(1<<(n)-1))
|
2002-06-26 04:01:00 -04:00
|
|
|
#define nd_func u1.id
|
2003-07-11 12:22:01 -04:00
|
|
|
#if SIZEOF_SHORT == 2
|
|
|
|
#define nd_term(node) ((signed short)(node)->u2.id)
|
|
|
|
#else
|
|
|
|
#define nd_term(node) SIGN_EXTEND((node)->u2.id, CHAR_BIT*2)
|
|
|
|
#endif
|
|
|
|
#define nd_paren(node) (char)((node)->u2.id >> CHAR_BIT*2)
|
2004-09-12 11:21:49 -04:00
|
|
|
#define nd_nest u3.cnt
|
|
|
|
|
|
|
|
/****** Ripper *******/
|
|
|
|
|
|
|
|
#ifdef RIPPER
|
|
|
|
#define RIPPER_VERSION "0.1.0"
|
|
|
|
|
|
|
|
#include "eventids1.c"
|
|
|
|
#include "eventids2.c"
|
|
|
|
static ID ripper_id_gets;
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
static VALUE ripper_dispatch0 _((struct parser_params*,ID));
|
|
|
|
static VALUE ripper_dispatch1 _((struct parser_params*,ID,VALUE));
|
|
|
|
static VALUE ripper_dispatch2 _((struct parser_params*,ID,VALUE,VALUE));
|
|
|
|
static VALUE ripper_dispatch3 _((struct parser_params*,ID,VALUE,VALUE,VALUE));
|
|
|
|
static VALUE ripper_dispatch4 _((struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE));
|
|
|
|
static VALUE ripper_dispatch5 _((struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE));
|
2004-09-12 11:21:49 -04:00
|
|
|
|
|
|
|
#define dispatch0(n) ripper_dispatch0(parser, TOKEN_PASTE(ripper_id_, n))
|
|
|
|
#define dispatch1(n,a) ripper_dispatch1(parser, TOKEN_PASTE(ripper_id_, n), a)
|
|
|
|
#define dispatch2(n,a,b) ripper_dispatch2(parser, TOKEN_PASTE(ripper_id_, n), a, b)
|
|
|
|
#define dispatch3(n,a,b,c) ripper_dispatch3(parser, TOKEN_PASTE(ripper_id_, n), a, b, c)
|
|
|
|
#define dispatch4(n,a,b,c,d) ripper_dispatch4(parser, TOKEN_PASTE(ripper_id_, n), a, b, c, d)
|
|
|
|
#define dispatch5(n,a,b,c,d,e) ripper_dispatch5(parser, TOKEN_PASTE(ripper_id_, n), a, b, c, d, e)
|
|
|
|
|
|
|
|
#define yyparse ripper_yyparse
|
|
|
|
#define yydebug ripper_yydebug
|
|
|
|
|
|
|
|
static VALUE ripper_intern _((const char*));
|
|
|
|
static VALUE ripper_id2sym _((ID));
|
|
|
|
|
|
|
|
#define arg_new() dispatch0(arglist_new)
|
|
|
|
#define arg_add(l,a) dispatch2(arglist_add, l, a)
|
|
|
|
#define arg_prepend(l,a) dispatch2(arglist_prepend, l, a)
|
|
|
|
#define arg_add_star(l,a) dispatch2(arglist_add_star, l, a)
|
|
|
|
#define arg_add_block(l,b) dispatch2(arglist_add_block, l, b)
|
|
|
|
#define arg_add_optblock(l,b) ((b)==Qundef? l : dispatch2(arglist_add_block, l, b))
|
|
|
|
#define bare_assoc(v) dispatch1(bare_assoc_hash, v)
|
|
|
|
#define arg_add_assocs(l,b) arg_add(l, bare_assoc(b))
|
|
|
|
|
|
|
|
#define args2mrhs(a) dispatch1(mrhs_new_from_arglist, a)
|
|
|
|
#define mrhs_new() dispatch0(mrhs_new)
|
|
|
|
#define mrhs_add(l,a) dispatch2(mrhs_add, l, a)
|
|
|
|
#define mrhs_add_star(l,a) dispatch2(mrhs_add_star, l, a)
|
|
|
|
|
|
|
|
#define mlhs_new() dispatch0(mlhs_new)
|
|
|
|
#define mlhs_add(l,a) dispatch2(mlhs_add, l, a)
|
|
|
|
#define mlhs_add_star(l,a) dispatch2(mlhs_add_star, l, a)
|
|
|
|
|
|
|
|
#define blockvar_new(p) dispatch1(blockvar_new, p)
|
|
|
|
#define blockvar_add_star(l,a) dispatch2(blockvar_add_star, l, a)
|
|
|
|
#define blockvar_add_block(l,a) dispatch2(blockvar_add_block, l, a)
|
|
|
|
|
|
|
|
#define method_optarg(m,a) ((a)==Qundef ? m : dispatch2(method_add_arg,m,a))
|
|
|
|
#define method_arg(m,a) dispatch2(method_add_arg,m,a)
|
|
|
|
#define escape_Qundef(x) ((x)==Qundef ? Qnil : (x))
|
|
|
|
#endif /* RIPPER */
|
|
|
|
|
|
|
|
#ifndef RIPPER
|
2004-10-31 01:22:58 -04:00
|
|
|
# define ifndef_ripper(x) x
|
2004-09-12 11:21:49 -04:00
|
|
|
#else
|
2004-10-31 01:22:58 -04:00
|
|
|
# define ifndef_ripper(x)
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef RIPPER
|
|
|
|
# define rb_warn0(fmt) rb_warn(fmt)
|
|
|
|
# define rb_warnI(fmt,a) rb_warn(fmt,a)
|
|
|
|
# define rb_warnS(fmt,a) rb_warn(fmt,a)
|
|
|
|
# define rb_warning0(fmt) rb_warning(fmt)
|
|
|
|
#else
|
|
|
|
# define rb_warn0(fmt) ripper_warn0(parser, fmt)
|
|
|
|
# define rb_warnI(fmt,a) ripper_warnI(parser, fmt, a)
|
|
|
|
# define rb_warnS(fmt,a) ripper_warnS(parser, fmt, a)
|
|
|
|
# define rb_warning0(fmt) ripper_warning0(parser, fmt)
|
2004-09-17 05:24:13 -04:00
|
|
|
static void ripper_warn0 _((struct parser_params*, const char*));
|
|
|
|
static void ripper_warnI _((struct parser_params*, const char*, int));
|
|
|
|
static void ripper_warnS _((struct parser_params*, const char*, const char*));
|
|
|
|
static void ripper_warning0 _((struct parser_params*, const char*));
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
static void ripper_compile_error _((struct parser_params*, const char *fmt, ...));
|
|
|
|
# define rb_compile_error ripper_compile_error
|
|
|
|
# define compile_error ripper_compile_error
|
|
|
|
# define PARSER_ARG parser,
|
2004-09-12 11:21:49 -04:00
|
|
|
#else
|
2004-09-17 05:24:13 -04:00
|
|
|
# define compile_error rb_compile_error
|
|
|
|
# define PARSER_ARG
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
2002-06-24 03:20:42 -04:00
|
|
|
|
2004-05-24 22:54:22 -04:00
|
|
|
#define NEW_BLOCK_VAR(b, v) NEW_NODE(NODE_BLOCK_PASS, 0, b, v)
|
|
|
|
|
2003-12-03 02:55:54 -05:00
|
|
|
/* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
|
|
|
|
for instance). This is too low for Ruby to parse some files, such as
|
|
|
|
date/format.rb, therefore bump the value up to at least Bison's default. */
|
|
|
|
#ifdef OLD_YACC
|
|
|
|
#ifndef YYMAXDEPTH
|
|
|
|
#define YYMAXDEPTH 10000
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
%}
|
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
%pure_parser
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
%union {
|
2004-09-12 11:21:49 -04:00
|
|
|
VALUE val;
|
1998-01-16 07:13:05 -05:00
|
|
|
NODE *node;
|
|
|
|
ID id;
|
|
|
|
int num;
|
|
|
|
struct RVarmap *vars;
|
|
|
|
}
|
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
|
|
|
%token
|
|
|
|
/*%
|
|
|
|
%token <val>
|
|
|
|
%*/
|
|
|
|
kCLASS
|
1998-01-16 07:19:22 -05:00
|
|
|
kMODULE
|
|
|
|
kDEF
|
|
|
|
kUNDEF
|
|
|
|
kBEGIN
|
|
|
|
kRESCUE
|
|
|
|
kENSURE
|
|
|
|
kEND
|
|
|
|
kIF
|
|
|
|
kUNLESS
|
|
|
|
kTHEN
|
|
|
|
kELSIF
|
|
|
|
kELSE
|
|
|
|
kCASE
|
|
|
|
kWHEN
|
|
|
|
kWHILE
|
|
|
|
kUNTIL
|
|
|
|
kFOR
|
|
|
|
kBREAK
|
|
|
|
kNEXT
|
|
|
|
kREDO
|
|
|
|
kRETRY
|
|
|
|
kIN
|
|
|
|
kDO
|
2001-01-26 00:02:19 -05:00
|
|
|
kDO_COND
|
|
|
|
kDO_BLOCK
|
1998-01-16 07:19:22 -05:00
|
|
|
kRETURN
|
|
|
|
kYIELD
|
|
|
|
kSUPER
|
|
|
|
kSELF
|
|
|
|
kNIL
|
|
|
|
kTRUE
|
|
|
|
kFALSE
|
|
|
|
kAND
|
|
|
|
kOR
|
|
|
|
kNOT
|
|
|
|
kIF_MOD
|
|
|
|
kUNLESS_MOD
|
|
|
|
kWHILE_MOD
|
|
|
|
kUNTIL_MOD
|
1999-11-10 01:47:11 -05:00
|
|
|
kRESCUE_MOD
|
1998-01-16 07:19:22 -05:00
|
|
|
kALIAS
|
|
|
|
kDEFINED
|
|
|
|
klBEGIN
|
|
|
|
klEND
|
1999-01-19 23:59:39 -05:00
|
|
|
k__LINE__
|
|
|
|
k__FILE__
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-03-20 11:45:41 -05:00
|
|
|
%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
|
2002-09-05 21:24:41 -04:00
|
|
|
%token <node> tINTEGER tFLOAT tSTRING_CONTENT
|
2002-06-26 04:01:00 -04:00
|
|
|
%token <node> tNTH_REF tBACK_REF
|
2002-06-24 03:20:42 -04:00
|
|
|
%token <num> tREGEXP_END
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
%type <node> singleton strings string string1 xstring regexp
|
|
|
|
%type <node> string_contents xstring_contents string_content
|
2002-06-26 04:01:00 -04:00
|
|
|
%type <node> words qwords word_list qword_list word
|
2003-03-03 00:17:39 -05:00
|
|
|
%type <node> literal numeric dsym cpath
|
2002-03-26 01:18:51 -05:00
|
|
|
%type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
|
2002-06-28 10:42:46 -04:00
|
|
|
%type <node> expr_value arg_value primary_value
|
2002-03-26 01:18:51 -05:00
|
|
|
%type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
|
2001-05-30 05:12:34 -04:00
|
|
|
%type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
|
2002-02-13 04:01:11 -05:00
|
|
|
%type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
|
2002-12-31 22:24:29 -05:00
|
|
|
%type <node> mrhs superclass block_call block_command
|
1999-01-19 23:59:39 -05:00
|
|
|
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
|
2004-04-05 09:16:40 -04:00
|
|
|
%type <node> assoc_list assocs assoc kwargs undef_list backref string_dvar
|
2004-05-24 22:54:22 -04:00
|
|
|
%type <node> for_var block_var opt_block_var block_par
|
2004-10-30 02:56:18 -04:00
|
|
|
%type <node> brace_block cmd_brace_block do_block lhs none fitem
|
2000-03-09 04:04:36 -05:00
|
|
|
%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
|
2004-10-30 02:56:18 -04:00
|
|
|
%type <id> fsym variable sym symbol operation operation2 operation3
|
2002-06-24 11:18:00 -04:00
|
|
|
%type <id> cname fname op f_rest_arg
|
2003-09-17 07:34:02 -04:00
|
|
|
%type <num> f_norm_arg f_arg
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
|
|
|
/*%
|
|
|
|
%type <val> program reswords then do dot_or_colon
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
%token tUPLUS /* unary+ */
|
|
|
|
%token tUMINUS /* unary- */
|
|
|
|
%token tPOW /* ** */
|
|
|
|
%token tCMP /* <=> */
|
|
|
|
%token tEQ /* == */
|
|
|
|
%token tEQQ /* === */
|
|
|
|
%token tNEQ /* != */
|
|
|
|
%token tGEQ /* >= */
|
|
|
|
%token tLEQ /* <= */
|
|
|
|
%token tANDOP tOROP /* && and || */
|
|
|
|
%token tMATCH tNMATCH /* =~ and !~ */
|
|
|
|
%token tDOT2 tDOT3 /* .. and ... */
|
|
|
|
%token tAREF tASET /* [] and []= */
|
|
|
|
%token tLSHFT tRSHFT /* << and >> */
|
|
|
|
%token tCOLON2 /* :: */
|
|
|
|
%token tCOLON3 /* :: at EXPR_BEG */
|
|
|
|
%token <id> tOP_ASGN /* +=, -= etc. */
|
|
|
|
%token tASSOC /* => */
|
|
|
|
%token tLPAREN /* ( */
|
2001-05-30 05:12:34 -04:00
|
|
|
%token tLPAREN_ARG /* ( */
|
2001-03-13 00:45:13 -05:00
|
|
|
%token tRPAREN /* ) */
|
1999-01-19 23:59:39 -05:00
|
|
|
%token tLBRACK /* [ */
|
|
|
|
%token tLBRACE /* { */
|
2001-05-30 05:12:34 -04:00
|
|
|
%token tLBRACE_ARG /* { */
|
1999-01-19 23:59:39 -05:00
|
|
|
%token tSTAR /* * */
|
|
|
|
%token tAMPER /* & */
|
2004-05-17 03:25:36 -04:00
|
|
|
%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
|
2002-06-24 03:20:42 -04:00
|
|
|
%token tSTRING_DBEG tSTRING_DVAR tSTRING_END
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
* precedence table
|
|
|
|
*/
|
|
|
|
|
2002-12-24 03:53:56 -05:00
|
|
|
%nonassoc tLOWEST
|
2002-12-20 03:33:17 -05:00
|
|
|
%nonassoc tLBRACE_ARG
|
|
|
|
|
2003-03-03 00:17:39 -05:00
|
|
|
%nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
|
1998-01-16 07:19:22 -05:00
|
|
|
%left kOR kAND
|
|
|
|
%right kNOT
|
|
|
|
%nonassoc kDEFINED
|
1999-01-19 23:59:39 -05:00
|
|
|
%right '=' tOP_ASGN
|
2002-10-17 03:27:00 -04:00
|
|
|
%left kRESCUE_MOD
|
1999-01-19 23:59:39 -05:00
|
|
|
%right '?' ':'
|
|
|
|
%nonassoc tDOT2 tDOT3
|
|
|
|
%left tOROP
|
|
|
|
%left tANDOP
|
|
|
|
%nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
|
|
|
|
%left '>' tGEQ '<' tLEQ
|
1998-01-16 07:13:05 -05:00
|
|
|
%left '|' '^'
|
|
|
|
%left '&'
|
1999-01-19 23:59:39 -05:00
|
|
|
%left tLSHFT tRSHFT
|
1998-01-16 07:13:05 -05:00
|
|
|
%left '+' '-'
|
|
|
|
%left '*' '/' '%'
|
2003-01-24 04:18:04 -05:00
|
|
|
%right tUMINUS_NUM tUMINUS
|
1999-01-19 23:59:39 -05:00
|
|
|
%right tPOW
|
2003-01-24 04:18:04 -05:00
|
|
|
%right '!' '~' tUPLUS
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-12-24 03:53:56 -05:00
|
|
|
%token tLAST_TOKEN
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
%%
|
|
|
|
program : {
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_BEG;
|
2004-09-12 11:21:49 -04:00
|
|
|
top_local_init();
|
2003-08-06 17:50:06 -04:00
|
|
|
if (ruby_class == rb_cObject) class_nest = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
else class_nest = 1;
|
|
|
|
/*%
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
class_nest = !parser->toplevel_p;
|
|
|
|
$$ = Qnil;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
if ($2 && !compile_for_eval) {
|
|
|
|
/* last expression should not be void */
|
|
|
|
if (nd_type($2) != NODE_BLOCK) void_expr($2);
|
|
|
|
else {
|
|
|
|
NODE *node = $2;
|
|
|
|
while (node->nd_next) {
|
|
|
|
node = node->nd_next;
|
|
|
|
}
|
|
|
|
void_expr(node->nd_head);
|
|
|
|
}
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
ruby_eval_tree = block_append(ruby_eval_tree, $2);
|
1998-01-16 07:13:05 -05:00
|
|
|
top_local_setup();
|
|
|
|
class_nest = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
class_nest = 0;
|
|
|
|
$$ = $2;
|
|
|
|
parser->result = dispatch1(program, $$);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
bodystmt : compstmt
|
|
|
|
opt_rescue
|
|
|
|
opt_else
|
|
|
|
opt_ensure
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-03-26 01:18:51 -05:00
|
|
|
$$ = $1;
|
|
|
|
if ($2) {
|
|
|
|
$$ = NEW_RESCUE($1, $2, $3);
|
|
|
|
}
|
|
|
|
else if ($3) {
|
|
|
|
rb_warn("else without rescue is useless");
|
2002-05-20 12:22:23 -04:00
|
|
|
$$ = block_append($$, $3);
|
2002-03-26 01:18:51 -05:00
|
|
|
}
|
|
|
|
if ($4) {
|
2004-02-02 21:23:20 -05:00
|
|
|
if ($$) {
|
|
|
|
$$ = NEW_ENSURE($$, $4);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$$ = block_append($4, NEW_NIL());
|
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
}
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(bodystmt,
|
|
|
|
escape_Qundef($1),
|
|
|
|
escape_Qundef($2),
|
|
|
|
escape_Qundef($3),
|
|
|
|
escape_Qundef($4));
|
|
|
|
%*/
|
2002-03-26 01:18:51 -05:00
|
|
|
}
|
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt : stmts opt_terms
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
void_stmts($1);
|
2002-03-26 01:18:51 -05:00
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
|
|
|
stmts : none
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{
|
|
|
|
$$ = dispatch2(stmts_add, dispatch0(stmts_new),
|
|
|
|
dispatch0(void_stmt));
|
|
|
|
}
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
| stmt
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-10-02 07:34:13 -04:00
|
|
|
$$ = newline_node(remove_begin($1));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(stmts_add, dispatch0(stmts_new), $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| stmts terms stmt
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-10-02 07:34:13 -04:00
|
|
|
$$ = block_append($1, newline_node(remove_begin($3)));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(stmts_add, $1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| error stmt
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-10-02 07:34:13 -04:00
|
|
|
$$ = remove_begin($2);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2001-01-20 09:02:28 -05:00
|
|
|
stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_ALIAS($2, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(alias, $2, $4);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| kALIAS tGVAR tGVAR
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_VALIAS($2, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(var_alias, $2, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| kALIAS tGVAR tBACK_REF
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
char buf[3];
|
|
|
|
|
2003-01-16 02:38:40 -05:00
|
|
|
sprintf(buf, "$%c", (char)$3->nd_nth);
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_VALIAS($2, rb_intern(buf));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(var_alias, $2, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| kALIAS tGVAR tNTH_REF
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
yyerror("can't make alias for the number variables");
|
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(var_alias, $2, $3);
|
|
|
|
$$ = dispatch1(alias_error, $$);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| kUNDEF undef_list
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(undef, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| stmt kIF_MOD expr_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_IF(cond($3), $1, 0);
|
|
|
|
fixpos($$, $3);
|
2003-03-20 02:03:22 -05:00
|
|
|
if (cond_negative(&$$->nd_cond)) {
|
2003-01-09 01:16:43 -05:00
|
|
|
$$->nd_else = $$->nd_body;
|
|
|
|
$$->nd_body = 0;
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(if_mod, $3, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| stmt kUNLESS_MOD expr_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_UNLESS(cond($3), $1, 0);
|
|
|
|
fixpos($$, $3);
|
2003-03-20 02:03:22 -05:00
|
|
|
if (cond_negative(&$$->nd_cond)) {
|
2003-01-09 01:16:43 -05:00
|
|
|
$$->nd_body = $$->nd_else;
|
|
|
|
$$->nd_else = 0;
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unless_mod, $3, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| stmt kWHILE_MOD expr_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-03-13 00:45:13 -05:00
|
|
|
if ($1 && nd_type($1) == NODE_BEGIN) {
|
|
|
|
$$ = NEW_WHILE(cond($3), $1->nd_body, 0);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
2001-03-13 00:45:13 -05:00
|
|
|
$$ = NEW_WHILE(cond($3), $1, 1);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-03-20 02:03:22 -05:00
|
|
|
if (cond_negative(&$$->nd_cond)) {
|
2003-01-09 01:16:43 -05:00
|
|
|
nd_set_type($$, NODE_UNTIL);
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(while_mod, $3, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| stmt kUNTIL_MOD expr_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-03-13 00:45:13 -05:00
|
|
|
if ($1 && nd_type($1) == NODE_BEGIN) {
|
|
|
|
$$ = NEW_UNTIL(cond($3), $1->nd_body, 0);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
2001-03-13 00:45:13 -05:00
|
|
|
$$ = NEW_UNTIL(cond($3), $1, 1);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-03-20 02:03:22 -05:00
|
|
|
if (cond_negative(&$$->nd_cond)) {
|
2003-01-09 01:16:43 -05:00
|
|
|
nd_set_type($$, NODE_WHILE);
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(until_mod, $3, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-03-03 00:17:39 -05:00
|
|
|
| stmt kRESCUE_MOD stmt
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
$$ = NEW_RESCUE($1, NEW_RESBODY(0,$3,0), 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(rescue_mod, $3, $1);
|
|
|
|
%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| klBEGIN
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-02-13 00:09:11 -05:00
|
|
|
if (in_def || in_single) {
|
1998-01-16 07:19:22 -05:00
|
|
|
yyerror("BEGIN in method");
|
|
|
|
}
|
2002-03-19 04:03:11 -05:00
|
|
|
local_push(0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
if (in_def || in_single) {
|
|
|
|
yyerror("BEGIN in method");
|
|
|
|
}
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
'{' compstmt '}'
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
|
1999-08-13 01:45:20 -04:00
|
|
|
NEW_PREEXE($4));
|
1998-01-16 07:19:22 -05:00
|
|
|
local_pop();
|
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(BEGIN, $4);
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
| klEND '{' compstmt '}'
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-10-06 03:03:20 -04:00
|
|
|
if (in_def || in_single) {
|
|
|
|
rb_warn("END in method; use at_exit");
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
$$ = NEW_ITER(0, NEW_POSTEXE(), $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
if (in_def || in_single) {
|
|
|
|
rb_warn0("END in method; use at_exit");
|
|
|
|
}
|
|
|
|
$$ = dispatch1(END, $3);
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2001-01-20 09:02:28 -05:00
|
|
|
| lhs '=' command_call
|
1999-08-13 01:45:20 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = node_assign($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(assign, $1, $3);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2001-01-20 09:02:28 -05:00
|
|
|
| mlhs '=' command_call
|
2000-08-31 01:29:54 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-08-31 01:29:54 -04:00
|
|
|
value_expr($3);
|
2003-10-06 15:15:29 -04:00
|
|
|
$1->nd_value = ($1->nd_head) ? NEW_TO_ARY($3) : NEW_ARRAY($3);
|
2000-08-31 01:29:54 -04:00
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(massign, $1, $3);
|
|
|
|
%*/
|
2000-08-31 01:29:54 -04:00
|
|
|
}
|
2002-02-13 04:01:11 -05:00
|
|
|
| var_lhs tOP_ASGN command_call
|
2001-10-30 03:43:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($3);
|
2002-02-13 04:01:11 -05:00
|
|
|
if ($1) {
|
2002-02-14 03:47:58 -05:00
|
|
|
ID vid = $1->nd_vid;
|
2001-11-08 01:43:14 -05:00
|
|
|
if ($2 == tOROP) {
|
2002-02-13 04:01:11 -05:00
|
|
|
$1->nd_value = $3;
|
|
|
|
$$ = NEW_OP_ASGN_OR(gettable(vid), $1);
|
2002-09-13 05:36:28 -04:00
|
|
|
if (is_asgn_or_id(vid)) {
|
2002-02-13 04:01:11 -05:00
|
|
|
$$->nd_aid = vid;
|
2001-11-08 01:43:14 -05:00
|
|
|
}
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
2001-11-08 01:43:14 -05:00
|
|
|
else if ($2 == tANDOP) {
|
2002-02-13 04:01:11 -05:00
|
|
|
$1->nd_value = $3;
|
|
|
|
$$ = NEW_OP_ASGN_AND(gettable(vid), $1);
|
2001-11-08 01:43:14 -05:00
|
|
|
}
|
|
|
|
else {
|
2002-02-13 04:01:11 -05:00
|
|
|
$$ = $1;
|
|
|
|
$$->nd_value = call_op(gettable(vid),$2,1,$3);
|
2001-11-08 01:43:14 -05:00
|
|
|
}
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
|
|
|
else {
|
2001-11-08 01:43:14 -05:00
|
|
|
$$ = 0;
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(opassign, $1, $2, $3);
|
|
|
|
%*/
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '[' aref_args ']' tOP_ASGN command_call
|
2001-10-30 03:43:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
NODE *args;
|
2001-10-30 03:43:28 -05:00
|
|
|
|
2002-06-11 13:39:38 -04:00
|
|
|
value_expr($6);
|
2002-06-11 03:02:23 -04:00
|
|
|
args = NEW_LIST($6);
|
2004-04-23 01:52:18 -04:00
|
|
|
if ($3 && nd_type($3) != NODE_ARRAY)
|
|
|
|
$3 = NEW_LIST($3);
|
2001-10-30 03:43:28 -05:00
|
|
|
$3 = list_append($3, NEW_NIL());
|
|
|
|
list_concat(args, $3);
|
|
|
|
if ($5 == tOROP) {
|
|
|
|
$5 = 0;
|
|
|
|
}
|
|
|
|
else if ($5 == tANDOP) {
|
|
|
|
$5 = 1;
|
|
|
|
}
|
|
|
|
$$ = NEW_OP_ASGN1($1, $5, args);
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(aref_field, $1, $3);
|
|
|
|
$$ = dispatch3(opassign, $$, $5, $6);
|
|
|
|
%*/
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' tIDENTIFIER tOP_ASGN command_call
|
2001-10-30 03:43:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($5);
|
2001-10-30 03:43:28 -05:00
|
|
|
if ($4 == tOROP) {
|
|
|
|
$4 = 0;
|
|
|
|
}
|
|
|
|
else if ($4 == tANDOP) {
|
|
|
|
$4 = 1;
|
|
|
|
}
|
|
|
|
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
|
|
|
|
$$ = dispatch3(opassign, $$, $4, $5);
|
|
|
|
%*/
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' tCONSTANT tOP_ASGN command_call
|
2001-10-30 03:43:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($5);
|
2001-10-30 03:43:28 -05:00
|
|
|
if ($4 == tOROP) {
|
|
|
|
$4 = 0;
|
|
|
|
}
|
|
|
|
else if ($4 == tANDOP) {
|
|
|
|
$4 = 1;
|
|
|
|
}
|
|
|
|
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
|
|
|
|
$$ = dispatch3(opassign, $$, $4, $5);
|
|
|
|
%*/
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
|
2001-10-30 03:43:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($5);
|
2001-10-30 03:43:28 -05:00
|
|
|
if ($4 == tOROP) {
|
|
|
|
$4 = 0;
|
|
|
|
}
|
|
|
|
else if ($4 == tANDOP) {
|
|
|
|
$4 = 1;
|
|
|
|
}
|
|
|
|
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(field, $1, ripper_intern("::"), $3);
|
|
|
|
$$ = dispatch3(opassign, $$, $4, $5);
|
|
|
|
%*/
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
|
|
|
| backref tOP_ASGN command_call
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-10-30 03:43:28 -05:00
|
|
|
rb_backref_error($1);
|
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(assign, dispatch1(var_field, $1), $3);
|
|
|
|
$$ = dispatch1(assign_error, $$);
|
|
|
|
%*/
|
2001-10-30 03:43:28 -05:00
|
|
|
}
|
2002-12-31 22:24:29 -05:00
|
|
|
| lhs '=' mrhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-12-31 22:24:29 -05:00
|
|
|
$$ = node_assign($1, NEW_SVALUE($3));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(assign, $1, $3);
|
|
|
|
%*/
|
2002-12-31 22:24:29 -05:00
|
|
|
}
|
|
|
|
| mlhs '=' arg_value
|
2000-12-05 04:36:54 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-10-06 15:15:29 -04:00
|
|
|
$1->nd_value = ($1->nd_head) ? NEW_TO_ARY($3) : NEW_ARRAY($3);
|
2002-12-31 22:24:29 -05:00
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
dispatch2(massign, $1, $3);
|
|
|
|
%*/
|
2000-12-05 04:36:54 -05:00
|
|
|
}
|
2001-05-07 05:26:29 -04:00
|
|
|
| mlhs '=' mrhs
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
$1->nd_value = $3;
|
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(massign, $1, $3);
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2001-05-07 05:26:29 -04:00
|
|
|
| expr
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2001-05-07 05:26:29 -04:00
|
|
|
|
2002-11-14 01:18:59 -05:00
|
|
|
expr : command_call
|
1998-01-16 07:19:22 -05:00
|
|
|
| expr kAND expr
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = logop(NODE_AND, $1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("and"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| expr kOR expr
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = logop(NODE_OR, $1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("or"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| kNOT expr
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_NOT(cond($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unary, ripper_intern("not"), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| '!' command_call
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_NOT(cond($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unary, ID2SYM('!'), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-02-18 04:52:48 -05:00
|
|
|
expr_value : expr
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-02-18 04:52:48 -05:00
|
|
|
value_expr($$);
|
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
2002-02-18 04:52:48 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2002-02-18 04:52:48 -05:00
|
|
|
|
2001-01-20 09:02:28 -05:00
|
|
|
command_call : command
|
2001-01-26 00:02:19 -05:00
|
|
|
| block_command
|
2002-11-14 01:18:59 -05:00
|
|
|
| kRETURN call_args
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-11-14 01:18:59 -05:00
|
|
|
$$ = NEW_RETURN(ret_args($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(return, $2);
|
|
|
|
%*/
|
2002-11-14 01:18:59 -05:00
|
|
|
}
|
|
|
|
| kBREAK call_args
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-11-14 01:18:59 -05:00
|
|
|
$$ = NEW_BREAK(ret_args($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(break, $2);
|
|
|
|
%*/
|
2002-11-14 01:18:59 -05:00
|
|
|
}
|
|
|
|
| kNEXT call_args
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-11-14 01:18:59 -05:00
|
|
|
$$ = NEW_NEXT(ret_args($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(next, $2);
|
|
|
|
%*/
|
2002-11-14 01:18:59 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2001-01-20 09:02:28 -05:00
|
|
|
|
2001-01-26 00:02:19 -05:00
|
|
|
block_command : block_call
|
2002-06-28 10:42:46 -04:00
|
|
|
| block_call '.' operation2 command_args
|
2001-01-20 09:02:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
|
|
|
|
$$ = method_arg($$, $4);
|
|
|
|
%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
}
|
2002-06-28 10:42:46 -04:00
|
|
|
| block_call tCOLON2 operation2 command_args
|
2001-01-20 09:02:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(call, $1, ripper_intern("::"), $3);
|
|
|
|
$$ = method_arg($$, $4);
|
|
|
|
%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2001-01-20 09:02:28 -05:00
|
|
|
|
2002-12-20 03:33:17 -05:00
|
|
|
cmd_brace_block : tLBRACE_ARG
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-12-20 03:33:17 -05:00
|
|
|
$<vars>$ = dyna_push();
|
|
|
|
$<num>1 = ruby_sourceline;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
%*/
|
2002-12-20 03:33:17 -05:00
|
|
|
}
|
2003-06-06 07:29:20 -04:00
|
|
|
opt_block_var {$<vars>$ = ruby_dyna_vars;}
|
2002-12-20 03:33:17 -05:00
|
|
|
compstmt
|
|
|
|
'}'
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-06-06 07:29:20 -04:00
|
|
|
$$ = NEW_ITER($3, 0, dyna_init($5, $<vars>4));
|
2002-12-20 03:33:17 -05:00
|
|
|
nd_set_line($$, $<num>1);
|
|
|
|
dyna_pop($<vars>2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(brace_block, escape_Qundef($3), $5);
|
|
|
|
%*/
|
2002-12-20 03:33:17 -05:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
2002-12-24 03:53:56 -05:00
|
|
|
command : operation command_args %prec tLOWEST
|
2002-12-20 03:33:17 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-12-20 03:33:17 -05:00
|
|
|
$$ = new_fcall($1, $2);
|
|
|
|
fixpos($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(command, $1, $2);
|
|
|
|
%*/
|
|
|
|
}
|
2002-12-20 03:33:17 -05:00
|
|
|
| operation command_args cmd_brace_block
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = new_fcall($1, $2);
|
2002-12-20 03:33:17 -05:00
|
|
|
if ($3) {
|
|
|
|
if (nd_type($$) == NODE_BLOCK_PASS) {
|
2004-09-17 05:24:13 -04:00
|
|
|
compile_error(PARSER_ARG "both block arg and actual block given");
|
2002-12-20 03:33:17 -05:00
|
|
|
}
|
|
|
|
$3->nd_iter = $$;
|
|
|
|
$$ = $3;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(command, $1, $2);
|
|
|
|
$$ = dispatch2(iter_block, $$, $3);
|
|
|
|
%*/
|
|
|
|
}
|
2002-12-24 03:53:56 -05:00
|
|
|
| primary_value '.' operation2 command_args %prec tLOWEST
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-12-20 03:33:17 -05:00
|
|
|
| primary_value '.' operation2 command_args cmd_brace_block
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-12-20 03:33:17 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
|
|
|
if ($5) {
|
|
|
|
if (nd_type($$) == NODE_BLOCK_PASS) {
|
2004-09-17 05:24:13 -04:00
|
|
|
compile_error(PARSER_ARG "both block arg and actual block given");
|
2002-12-20 03:33:17 -05:00
|
|
|
}
|
|
|
|
$5->nd_iter = $$;
|
|
|
|
$$ = $5;
|
|
|
|
}
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(command_call, $1, ripper_id2sym('.'), $3, $4);
|
|
|
|
$$ = dispatch2(iter_block, $$, $5);
|
|
|
|
%*/
|
2002-12-20 03:33:17 -05:00
|
|
|
}
|
2002-12-24 03:53:56 -05:00
|
|
|
| primary_value tCOLON2 operation2 command_args %prec tLOWEST
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
1998-01-16 07:19:22 -05:00
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-12-20 03:33:17 -05:00
|
|
|
| primary_value tCOLON2 operation2 command_args cmd_brace_block
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-12-20 03:33:17 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
|
|
|
if ($5) {
|
|
|
|
if (nd_type($$) == NODE_BLOCK_PASS) {
|
2004-09-17 05:24:13 -04:00
|
|
|
compile_error(PARSER_ARG "both block arg and actual block given");
|
2002-12-20 03:33:17 -05:00
|
|
|
}
|
|
|
|
$5->nd_iter = $$;
|
|
|
|
$$ = $5;
|
|
|
|
}
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(command_call, $1, ripper_intern("::"), $3, $4);
|
|
|
|
$$ = dispatch2(iter_block, $$, $5);
|
|
|
|
%*/
|
2002-12-20 03:33:17 -05:00
|
|
|
}
|
2001-01-26 00:02:19 -05:00
|
|
|
| kSUPER command_args
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-06-23 03:05:59 -04:00
|
|
|
$$ = new_super($2);
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(super, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-10-10 04:21:13 -04:00
|
|
|
| kYIELD command_args
|
2000-09-12 01:37:38 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-06-20 03:11:44 -04:00
|
|
|
$$ = new_yield($2);
|
2000-09-12 01:37:38 -04:00
|
|
|
fixpos($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(yield, $2);
|
|
|
|
%*/
|
2000-09-12 01:37:38 -04:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2000-09-12 01:37:38 -04:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
mlhs : mlhs_basic
|
2004-02-12 01:23:24 -05:00
|
|
|
| tLPAREN mlhs_entry rparen
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(mlhs_paren, $2);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
|
|
|
mlhs_entry : mlhs_basic
|
2004-02-12 01:23:24 -05:00
|
|
|
| tLPAREN mlhs_entry rparen
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_MASGN(NEW_LIST($2), 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(mlhs_paren, $2);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
|
|
|
mlhs_basic : mlhs_head
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-03-09 04:04:36 -05:00
|
|
|
$$ = NEW_MASGN($1, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
2004-09-27 02:02:27 -04:00
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-03-09 04:04:36 -05:00
|
|
|
| mlhs_head mlhs_item
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-03-09 04:04:36 -05:00
|
|
|
$$ = NEW_MASGN(list_append($1,$2), 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add($1, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-03-09 04:04:36 -05:00
|
|
|
| mlhs_head tSTAR mlhs_node
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-03-09 04:04:36 -05:00
|
|
|
$$ = NEW_MASGN($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add_star($1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-03-09 04:04:36 -05:00
|
|
|
| mlhs_head tSTAR
|
1999-08-13 01:45:20 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-03-09 04:04:36 -05:00
|
|
|
$$ = NEW_MASGN($1, -1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add_star($1, Qnil);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
|
|
|
| tSTAR mlhs_node
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_MASGN(0, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add_star(mlhs_new(), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
| tSTAR
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = NEW_MASGN(0, -1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add_star(mlhs_new(), Qnil);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
mlhs_item : mlhs_node
|
2004-02-12 01:23:24 -05:00
|
|
|
| tLPAREN mlhs_entry rparen
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(mlhs_paren, $2);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
|
|
|
mlhs_head : mlhs_item ','
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_LIST($1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add(mlhs_new(), $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-03-09 04:04:36 -05:00
|
|
|
| mlhs_head mlhs_item ','
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-03-09 04:04:36 -05:00
|
|
|
$$ = list_append($1, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add($1, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
mlhs_node : variable
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = assignable($1, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '[' aref_args ']'
|
1999-08-13 01:45:20 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = aryset($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(aref_field, $1, $3);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' tIDENTIFIER
|
1999-08-13 01:45:20 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = attrset($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value tCOLON2 tIDENTIFIER
|
2000-01-31 22:12:21 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
$$ = attrset($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(constpath_field, $1, $3);
|
|
|
|
%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' tCONSTANT
|
2000-05-09 00:53:16 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-05-09 00:53:16 -04:00
|
|
|
$$ = attrset($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
|
|
|
|
%*/
|
2000-05-09 00:53:16 -04:00
|
|
|
}
|
2003-03-03 00:17:39 -05:00
|
|
|
| primary_value tCOLON2 tCONSTANT
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
if (in_def || in_single)
|
|
|
|
yyerror("dynamic constant assignment");
|
|
|
|
$$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
if (in_def || in_single)
|
|
|
|
yyerror("dynamic constant assignment");
|
|
|
|
$$ = dispatch2(constpath_field, $1, $3);
|
|
|
|
%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
}
|
2003-08-14 13:20:14 -04:00
|
|
|
| tCOLON3 tCONSTANT
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-08-14 13:20:14 -04:00
|
|
|
if (in_def || in_single)
|
|
|
|
yyerror("dynamic constant assignment");
|
|
|
|
$$ = NEW_CDECL(0, 0, NEW_COLON3($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(topconst_field, $2);
|
|
|
|
%*/
|
2003-08-14 13:20:14 -04:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
| backref
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
rb_backref_error($1);
|
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(var_field, $1);
|
|
|
|
$$ = dispatch1(assign_error, $$);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
lhs : variable
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = assignable($1, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(var_field, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '[' aref_args ']'
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = aryset($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(aref_field, $1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' tIDENTIFIER
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = attrset($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value tCOLON2 tIDENTIFIER
|
2000-01-31 22:12:21 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
$$ = attrset($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(field, $1, ripper_intern("::"), $3);
|
|
|
|
%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' tCONSTANT
|
2000-05-09 00:53:16 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-05-09 00:53:16 -04:00
|
|
|
$$ = attrset($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(field, $1, ripper_id2sym('.'), $3);
|
|
|
|
%*/
|
2000-05-09 00:53:16 -04:00
|
|
|
}
|
2003-03-03 00:17:39 -05:00
|
|
|
| primary_value tCOLON2 tCONSTANT
|
2003-02-19 22:35:44 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-02-19 22:35:44 -05:00
|
|
|
if (in_def || in_single)
|
|
|
|
yyerror("dynamic constant assignment");
|
|
|
|
$$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(constpath_field, $1, $3);
|
|
|
|
if (in_def || in_single) {
|
|
|
|
$$ = dispatch1(assign_error, $$);
|
|
|
|
}
|
|
|
|
%*/
|
2003-02-19 22:35:44 -05:00
|
|
|
}
|
2003-08-14 13:20:14 -04:00
|
|
|
| tCOLON3 tCONSTANT
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-08-14 13:20:14 -04:00
|
|
|
if (in_def || in_single)
|
|
|
|
yyerror("dynamic constant assignment");
|
|
|
|
$$ = NEW_CDECL(0, 0, NEW_COLON3($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(topconst_field, $2);
|
|
|
|
if (in_def || in_single) {
|
|
|
|
$$ = dispatch1(assign_error, $$);
|
|
|
|
}
|
|
|
|
%*/
|
2003-08-14 13:20:14 -04:00
|
|
|
}
|
2003-03-03 00:17:39 -05:00
|
|
|
| backref
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
rb_backref_error($1);
|
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(assign_error, $1);
|
|
|
|
%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
}
|
2003-02-19 22:35:44 -05:00
|
|
|
;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
cname : tIDENTIFIER
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
yyerror("class/module name must be CONSTANT");
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(class_name_error, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| tCONSTANT
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2003-02-19 22:35:44 -05:00
|
|
|
cpath : tCOLON3 cname
|
2003-02-19 04:27:49 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-02-19 04:27:49 -05:00
|
|
|
$$ = NEW_COLON3($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(topconst_ref, $2);
|
|
|
|
%*/
|
2003-02-19 04:27:49 -05:00
|
|
|
}
|
|
|
|
| cname
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-02-19 22:35:44 -05:00
|
|
|
$$ = NEW_COLON2(0, $$);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(const_ref, $1);
|
|
|
|
%*/
|
2003-02-19 04:27:49 -05:00
|
|
|
}
|
2003-02-19 22:35:44 -05:00
|
|
|
| primary_value tCOLON2 cname
|
2003-02-19 04:27:49 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-02-19 04:27:49 -05:00
|
|
|
$$ = NEW_COLON2($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(constpath_ref, $1, $3);
|
|
|
|
%*/
|
2003-02-19 04:27:49 -05:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
fname : tIDENTIFIER
|
|
|
|
| tCONSTANT
|
|
|
|
| tFID
|
1998-01-16 07:13:05 -05:00
|
|
|
| op
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
$$ = $1;
|
|
|
|
/*%
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_END;
|
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| reswords
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
lex_state = EXPR_END;
|
|
|
|
$$ = $<id>1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-10-30 02:56:18 -04:00
|
|
|
fsym : fname
|
1999-08-13 01:45:20 -04:00
|
|
|
| symbol
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
2004-10-30 02:56:18 -04:00
|
|
|
fitem : fsym
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
$$ = NEW_LIT(ID2SYM($1));
|
|
|
|
/*%
|
|
|
|
$$ = dispatch1(symbol_literal, $1);
|
|
|
|
%*/
|
|
|
|
}
|
|
|
|
| dsym
|
|
|
|
;
|
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
undef_list : fitem
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_UNDEF($1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = rb_ary_new3(1, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
| undef_list ',' {lex_state = EXPR_FNAME;} fitem
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = block_append($1, NEW_UNDEF($4));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
rb_ary_push($1, $4);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-10-31 01:22:58 -04:00
|
|
|
op : '|' { ifndef_ripper($$ = '|'); }
|
|
|
|
| '^' { ifndef_ripper($$ = '^'); }
|
|
|
|
| '&' { ifndef_ripper($$ = '&'); }
|
|
|
|
| tCMP { ifndef_ripper($$ = tCMP); }
|
|
|
|
| tEQ { ifndef_ripper($$ = tEQ); }
|
|
|
|
| tEQQ { ifndef_ripper($$ = tEQQ); }
|
|
|
|
| tMATCH { ifndef_ripper($$ = tMATCH); }
|
|
|
|
| '>' { ifndef_ripper($$ = '>'); }
|
|
|
|
| tGEQ { ifndef_ripper($$ = tGEQ); }
|
|
|
|
| '<' { ifndef_ripper($$ = '<'); }
|
|
|
|
| tLEQ { ifndef_ripper($$ = tLEQ); }
|
|
|
|
| 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); }
|
|
|
|
| '~' { ifndef_ripper($$ = '~'); }
|
|
|
|
| tUPLUS { ifndef_ripper($$ = tUPLUS); }
|
|
|
|
| tUMINUS { ifndef_ripper($$ = tUMINUS); }
|
|
|
|
| tAREF { ifndef_ripper($$ = tAREF); }
|
|
|
|
| tASET { ifndef_ripper($$ = tASET); }
|
|
|
|
| '`' { ifndef_ripper($$ = '`'); }
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-01-04 23:41:21 -05:00
|
|
|
reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
|
1999-01-19 23:59:39 -05:00
|
|
|
| kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
|
|
|
|
| kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
|
2003-03-07 00:59:42 -05:00
|
|
|
| kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
|
1999-01-19 23:59:39 -05:00
|
|
|
| kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER
|
2003-03-03 00:17:39 -05:00
|
|
|
| kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
|
2003-03-07 00:59:42 -05:00
|
|
|
| kIF_MOD | kUNLESS_MOD | kWHILE_MOD | kUNTIL_MOD | kRESCUE_MOD
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
arg : lhs '=' arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = node_assign($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(assign, $1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-03-03 00:17:39 -05:00
|
|
|
| lhs '=' arg kRESCUE_MOD arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
$$ = node_assign($1, NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(assign, $1, dispatch2(rescue_mod,$3,$5));
|
|
|
|
%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
}
|
2002-02-13 04:01:11 -05:00
|
|
|
| var_lhs tOP_ASGN arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($3);
|
2002-02-13 04:01:11 -05:00
|
|
|
if ($1) {
|
2002-02-14 03:47:58 -05:00
|
|
|
ID vid = $1->nd_vid;
|
2001-11-08 01:43:14 -05:00
|
|
|
if ($2 == tOROP) {
|
2002-02-13 04:01:11 -05:00
|
|
|
$1->nd_value = $3;
|
|
|
|
$$ = NEW_OP_ASGN_OR(gettable(vid), $1);
|
2002-09-13 05:36:28 -04:00
|
|
|
if (is_asgn_or_id(vid)) {
|
2002-02-13 04:01:11 -05:00
|
|
|
$$->nd_aid = vid;
|
2001-11-08 01:43:14 -05:00
|
|
|
}
|
2001-05-07 05:26:29 -04:00
|
|
|
}
|
2001-11-08 01:43:14 -05:00
|
|
|
else if ($2 == tANDOP) {
|
2002-02-13 04:01:11 -05:00
|
|
|
$1->nd_value = $3;
|
|
|
|
$$ = NEW_OP_ASGN_AND(gettable(vid), $1);
|
2001-11-08 01:43:14 -05:00
|
|
|
}
|
|
|
|
else {
|
2002-02-13 04:01:11 -05:00
|
|
|
$$ = $1;
|
|
|
|
$$->nd_value = call_op(gettable(vid),$2,1,$3);
|
2001-11-08 01:43:14 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
else {
|
2001-11-08 01:43:14 -05:00
|
|
|
$$ = 0;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(opassign, $1, $2, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '[' aref_args ']' tOP_ASGN arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
NODE *args;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($6);
|
|
|
|
args = NEW_LIST($6);
|
2004-04-23 01:52:18 -04:00
|
|
|
if ($3 && nd_type($3) != NODE_ARRAY)
|
|
|
|
$3 = NEW_LIST($3);
|
2001-09-26 13:09:47 -04:00
|
|
|
$3 = list_append($3, NEW_NIL());
|
1998-01-16 07:13:05 -05:00
|
|
|
list_concat(args, $3);
|
1999-01-19 23:59:39 -05:00
|
|
|
if ($5 == tOROP) {
|
|
|
|
$5 = 0;
|
|
|
|
}
|
|
|
|
else if ($5 == tANDOP) {
|
|
|
|
$5 = 1;
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
$$ = NEW_OP_ASGN1($1, $5, args);
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$1 = dispatch2(aref_field, $1, $3);
|
|
|
|
$$ = dispatch3(opassign, $1, $5, $6);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' tIDENTIFIER tOP_ASGN arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($5);
|
1999-01-19 23:59:39 -05:00
|
|
|
if ($4 == tOROP) {
|
|
|
|
$4 = 0;
|
|
|
|
}
|
|
|
|
else if ($4 == tANDOP) {
|
|
|
|
$4 = 1;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
|
1998-01-16 07:19:22 -05:00
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$1 = dispatch3(field, $1, ripper_id2sym('.'), $3);
|
|
|
|
$$ = dispatch3(opassign, $1, $4, $5);
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' tCONSTANT tOP_ASGN arg
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($5);
|
1999-01-19 23:59:39 -05:00
|
|
|
if ($4 == tOROP) {
|
|
|
|
$4 = 0;
|
|
|
|
}
|
|
|
|
else if ($4 == tANDOP) {
|
|
|
|
$4 = 1;
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$1 = dispatch3(field, $1, ripper_id2sym('.'), $3);
|
|
|
|
$$ = dispatch3(opassign, $1, $4, $5);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
|
2000-01-31 22:12:21 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-11 03:02:23 -04:00
|
|
|
value_expr($5);
|
2000-01-31 22:12:21 -05:00
|
|
|
if ($4 == tOROP) {
|
|
|
|
$4 = 0;
|
|
|
|
}
|
|
|
|
else if ($4 == tANDOP) {
|
|
|
|
$4 = 1;
|
|
|
|
}
|
|
|
|
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$1 = dispatch3(field, $1, ripper_intern("::"), $3);
|
|
|
|
$$ = dispatch3(opassign, $1, $4, $5);
|
|
|
|
%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
2003-03-03 00:17:39 -05:00
|
|
|
| primary_value tCOLON2 tCONSTANT tOP_ASGN arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
yyerror("constant re-assignment");
|
2003-12-23 19:38:53 -05:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(constpath_field, $1, $3);
|
|
|
|
$$ = dispatch3(opassign, $$, $4, $5);
|
|
|
|
$$ = dispatch1(assign_error, $$);
|
|
|
|
%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
}
|
2003-08-14 13:20:14 -04:00
|
|
|
| tCOLON3 tCONSTANT tOP_ASGN arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-08-14 13:20:14 -04:00
|
|
|
yyerror("constant re-assignment");
|
2003-12-23 19:38:53 -05:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(topconst_field, $2);
|
|
|
|
$$ = dispatch3(opassign, $$, $3, $4);
|
|
|
|
$$ = dispatch1(assign_error, $$);
|
|
|
|
%*/
|
2003-08-14 13:20:14 -04:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| backref tOP_ASGN arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_backref_error($1);
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(var_field, $1);
|
|
|
|
$$ = dispatch3(opassign, $$, $2, $3);
|
|
|
|
$$ = dispatch1(assign_error, $$);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tDOT2 arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-12 05:22:20 -04:00
|
|
|
value_expr($1);
|
|
|
|
value_expr($3);
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_DOT2($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(dot2, $1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tDOT3 arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-12 05:22:20 -04:00
|
|
|
value_expr($1);
|
|
|
|
value_expr($3);
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_DOT3($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(dot3, $1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '+' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '+', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('+'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '-' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '-', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('-'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '*' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '*', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('*'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '/' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '/', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('/'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '%' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '%', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('%'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tPOW arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = call_op($1, tPOW, 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("**"), $3);
|
|
|
|
%*/
|
2003-01-22 22:39:25 -05:00
|
|
|
}
|
|
|
|
| tUMINUS_NUM tINTEGER tPOW arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-01-23 01:50:10 -05:00
|
|
|
$$ = call_op(call_op($2, tPOW, 1, $4), tUMINUS, 0, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $2, ripper_intern("**"), $4);
|
|
|
|
$$ = dispatch2(unary, ripper_intern("-@"), $$);
|
|
|
|
%*/
|
2003-01-22 22:39:25 -05:00
|
|
|
}
|
|
|
|
| tUMINUS_NUM tFLOAT tPOW arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-01-23 01:50:10 -05:00
|
|
|
$$ = call_op(call_op($2, tPOW, 1, $4), tUMINUS, 0, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $2, ripper_intern("**"), $4);
|
|
|
|
$$ = dispatch2(unary, ripper_intern("-@"), $$);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| tUPLUS arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-01-04 23:41:21 -05:00
|
|
|
if ($2 && nd_type($2) == NODE_LIT) {
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
else {
|
1999-12-14 01:50:43 -05:00
|
|
|
$$ = call_op($2, tUPLUS, 0, 0);
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unary, ripper_intern("+@"), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| tUMINUS arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-01-22 22:39:25 -05:00
|
|
|
$$ = call_op($2, tUMINUS, 0, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unary, ripper_intern("-@"), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '|' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '|', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('!'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '^' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '^', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('^'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '&' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '&', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('&'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tCMP arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = call_op($1, tCMP, 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("<=>"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '>' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '>', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('>'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tGEQ arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = call_op($1, tGEQ, 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern(">="), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| arg '<' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = call_op($1, '<', 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ID2SYM('<'), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tLEQ arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = call_op($1, tLEQ, 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("<="), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tEQ arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = call_op($1, tEQ, 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("=="), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tEQQ arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = call_op($1, tEQQ, 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("==="), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tNEQ arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_NOT(call_op($1, tEQ, 1, $3));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("!="), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tMATCH arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-09-17 05:24:13 -04:00
|
|
|
$$ = match_op($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("=~"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tNMATCH arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-09-17 05:24:13 -04:00
|
|
|
$$ = NEW_NOT(match_op($1, $3));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("!~"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| '!' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_NOT(cond($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unary, ID2SYM('!'), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| '~' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-12-14 01:50:43 -05:00
|
|
|
$$ = call_op($2, '~', 0, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unary, ID2SYM('~'), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tLSHFT arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = call_op($1, tLSHFT, 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("<<"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tRSHFT arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = call_op($1, tRSHFT, 1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern(">>"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tANDOP arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = logop(NODE_AND, $1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("&&"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg tOROP arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = logop(NODE_OR, $1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(binary, $1, ripper_intern("||"), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| kDEFINED opt_nl {in_defined = 1;} arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
in_defined = 0;
|
|
|
|
$$ = NEW_DEFINED($4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
in_defined = 0;
|
|
|
|
$$ = dispatch1(defined, $4);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| arg '?' arg ':' arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_IF(cond($1), $3, $5);
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(ifop, $1, $3, $5);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
| primary
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-02-18 04:52:48 -05:00
|
|
|
arg_value : arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-02-18 04:52:48 -05:00
|
|
|
value_expr($1);
|
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
2002-02-18 04:52:48 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2002-02-18 04:52:48 -05:00
|
|
|
|
2000-07-03 01:46:36 -04:00
|
|
|
aref_args : none
|
2001-05-07 05:26:29 -04:00
|
|
|
| command opt_nl
|
2000-07-21 04:45:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-28 10:42:46 -04:00
|
|
|
rb_warn("parenthesize argument(s) for future version");
|
2000-07-21 04:45:34 -04:00
|
|
|
$$ = NEW_LIST($1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
rb_warn0("parenthesize argument(s) for future version");
|
|
|
|
$$ = arg_add(arg_new(), $1);
|
|
|
|
%*/
|
2000-07-21 04:45:34 -04:00
|
|
|
}
|
2000-09-04 04:24:09 -04:00
|
|
|
| args trailer
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
}
|
2000-07-03 01:46:36 -04:00
|
|
|
| args ',' tSTAR arg opt_nl
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-07-03 01:46:36 -04:00
|
|
|
value_expr($4);
|
|
|
|
$$ = arg_concat($1, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star($1, $4);
|
|
|
|
%*/
|
2000-07-03 01:46:36 -04:00
|
|
|
}
|
2000-09-04 04:24:09 -04:00
|
|
|
| assocs trailer
|
2000-07-06 23:20:53 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-07-06 23:20:53 -04:00
|
|
|
$$ = NEW_LIST(NEW_HASH($1));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_assocs(arg_new(), $1);
|
|
|
|
%*/
|
2000-07-06 23:20:53 -04:00
|
|
|
}
|
2000-07-03 01:46:36 -04:00
|
|
|
| tSTAR arg opt_nl
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-07-03 01:46:36 -04:00
|
|
|
value_expr($2);
|
2004-04-23 01:52:18 -04:00
|
|
|
$$ = newline_node(NEW_SPLAT($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star(arg_new(), $2);
|
|
|
|
%*/
|
2000-07-03 01:46:36 -04:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2001-01-23 03:08:59 -05:00
|
|
|
paren_args : '(' none ')'
|
2000-09-01 05:18:11 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(arg_paren, arg_new());
|
|
|
|
%*/
|
2000-09-01 05:18:11 -04:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| '(' call_args rparen
|
2000-09-04 04:24:09 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(arg_paren, $2);
|
|
|
|
%*/
|
2000-09-04 04:24:09 -04:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| '(' block_call rparen
|
2001-01-23 03:08:59 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-28 10:42:46 -04:00
|
|
|
rb_warn("parenthesize argument for future version");
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = NEW_LIST($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
rb_warn0("parenthesize argument for future version");
|
|
|
|
$$ = arg_add(arg_new(), $2);
|
|
|
|
%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| '(' args ',' block_call rparen
|
2001-01-23 03:08:59 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-28 10:42:46 -04:00
|
|
|
rb_warn("parenthesize argument for future version");
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = list_append($2, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
rb_warn0("parenthesize argument for future version");
|
|
|
|
$$ = dispatch1(arg_paren, arg_add(arg_new(), $4));
|
|
|
|
%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2001-01-23 03:08:59 -05:00
|
|
|
|
|
|
|
opt_paren_args : none
|
|
|
|
| paren_args
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2001-01-20 09:02:28 -05:00
|
|
|
call_args : command
|
2000-07-01 02:51:28 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-28 10:42:46 -04:00
|
|
|
rb_warn("parenthesize argument(s) for future version");
|
2000-07-01 02:51:28 -04:00
|
|
|
$$ = NEW_LIST($1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
rb_warn0("parenthesize argument(s) for future version");
|
|
|
|
$$ = arg_add(arg_new(), $1);
|
|
|
|
%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| args opt_block_arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = arg_blk_pass($1, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_optblock($1, $2);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| args ',' tSTAR arg_value opt_block_arg
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = arg_concat($1, $4);
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = arg_blk_pass($$, $5);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
arg_add_optblock(arg_add_star($1, $4), $5);
|
|
|
|
%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| assocs opt_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_LIST(NEW_HASH($1));
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = arg_blk_pass($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_assocs(arg_new(), $1);
|
|
|
|
$$ = arg_add_optblock($$, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| assocs ',' tSTAR arg_value opt_block_arg
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = arg_blk_pass($$, $5);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star(arg_add_assocs(arg_new(), $1), $4);
|
|
|
|
$$ = arg_add_optblock($$, $5);
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| args ',' assocs opt_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = list_append($1, NEW_HASH($3));
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = arg_blk_pass($$, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_optblock(arg_add_assocs($1, $3), $4);
|
|
|
|
%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| args ',' assocs ',' tSTAR arg opt_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-07-03 01:46:36 -04:00
|
|
|
value_expr($6);
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = arg_concat(list_append($1, NEW_HASH($3)), $6);
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = arg_blk_pass($$, $7);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star(arg_add_assocs($1, $3), $6);
|
|
|
|
$$ = arg_add_optblock($$, $7);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| tSTAR arg_value opt_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-08-27 15:43:50 -04:00
|
|
|
$$ = arg_blk_pass(NEW_SPLAT($2), $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_optblock(arg_add_star(arg_new(), $2), $3);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
| block_arg
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{
|
|
|
|
$$ = arg_add_block(arg_new(), $1);
|
|
|
|
}
|
|
|
|
%*/
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2002-02-18 04:52:48 -05:00
|
|
|
call_args2 : arg_value ',' args opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-06-01 03:52:34 -04:00
|
|
|
$$ = arg_blk_pass(list_concat(NEW_LIST($1),$3), $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_optblock(arg_prepend($3, $1), $4);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| arg_value ',' block_arg
|
2001-11-21 10:42:12 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-11-21 10:42:12 -05:00
|
|
|
$$ = arg_blk_pass($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_block(arg_add(arg_new(), $1), $3);
|
|
|
|
%*/
|
2001-11-21 10:42:12 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| arg_value ',' tSTAR arg_value opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = arg_concat(NEW_LIST($1), $4);
|
|
|
|
$$ = arg_blk_pass($$, $5);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star(arg_add(arg_new(), $1), $4);
|
|
|
|
$$ = arg_add_optblock($$, $5);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| arg_value ',' args ',' tSTAR arg_value opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
|
|
|
$$ = arg_concat(list_concat(NEW_LIST($1),$3), $6);
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = arg_blk_pass($$, $7);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star(arg_prepend($3, $1), $6);
|
|
|
|
$$ = arg_add_optblock($$, $7);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
|
|
|
| assocs opt_block_arg
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = NEW_LIST(NEW_HASH($1));
|
|
|
|
$$ = arg_blk_pass($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_optblock(arg_add_assocs(arg_new(), $1), $2);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| assocs ',' tSTAR arg_value opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
|
|
|
|
$$ = arg_blk_pass($$, $5);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star(arg_add_assocs(arg_new(), $1), $4);
|
|
|
|
$$ = arg_add_optblock($$, $4);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| arg_value ',' assocs opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = list_append(NEW_LIST($1), NEW_HASH($3));
|
|
|
|
$$ = arg_blk_pass($$, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_assocs(arg_add(arg_new(), $1), $3);
|
|
|
|
$$ = arg_add_optblock($$, $4);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| arg_value ',' args ',' assocs opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-01-28 03:44:45 -05:00
|
|
|
$$ = list_append(list_concat(NEW_LIST($1),$3), NEW_HASH($5));
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = arg_blk_pass($$, $6);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_assocs(arg_prepend($3, $1), $5);
|
|
|
|
$$ = arg_add_optblock($$, $6);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| arg_value ',' assocs ',' tSTAR arg_value opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = arg_concat(list_append(NEW_LIST($1), NEW_HASH($3)), $6);
|
|
|
|
$$ = arg_blk_pass($$, $7);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_assocs(arg_add(arg_new(), $1), $3);
|
|
|
|
$$ = arg_add_star($$, $6);
|
|
|
|
$$ = arg_add_optblock($$, $7);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| arg_value ',' args ',' assocs ',' tSTAR arg_value opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-06-01 03:52:34 -04:00
|
|
|
$$ = arg_concat(list_append(list_concat(NEW_LIST($1), $3), NEW_HASH($5)), $8);
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = arg_blk_pass($$, $9);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_assocs(arg_prepend($3, $1), $5);
|
|
|
|
$$ = arg_add_star($$, $8);
|
|
|
|
$$ = arg_add_optblock($$, $9);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| tSTAR arg_value opt_block_arg
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-08-27 15:43:50 -04:00
|
|
|
$$ = arg_blk_pass(NEW_SPLAT($2), $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_optblock(arg_add_star(arg_new(), $2), $3);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
|
|
|
| block_arg
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2001-05-30 05:12:34 -04:00
|
|
|
|
|
|
|
command_args : {
|
|
|
|
$<num>$ = cmdarg_stack;
|
|
|
|
CMDARG_PUSH(1);
|
|
|
|
}
|
|
|
|
open_args
|
|
|
|
{
|
|
|
|
/* CMDARG_POP() */
|
|
|
|
cmdarg_stack = $<num>1;
|
|
|
|
$$ = $2;
|
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2001-05-30 05:12:34 -04:00
|
|
|
|
|
|
|
open_args : call_args
|
2004-02-12 01:23:24 -05:00
|
|
|
| tLPAREN_ARG {lex_state = EXPR_ENDARG;} rparen
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-04-26 10:59:19 -04:00
|
|
|
rb_warn("don't put space before argument parentheses");
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(space, dispatch1(arg_paren, arg_new()));
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} rparen
|
2001-01-26 00:02:19 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-04-26 10:59:19 -04:00
|
|
|
rb_warn("don't put space before argument parentheses");
|
2001-01-26 00:02:19 -05:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(space, dispatch1(arg_paren, $2));
|
|
|
|
%*/
|
2001-01-26 00:02:19 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2001-01-26 00:02:19 -05:00
|
|
|
|
2002-02-18 04:52:48 -05:00
|
|
|
block_arg : tAMPER arg_value
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_BLOCK_PASS($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $2;
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
|
|
|
opt_block_arg : ',' block_arg
|
|
|
|
{
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = $2;
|
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
| none
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-02-18 04:52:48 -05:00
|
|
|
args : arg_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_LIST($1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add(arg_new(), $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| args ',' arg_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = list_append($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add($1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-12-31 22:24:29 -05:00
|
|
|
mrhs : args ',' arg_value
|
2000-12-05 04:36:54 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-12-05 04:36:54 -05:00
|
|
|
$$ = list_append($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mrhs_add(args2mrhs($1), $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| args ',' tSTAR arg_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = arg_concat($1, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mrhs_add_star(args2mrhs($1), $4);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| tSTAR arg_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-03-26 02:01:14 -05:00
|
|
|
$$ = NEW_SPLAT($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mrhs_add_star(mrhs_new(), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
primary : literal
|
2002-06-24 03:20:42 -04:00
|
|
|
| strings
|
|
|
|
| xstring
|
|
|
|
| regexp
|
2002-06-26 04:01:00 -04:00
|
|
|
| words
|
|
|
|
| qwords
|
1998-01-16 07:13:05 -05:00
|
|
|
| var_ref
|
|
|
|
| backref
|
2000-01-31 22:12:21 -05:00
|
|
|
| tFID
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-07-18 01:29:46 -04:00
|
|
|
$$ = NEW_FCALL($1, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = method_arg(dispatch1(fcall, $1), arg_new());
|
|
|
|
%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
|
|
|
| kBEGIN
|
2002-11-14 08:51:19 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-11-14 08:51:19 -05:00
|
|
|
$<num>1 = ruby_sourceline;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
%*/
|
2002-11-14 08:51:19 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
bodystmt
|
2000-01-31 22:12:21 -05:00
|
|
|
kEND
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-06-29 22:39:38 -04:00
|
|
|
if ($3 == NULL)
|
|
|
|
$$ = NEW_NIL();
|
|
|
|
else
|
|
|
|
$$ = NEW_BEGIN($3);
|
2002-11-14 08:51:19 -05:00
|
|
|
nd_set_line($$, $<num>1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(begin, $3);
|
|
|
|
%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} rparen
|
2001-05-30 05:12:34 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-12 05:22:20 -04:00
|
|
|
rb_warning("(...) interpreted as grouped expression");
|
2001-05-30 05:12:34 -04:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
rb_warning0("(...) interpreted as grouped expression");
|
|
|
|
$$ = dispatch1(paren, $2);
|
|
|
|
%*/
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2000-01-31 22:12:21 -05:00
|
|
|
| tLPAREN compstmt ')'
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-07 04:44:24 -04:00
|
|
|
if (!$2) $$ = NEW_NIL();
|
|
|
|
else $$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(paren, $2);
|
|
|
|
%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value tCOLON2 tCONSTANT
|
2000-01-31 22:12:21 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
$$ = NEW_COLON2($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(constpath_ref, $1, $3);
|
|
|
|
%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
2003-08-14 13:20:14 -04:00
|
|
|
| tCOLON3 tCONSTANT
|
2000-01-31 22:12:21 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
$$ = NEW_COLON3($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(topconst_ref, $2);
|
|
|
|
%*/
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '[' aref_args ']'
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-11-09 10:07:14 -05:00
|
|
|
if ($1 && nd_type($1) == NODE_SELF)
|
2003-02-19 22:35:44 -05:00
|
|
|
$$ = NEW_FCALL(tAREF, $3);
|
|
|
|
else
|
|
|
|
$$ = NEW_CALL($1, tAREF, $3);
|
2004-01-12 09:27:22 -05:00
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(aref, $1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-09-12 01:37:38 -04:00
|
|
|
| tLBRACK aref_args ']'
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-06-07 04:29:59 -04:00
|
|
|
if ($2 == 0) {
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_ZARRAY(); /* zero length array*/
|
2001-06-07 04:29:59 -04:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
else {
|
|
|
|
$$ = $2;
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(array, escape_Qundef($2));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| tLBRACE assoc_list '}'
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_HASH($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(hash, escape_Qundef($2));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| kRETURN
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_RETURN(0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(return0);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| kYIELD '(' call_args rparen
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-06-20 03:11:44 -04:00
|
|
|
$$ = new_yield($3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(yield, dispatch1(paren, $3));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| kYIELD '(' rparen
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-06-20 03:11:44 -04:00
|
|
|
$$ = NEW_YIELD(0, Qfalse);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(yield, dispatch1(paren, arg_new()));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| kYIELD
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-06-20 03:11:44 -04:00
|
|
|
$$ = NEW_YIELD(0, Qfalse);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(yield0);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| kDEFINED opt_nl '(' {in_defined = 1;} expr rparen
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
in_defined = 0;
|
|
|
|
$$ = NEW_DEFINED($5);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
in_defined = 0;
|
|
|
|
$$ = dispatch1(defined, $5);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
| operation brace_block
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$2->nd_iter = NEW_FCALL($1, 0);
|
|
|
|
$$ = $2;
|
2004-01-12 09:27:22 -05:00
|
|
|
fixpos($2->nd_iter, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = method_arg(dispatch1(fcall, $1), arg_new());
|
|
|
|
$$ = dispatch2(iter_block, $$, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| method_call
|
1999-08-13 01:45:20 -04:00
|
|
|
| method_call brace_block
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
|
2004-09-17 05:24:13 -04:00
|
|
|
compile_error(PARSER_ARG "both block arg and actual block given");
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
$2->nd_iter = $1;
|
|
|
|
$$ = $2;
|
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(iter_block, $1, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| kIF expr_value then
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
1998-01-16 07:13:05 -05:00
|
|
|
if_tail
|
1998-01-16 07:19:22 -05:00
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_IF(cond($2), $4, $5);
|
|
|
|
fixpos($$, $2);
|
2003-03-20 02:03:22 -05:00
|
|
|
if (cond_negative(&$$->nd_cond)) {
|
2003-01-09 01:16:43 -05:00
|
|
|
NODE *tmp = $$->nd_body;
|
|
|
|
$$->nd_body = $$->nd_else;
|
|
|
|
$$->nd_else = tmp;
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(if, $2, $4, escape_Qundef($5));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| kUNLESS expr_value then
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
1998-01-16 07:13:05 -05:00
|
|
|
opt_else
|
1998-01-16 07:19:22 -05:00
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_UNLESS(cond($2), $4, $5);
|
|
|
|
fixpos($$, $2);
|
2003-03-20 02:03:22 -05:00
|
|
|
if (cond_negative(&$$->nd_cond)) {
|
2003-01-09 01:16:43 -05:00
|
|
|
NODE *tmp = $$->nd_body;
|
|
|
|
$$->nd_body = $$->nd_else;
|
|
|
|
$$->nd_else = tmp;
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(unless, $2, $4, escape_Qundef($5));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| kWHILE {COND_PUSH(1);} expr_value do {COND_POP();}
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = NEW_WHILE(cond($3), $6, 1);
|
|
|
|
fixpos($$, $3);
|
2003-03-20 02:03:22 -05:00
|
|
|
if (cond_negative(&$$->nd_cond)) {
|
2003-01-09 01:16:43 -05:00
|
|
|
nd_set_type($$, NODE_UNTIL);
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(while, $3, $6);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| kUNTIL {COND_PUSH(1);} expr_value do {COND_POP();}
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = NEW_UNTIL(cond($3), $6, 1);
|
|
|
|
fixpos($$, $3);
|
2003-03-20 02:03:22 -05:00
|
|
|
if (cond_negative(&$$->nd_cond)) {
|
2003-01-09 01:16:43 -05:00
|
|
|
nd_set_type($$, NODE_WHILE);
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(until, $3, $6);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| kCASE expr_value opt_terms
|
1998-01-16 07:13:05 -05:00
|
|
|
case_body
|
1998-01-16 07:19:22 -05:00
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-12-18 04:46:21 -05:00
|
|
|
$$ = NEW_CASE($2, $4);
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(case, $2, $4);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-01-13 00:48:59 -05:00
|
|
|
| kCASE expr_value opt_terms kELSE compstmt kEND
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-01-13 00:48:59 -05:00
|
|
|
$$ = block_append($2, $5);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(case, $2, dispatch1(else, $5));
|
|
|
|
%*/
|
2004-01-13 00:48:59 -05:00
|
|
|
}
|
2000-12-18 04:46:21 -05:00
|
|
|
| kCASE opt_terms case_body kEND
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-12-18 04:46:21 -05:00
|
|
|
$$ = $3;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(case, Qnil, $3);
|
|
|
|
%*/
|
2000-12-18 04:46:21 -05:00
|
|
|
}
|
2002-11-07 14:18:16 -05:00
|
|
|
| kCASE opt_terms kELSE compstmt kEND
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-11-07 14:18:16 -05:00
|
|
|
$$ = $4;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(case, Qnil, dispatch1(else, $4));
|
|
|
|
%*/
|
2002-11-07 14:18:16 -05:00
|
|
|
}
|
2004-05-24 22:54:22 -04:00
|
|
|
| kFOR for_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = NEW_FOR($2, $5, $8);
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(for, $2, $5, $8);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-02-19 04:27:49 -05:00
|
|
|
| kCLASS cpath superclass
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-02-13 00:09:11 -05:00
|
|
|
if (in_def || in_single)
|
1998-01-16 07:13:05 -05:00
|
|
|
yyerror("class definition in method body");
|
|
|
|
class_nest++;
|
2002-03-19 04:03:11 -05:00
|
|
|
local_push(0);
|
2000-09-22 14:15:52 -04:00
|
|
|
$<num>$ = ruby_sourceline;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
if (in_def || in_single)
|
|
|
|
yyerror("class definition in method body");
|
|
|
|
class_nest++;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
bodystmt
|
1998-01-16 07:19:22 -05:00
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_CLASS($2, $5, $3);
|
2000-09-22 14:15:52 -04:00
|
|
|
nd_set_line($$, $<num>4);
|
1998-01-16 07:13:05 -05:00
|
|
|
local_pop();
|
|
|
|
class_nest--;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(class, $2, $3, $5);
|
|
|
|
class_nest--;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-02-26 00:29:06 -05:00
|
|
|
| kCLASS tLSHFT expr
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-02-26 00:29:06 -05:00
|
|
|
$<num>$ = in_def;
|
|
|
|
in_def = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
in_def = 0;
|
|
|
|
%*/
|
2001-02-26 00:29:06 -05:00
|
|
|
}
|
|
|
|
term
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-02-13 00:09:11 -05:00
|
|
|
$<num>$ = in_single;
|
|
|
|
in_single = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
class_nest++;
|
2002-03-19 04:03:11 -05:00
|
|
|
local_push(0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = in_single;
|
|
|
|
in_single = 0;
|
|
|
|
class_nest++;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
bodystmt
|
1998-01-16 07:19:22 -05:00
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-02-13 00:09:11 -05:00
|
|
|
$$ = NEW_SCLASS($3, $7);
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $3);
|
|
|
|
local_pop();
|
|
|
|
class_nest--;
|
2001-02-26 00:29:06 -05:00
|
|
|
in_def = $<num>4;
|
|
|
|
in_single = $<num>6;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(sclass, $3, $7);
|
|
|
|
class_nest--;
|
|
|
|
in_def = $<val>4;
|
|
|
|
in_single = $<val>6;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-02-19 04:27:49 -05:00
|
|
|
| kMODULE cpath
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-02-13 00:09:11 -05:00
|
|
|
if (in_def || in_single)
|
1998-01-16 07:13:05 -05:00
|
|
|
yyerror("module definition in method body");
|
|
|
|
class_nest++;
|
2002-03-19 04:03:11 -05:00
|
|
|
local_push(0);
|
2000-09-22 14:15:52 -04:00
|
|
|
$<num>$ = ruby_sourceline;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
if (in_def || in_single)
|
|
|
|
yyerror("module definition in method body");
|
|
|
|
class_nest++;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
bodystmt
|
1998-01-16 07:19:22 -05:00
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_MODULE($2, $4);
|
2000-09-22 14:15:52 -04:00
|
|
|
nd_set_line($$, $<num>3);
|
1998-01-16 07:13:05 -05:00
|
|
|
local_pop();
|
|
|
|
class_nest--;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(module, $2, $4);
|
|
|
|
class_nest--;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
| kDEF fname
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-02-13 00:09:11 -05:00
|
|
|
$<id>$ = cur_mid;
|
1998-01-16 07:13:05 -05:00
|
|
|
cur_mid = $2;
|
2001-02-13 00:09:11 -05:00
|
|
|
in_def++;
|
2002-03-19 04:03:11 -05:00
|
|
|
local_push(0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$<id>$ = cur_mid;
|
|
|
|
cur_mid = $2;
|
|
|
|
in_def++;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
f_arglist
|
2002-03-26 01:18:51 -05:00
|
|
|
bodystmt
|
1998-01-16 07:19:22 -05:00
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-02-02 21:23:20 -05:00
|
|
|
NODE *body = remove_begin($5);
|
|
|
|
reduce_nodes(&body);
|
|
|
|
$$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $4);
|
|
|
|
local_pop();
|
2001-02-13 00:09:11 -05:00
|
|
|
in_def--;
|
|
|
|
cur_mid = $<id>3;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(def, $2, $4, $5);
|
|
|
|
class_nest--;
|
|
|
|
cur_mid = $<id>3;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| kDEF singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
in_single++;
|
2002-03-19 04:03:11 -05:00
|
|
|
local_push(0);
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_END; /* force for args */
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
in_single++;
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
f_arglist
|
2002-03-26 01:18:51 -05:00
|
|
|
bodystmt
|
1998-01-16 07:19:22 -05:00
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-02-02 21:23:20 -05:00
|
|
|
NODE *body = remove_begin($8);
|
|
|
|
reduce_nodes(&body);
|
|
|
|
$$ = NEW_DEFS($2, $5, $7, body);
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $2);
|
|
|
|
local_pop();
|
|
|
|
in_single--;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch5(defs, $2, $3, $5, $7, $8);
|
|
|
|
in_single--;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-05-22 04:28:11 -04:00
|
|
|
| kBREAK
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-22 04:28:11 -04:00
|
|
|
$$ = NEW_BREAK(0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(break, arg_new());
|
|
|
|
%*/
|
2001-05-22 04:28:11 -04:00
|
|
|
}
|
|
|
|
| kNEXT
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-22 04:28:11 -04:00
|
|
|
$$ = NEW_NEXT(0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(next, arg_new());
|
|
|
|
%*/
|
2001-05-22 04:28:11 -04:00
|
|
|
}
|
|
|
|
| kREDO
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-22 04:28:11 -04:00
|
|
|
$$ = NEW_REDO();
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(redo);
|
|
|
|
%*/
|
2001-05-22 04:28:11 -04:00
|
|
|
}
|
|
|
|
| kRETRY
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-05-22 04:28:11 -04:00
|
|
|
$$ = NEW_RETRY();
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(retry);
|
|
|
|
%*/
|
2001-05-22 04:28:11 -04:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-02-18 04:52:48 -05:00
|
|
|
primary_value : primary
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-02-18 04:52:48 -05:00
|
|
|
value_expr($1);
|
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
2002-02-18 04:52:48 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2002-02-18 04:52:48 -05:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
then : term
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{ $$ = Qnil; }
|
|
|
|
%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
| ':'
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{ $$ = Qnil; }
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
| kTHEN
|
|
|
|
| term kTHEN
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{ $$ = $2; }
|
|
|
|
%*/
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:19:22 -05:00
|
|
|
|
|
|
|
do : term
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{ $$ = Qnil; }
|
|
|
|
%*/
|
2003-03-03 00:17:39 -05:00
|
|
|
| ':'
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{ $$ = Qnil; }
|
|
|
|
%*/
|
2001-01-26 00:02:19 -05:00
|
|
|
| kDO_COND
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
if_tail : opt_else
|
2002-02-18 04:52:48 -05:00
|
|
|
| kELSIF expr_value then
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
1998-01-16 07:13:05 -05:00
|
|
|
if_tail
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_IF(cond($2), $4, $5);
|
|
|
|
fixpos($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(elsif, $2, $4, escape_Qundef($5));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
opt_else : none
|
1998-01-16 07:19:22 -05:00
|
|
|
| kELSE compstmt
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(else, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-05-24 22:54:22 -04:00
|
|
|
for_var : lhs
|
1998-01-16 07:13:05 -05:00
|
|
|
| mlhs
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-05-24 22:54:22 -04:00
|
|
|
block_par : mlhs_item
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_LIST($1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add(mlhs_new(), $1);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| block_par ',' mlhs_item
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = list_append($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = mlhs_add($1, $3);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
block_var : block_par
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
if ($1->nd_alen == 1) {
|
|
|
|
$$ = $1->nd_head;
|
|
|
|
rb_gc_force_recycle((VALUE)$1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$$ = NEW_MASGN($1, 0);
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_new($1);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| block_par ','
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_MASGN($1, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_new($1);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| block_par ',' tAMPER lhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_BLOCK_VAR($4, NEW_MASGN($1, 0));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_block(blockvar_new($1), $4);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| block_par ',' tSTAR lhs ',' tAMPER lhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_BLOCK_VAR($7, NEW_MASGN($1, $4));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_star(blockvar_new($1), $4);
|
|
|
|
$$ = blockvar_add_block($$, $7);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| block_par ',' tSTAR ',' tAMPER lhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_BLOCK_VAR($6, NEW_MASGN($1, -1));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_star(blockvar_new($1), Qnil);
|
|
|
|
$$ = blockvar_add_block($$, $6);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| block_par ',' tSTAR lhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_MASGN($1, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_star(blockvar_new($1), $4);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| block_par ',' tSTAR
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_MASGN($1, -1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_star(blockvar_new($1), Qnil);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| tSTAR lhs ',' tAMPER lhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_BLOCK_VAR($5, NEW_MASGN(0, $2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_star(blockvar_new(Qnil), $2);
|
|
|
|
$$ = blockvar_add_block($$, $5);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| tSTAR ',' tAMPER lhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_BLOCK_VAR($4, NEW_MASGN(0, -1));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
|
|
|
|
$$ = blockvar_add_block($$, $4);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| tSTAR lhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_MASGN(0, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_star(blockvar_new(Qnil), $2);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| tSTAR
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_MASGN(0, -1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_star(blockvar_new(Qnil), Qnil);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
| tAMPER lhs
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
$$ = NEW_BLOCK_VAR($2, (NODE*)1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = blockvar_add_block(blockvar_new(Qnil), $2);
|
|
|
|
%*/
|
2004-05-24 22:54:22 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
opt_block_var : none
|
1999-01-19 23:59:39 -05:00
|
|
|
| '|' /* none */ '|'
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-12-05 04:36:54 -05:00
|
|
|
$$ = (NODE*)1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(blockvar_new, mlhs_new());
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| tOROP
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-12-05 04:36:54 -05:00
|
|
|
$$ = (NODE*)1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(blockvar_new, mlhs_new());
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
| '|' block_var '|'
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(blockvar_new, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2000-10-16 05:13:20 -04:00
|
|
|
|
2001-01-26 00:02:19 -05:00
|
|
|
do_block : kDO_BLOCK
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$<vars>$ = dyna_push();
|
2002-11-14 08:51:19 -05:00
|
|
|
$<num>1 = ruby_sourceline;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*% %*/
|
|
|
|
}
|
|
|
|
opt_block_var
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
$<vars>$ = ruby_dyna_vars;
|
|
|
|
/*% %*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
|
|
|
kEND
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-06-06 07:29:20 -04:00
|
|
|
$$ = NEW_ITER($3, 0, dyna_init($5, $<vars>4));
|
2002-11-14 08:51:19 -05:00
|
|
|
nd_set_line($$, $<num>1);
|
1998-01-16 07:13:05 -05:00
|
|
|
dyna_pop($<vars>2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(do_block, escape_Qundef($3), $5);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2001-01-26 00:02:19 -05:00
|
|
|
block_call : command do_block
|
1999-08-13 01:45:20 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
|
2004-09-17 05:24:13 -04:00
|
|
|
compile_error(PARSER_ARG "both block arg and actual block given");
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
|
|
|
$2->nd_iter = $1;
|
|
|
|
$$ = $2;
|
2002-12-20 03:33:17 -05:00
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(iter_block, $1, $2);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2002-06-28 10:42:46 -04:00
|
|
|
| block_call '.' operation2 opt_paren_args
|
2001-01-20 09:02:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
|
|
|
|
$$ = method_optarg($$, $4);
|
|
|
|
%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
}
|
2002-06-28 10:42:46 -04:00
|
|
|
| block_call tCOLON2 operation2 opt_paren_args
|
2001-01-20 09:02:28 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(call, $1, ripper_intern("::"), $3);
|
|
|
|
$$ = method_optarg($$, $4);
|
|
|
|
%*/
|
2001-01-20 09:02:28 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
2001-01-23 03:08:59 -05:00
|
|
|
method_call : operation paren_args
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = new_fcall($1, $2);
|
|
|
|
fixpos($$, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = method_arg(dispatch1(fcall, $1), $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value '.' operation2 opt_paren_args
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
1999-01-19 23:59:39 -05:00
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
|
|
|
|
$$ = method_optarg($$, $4);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value tCOLON2 operation2 paren_args
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = new_call($1, $3, $4);
|
1998-01-16 07:13:05 -05:00
|
|
|
fixpos($$, $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(call, $1, ripper_id2sym('.'), $3);
|
|
|
|
$$ = method_optarg($$, $4);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| primary_value tCOLON2 operation3
|
1999-08-13 01:45:20 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = new_call($1, $3, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(call, $1, ripper_intern("::"), $3);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2001-01-23 03:08:59 -05:00
|
|
|
| kSUPER paren_args
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-23 03:08:59 -05:00
|
|
|
$$ = new_super($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(super, $2);
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
| kSUPER
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
$$ = NEW_ZSUPER();
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(zsuper);
|
|
|
|
%*/
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2001-01-26 00:02:19 -05:00
|
|
|
brace_block : '{'
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-26 00:02:19 -05:00
|
|
|
$<vars>$ = dyna_push();
|
2002-11-14 08:51:19 -05:00
|
|
|
$<num>1 = ruby_sourceline;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*% %*/
|
|
|
|
}
|
|
|
|
opt_block_var
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
$<vars>$ = ruby_dyna_vars;
|
|
|
|
/*%
|
|
|
|
%*/
|
2001-01-26 00:02:19 -05:00
|
|
|
}
|
|
|
|
compstmt '}'
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-06-06 07:29:20 -04:00
|
|
|
$$ = NEW_ITER($3, 0, dyna_init($5, $<vars>4));
|
2002-11-14 08:51:19 -05:00
|
|
|
nd_set_line($$, $<num>1);
|
2001-01-26 00:02:19 -05:00
|
|
|
dyna_pop($<vars>2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(brace_block, escape_Qundef($3), $5);
|
|
|
|
%*/
|
2001-01-26 00:02:19 -05:00
|
|
|
}
|
|
|
|
| kDO
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2001-01-26 00:02:19 -05:00
|
|
|
$<vars>$ = dyna_push();
|
2002-11-14 08:51:19 -05:00
|
|
|
$<num>1 = ruby_sourceline;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*% %*/
|
|
|
|
}
|
|
|
|
opt_block_var
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
$<vars>$ = ruby_dyna_vars;
|
|
|
|
/*%
|
|
|
|
%*/
|
2001-01-26 00:02:19 -05:00
|
|
|
}
|
|
|
|
compstmt kEND
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-06-06 07:29:20 -04:00
|
|
|
$$ = NEW_ITER($3, 0, dyna_init($5, $<vars>4));
|
2002-11-14 08:51:19 -05:00
|
|
|
nd_set_line($$, $<num>1);
|
2001-01-26 00:02:19 -05:00
|
|
|
dyna_pop($<vars>2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(do_block, escape_Qundef($3), $5);
|
|
|
|
%*/
|
2001-01-26 00:02:19 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2001-01-26 00:02:19 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
case_body : kWHEN when_args then
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
1998-01-16 07:13:05 -05:00
|
|
|
cases
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_WHEN($2, $4, $5);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch3(when, $2, $4, escape_Qundef($5));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
when_args : args
|
2002-02-18 04:52:48 -05:00
|
|
|
| args ',' tSTAR arg_value
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = list_append($1, NEW_WHEN($4, 0, 0));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star($1, $4);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
| tSTAR arg_value
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_LIST(NEW_WHEN($2, 0, 0));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = arg_add_star(arg_new(), $2);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
cases : opt_else
|
|
|
|
| case_body
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-03-26 01:18:51 -05:00
|
|
|
opt_rescue : kRESCUE exc_list exc_var then
|
1998-01-16 07:19:22 -05:00
|
|
|
compstmt
|
2002-03-26 01:18:51 -05:00
|
|
|
opt_rescue
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-09-04 04:24:09 -04:00
|
|
|
if ($3) {
|
2004-01-22 03:31:33 -05:00
|
|
|
$3 = node_assign($3, NEW_ERRINFO());
|
2000-03-23 03:37:35 -05:00
|
|
|
$5 = block_append($3, $5);
|
|
|
|
}
|
|
|
|
$$ = NEW_RESBODY($2, $5, $6);
|
|
|
|
fixpos($$, $2?$2:$5);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(rescue,
|
|
|
|
escape_Qundef($2),
|
|
|
|
escape_Qundef($3),
|
|
|
|
escape_Qundef($5),
|
|
|
|
escape_Qundef($6));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
| none
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2003-12-04 02:41:20 -05:00
|
|
|
exc_list : arg_value
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-12-04 02:41:20 -05:00
|
|
|
$$ = NEW_LIST($1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = rb_ary_new3(1, $1);
|
|
|
|
%*/
|
2003-12-04 02:41:20 -05:00
|
|
|
}
|
|
|
|
| mrhs
|
2002-03-26 01:18:51 -05:00
|
|
|
| none
|
|
|
|
;
|
|
|
|
|
|
|
|
exc_var : tASSOC lhs
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
| none
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_ensure : kENSURE compstmt
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-10-02 07:34:13 -04:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(ensure, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
| none
|
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
literal : numeric
|
1999-08-13 01:45:20 -04:00
|
|
|
| symbol
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-09-05 21:24:41 -04:00
|
|
|
$$ = NEW_LIT(ID2SYM($1));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(symbol_literal, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-10-23 06:17:30 -04:00
|
|
|
| dsym
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
strings : string
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
NODE *node = $1;
|
|
|
|
if (!node) {
|
|
|
|
node = NEW_STR(rb_str_new(0, 0));
|
|
|
|
}
|
2003-05-21 12:01:49 -04:00
|
|
|
else {
|
|
|
|
node = evstr2dstr(node);
|
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
$$ = node;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
2002-06-24 03:59:02 -04:00
|
|
|
;
|
2002-06-24 03:20:42 -04:00
|
|
|
|
|
|
|
string : string1
|
|
|
|
| string string1
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
$$ = literal_concat($1, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(string_concat, $1, $2);
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
2002-06-25 05:56:36 -04:00
|
|
|
string1 : tSTRING_BEG string_contents tSTRING_END
|
1999-10-15 04:52:18 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-25 05:56:36 -04:00
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(string_literal, $2);
|
|
|
|
%*/
|
1999-10-15 04:52:18 -04:00
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
;
|
|
|
|
|
2002-06-25 05:56:36 -04:00
|
|
|
xstring : tXSTRING_BEG xstring_contents tSTRING_END
|
1999-10-15 04:52:18 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-25 05:56:36 -04:00
|
|
|
NODE *node = $2;
|
2002-06-24 03:20:42 -04:00
|
|
|
if (!node) {
|
|
|
|
node = NEW_XSTR(rb_str_new(0, 0));
|
1999-10-15 04:52:18 -04:00
|
|
|
}
|
|
|
|
else {
|
2002-06-24 03:20:42 -04:00
|
|
|
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:
|
2003-07-04 11:30:35 -04:00
|
|
|
node = NEW_NODE(NODE_DXSTR, rb_str_new(0, 0), 1, NEW_LIST(node));
|
2002-06-24 03:20:42 -04:00
|
|
|
break;
|
|
|
|
}
|
1999-10-15 04:52:18 -04:00
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
$$ = node;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(xstring_literal, $2);
|
|
|
|
%*/
|
1999-10-15 04:52:18 -04:00
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
;
|
|
|
|
|
2002-06-25 05:56:36 -04:00
|
|
|
regexp : tREGEXP_BEG xstring_contents tREGEXP_END
|
1999-10-15 04:52:18 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-25 05:56:36 -04:00
|
|
|
int options = $3;
|
|
|
|
NODE *node = $2;
|
2002-06-24 03:20:42 -04:00
|
|
|
if (!node) {
|
2004-09-24 01:53:43 -04:00
|
|
|
node = NEW_LIT(rb_reg_compile("", 0, options & ~RE_OPTION_ONCE));
|
1999-10-15 04:52:18 -04:00
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
else switch (nd_type(node)) {
|
|
|
|
case NODE_STR:
|
|
|
|
{
|
|
|
|
VALUE src = node->nd_lit;
|
|
|
|
nd_set_type(node, NODE_LIT);
|
2004-09-24 01:53:43 -04:00
|
|
|
node->nd_lit = rb_reg_compile(RSTRING(src)->ptr,
|
|
|
|
RSTRING(src)->len,
|
|
|
|
options & ~RE_OPTION_ONCE);
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2003-07-04 11:30:35 -04:00
|
|
|
node = NEW_NODE(NODE_DSTR, rb_str_new(0, 0), 1, NEW_LIST(node));
|
2002-06-24 03:20:42 -04:00
|
|
|
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_ONCE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
$$ = node;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(regexp_literal, $2);
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
2002-06-26 04:01:00 -04:00
|
|
|
words : tWORDS_BEG ' ' tSTRING_END
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
$$ = NEW_ZARRAY();
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(words_new);
|
|
|
|
%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
}
|
|
|
|
| tWORDS_BEG word_list tSTRING_END
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
word_list : /* none */
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(words_new);
|
|
|
|
%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
}
|
|
|
|
| word_list word ' '
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-05-21 12:01:49 -04:00
|
|
|
$$ = list_append($1, evstr2dstr($2));
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(words_add, $1, $2);
|
|
|
|
%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
word : string_content
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{
|
|
|
|
$$ = dispatch0(word_new);
|
|
|
|
$$ = dispatch2(word_add, $$, $1);
|
|
|
|
}
|
|
|
|
%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
| word string_content
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
$$ = literal_concat($1, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(word_add, $1, $2);
|
|
|
|
%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
}
|
2002-06-27 13:16:39 -04:00
|
|
|
;
|
2002-06-26 04:01:00 -04:00
|
|
|
|
|
|
|
qwords : tQWORDS_BEG ' ' tSTRING_END
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
$$ = NEW_ZARRAY();
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(qwords_new);
|
|
|
|
%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
}
|
|
|
|
| tQWORDS_BEG qword_list tSTRING_END
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
qword_list : /* none */
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(qwords_new);
|
|
|
|
%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
}
|
|
|
|
| qword_list tSTRING_CONTENT ' '
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-09-05 21:24:41 -04:00
|
|
|
$$ = list_append($1, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(qwords_add, $1, $2);
|
|
|
|
%*/
|
2002-06-26 04:01:00 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
string_contents : /* none */
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(string_content);
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
| string_contents string_content
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
$$ = literal_concat($1, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(string_add, $1, $2);
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
xstring_contents: /* none */
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch0(xstring_new);
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
| xstring_contents string_content
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-09-20 10:03:45 -04:00
|
|
|
$$ = literal_concat($1, $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(xstring_add, $1, $2);
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
2002-09-05 21:24:41 -04:00
|
|
|
string_content : tSTRING_CONTENT
|
2002-06-24 03:20:42 -04:00
|
|
|
| tSTRING_DVAR
|
|
|
|
{
|
|
|
|
$<node>$ = lex_strterm;
|
|
|
|
lex_strterm = 0;
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
}
|
|
|
|
string_dvar
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
lex_strterm = $<node>2;
|
2002-07-26 02:12:39 -04:00
|
|
|
$$ = NEW_EVSTR($3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
lex_strterm = $<node>2;
|
|
|
|
$$ = dispatch1(string_dvar, $3);
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
2003-09-17 07:34:02 -04:00
|
|
|
| tSTRING_DBEG
|
2002-06-24 03:20:42 -04:00
|
|
|
{
|
|
|
|
$<node>$ = lex_strterm;
|
|
|
|
lex_strterm = 0;
|
|
|
|
lex_state = EXPR_BEG;
|
2004-01-22 02:21:40 -05:00
|
|
|
COND_PUSH(0);
|
|
|
|
CMDARG_PUSH(0);
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
compstmt '}'
|
|
|
|
{
|
2003-09-17 07:34:02 -04:00
|
|
|
lex_strterm = $<node>2;
|
2004-01-22 02:21:40 -05:00
|
|
|
COND_LEXPOP();
|
|
|
|
CMDARG_LEXPOP();
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
|
|
|
FL_UNSET($3, NODE_NEWLINE);
|
2004-01-21 11:47:23 -05:00
|
|
|
$$ = new_evstr($3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(string_embexpr, $3);
|
|
|
|
%*/
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
string_dvar : tGVAR
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
$$ = NEW_GVAR($1);
|
|
|
|
/*%
|
|
|
|
$$ = dispatch1(var_ref, $1);
|
|
|
|
%*/
|
|
|
|
}
|
|
|
|
| tIVAR
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
$$ = NEW_IVAR($1);
|
|
|
|
/*%
|
|
|
|
$$ = dispatch1(var_ref, $1);
|
|
|
|
%*/
|
|
|
|
}
|
|
|
|
| tCVAR
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
$$ = NEW_CVAR($1);
|
|
|
|
/*%
|
|
|
|
$$ = dispatch1(var_ref, $1);
|
|
|
|
%*/
|
|
|
|
}
|
2002-06-24 11:18:00 -04:00
|
|
|
| backref
|
2002-06-24 03:20:42 -04:00
|
|
|
;
|
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
symbol : tSYMBEG sym
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
lex_state = EXPR_END;
|
|
|
|
$$ = $2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
$$ = dispatch1(symbol, $2);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
|
|
|
sym : fname
|
1999-01-19 23:59:39 -05:00
|
|
|
| tIVAR
|
|
|
|
| tGVAR
|
2000-10-16 05:13:20 -04:00
|
|
|
| tCVAR
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
2002-10-23 06:17:30 -04:00
|
|
|
dsym : tSYMBEG xstring_contents tSTRING_END
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-10-23 06:17:30 -04:00
|
|
|
lex_state = EXPR_END;
|
2002-11-17 09:01:57 -05:00
|
|
|
if (!($$ = $2)) {
|
2002-10-23 06:17:30 -04:00
|
|
|
yyerror("empty symbol literal");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switch (nd_type($$)) {
|
|
|
|
case NODE_DSTR:
|
|
|
|
nd_set_type($$, NODE_DSYM);
|
|
|
|
break;
|
2003-03-07 00:59:42 -05:00
|
|
|
case NODE_STR:
|
|
|
|
if (strlen(RSTRING($$->nd_lit)->ptr) == RSTRING($$->nd_lit)->len) {
|
|
|
|
$$->nd_lit = ID2SYM(rb_intern(RSTRING($$->nd_lit)->ptr));
|
|
|
|
nd_set_type($$, NODE_LIT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through */
|
2002-10-23 06:17:30 -04:00
|
|
|
default:
|
2003-07-04 11:30:35 -04:00
|
|
|
$$ = NEW_NODE(NODE_DSYM, rb_str_new(0, 0), 1, NEW_LIST($$));
|
2002-10-23 06:17:30 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
$$ = dispatch1(dyna_symbol, $2);
|
|
|
|
%*/
|
2002-10-23 06:17:30 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
numeric : tINTEGER
|
1999-01-19 23:59:39 -05:00
|
|
|
| tFLOAT
|
2003-01-22 22:39:25 -05:00
|
|
|
| tUMINUS_NUM tINTEGER %prec tLOWEST
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-01-22 22:39:25 -05:00
|
|
|
$$ = negate_lit($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unary, ripper_intern("-@"), $2);
|
|
|
|
%*/
|
2003-01-22 22:39:25 -05:00
|
|
|
}
|
|
|
|
| tUMINUS_NUM tFLOAT %prec tLOWEST
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2003-01-22 22:39:25 -05:00
|
|
|
$$ = negate_lit($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(unary, ripper_intern("-@"), $2);
|
|
|
|
%*/
|
2003-01-22 22:39:25 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
variable : tIDENTIFIER
|
|
|
|
| tIVAR
|
|
|
|
| tGVAR
|
|
|
|
| tCONSTANT
|
2000-03-23 03:37:35 -05:00
|
|
|
| tCVAR
|
2004-10-31 01:22:58 -04:00
|
|
|
| kNIL {ifndef_ripper($$ = kNIL);}
|
|
|
|
| kSELF {ifndef_ripper($$ = kSELF);}
|
|
|
|
| kTRUE {ifndef_ripper($$ = kTRUE);}
|
|
|
|
| kFALSE {ifndef_ripper($$ = kFALSE);}
|
|
|
|
| k__FILE__ {ifndef_ripper($$ = k__FILE__);}
|
|
|
|
| k__LINE__ {ifndef_ripper($$ = k__LINE__);}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
var_ref : variable
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = gettable($1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(var_ref, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-02-13 04:01:11 -05:00
|
|
|
var_lhs : variable
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-02-13 11:39:37 -05:00
|
|
|
$$ = assignable($1, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(var_field, $1);
|
|
|
|
%*/
|
2002-02-13 04:01:11 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
2002-02-13 04:01:11 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
backref : tNTH_REF
|
|
|
|
| tBACK_REF
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
superclass : term
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = Qnil;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| '<'
|
|
|
|
{
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
}
|
2002-02-18 04:52:48 -05:00
|
|
|
expr_value term
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
$$ = $3;
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
| error term
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
yyerrok;
|
|
|
|
$$ = 0;
|
|
|
|
/*%
|
|
|
|
yyerrok;
|
|
|
|
$$ = Qnil;
|
|
|
|
%*/
|
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-02-12 01:23:24 -05:00
|
|
|
f_arglist : '(' f_args rparen
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = $2;
|
|
|
|
lex_state = EXPR_BEG;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(paren, $2);
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| f_args term
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = block_append(NEW_ARGS($1, $3, $5), $6);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, $1, $3, $5, escape_Qundef($6));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| f_arg ',' f_optarg opt_f_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = block_append(NEW_ARGS($1, $3, -1), $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, $1, $3, Qnil, escape_Qundef($4));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| f_arg ',' f_rest_arg opt_f_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = block_append(NEW_ARGS($1, 0, $3), $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, $1, Qnil, $3, escape_Qundef($4));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| f_arg opt_f_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = block_append(NEW_ARGS($1, 0, -1), $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, $1, Qnil, Qnil, escape_Qundef($2));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| f_optarg ',' f_rest_arg opt_f_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = block_append(NEW_ARGS(0, $1, $3), $4);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, Qnil, $1, $3, escape_Qundef($4));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| f_optarg opt_f_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = block_append(NEW_ARGS(0, $1, -1), $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, Qnil, $1, Qnil, escape_Qundef($2));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| f_rest_arg opt_f_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = block_append(NEW_ARGS(0, 0, $1), $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, Qnil, Qnil, $1, escape_Qundef($2));
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
| f_block_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = block_append(NEW_ARGS(0, 0, -1), $1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, Qnil, Qnil, Qnil, $1);
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
| /* none */
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_ARGS(0, 0, -1);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch4(params, Qnil, Qnil, Qnil, Qnil);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-03-13 02:18:45 -05:00
|
|
|
f_norm_arg : tCONSTANT
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-07-01 02:47:47 -04:00
|
|
|
yyerror("formal argument cannot be a constant");
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(param_error, $1);
|
|
|
|
%*/
|
2000-07-01 02:47:47 -04:00
|
|
|
}
|
|
|
|
| tIVAR
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-07-01 02:47:47 -04:00
|
|
|
yyerror("formal argument cannot be an instance variable");
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(param_error, $1);
|
|
|
|
%*/
|
2000-07-01 02:47:47 -04:00
|
|
|
}
|
|
|
|
| tGVAR
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-07-01 02:47:47 -04:00
|
|
|
yyerror("formal argument cannot be a global variable");
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(param_error, $1);
|
|
|
|
%*/
|
2000-07-01 02:47:47 -04:00
|
|
|
}
|
|
|
|
| tCVAR
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-07-01 02:47:47 -04:00
|
|
|
yyerror("formal argument cannot be a class variable");
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(param_error, $1);
|
|
|
|
%*/
|
2000-03-13 02:18:45 -05:00
|
|
|
}
|
|
|
|
| tIDENTIFIER
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
if (!is_local_id($1))
|
|
|
|
yyerror("formal argument must be local variable");
|
1999-08-13 01:45:20 -04:00
|
|
|
else if (local_id($1))
|
|
|
|
yyerror("duplicate argument name");
|
1998-01-16 07:13:05 -05:00
|
|
|
local_cnt($1);
|
|
|
|
$$ = 1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
|
|
|
f_arg : f_norm_arg
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{ $$ = rb_ary_new3(1, $1); }
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
| f_arg ',' f_norm_arg
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ += 1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
rb_ary_push($$, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-02-18 04:52:48 -05:00
|
|
|
f_opt : tIDENTIFIER '=' arg_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
if (!is_local_id($1))
|
|
|
|
yyerror("formal argument must be local variable");
|
1999-08-13 01:45:20 -04:00
|
|
|
else if (local_id($1))
|
|
|
|
yyerror("duplicate optional argument name");
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = assignable($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = rb_assoc_new($1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
f_optarg : f_opt
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = NEW_BLOCK($1);
|
|
|
|
$$->nd_end = $$;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = rb_ary_new3(1, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
| f_optarg ',' f_opt
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = block_append($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = rb_ary_push($1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2003-10-04 13:51:11 -04:00
|
|
|
restarg_mark : '*'
|
|
|
|
| tSTAR
|
|
|
|
;
|
|
|
|
|
|
|
|
f_rest_arg : restarg_mark tIDENTIFIER
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
if (!is_local_id($2))
|
|
|
|
yyerror("rest argument must be local variable");
|
1999-08-13 01:45:20 -04:00
|
|
|
else if (local_id($2))
|
|
|
|
yyerror("duplicate rest argument name");
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = local_cnt($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(restparam, $2);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-10-04 13:51:11 -04:00
|
|
|
| restarg_mark
|
1999-08-13 01:45:20 -04:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = -2;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(restparam, Qnil);
|
|
|
|
%*/
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2003-10-04 13:51:11 -04:00
|
|
|
blkarg_mark : '&'
|
|
|
|
| tAMPER
|
|
|
|
;
|
|
|
|
|
|
|
|
f_block_arg : blkarg_mark tIDENTIFIER
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2000-02-18 01:59:36 -05:00
|
|
|
if (!is_local_id($2))
|
|
|
|
yyerror("block argument must be local variable");
|
|
|
|
else if (local_id($2))
|
|
|
|
yyerror("duplicate block argument name");
|
1999-01-19 23:59:39 -05:00
|
|
|
$$ = NEW_BLOCK_ARG($2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $2;
|
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
|
|
|
opt_f_block_arg : ',' f_block_arg
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
| none
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
singleton : var_ref
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
if (nd_type($1) == NODE_SELF) {
|
|
|
|
$$ = NEW_SELF();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$$ = $1;
|
2002-02-18 04:52:48 -05:00
|
|
|
value_expr($$);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = $1;
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-02-12 01:23:24 -05:00
|
|
|
| '(' {lex_state = EXPR_BEG;} expr rparen
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2002-06-12 05:22:20 -04:00
|
|
|
if ($3 == 0) {
|
2003-08-27 16:04:23 -04:00
|
|
|
yyerror("can't define singleton method for ().");
|
2002-06-12 05:22:20 -04:00
|
|
|
}
|
|
|
|
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:
|
2003-08-27 16:04:23 -04:00
|
|
|
yyerror("can't define singleton method for literals");
|
2002-06-12 05:22:20 -04:00
|
|
|
default:
|
|
|
|
value_expr($3);
|
|
|
|
break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
$$ = $3;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(paren, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
assoc_list : none
|
1998-01-16 07:13:05 -05:00
|
|
|
| assocs trailer
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
| args trailer
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
if ($1->nd_alen%2 != 0) {
|
|
|
|
yyerror("odd number list for Hash");
|
|
|
|
}
|
|
|
|
$$ = $1;
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch1(assoclist_from_args, $1);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-04-05 09:16:40 -04:00
|
|
|
| kwargs trailer
|
2004-03-20 11:45:41 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
$$ = $1;
|
2004-03-20 11:45:41 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
assocs : assoc
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
|
|
|
{
|
|
|
|
$$ = rb_ary_new3(1, $1);
|
|
|
|
}
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
| assocs ',' assoc
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = list_concat($1, $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
rb_ary_push($$, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-02-18 04:52:48 -05:00
|
|
|
assoc : arg_value tASSOC arg_value
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
$$ = list_append(NEW_LIST($1), $3);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(assoc_new, $1, $3);
|
|
|
|
%*/
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2004-04-05 09:16:40 -04:00
|
|
|
kwargs : tLABEL arg_value
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-04-05 09:16:40 -04:00
|
|
|
$$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
$$ = dispatch2(assoc_new, $1, $2);
|
|
|
|
%*/
|
2004-04-05 09:16:40 -04:00
|
|
|
}
|
|
|
|
| kwargs ',' tLABEL arg_value
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%%%*/
|
2004-04-05 09:16:40 -04:00
|
|
|
$$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($3))), $4);
|
|
|
|
$$ = list_concat($1, $$);
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%
|
|
|
|
rb_ary_push($$, dispatch2(assoc_new, $3, $4));
|
|
|
|
%*/
|
2004-04-05 09:16:40 -04:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
operation : tIDENTIFIER
|
|
|
|
| tCONSTANT
|
|
|
|
| tFID
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
operation2 : tIDENTIFIER
|
|
|
|
| tCONSTANT
|
|
|
|
| tFID
|
|
|
|
| op
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
|
|
|
operation3 : tIDENTIFIER
|
|
|
|
| tFID
|
|
|
|
| op
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
dot_or_colon : '.'
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
2004-10-31 01:22:58 -04:00
|
|
|
{ $$ = $<val>1; }
|
2004-09-12 11:21:49 -04:00
|
|
|
%*/
|
1999-01-19 23:59:39 -05:00
|
|
|
| tCOLON2
|
2004-09-12 11:21:49 -04:00
|
|
|
/*%c%*/
|
|
|
|
/*%c
|
2004-10-31 01:22:58 -04:00
|
|
|
{ $$ = $<val>1; }
|
2004-09-12 11:21:49 -04:00
|
|
|
%*/
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
opt_terms : /* none */
|
|
|
|
| terms
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
opt_nl : /* none */
|
|
|
|
| '\n'
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-02-12 01:23:24 -05:00
|
|
|
rparen : opt_nl ')'
|
|
|
|
;
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
trailer : /* none */
|
|
|
|
| '\n'
|
|
|
|
| ','
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
term : ';' {yyerrok;}
|
|
|
|
| '\n'
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
terms : term
|
|
|
|
| terms ';' {yyerrok;}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
none : /* none */
|
|
|
|
{
|
|
|
|
/*%%%*/
|
|
|
|
$$ = 0;
|
|
|
|
/*%
|
|
|
|
$$ = Qundef;
|
|
|
|
%*/
|
|
|
|
}
|
2002-03-26 01:18:51 -05:00
|
|
|
;
|
1998-01-16 07:13:05 -05:00
|
|
|
%%
|
2004-09-12 11:21:49 -04:00
|
|
|
|
|
|
|
# undef parser
|
2004-09-17 05:24:13 -04:00
|
|
|
# undef yylex
|
2004-09-12 11:21:49 -04:00
|
|
|
# undef yylval
|
2004-09-17 05:24:13 -04:00
|
|
|
# define yylval (*((YYSTYPE*)(parser->parser_yylval)))
|
|
|
|
|
2004-09-20 01:40:23 -04:00
|
|
|
#ifndef RIPPER
|
2004-09-17 05:24:13 -04:00
|
|
|
static struct parser_params* parser_new _((void));
|
2004-09-20 01:40:23 -04:00
|
|
|
#endif
|
2004-09-17 05:24:13 -04:00
|
|
|
static int parser_regx_options _((struct parser_params*));
|
|
|
|
static int parser_tokadd_string _((struct parser_params*,int,int,int,long*));
|
|
|
|
static int parser_parse_string _((struct parser_params*,NODE*));
|
|
|
|
static int parser_here_document _((struct parser_params*,NODE*));
|
|
|
|
|
|
|
|
# define nextc() parser_nextc(parser)
|
|
|
|
# define pushback(c) parser_pushback(parser, c)
|
|
|
|
# define newtok() parser_newtok(parser)
|
|
|
|
# define tokadd(c) parser_tokadd(parser, c)
|
|
|
|
# define read_escape() parser_read_escape(parser)
|
|
|
|
# define tokadd_escape(t) parser_tokadd_escape(parser, t)
|
|
|
|
# define regx_options() parser_regx_options(parser)
|
|
|
|
# define tokadd_string(f,t,p,n) parser_tokadd_string(parser,f,t,p,n)
|
|
|
|
# define parse_string(n) parser_parse_string(parser,n)
|
|
|
|
# define here_document(n) parser_here_document(parser,n)
|
|
|
|
# define heredoc_identifier() parser_heredoc_identifier(parser)
|
|
|
|
# define heredoc_restore(n) parser_heredoc_restore(parser,n)
|
|
|
|
# define whole_match_p(e,l,i) parser_whole_match_p(parser,e,l,i)
|
2004-09-12 11:21:49 -04:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
#ifdef RIPPER
|
2004-09-12 11:21:49 -04:00
|
|
|
/* FIXME */
|
|
|
|
# define local_cnt(x) 3
|
|
|
|
# define local_id(x) 1
|
|
|
|
# define dyna_in_block() 1
|
|
|
|
#endif /* RIPPER */
|
|
|
|
|
|
|
|
#ifndef RIPPER
|
|
|
|
# define set_yylval_str(x) yylval.node = NEW_STR(x)
|
|
|
|
# define set_yylval_num(x) yylval.num = x
|
|
|
|
# define set_yylval_id(x) yylval.id = x
|
|
|
|
# define set_yylval_literal(x) yylval.node = NEW_LIT(x)
|
2004-10-31 01:22:58 -04:00
|
|
|
# define set_yylval_node(x) yylval.node = x
|
|
|
|
# define yylval_id() yylval.id
|
2004-09-12 11:21:49 -04:00
|
|
|
#else
|
2004-10-31 01:22:58 -04:00
|
|
|
# define set_yylval_str(x) x
|
|
|
|
# define set_yylval_num(x) x
|
|
|
|
# define set_yylval_id(x) x
|
|
|
|
# define set_yylval_literal(x) x
|
|
|
|
# define set_yylval_node(x) x
|
|
|
|
# define yylval_id() SYM2ID(yylval.val)
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
|
|
|
|
2004-09-19 23:03:12 -04:00
|
|
|
#ifdef RIPPER
|
2004-09-20 01:40:23 -04:00
|
|
|
#define ripper_flush(p) (p->tokp = p->parser_lex_p)
|
2004-09-17 05:24:13 -04:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
static void
|
2004-09-20 01:40:23 -04:00
|
|
|
ripper_dispatch_scan_event(parser, t)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-19 23:03:12 -04:00
|
|
|
int t;
|
2004-09-12 11:21:49 -04:00
|
|
|
{
|
2004-09-20 01:40:23 -04:00
|
|
|
VALUE str;
|
|
|
|
|
|
|
|
if (lex_p < parser->tokp) rb_raise(rb_eRuntimeError, "lex_p < tokp");
|
|
|
|
if (lex_p == parser->tokp) return;
|
|
|
|
str = rb_str_new(parser->tokp, lex_p - parser->tokp);
|
2004-09-22 01:22:50 -04:00
|
|
|
yylval.val = ripper_dispatch1(parser, ripper_token2eventid(t), str);
|
2004-09-20 01:40:23 -04:00
|
|
|
ripper_flush(parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-09-20 03:59:30 -04:00
|
|
|
ripper_dispatch_delayed_token(parser, t)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-20 03:59:30 -04:00
|
|
|
int t;
|
2004-09-12 11:21:49 -04:00
|
|
|
{
|
2004-09-20 03:59:30 -04:00
|
|
|
int saved_line = ruby_sourceline;
|
|
|
|
char *saved_tokp = parser->tokp;
|
|
|
|
|
|
|
|
ruby_sourceline = parser->delayed_line;
|
|
|
|
parser->tokp = lex_pbeg + parser->delayed_col;
|
2004-09-22 01:22:50 -04:00
|
|
|
yylval.val = ripper_dispatch1(parser, ripper_token2eventid(t), parser->delayed);
|
2004-09-20 03:59:30 -04:00
|
|
|
parser->delayed = Qnil;
|
2004-09-20 01:40:23 -04:00
|
|
|
ruby_sourceline = saved_line;
|
|
|
|
parser->tokp = saved_tokp;
|
2004-09-12 11:21:49 -04:00
|
|
|
}
|
|
|
|
#endif /* RIPPER */
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
#include "regex.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
2000-10-20 12:37:01 -04:00
|
|
|
/* We remove any previous definition of `SIGN_EXTEND_CHAR',
|
|
|
|
since ours (we hope) works properly with all combinations of
|
|
|
|
machines, compilers, `char' and `unsigned char' argument types.
|
|
|
|
(Per Bothner suggested the basic approach.) */
|
|
|
|
#undef SIGN_EXTEND_CHAR
|
|
|
|
#if __STDC__
|
|
|
|
# define SIGN_EXTEND_CHAR(c) ((signed char)(c))
|
|
|
|
#else /* not __STDC__ */
|
|
|
|
/* As in Harbison and Steele. */
|
|
|
|
# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
|
|
|
|
#endif
|
|
|
|
#define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_' || ismbchar(c)))
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_yyerror(parser, msg)
|
|
|
|
struct parser_params *parser;
|
2003-09-17 07:34:02 -04:00
|
|
|
const char *msg;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
#ifndef RIPPER
|
1998-01-16 07:13:05 -05:00
|
|
|
char *p, *pe, *buf;
|
|
|
|
int len, i;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_compile_error("%s", msg);
|
1998-01-16 07:13:05 -05:00
|
|
|
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) {
|
|
|
|
buf = ALLOCA_N(char, len+2);
|
|
|
|
MEMCPY(buf, p, char, len);
|
|
|
|
buf[len] = '\0';
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_compile_error_append("%s", buf);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
i = lex_p - p;
|
|
|
|
p = buf; pe = p + len;
|
|
|
|
|
|
|
|
while (p < pe) {
|
|
|
|
if (*p != '\t') *p = ' ';
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
buf[i] = '^';
|
|
|
|
buf[i+1] = '\0';
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_compile_error_append("%s", buf);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
#else
|
|
|
|
dispatch1(parse_error, rb_str_new2(msg));
|
2004-09-17 05:24:13 -04:00
|
|
|
#endif /* !RIPPER */
|
2004-09-12 11:21:49 -04:00
|
|
|
return 0;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifndef RIPPER
|
1999-01-19 23:59:39 -05:00
|
|
|
int ruby__end__seen;
|
1999-10-15 04:52:18 -04:00
|
|
|
static VALUE ruby_debug_lines;
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static NODE*
|
2004-09-17 05:24:13 -04:00
|
|
|
yycompile(parser, f, line)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
char *f;
|
2000-01-04 23:41:21 -05:00
|
|
|
int line;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
int n;
|
2000-07-27 05:49:34 -04:00
|
|
|
NODE *node = 0;
|
2002-06-04 03:34:19 -04:00
|
|
|
struct RVarmap *vp, *vars = ruby_dyna_vars;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-07-18 02:00:45 -04:00
|
|
|
if (!compile_for_eval && rb_safe_level() == 0 &&
|
2000-01-04 23:41:21 -05:00
|
|
|
rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
|
1999-10-15 04:52:18 -04:00
|
|
|
VALUE hash, fname;
|
|
|
|
|
2000-01-04 23:41:21 -05:00
|
|
|
hash = rb_const_get(rb_cObject, rb_intern("SCRIPT_LINES__"));
|
1999-10-15 04:52:18 -04:00
|
|
|
if (TYPE(hash) == T_HASH) {
|
|
|
|
fname = rb_str_new2(f);
|
|
|
|
ruby_debug_lines = rb_hash_aref(hash, fname);
|
|
|
|
if (NIL_P(ruby_debug_lines)) {
|
|
|
|
ruby_debug_lines = rb_ary_new();
|
|
|
|
rb_hash_aset(hash, fname, ruby_debug_lines);
|
|
|
|
}
|
|
|
|
}
|
2000-01-04 23:41:21 -05:00
|
|
|
if (line > 1) {
|
|
|
|
VALUE str = rb_str_new(0,0);
|
|
|
|
while (line > 1) {
|
|
|
|
rb_ary_push(ruby_debug_lines, str);
|
|
|
|
line--;
|
|
|
|
}
|
|
|
|
}
|
1999-10-15 04:52:18 -04:00
|
|
|
}
|
|
|
|
|
2002-08-15 07:49:40 -04:00
|
|
|
ruby_current_node = 0;
|
2002-03-07 06:19:37 -05:00
|
|
|
ruby_sourcefile = rb_source_filename(f);
|
2004-10-20 02:53:42 -04:00
|
|
|
ruby_sourceline = line - 1;
|
2004-09-17 05:24:13 -04:00
|
|
|
n = yyparse((void*)parser);
|
1999-10-15 04:52:18 -04:00
|
|
|
ruby_debug_lines = 0;
|
1999-08-13 01:45:20 -04:00
|
|
|
compile_for_eval = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-04 03:34:19 -04:00
|
|
|
vp = ruby_dyna_vars;
|
|
|
|
ruby_dyna_vars = vars;
|
2002-06-24 03:20:42 -04:00
|
|
|
lex_strterm = 0;
|
2002-06-04 03:34:19 -04:00
|
|
|
while (vp && vp != vars) {
|
|
|
|
struct RVarmap *tmp = vp;
|
|
|
|
vp = vp->next;
|
|
|
|
rb_gc_force_recycle((VALUE)tmp);
|
|
|
|
}
|
2004-09-21 20:19:15 -04:00
|
|
|
if (ruby_eval_tree_begin) {
|
|
|
|
return NEW_PRELUDE(ruby_eval_tree_begin, ruby_eval_tree);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return ruby_eval_tree;
|
|
|
|
}
|
|
|
|
|
2000-07-27 05:49:34 -04:00
|
|
|
if (n == 0) node = ruby_eval_tree;
|
2003-03-03 02:34:24 -05:00
|
|
|
else ruby_eval_tree_begin = 0;
|
2000-07-27 05:49:34 -04:00
|
|
|
return node;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif /* !RIPPER */
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-09-17 07:38:49 -04:00
|
|
|
static VALUE lex_get_str _((struct parser_params *, VALUE));
|
1999-01-19 23:59:39 -05:00
|
|
|
static VALUE
|
2004-09-17 05:24:13 -04:00
|
|
|
lex_get_str(parser, s)
|
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
VALUE s;
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
|
|
|
char *beg, *end, *pend;
|
|
|
|
|
|
|
|
beg = RSTRING(s)->ptr;
|
|
|
|
if (lex_gets_ptr) {
|
|
|
|
if (RSTRING(s)->len == lex_gets_ptr) return Qnil;
|
|
|
|
beg += lex_gets_ptr;
|
|
|
|
}
|
|
|
|
pend = RSTRING(s)->ptr + RSTRING(s)->len;
|
|
|
|
end = beg;
|
|
|
|
while (end < pend) {
|
|
|
|
if (*end++ == '\n') break;
|
|
|
|
}
|
|
|
|
lex_gets_ptr = end - RSTRING(s)->ptr;
|
|
|
|
return rb_str_new(beg, end - beg);
|
|
|
|
}
|
|
|
|
|
1999-10-15 04:52:18 -04:00
|
|
|
static VALUE
|
2004-09-17 05:24:13 -04:00
|
|
|
lex_getline(parser)
|
|
|
|
struct parser_params *parser;
|
1999-10-15 04:52:18 -04:00
|
|
|
{
|
2004-10-20 02:53:42 -04:00
|
|
|
VALUE line = (*parser->parser_lex_gets)(parser, parser->parser_lex_input);
|
2004-10-20 11:44:06 -04:00
|
|
|
#ifndef RIPPER
|
2004-10-20 02:53:42 -04:00
|
|
|
if (ruby_debug_lines && !NIL_P(line)) {
|
|
|
|
rb_ary_push(ruby_debug_lines, line);
|
|
|
|
}
|
2004-10-20 11:44:06 -04:00
|
|
|
#endif
|
2004-10-20 02:53:42 -04:00
|
|
|
return line;
|
2004-09-12 11:21:49 -04:00
|
|
|
}
|
1999-10-15 04:52:18 -04:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifndef RIPPER
|
1998-01-16 07:13:05 -05:00
|
|
|
NODE*
|
1999-08-13 01:45:20 -04:00
|
|
|
rb_compile_string(f, s, line)
|
|
|
|
const char *f;
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE s;
|
1999-08-13 01:45:20 -04:00
|
|
|
int line;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser = parser_new();
|
2004-10-06 03:40:06 -04:00
|
|
|
volatile VALUE p = parser->value;
|
2004-09-17 05:24:13 -04:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
lex_gets = lex_get_str;
|
|
|
|
lex_gets_ptr = 0;
|
|
|
|
lex_input = s;
|
|
|
|
lex_pbeg = lex_p = lex_pend = 0;
|
2000-05-30 00:24:17 -04:00
|
|
|
compile_for_eval = ruby_in_eval;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
return yycompile(parser, f, line);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
NODE*
|
1999-08-13 01:45:20 -04:00
|
|
|
rb_compile_cstr(f, s, len, line)
|
|
|
|
const char *f, *s;
|
|
|
|
int len, line;
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
1999-08-13 01:45:20 -04:00
|
|
|
return rb_compile_string(f, rb_str_new(s, len), line);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
|
2004-09-17 07:38:49 -04:00
|
|
|
static VALUE lex_io_gets _((struct parser_params *, VALUE));
|
2004-09-17 05:24:13 -04:00
|
|
|
static VALUE
|
|
|
|
lex_io_gets(parser, io)
|
|
|
|
struct parser_params *parser;
|
|
|
|
VALUE io;
|
|
|
|
{
|
|
|
|
return rb_io_gets(io);
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
NODE*
|
|
|
|
rb_compile_file(f, file, start)
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *f;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE file;
|
|
|
|
int start;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser = parser_new();
|
|
|
|
volatile VALUE p = parser->value;
|
|
|
|
|
|
|
|
lex_gets = lex_io_gets;
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_input = file;
|
|
|
|
lex_pbeg = lex_p = lex_pend = 0;
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
return yycompile(parser, f, start);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif /* !RIPPER */
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2001-01-10 05:07:31 -05:00
|
|
|
static inline int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_nextc(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
if (lex_p == lex_pend) {
|
2004-09-12 11:21:49 -04:00
|
|
|
if (parser->eofp)
|
|
|
|
return -1;
|
1998-01-16 07:13:05 -05:00
|
|
|
if (lex_input) {
|
2004-09-17 05:24:13 -04:00
|
|
|
VALUE v = lex_getline(parser);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
if (NIL_P(v)) {
|
|
|
|
parser->eofp = Qtrue;
|
|
|
|
return -1;
|
|
|
|
}
|
2004-09-19 23:03:12 -04:00
|
|
|
#ifdef RIPPER
|
2004-09-20 01:40:23 -04:00
|
|
|
if (parser->tokp < lex_pend) {
|
2004-09-20 03:59:30 -04:00
|
|
|
if (NIL_P(parser->delayed)) {
|
|
|
|
parser->delayed = rb_str_buf_new(1024);
|
|
|
|
rb_str_buf_cat(parser->delayed,
|
|
|
|
parser->tokp, lex_pend - parser->tokp);
|
|
|
|
parser->delayed_line = ruby_sourceline;
|
|
|
|
parser->delayed_col = parser->tokp - lex_pbeg;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_str_buf_cat(parser->delayed,
|
|
|
|
parser->tokp, lex_pend - parser->tokp);
|
|
|
|
}
|
2004-09-20 01:40:23 -04:00
|
|
|
}
|
2004-09-19 23:03:12 -04:00
|
|
|
#endif
|
2002-09-10 10:38:20 -04:00
|
|
|
if (heredoc_end > 0) {
|
|
|
|
ruby_sourceline = heredoc_end;
|
|
|
|
heredoc_end = 0;
|
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
ruby_sourceline++;
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_pbeg = lex_p = RSTRING(v)->ptr;
|
|
|
|
lex_pend = lex_p + RSTRING(v)->len;
|
2004-09-19 23:03:12 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
ripper_flush(parser);
|
|
|
|
#endif
|
1998-01-16 07:19:22 -05:00
|
|
|
lex_lastline = v;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
1998-01-16 07:19:22 -05:00
|
|
|
lex_lastline = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c = (unsigned char)*lex_p++;
|
2002-12-16 01:56:33 -05:00
|
|
|
if (c == '\r' && lex_p < lex_pend && *lex_p == '\n') {
|
1999-09-16 05:40:33 -04:00
|
|
|
lex_p++;
|
|
|
|
c = '\n';
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static void
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_pushback(parser, c)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
int c;
|
|
|
|
{
|
|
|
|
if (c == -1) return;
|
|
|
|
lex_p--;
|
2004-09-19 23:03:12 -04:00
|
|
|
if (lex_p > lex_pbeg && lex_p[0] == '\n' && lex_p[-1] == '\r') {
|
|
|
|
lex_p--;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2004-09-19 23:03:12 -04:00
|
|
|
#define lex_goto_eol(parser) (parser->parser_lex_p = parser->parser_lex_pend)
|
2002-12-30 17:56:21 -05:00
|
|
|
#define was_bol() (lex_p == lex_pbeg + 1)
|
1999-08-13 01:45:20 -04:00
|
|
|
#define peek(c) (lex_p != lex_pend && (c) == *lex_p)
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
#define tokfix() (tokenbuf[tokidx]='\0')
|
|
|
|
#define tok() tokenbuf
|
|
|
|
#define toklen() tokidx
|
|
|
|
#define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
|
|
|
|
|
|
|
|
static char*
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_newtok(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
tokidx = 0;
|
|
|
|
if (!tokenbuf) {
|
|
|
|
toksiz = 60;
|
|
|
|
tokenbuf = ALLOC_N(char, 60);
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
if (toksiz > 4096) {
|
1998-01-16 07:13:05 -05:00
|
|
|
toksiz = 60;
|
|
|
|
REALLOC_N(tokenbuf, char, 60);
|
|
|
|
}
|
|
|
|
return tokenbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_tokadd(parser, c)
|
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
char c;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
tokenbuf[tokidx++] = c;
|
|
|
|
if (tokidx >= toksiz) {
|
|
|
|
toksiz *= 2;
|
|
|
|
REALLOC_N(tokenbuf, char, toksiz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_read_escape(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
switch (c = nextc()) {
|
|
|
|
case '\\': /* Backslash */
|
|
|
|
return c;
|
|
|
|
|
|
|
|
case 'n': /* newline */
|
|
|
|
return '\n';
|
|
|
|
|
|
|
|
case 't': /* horizontal tab */
|
|
|
|
return '\t';
|
|
|
|
|
|
|
|
case 'r': /* carriage-return */
|
|
|
|
return '\r';
|
|
|
|
|
|
|
|
case 'f': /* form-feed */
|
|
|
|
return '\f';
|
|
|
|
|
|
|
|
case 'v': /* vertical tab */
|
|
|
|
return '\13';
|
|
|
|
|
|
|
|
case 'a': /* alarm(bell) */
|
|
|
|
return '\007';
|
|
|
|
|
|
|
|
case 'e': /* escape */
|
|
|
|
return 033;
|
|
|
|
|
|
|
|
case '0': case '1': case '2': case '3': /* octal constant */
|
|
|
|
case '4': case '5': case '6': case '7':
|
|
|
|
{
|
2002-03-12 04:28:50 -05:00
|
|
|
int numlen;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
pushback(c);
|
2002-03-12 04:28:50 -05:00
|
|
|
c = scan_oct(lex_p, 3, &numlen);
|
|
|
|
lex_p += numlen;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
return c;
|
|
|
|
|
|
|
|
case 'x': /* hex constant */
|
|
|
|
{
|
2000-03-08 01:25:19 -05:00
|
|
|
int numlen;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
2000-03-08 01:25:19 -05:00
|
|
|
c = scan_hex(lex_p, 2, &numlen);
|
2002-06-14 02:27:18 -04:00
|
|
|
if (numlen == 0) {
|
|
|
|
yyerror("Invalid escape character syntax");
|
|
|
|
return 0;
|
|
|
|
}
|
2000-03-08 01:25:19 -05:00
|
|
|
lex_p += numlen;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
return c;
|
|
|
|
|
|
|
|
case 'b': /* backspace */
|
1999-08-13 01:45:20 -04:00
|
|
|
return '\010';
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
case 's': /* space */
|
|
|
|
return ' ';
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
case 'M':
|
|
|
|
if ((c = nextc()) != '-') {
|
|
|
|
yyerror("Invalid escape character syntax");
|
|
|
|
pushback(c);
|
|
|
|
return '\0';
|
|
|
|
}
|
|
|
|
if ((c = nextc()) == '\\') {
|
|
|
|
return read_escape() | 0x80;
|
|
|
|
}
|
|
|
|
else if (c == -1) goto eof;
|
|
|
|
else {
|
|
|
|
return ((c & 0xff) | 0x80);
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'C':
|
|
|
|
if ((c = nextc()) != '-') {
|
|
|
|
yyerror("Invalid escape character syntax");
|
|
|
|
pushback(c);
|
|
|
|
return '\0';
|
|
|
|
}
|
|
|
|
case 'c':
|
|
|
|
if ((c = nextc())== '\\') {
|
|
|
|
c = read_escape();
|
|
|
|
}
|
|
|
|
else if (c == '?')
|
|
|
|
return 0177;
|
|
|
|
else if (c == -1) goto eof;
|
|
|
|
return c & 0x9f;
|
|
|
|
|
|
|
|
eof:
|
|
|
|
case -1:
|
|
|
|
yyerror("Invalid escape character syntax");
|
|
|
|
return '\0';
|
|
|
|
|
|
|
|
default:
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-05-12 05:07:57 -04:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_tokadd_escape(parser, term)
|
|
|
|
struct parser_params *parser;
|
2001-08-20 00:29:58 -04:00
|
|
|
int term;
|
2000-05-12 05:07:57 -04:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
switch (c = nextc()) {
|
|
|
|
case '\n':
|
|
|
|
return 0; /* just ignore */
|
|
|
|
|
|
|
|
case '0': case '1': case '2': case '3': /* octal constant */
|
|
|
|
case '4': case '5': case '6': case '7':
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
tokadd('\\');
|
|
|
|
tokadd(c);
|
|
|
|
for (i=0; i<2; i++) {
|
|
|
|
c = nextc();
|
|
|
|
if (c == -1) goto eof;
|
|
|
|
if (c < '0' || '7' < c) {
|
|
|
|
pushback(c);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tokadd(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case 'x': /* hex constant */
|
|
|
|
{
|
|
|
|
int numlen;
|
|
|
|
|
2000-05-25 01:55:12 -04:00
|
|
|
tokadd('\\');
|
|
|
|
tokadd(c);
|
2000-05-12 05:07:57 -04:00
|
|
|
scan_hex(lex_p, 2, &numlen);
|
2002-06-14 02:27:18 -04:00
|
|
|
if (numlen == 0) {
|
|
|
|
yyerror("Invalid escape character syntax");
|
|
|
|
return -1;
|
|
|
|
}
|
2000-05-12 05:07:57 -04:00
|
|
|
while (numlen--)
|
|
|
|
tokadd(nextc());
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case 'M':
|
|
|
|
if ((c = nextc()) != '-') {
|
|
|
|
yyerror("Invalid escape character syntax");
|
|
|
|
pushback(c);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
tokadd('\\'); tokadd('M'); tokadd('-');
|
|
|
|
goto escaped;
|
|
|
|
|
|
|
|
case 'C':
|
|
|
|
if ((c = nextc()) != '-') {
|
|
|
|
yyerror("Invalid escape character syntax");
|
|
|
|
pushback(c);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
tokadd('\\'); tokadd('C'); tokadd('-');
|
|
|
|
goto escaped;
|
|
|
|
|
|
|
|
case 'c':
|
|
|
|
tokadd('\\'); tokadd('c');
|
|
|
|
escaped:
|
|
|
|
if ((c = nextc()) == '\\') {
|
2001-08-20 00:29:58 -04:00
|
|
|
return tokadd_escape(term);
|
2000-05-12 05:07:57 -04:00
|
|
|
}
|
|
|
|
else if (c == -1) goto eof;
|
|
|
|
tokadd(c);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
eof:
|
|
|
|
case -1:
|
|
|
|
yyerror("Invalid escape character syntax");
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
default:
|
2002-06-11 03:02:23 -04:00
|
|
|
if (c != '\\' || c != term)
|
2001-08-20 00:29:58 -04:00
|
|
|
tokadd('\\');
|
2000-05-12 05:07:57 -04:00
|
|
|
tokadd(c);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_regx_options(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
char kcode = 0;
|
1999-01-19 23:59:39 -05:00
|
|
|
int options = 0;
|
2002-06-24 03:20:42 -04:00
|
|
|
int c;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
newtok();
|
2002-06-24 03:20:42 -04:00
|
|
|
while (c = nextc(), ISALPHA(c)) {
|
1998-01-16 07:13:05 -05:00
|
|
|
switch (c) {
|
2002-06-24 03:20:42 -04:00
|
|
|
case 'i':
|
|
|
|
options |= RE_OPTION_IGNORECASE;
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
options |= RE_OPTION_EXTENDED;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
options |= RE_OPTION_MULTILINE;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
options |= RE_OPTION_ONCE;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
kcode = 16;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
kcode = 32;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
kcode = 48;
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
kcode = 64;
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
default:
|
2002-06-24 03:20:42 -04:00
|
|
|
tokadd(c);
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
pushback(c);
|
|
|
|
if (toklen()) {
|
|
|
|
tokfix();
|
2004-09-17 05:24:13 -04:00
|
|
|
compile_error(PARSER_ARG "unknown regexp option%s - %s",
|
|
|
|
toklen() > 1 ? "s" : "", tok());
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
return options | kcode;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2002-06-26 04:01:00 -04:00
|
|
|
#define STR_FUNC_ESCAPE 0x01
|
|
|
|
#define STR_FUNC_EXPAND 0x02
|
|
|
|
#define STR_FUNC_REGEXP 0x04
|
|
|
|
#define STR_FUNC_QWORDS 0x08
|
2002-10-23 06:17:30 -04:00
|
|
|
#define STR_FUNC_SYMBOL 0x10
|
2002-06-26 04:01:00 -04:00
|
|
|
#define STR_FUNC_INDENT 0x20
|
|
|
|
|
|
|
|
enum string_type {
|
|
|
|
str_squote = (0),
|
|
|
|
str_dquote = (STR_FUNC_EXPAND),
|
2003-09-24 03:42:06 -04:00
|
|
|
str_xquote = (STR_FUNC_EXPAND),
|
2002-06-26 04:01:00 -04:00
|
|
|
str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
|
|
|
|
str_sword = (STR_FUNC_QWORDS),
|
|
|
|
str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
|
2002-10-23 06:17:30 -04:00
|
|
|
str_ssym = (STR_FUNC_SYMBOL),
|
|
|
|
str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND),
|
2002-06-26 04:01:00 -04:00
|
|
|
};
|
|
|
|
|
2002-12-14 21:48:40 -05:00
|
|
|
static void
|
|
|
|
dispose_string(str)
|
|
|
|
VALUE str;
|
|
|
|
{
|
2004-10-02 07:34:13 -04:00
|
|
|
xfree(RSTRING(str)->ptr);
|
2002-12-14 21:48:40 -05:00
|
|
|
rb_gc_force_recycle(str);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_tokadd_string(parser, func, term, paren, nest)
|
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
int func, term, paren;
|
|
|
|
long *nest;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
int c;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
while ((c = nextc()) != -1) {
|
|
|
|
if (paren && c == paren) {
|
2003-07-11 12:22:01 -04:00
|
|
|
++*nest;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
else if (c == term) {
|
2003-07-11 12:22:01 -04:00
|
|
|
if (!nest || !*nest) {
|
2002-06-24 03:20:42 -04:00
|
|
|
pushback(c);
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-07-11 12:22:01 -04:00
|
|
|
--*nest;
|
2002-03-17 21:04:23 -05:00
|
|
|
}
|
2002-06-26 04:01:00 -04:00
|
|
|
else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) {
|
2002-06-24 03:20:42 -04:00
|
|
|
int c2 = *lex_p;
|
|
|
|
if (c2 == '$' || c2 == '@' || c2 == '{') {
|
|
|
|
pushback(c);
|
|
|
|
break;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else if (c == '\\') {
|
|
|
|
c = nextc();
|
|
|
|
switch (c) {
|
|
|
|
case '\n':
|
2003-09-04 10:59:43 -04:00
|
|
|
if (func & STR_FUNC_QWORDS) break;
|
|
|
|
if (func & STR_FUNC_EXPAND) continue;
|
|
|
|
tokadd('\\');
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '\\':
|
2002-06-26 04:01:00 -04:00
|
|
|
if (func & STR_FUNC_ESCAPE) tokadd(c);
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2002-06-26 04:01:00 -04:00
|
|
|
if (func & STR_FUNC_REGEXP) {
|
2002-06-24 03:20:42 -04:00
|
|
|
pushback(c);
|
|
|
|
if (tokadd_escape(term) < 0)
|
|
|
|
return -1;
|
2001-02-08 04:19:27 -05:00
|
|
|
continue;
|
|
|
|
}
|
2002-06-26 04:01:00 -04:00
|
|
|
else if (func & STR_FUNC_EXPAND) {
|
2002-06-24 03:20:42 -04:00
|
|
|
pushback(c);
|
2002-06-26 04:01:00 -04:00
|
|
|
if (func & STR_FUNC_ESCAPE) tokadd('\\');
|
2002-06-24 03:20:42 -04:00
|
|
|
c = read_escape();
|
|
|
|
}
|
2002-08-01 05:42:38 -04:00
|
|
|
else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
|
|
|
|
/* ignore backslashed spaces in %w */
|
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
else if (c != term && !(paren && c == paren)) {
|
|
|
|
tokadd('\\');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ismbchar(c)) {
|
|
|
|
int i, len = mbclen(c)-1;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
tokadd(c);
|
|
|
|
c = nextc();
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
2002-06-26 04:01:00 -04:00
|
|
|
else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
|
2000-01-31 22:12:21 -05:00
|
|
|
pushback(c);
|
2002-06-26 04:01:00 -04:00
|
|
|
break;
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
2002-10-23 06:17:30 -04:00
|
|
|
if (!c && (func & STR_FUNC_SYMBOL)) {
|
|
|
|
func &= ~STR_FUNC_SYMBOL;
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "symbol cannot contain '\\0'");
|
2002-10-23 06:17:30 -04:00
|
|
|
continue;
|
|
|
|
}
|
2000-01-31 22:12:21 -05:00
|
|
|
tokadd(c);
|
|
|
|
}
|
2002-06-26 04:01:00 -04:00
|
|
|
return c;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2004-09-19 22:02:58 -04:00
|
|
|
#define NEW_STRTERM0(func, term, paren) \
|
2003-07-11 12:22:01 -04:00
|
|
|
rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
|
2004-09-19 22:02:58 -04:00
|
|
|
#ifndef RIPPER
|
2004-09-19 23:03:12 -04:00
|
|
|
# define NEW_STRTERM(func, term, paren) NEW_STRTERM0(func, term, paren)
|
2004-09-19 22:02:58 -04:00
|
|
|
#else
|
2004-09-19 23:03:12 -04:00
|
|
|
# define NEW_STRTERM(func, term, paren) ripper_new_strterm(parser, func, term, paren)
|
2004-09-19 22:02:58 -04:00
|
|
|
static NODE *
|
|
|
|
ripper_new_strterm(parser, func, term, paren)
|
|
|
|
struct parser_params *parser;
|
|
|
|
VALUE func, term, paren;
|
|
|
|
{
|
|
|
|
NODE *node = NEW_STRTERM0(func, term, paren);
|
|
|
|
nd_set_line(node, ruby_sourceline);
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
#endif
|
2002-06-24 03:20:42 -04:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_parse_string(parser, quote)
|
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
NODE *quote;
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2002-06-26 04:01:00 -04:00
|
|
|
int func = quote->nd_func;
|
2003-07-11 12:22:01 -04:00
|
|
|
int term = nd_term(quote);
|
|
|
|
int paren = nd_paren(quote);
|
2002-06-26 04:01:00 -04:00
|
|
|
int c, space = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
if (func == -1) return tSTRING_END;
|
|
|
|
c = nextc();
|
2002-06-26 04:01:00 -04:00
|
|
|
if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
|
|
|
|
do {c = nextc();} while (ISSPACE(c));
|
|
|
|
space = 1;
|
|
|
|
}
|
2003-09-17 07:34:02 -04:00
|
|
|
if (c == term && !quote->nd_nest) {
|
2002-12-30 17:56:21 -05:00
|
|
|
if (func & STR_FUNC_QWORDS) {
|
|
|
|
quote->nd_func = -1;
|
|
|
|
return ' ';
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
2002-12-30 17:56:21 -05:00
|
|
|
if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_num(regx_options());
|
2002-12-30 17:56:21 -05:00
|
|
|
return tREGEXP_END;
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
2002-06-26 04:01:00 -04:00
|
|
|
if (space) {
|
|
|
|
pushback(c);
|
|
|
|
return ' ';
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
newtok();
|
2002-06-26 04:01:00 -04:00
|
|
|
if ((func & STR_FUNC_EXPAND) && c == '#') {
|
2002-06-24 03:20:42 -04:00
|
|
|
switch (c = nextc()) {
|
|
|
|
case '$':
|
|
|
|
case '@':
|
|
|
|
pushback(c);
|
|
|
|
return tSTRING_DVAR;
|
|
|
|
case '{':
|
|
|
|
return tSTRING_DBEG;
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
tokadd('#');
|
|
|
|
}
|
|
|
|
pushback(c);
|
2003-07-11 12:22:01 -04:00
|
|
|
if (tokadd_string(func, term, paren, "e->nd_nest) == -1) {
|
2002-06-24 03:20:42 -04:00
|
|
|
ruby_sourceline = nd_line(quote);
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "unterminated string meets end of file");
|
2002-06-24 03:20:42 -04:00
|
|
|
return tSTRING_END;
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
tokfix();
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_str(rb_str_new(tok(), toklen()));
|
2002-06-24 03:20:42 -04:00
|
|
|
return tSTRING_CONTENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_heredoc_identifier(parser)
|
|
|
|
struct parser_params *parser;
|
2002-06-24 03:20:42 -04:00
|
|
|
{
|
2002-06-26 04:01:00 -04:00
|
|
|
int c = nextc(), term, func = 0, len;
|
2002-06-24 03:20:42 -04:00
|
|
|
|
|
|
|
if (c == '-') {
|
|
|
|
c = nextc();
|
2002-06-26 04:01:00 -04:00
|
|
|
func = STR_FUNC_INDENT;
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
switch (c) {
|
|
|
|
case '\'':
|
2002-07-14 21:33:36 -04:00
|
|
|
func |= str_squote; goto quoted;
|
2002-06-24 03:20:42 -04:00
|
|
|
case '"':
|
2002-07-14 21:33:36 -04:00
|
|
|
func |= str_dquote; goto quoted;
|
2002-06-24 03:20:42 -04:00
|
|
|
case '`':
|
2002-06-26 04:01:00 -04:00
|
|
|
func |= str_xquote;
|
2002-07-14 21:33:36 -04:00
|
|
|
quoted:
|
2002-06-24 03:20:42 -04:00
|
|
|
newtok();
|
2002-06-26 04:01:00 -04:00
|
|
|
tokadd(func);
|
2002-06-24 03:20:42 -04:00
|
|
|
term = c;
|
|
|
|
while ((c = nextc()) != -1 && c != term) {
|
|
|
|
len = mbclen(c);
|
|
|
|
do {tokadd(c);} while (--len > 0 && (c = nextc()) != -1);
|
|
|
|
}
|
|
|
|
if (c == -1) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "unterminated here document identifier");
|
2002-06-24 03:20:42 -04:00
|
|
|
return 0;
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2002-12-30 17:56:21 -05:00
|
|
|
if (!is_identchar(c)) {
|
|
|
|
pushback(c);
|
|
|
|
if (func & STR_FUNC_INDENT) {
|
|
|
|
pushback('-');
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
newtok();
|
|
|
|
term = '"';
|
2002-06-26 04:01:00 -04:00
|
|
|
tokadd(func |= str_dquote);
|
2002-06-24 03:20:42 -04:00
|
|
|
do {
|
|
|
|
len = mbclen(c);
|
|
|
|
do {tokadd(c);} while (--len > 0 && (c = nextc()) != -1);
|
|
|
|
} while ((c = nextc()) != -1 && is_identchar(c));
|
1998-01-16 07:19:22 -05:00
|
|
|
pushback(c);
|
|
|
|
break;
|
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
tokfix();
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
2004-09-19 23:03:12 -04:00
|
|
|
ripper_dispatch_scan_event(parser, tHEREDOC_BEG);
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
2002-06-24 03:20:42 -04:00
|
|
|
len = lex_p - lex_pbeg;
|
2004-09-19 23:03:12 -04:00
|
|
|
lex_goto_eol(parser);
|
2002-06-24 03:20:42 -04:00
|
|
|
lex_strterm = rb_node_newnode(NODE_HEREDOC,
|
|
|
|
rb_str_new(tok(), toklen()), /* nd_lit */
|
|
|
|
len, /* nd_nth */
|
|
|
|
lex_lastline); /* nd_orig */
|
2004-09-19 22:02:58 -04:00
|
|
|
nd_set_line(lex_strterm, ruby_sourceline);
|
2004-09-19 23:03:12 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
ripper_flush(parser);
|
|
|
|
#endif
|
2002-06-24 03:20:42 -04:00
|
|
|
return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
static void
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_heredoc_restore(parser, here)
|
|
|
|
struct parser_params *parser;
|
2002-06-24 03:20:42 -04:00
|
|
|
NODE *here;
|
|
|
|
{
|
2004-09-12 11:21:49 -04:00
|
|
|
VALUE line;
|
|
|
|
|
|
|
|
#ifdef RIPPER
|
2004-09-20 03:59:30 -04:00
|
|
|
if (!NIL_P(parser->delayed))
|
|
|
|
ripper_dispatch_delayed_token(parser, tSTRING_CONTENT);
|
2004-09-19 23:03:12 -04:00
|
|
|
lex_goto_eol(parser);
|
|
|
|
ripper_dispatch_scan_event(parser, tHEREDOC_END);
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
|
|
|
line = here->nd_orig;
|
2002-06-24 03:20:42 -04:00
|
|
|
lex_lastline = line;
|
|
|
|
lex_pbeg = RSTRING(line)->ptr;
|
|
|
|
lex_pend = lex_pbeg + RSTRING(line)->len;
|
|
|
|
lex_p = lex_pbeg + here->nd_nth;
|
2002-09-10 10:38:20 -04:00
|
|
|
heredoc_end = ruby_sourceline;
|
|
|
|
ruby_sourceline = nd_line(here);
|
2002-12-14 21:48:40 -05:00
|
|
|
dispose_string(here->nd_lit);
|
2002-06-24 03:20:42 -04:00
|
|
|
rb_gc_force_recycle((VALUE)here);
|
2004-09-19 23:03:12 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
ripper_flush(parser);
|
|
|
|
#endif
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_whole_match_p(parser, eos, len, indent)
|
|
|
|
struct parser_params *parser;
|
2002-06-24 03:20:42 -04:00
|
|
|
char *eos;
|
|
|
|
int len, indent;
|
|
|
|
{
|
|
|
|
char *p = lex_pbeg;
|
2002-12-30 13:19:08 -05:00
|
|
|
int n;
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
if (indent) {
|
|
|
|
while (*p && ISSPACE(*p)) p++;
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-12-30 13:19:08 -05:00
|
|
|
n= lex_pend - (p + len);
|
2003-01-16 02:38:40 -05:00
|
|
|
if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return Qfalse;
|
2002-12-30 13:19:08 -05:00
|
|
|
if (strncmp(eos, p, len) == 0) return Qtrue;
|
2002-06-24 03:20:42 -04:00
|
|
|
return Qfalse;
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_here_document(parser, here)
|
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
NODE *here;
|
2002-06-24 03:20:42 -04:00
|
|
|
{
|
|
|
|
int c, func, indent = 0;
|
2002-12-30 17:56:21 -05:00
|
|
|
char *eos, *p, *pend;
|
2002-08-21 11:47:54 -04:00
|
|
|
long len;
|
2002-12-30 17:56:21 -05:00
|
|
|
VALUE str = 0;
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
eos = RSTRING(here->nd_lit)->ptr;
|
|
|
|
len = RSTRING(here->nd_lit)->len - 1;
|
2002-06-26 04:01:00 -04:00
|
|
|
indent = (func = *eos++) & STR_FUNC_INDENT;
|
2002-06-24 03:20:42 -04:00
|
|
|
|
|
|
|
if ((c = nextc()) == -1) {
|
|
|
|
error:
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "can't find string \"%s\" anywhere before EOF", eos);
|
2002-06-24 03:20:42 -04:00
|
|
|
heredoc_restore(lex_strterm);
|
|
|
|
lex_strterm = 0;
|
|
|
|
return 0;
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-12-30 17:56:21 -05:00
|
|
|
if (was_bol() && whole_match_p(eos, len, indent)) {
|
2002-06-24 03:20:42 -04:00
|
|
|
heredoc_restore(lex_strterm);
|
|
|
|
return tSTRING_END;
|
|
|
|
}
|
|
|
|
|
2002-06-26 04:01:00 -04:00
|
|
|
if (!(func & STR_FUNC_EXPAND)) {
|
2002-06-24 03:20:42 -04:00
|
|
|
do {
|
2002-12-30 17:56:21 -05:00
|
|
|
p = RSTRING(lex_lastline)->ptr;
|
|
|
|
pend = lex_pend;
|
|
|
|
if (pend > p) {
|
|
|
|
switch (pend[-1]) {
|
|
|
|
case '\n':
|
|
|
|
if (--pend == p || pend[-1] != '\r') {
|
|
|
|
pend++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case '\r':
|
|
|
|
--pend;
|
|
|
|
}
|
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
if (str)
|
2002-12-30 17:56:21 -05:00
|
|
|
rb_str_cat(str, p, pend - p);
|
2002-06-24 03:20:42 -04:00
|
|
|
else
|
2002-12-30 17:56:21 -05:00
|
|
|
str = rb_str_new(p, pend - p);
|
|
|
|
if (pend < lex_pend) rb_str_cat(str, "\n", 1);
|
2004-09-19 23:03:12 -04:00
|
|
|
lex_goto_eol(parser);
|
2002-06-24 03:20:42 -04:00
|
|
|
if (nextc() == -1) {
|
2002-12-14 21:48:40 -05:00
|
|
|
if (str) dispose_string(str);
|
2002-06-24 03:20:42 -04:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} while (!whole_match_p(eos, len, indent));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
newtok();
|
|
|
|
if (c == '#') {
|
|
|
|
switch (c = nextc()) {
|
|
|
|
case '$':
|
|
|
|
case '@':
|
|
|
|
pushback(c);
|
|
|
|
return tSTRING_DVAR;
|
|
|
|
case '{':
|
|
|
|
return tSTRING_DBEG;
|
|
|
|
}
|
|
|
|
tokadd('#');
|
|
|
|
}
|
|
|
|
do {
|
|
|
|
pushback(c);
|
2003-07-11 12:22:01 -04:00
|
|
|
if ((c = tokadd_string(func, '\n', 0, NULL)) == -1) goto error;
|
2002-06-24 03:20:42 -04:00
|
|
|
if (c != '\n') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_str(rb_str_new(tok(), toklen()));
|
2002-06-24 03:20:42 -04:00
|
|
|
return tSTRING_CONTENT;
|
|
|
|
}
|
|
|
|
tokadd(nextc());
|
|
|
|
if ((c = nextc()) == -1) goto error;
|
|
|
|
} while (!whole_match_p(eos, len, indent));
|
|
|
|
str = rb_str_new(tok(), toklen());
|
|
|
|
}
|
|
|
|
heredoc_restore(lex_strterm);
|
|
|
|
lex_strterm = NEW_STRTERM(-1, 0, 0);
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_str(str);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tSTRING_CONTENT;
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#include "lex.c"
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifndef RIPPER
|
1998-01-16 07:13:05 -05:00
|
|
|
static void
|
|
|
|
arg_ambiguous()
|
|
|
|
{
|
2003-04-22 04:18:19 -04:00
|
|
|
rb_warning("ambiguous first argument; put parentheses or even spaces");
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
#else
|
|
|
|
static void
|
|
|
|
ripper_arg_ambiguous(parser)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
{
|
|
|
|
dispatch0(arg_ambiguous);
|
|
|
|
}
|
2004-09-17 05:24:13 -04:00
|
|
|
#define arg_ambiguous() ripper_arg_ambiguous(parser)
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
2004-10-02 07:34:13 -04:00
|
|
|
lvar_defined_gen(parser, id)
|
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
#ifndef RIPPER
|
|
|
|
return (dyna_in_block() && rb_dvar_defined(id)) || local_id(id);
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2003-01-30 23:00:17 -05:00
|
|
|
#define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
|
2004-08-28 10:14:11 -04:00
|
|
|
#define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || lex_state == EXPR_TERNARY || lex_state == EXPR_CLASS)
|
2001-05-30 05:12:34 -04:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_yylex(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
register int c;
|
|
|
|
int space_seen = 0;
|
2001-05-30 05:12:34 -04:00
|
|
|
int cmd_state;
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
int fallthru = Qfalse;
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
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;
|
|
|
|
}
|
2001-05-30 05:12:34 -04:00
|
|
|
cmd_state = command_start;
|
|
|
|
command_start = Qfalse;
|
1999-08-13 01:45:20 -04:00
|
|
|
retry:
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
while ((c = nextc())) {
|
|
|
|
switch (c) {
|
|
|
|
case ' ': case '\t': case '\f': case '\r':
|
|
|
|
case '\13': /* '\v' */
|
|
|
|
space_seen++;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto outofloop;
|
|
|
|
}
|
|
|
|
}
|
2004-09-19 23:03:12 -04:00
|
|
|
outofloop:
|
2004-09-12 11:21:49 -04:00
|
|
|
pushback(c);
|
2004-09-19 23:03:12 -04:00
|
|
|
ripper_dispatch_scan_event(parser, tSP);
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
switch (c = nextc()) {
|
|
|
|
case '\0': /* NUL */
|
|
|
|
case '\004': /* ^D */
|
|
|
|
case '\032': /* ^Z */
|
|
|
|
case -1: /* end of script. */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* white spaces */
|
|
|
|
case ' ': case '\t': case '\f': case '\r':
|
|
|
|
case '\13': /* '\v' */
|
2000-12-12 02:42:35 -05:00
|
|
|
space_seen++;
|
1998-01-16 07:13:05 -05:00
|
|
|
goto retry;
|
|
|
|
|
|
|
|
case '#': /* it's a comment */
|
|
|
|
while ((c = nextc()) != '\n') {
|
2004-09-12 11:21:49 -04:00
|
|
|
if (c == -1) {
|
|
|
|
#ifdef RIPPER
|
|
|
|
ripper_dispatch_scan_event(parser, tCOMMENT);
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
ripper_dispatch_scan_event(parser, tCOMMENT);
|
|
|
|
fallthru = Qtrue;
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
/* fall through */
|
|
|
|
case '\n':
|
1999-01-19 23:59:39 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_BEG:
|
|
|
|
case EXPR_FNAME:
|
|
|
|
case EXPR_DOT:
|
2002-03-08 02:03:09 -05:00
|
|
|
case EXPR_CLASS:
|
2004-03-20 11:45:41 -05:00
|
|
|
case EXPR_TERNARY:
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
if (!fallthru) {
|
|
|
|
ripper_dispatch_scan_event(parser, tIGNORED_NL);
|
|
|
|
}
|
2004-10-09 13:45:20 -04:00
|
|
|
fallthru = Qfalse;
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
goto retry;
|
1999-01-19 23:59:39 -05:00
|
|
|
default:
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-05-30 05:12:34 -04:00
|
|
|
command_start = Qtrue;
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
return '\n';
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
if ((c = nextc()) == '*') {
|
2002-06-02 18:16:55 -04:00
|
|
|
if ((c = nextc()) == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id(tPOW);
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
2002-02-19 00:39:06 -05:00
|
|
|
c = tPOW;
|
2000-05-30 00:24:17 -04:00
|
|
|
}
|
|
|
|
else {
|
2002-02-19 00:39:06 -05:00
|
|
|
if (c == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id('*');
|
2002-02-19 00:39:06 -05:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
return tOP_ASGN;
|
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
if (IS_ARG() && space_seen && !ISSPACE(c)){
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_warning0("`*' interpreted as argument prefix");
|
2002-02-19 00:39:06 -05:00
|
|
|
c = tSTAR;
|
|
|
|
}
|
2004-03-20 11:45:41 -05:00
|
|
|
else if (IS_BEG()) {
|
2002-02-19 00:39:06 -05:00
|
|
|
c = tSTAR;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
c = '*';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG; break;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-05-30 00:24:17 -04:00
|
|
|
return c;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '!':
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
if ((c = nextc()) == '=') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tNEQ;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
if (c == '~') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tNMATCH;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return '!';
|
|
|
|
|
|
|
|
case '=':
|
2002-12-30 17:56:21 -05:00
|
|
|
if (was_bol()) {
|
1998-01-16 07:13:05 -05:00
|
|
|
/* skip embedded rd document */
|
1999-01-19 23:59:39 -05:00
|
|
|
if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
int first_p = Qtrue;
|
|
|
|
|
2004-09-19 23:03:12 -04:00
|
|
|
lex_goto_eol(parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
ripper_dispatch_scan_event(parser, tEMBDOC_BEG);
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
for (;;) {
|
2004-09-19 23:03:12 -04:00
|
|
|
lex_goto_eol(parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
if (!first_p) {
|
|
|
|
ripper_dispatch_scan_event(parser, tEMBDOC);
|
|
|
|
}
|
|
|
|
first_p = Qfalse;
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
c = nextc();
|
1998-01-16 07:19:22 -05:00
|
|
|
if (c == -1) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "embedded document meets end of file");
|
1998-01-16 07:19:22 -05:00
|
|
|
return 0;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
if (c != '=') continue;
|
2000-10-31 03:37:47 -05:00
|
|
|
if (strncmp(lex_p, "end", 3) == 0 &&
|
|
|
|
(lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-09-19 23:03:12 -04:00
|
|
|
lex_goto_eol(parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
ripper_dispatch_scan_event(parser, tEMBDOC_END);
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-02-19 00:39:06 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG; break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
if ((c = nextc()) == '=') {
|
|
|
|
if ((c = nextc()) == '=') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tEQQ;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
1999-01-19 23:59:39 -05:00
|
|
|
return tEQ;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
if (c == '~') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tMATCH;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else if (c == '>') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tASSOC;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return '=';
|
|
|
|
|
|
|
|
case '<':
|
1998-01-16 07:19:22 -05:00
|
|
|
c = nextc();
|
|
|
|
if (c == '<' &&
|
2001-06-01 02:47:32 -04:00
|
|
|
lex_state != EXPR_END &&
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state != EXPR_DOT &&
|
|
|
|
lex_state != EXPR_ENDARG &&
|
|
|
|
lex_state != EXPR_CLASS &&
|
2001-05-30 05:12:34 -04:00
|
|
|
(!IS_ARG() || space_seen)) {
|
2002-06-24 03:20:42 -04:00
|
|
|
int token = heredoc_identifier();
|
|
|
|
if (token) return token;
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-02-19 00:39:06 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG; break;
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
if (c == '=') {
|
1998-01-16 07:13:05 -05:00
|
|
|
if ((c = nextc()) == '>') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tCMP;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
1999-01-19 23:59:39 -05:00
|
|
|
return tLEQ;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
if (c == '<') {
|
2002-06-17 23:53:23 -04:00
|
|
|
if ((c = nextc()) == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id(tLSHFT);
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
1999-01-19 23:59:39 -05:00
|
|
|
return tLSHFT;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return '<';
|
|
|
|
|
|
|
|
case '>':
|
2002-02-19 00:39:06 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG; break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
if ((c = nextc()) == '=') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tGEQ;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
if (c == '>') {
|
|
|
|
if ((c = nextc()) == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id(tRSHFT);
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
1999-01-19 23:59:39 -05:00
|
|
|
return tRSHFT;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return '>';
|
|
|
|
|
|
|
|
case '"':
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tSTRING_BEG;
|
2002-06-18 02:29:07 -04:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
case '`':
|
2002-06-18 02:29:07 -04:00
|
|
|
if (lex_state == EXPR_FNAME) {
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
if (lex_state == EXPR_DOT) {
|
2003-01-30 23:00:17 -05:00
|
|
|
if (cmd_state)
|
|
|
|
lex_state = EXPR_CMDARG;
|
|
|
|
else
|
|
|
|
lex_state = EXPR_ARG;
|
2002-06-18 02:29:07 -04:00
|
|
|
return c;
|
|
|
|
}
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_xquote, '`', 0);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tXSTRING_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '\'':
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tSTRING_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '?':
|
2001-06-01 02:47:32 -04:00
|
|
|
if (lex_state == EXPR_END || lex_state == EXPR_ENDARG) {
|
2004-03-20 11:45:41 -05:00
|
|
|
lex_state = EXPR_TERNARY;
|
1999-01-19 23:59:39 -05:00
|
|
|
return '?';
|
|
|
|
}
|
|
|
|
c = nextc();
|
2001-08-29 02:28:51 -04:00
|
|
|
if (c == -1) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "incomplete character syntax");
|
2000-12-12 02:42:35 -05:00
|
|
|
return 0;
|
|
|
|
}
|
2002-06-18 02:29:07 -04:00
|
|
|
if (ISSPACE(c)){
|
|
|
|
if (!IS_ARG()){
|
2002-09-04 02:37:39 -04:00
|
|
|
int c2 = 0;
|
2002-06-18 02:29:07 -04:00
|
|
|
switch (c) {
|
|
|
|
case ' ':
|
2002-09-04 02:37:39 -04:00
|
|
|
c2 = 's';
|
2002-06-18 02:29:07 -04:00
|
|
|
break;
|
|
|
|
case '\n':
|
2002-09-04 02:37:39 -04:00
|
|
|
c2 = 'n';
|
2002-06-18 02:29:07 -04:00
|
|
|
break;
|
|
|
|
case '\t':
|
2002-09-04 02:37:39 -04:00
|
|
|
c2 = 't';
|
2002-06-18 02:29:07 -04:00
|
|
|
break;
|
|
|
|
case '\v':
|
2002-09-04 02:37:39 -04:00
|
|
|
c2 = 'v';
|
|
|
|
break;
|
|
|
|
case '\r':
|
|
|
|
c2 = 'r';
|
|
|
|
break;
|
|
|
|
case '\f':
|
|
|
|
c2 = 'f';
|
2002-06-18 02:29:07 -04:00
|
|
|
break;
|
|
|
|
}
|
2002-09-04 02:37:39 -04:00
|
|
|
if (c2) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_warnI("invalid character syntax; use ?\\%c", c2);
|
2002-06-18 02:29:07 -04:00
|
|
|
}
|
|
|
|
}
|
2002-06-18 11:53:57 -04:00
|
|
|
ternary:
|
1999-01-19 23:59:39 -05:00
|
|
|
pushback(c);
|
2004-03-20 11:45:41 -05:00
|
|
|
lex_state = EXPR_TERNARY;
|
1999-01-19 23:59:39 -05:00
|
|
|
return '?';
|
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
else if (ismbchar(c)) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_warnI("multibyte character literal not supported yet; use ?\\%.3o", c);
|
2002-06-24 03:20:42 -04:00
|
|
|
goto ternary;
|
|
|
|
}
|
|
|
|
else if ((ISALNUM(c) || c == '_') && lex_p < lex_pend && is_identchar(*lex_p)) {
|
2002-06-18 11:53:57 -04:00
|
|
|
goto ternary;
|
|
|
|
}
|
2002-06-18 02:29:07 -04:00
|
|
|
else if (c == '\\') {
|
1998-01-16 07:13:05 -05:00
|
|
|
c = read_escape();
|
|
|
|
}
|
|
|
|
c &= 0xff;
|
|
|
|
lex_state = EXPR_END;
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_literal(INT2FIX(c));
|
1999-01-19 23:59:39 -05:00
|
|
|
return tINTEGER;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '&':
|
|
|
|
if ((c = nextc()) == '&') {
|
1999-01-19 23:59:39 -05:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
if ((c = nextc()) == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id(tANDOP);
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return tANDOP;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else if (c == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id('&');
|
1999-01-19 23:59:39 -05:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
2001-05-30 05:12:34 -04:00
|
|
|
if (IS_ARG() && space_seen && !ISSPACE(c)){
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_warning0("`&' interpreted as argument prefix");
|
2000-05-30 00:24:17 -04:00
|
|
|
c = tAMPER;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2004-03-20 11:45:41 -05:00
|
|
|
else if (IS_BEG()) {
|
2000-05-30 00:24:17 -04:00
|
|
|
c = tAMPER;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
c = '&';
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-02-19 00:39:06 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
}
|
2000-05-30 00:24:17 -04:00
|
|
|
return c;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '|':
|
|
|
|
if ((c = nextc()) == '|') {
|
2002-02-19 00:39:06 -05:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
if ((c = nextc()) == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id(tOROP);
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return tOROP;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-19 00:39:06 -05:00
|
|
|
if (c == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id('|');
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-19 00:39:06 -05:00
|
|
|
if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
|
|
|
|
lex_state = EXPR_ARG;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
pushback(c);
|
|
|
|
return '|';
|
|
|
|
|
|
|
|
case '+':
|
|
|
|
c = nextc();
|
1999-08-13 01:45:20 -04:00
|
|
|
if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
|
2002-02-19 00:39:06 -05:00
|
|
|
lex_state = EXPR_ARG;
|
1998-01-16 07:13:05 -05:00
|
|
|
if (c == '@') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tUPLUS;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return '+';
|
|
|
|
}
|
|
|
|
if (c == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id('+');
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-03-20 11:45:41 -05:00
|
|
|
if (IS_BEG() ||
|
2001-05-30 05:12:34 -04:00
|
|
|
(IS_ARG() && space_seen && !ISSPACE(c))) {
|
|
|
|
if (IS_ARG()) arg_ambiguous();
|
2000-05-30 00:24:17 -04:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
pushback(c);
|
2000-02-25 20:16:48 -05:00
|
|
|
if (ISDIGIT(c)) {
|
|
|
|
c = '+';
|
|
|
|
goto start_num;
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
return tUPLUS;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
pushback(c);
|
|
|
|
return '+';
|
|
|
|
|
|
|
|
case '-':
|
|
|
|
c = nextc();
|
1999-08-13 01:45:20 -04:00
|
|
|
if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
|
2002-02-19 00:39:06 -05:00
|
|
|
lex_state = EXPR_ARG;
|
1998-01-16 07:13:05 -05:00
|
|
|
if (c == '@') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tUMINUS;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return '-';
|
|
|
|
}
|
|
|
|
if (c == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id('-');
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-03-20 11:45:41 -05:00
|
|
|
if (IS_BEG() ||
|
2001-05-30 05:12:34 -04:00
|
|
|
(IS_ARG() && space_seen && !ISSPACE(c))) {
|
|
|
|
if (IS_ARG()) arg_ambiguous();
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
pushback(c);
|
2000-01-31 22:12:21 -05:00
|
|
|
if (ISDIGIT(c)) {
|
2003-01-22 22:39:25 -05:00
|
|
|
return tUMINUS_NUM;
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
return tUMINUS;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
pushback(c);
|
|
|
|
return '-';
|
|
|
|
|
|
|
|
case '.':
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
if ((c = nextc()) == '.') {
|
|
|
|
if ((c = nextc()) == '.') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tDOT3;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
1999-01-19 23:59:39 -05:00
|
|
|
return tDOT2;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
2003-02-05 03:11:27 -05:00
|
|
|
if (ISDIGIT(c)) {
|
2003-02-20 15:40:20 -05:00
|
|
|
yyerror("no .<digit> floating literal anymore; put 0 before dot");
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-02-05 03:11:27 -05:00
|
|
|
lex_state = EXPR_DOT;
|
|
|
|
return '.';
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
start_num:
|
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
|
|
case '5': case '6': case '7': case '8': case '9':
|
|
|
|
{
|
2002-01-28 04:33:56 -05:00
|
|
|
int is_float, seen_point, seen_e, nondigit;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-01-28 04:33:56 -05:00
|
|
|
is_float = seen_point = seen_e = nondigit = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_END;
|
|
|
|
newtok();
|
|
|
|
if (c == '-' || c == '+') {
|
|
|
|
tokadd(c);
|
|
|
|
c = nextc();
|
|
|
|
}
|
|
|
|
if (c == '0') {
|
2002-01-28 04:33:56 -05:00
|
|
|
int start = toklen();
|
1998-01-16 07:13:05 -05:00
|
|
|
c = nextc();
|
|
|
|
if (c == 'x' || c == 'X') {
|
|
|
|
/* hexadecimal */
|
1999-08-13 01:45:20 -04:00
|
|
|
c = nextc();
|
2002-01-28 04:33:56 -05:00
|
|
|
if (ISXDIGIT(c)) {
|
|
|
|
do {
|
|
|
|
if (c == '_') {
|
|
|
|
if (nondigit) break;
|
|
|
|
nondigit = c;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!ISXDIGIT(c)) break;
|
|
|
|
nondigit = 0;
|
|
|
|
tokadd(c);
|
2002-09-23 11:48:42 -04:00
|
|
|
} while ((c = nextc()) != -1);
|
2002-01-28 04:33:56 -05:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
pushback(c);
|
|
|
|
tokfix();
|
2002-01-28 04:33:56 -05:00
|
|
|
if (toklen() == start) {
|
2002-07-26 02:12:39 -04:00
|
|
|
yyerror("numeric literal without digits");
|
2000-12-21 22:22:25 -05:00
|
|
|
}
|
2002-01-28 04:33:56 -05:00
|
|
|
else if (nondigit) goto trailing_uc;
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_literal(rb_cstr_to_inum(tok(), 16, Qfalse));
|
1999-01-19 23:59:39 -05:00
|
|
|
return tINTEGER;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
if (c == 'b' || c == 'B') {
|
|
|
|
/* binary */
|
|
|
|
c = nextc();
|
2002-01-28 04:33:56 -05:00
|
|
|
if (c == '0' || c == '1') {
|
|
|
|
do {
|
|
|
|
if (c == '_') {
|
|
|
|
if (nondigit) break;
|
|
|
|
nondigit = c;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (c != '0' && c != '1') break;
|
|
|
|
nondigit = 0;
|
|
|
|
tokadd(c);
|
2002-09-23 11:48:42 -04:00
|
|
|
} while ((c = nextc()) != -1);
|
2002-01-28 04:33:56 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
pushback(c);
|
|
|
|
tokfix();
|
2002-01-28 04:33:56 -05:00
|
|
|
if (toklen() == start) {
|
2000-12-21 22:22:25 -05:00
|
|
|
yyerror("numeric literal without digits");
|
|
|
|
}
|
2002-01-28 04:33:56 -05:00
|
|
|
else if (nondigit) goto trailing_uc;
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_literal(rb_cstr_to_inum(tok(), 2, Qfalse));
|
1999-08-13 01:45:20 -04:00
|
|
|
return tINTEGER;
|
|
|
|
}
|
2002-07-26 02:12:39 -04:00
|
|
|
if (c == 'd' || c == 'D') {
|
|
|
|
/* decimal */
|
|
|
|
c = nextc();
|
|
|
|
if (ISDIGIT(c)) {
|
|
|
|
do {
|
|
|
|
if (c == '_') {
|
|
|
|
if (nondigit) break;
|
|
|
|
nondigit = c;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!ISDIGIT(c)) break;
|
|
|
|
nondigit = 0;
|
|
|
|
tokadd(c);
|
2002-09-23 11:48:42 -04:00
|
|
|
} while ((c = nextc()) != -1);
|
2002-07-26 02:12:39 -04:00
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
tokfix();
|
|
|
|
if (toklen() == start) {
|
|
|
|
yyerror("numeric literal without digits");
|
|
|
|
}
|
|
|
|
else if (nondigit) goto trailing_uc;
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_literal(rb_cstr_to_inum(tok(), 10, Qfalse));
|
2002-07-26 02:12:39 -04:00
|
|
|
return tINTEGER;
|
|
|
|
}
|
|
|
|
if (c == '_') {
|
|
|
|
/* 0_0 */
|
|
|
|
goto octal_number;
|
|
|
|
}
|
|
|
|
if (c == 'o' || c == 'O') {
|
|
|
|
/* prefixed octal */
|
|
|
|
c = nextc();
|
|
|
|
if (c == '_') {
|
|
|
|
yyerror("numeric literal without digits");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (c >= '0' && c <= '7') {
|
1999-08-13 01:45:20 -04:00
|
|
|
/* octal */
|
2002-07-26 02:12:39 -04:00
|
|
|
octal_number:
|
1999-08-13 01:45:20 -04:00
|
|
|
do {
|
2000-12-21 22:22:25 -05:00
|
|
|
if (c == '_') {
|
2002-01-28 04:33:56 -05:00
|
|
|
if (nondigit) break;
|
|
|
|
nondigit = c;
|
2000-12-21 22:22:25 -05:00
|
|
|
continue;
|
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
if (c < '0' || c > '7') break;
|
2002-01-28 04:33:56 -05:00
|
|
|
nondigit = 0;
|
1999-08-13 01:45:20 -04:00
|
|
|
tokadd(c);
|
2002-09-23 11:48:42 -04:00
|
|
|
} while ((c = nextc()) != -1);
|
2002-01-28 04:33:56 -05:00
|
|
|
if (toklen() > start) {
|
|
|
|
pushback(c);
|
|
|
|
tokfix();
|
|
|
|
if (nondigit) goto trailing_uc;
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_literal(rb_cstr_to_inum(tok(), 8, Qfalse));
|
2002-01-28 04:33:56 -05:00
|
|
|
return tINTEGER;
|
|
|
|
}
|
2002-06-10 06:06:12 -04:00
|
|
|
if (nondigit) {
|
|
|
|
pushback(c);
|
|
|
|
goto trailing_uc;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
if (c > '7' && c <= '9') {
|
1998-01-16 07:19:22 -05:00
|
|
|
yyerror("Illegal octal digit");
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-01-28 04:33:56 -05:00
|
|
|
else if (c == '.' || c == 'e' || c == 'E') {
|
1998-01-16 07:13:05 -05:00
|
|
|
tokadd('0');
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pushback(c);
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_literal(INT2FIX(0));
|
1999-01-19 23:59:39 -05:00
|
|
|
return tINTEGER;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
switch (c) {
|
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
|
|
case '5': case '6': case '7': case '8': case '9':
|
2002-01-28 04:33:56 -05:00
|
|
|
nondigit = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
tokadd(c);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '.':
|
2002-01-28 04:33:56 -05:00
|
|
|
if (nondigit) goto trailing_uc;
|
1999-01-19 23:59:39 -05:00
|
|
|
if (seen_point || seen_e) {
|
1998-01-16 07:13:05 -05:00
|
|
|
goto decode_num;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int c0 = nextc();
|
1999-01-19 23:59:39 -05:00
|
|
|
if (!ISDIGIT(c0)) {
|
1998-01-16 07:13:05 -05:00
|
|
|
pushback(c0);
|
|
|
|
goto decode_num;
|
|
|
|
}
|
|
|
|
c = c0;
|
|
|
|
}
|
|
|
|
tokadd('.');
|
|
|
|
tokadd(c);
|
|
|
|
is_float++;
|
|
|
|
seen_point++;
|
2002-01-28 04:33:56 -05:00
|
|
|
nondigit = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'e':
|
|
|
|
case 'E':
|
2002-01-28 04:33:56 -05:00
|
|
|
if (nondigit) {
|
|
|
|
pushback(c);
|
|
|
|
c = nondigit;
|
|
|
|
goto decode_num;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
if (seen_e) {
|
|
|
|
goto decode_num;
|
|
|
|
}
|
|
|
|
tokadd(c);
|
|
|
|
seen_e++;
|
|
|
|
is_float++;
|
2002-01-28 04:33:56 -05:00
|
|
|
nondigit = c;
|
|
|
|
c = nextc();
|
|
|
|
if (c != '-' && c != '+') continue;
|
|
|
|
tokadd(c);
|
|
|
|
nondigit = c;
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
|
2000-12-21 22:22:25 -05:00
|
|
|
case '_': /* `_' in number just ignored */
|
2002-01-28 04:33:56 -05:00
|
|
|
if (nondigit) goto decode_num;
|
|
|
|
nondigit = c;
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
goto decode_num;
|
|
|
|
}
|
|
|
|
c = nextc();
|
|
|
|
}
|
|
|
|
|
|
|
|
decode_num:
|
|
|
|
pushback(c);
|
|
|
|
tokfix();
|
2002-01-28 04:33:56 -05:00
|
|
|
if (nondigit) {
|
|
|
|
char tmp[30];
|
2000-12-21 22:22:25 -05:00
|
|
|
trailing_uc:
|
2002-01-28 04:33:56 -05:00
|
|
|
sprintf(tmp, "trailing `%c' in number", nondigit);
|
|
|
|
yyerror(tmp);
|
2000-12-21 22:22:25 -05:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
if (is_float) {
|
1999-08-13 01:45:20 -04:00
|
|
|
double d = strtod(tok(), 0);
|
|
|
|
if (errno == ERANGE) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_warnS("Float %s out of range", tok());
|
1999-08-13 01:45:20 -04:00
|
|
|
errno = 0;
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_literal(rb_float_new(d));
|
1999-01-19 23:59:39 -05:00
|
|
|
return tFLOAT;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_literal(rb_cstr_to_inum(tok(), 10, Qfalse));
|
1999-01-19 23:59:39 -05:00
|
|
|
return tINTEGER;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
case ']':
|
|
|
|
case '}':
|
|
|
|
case ')':
|
2001-05-30 05:12:34 -04:00
|
|
|
COND_LEXPOP();
|
|
|
|
CMDARG_LEXPOP();
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_END;
|
|
|
|
return c;
|
|
|
|
|
|
|
|
case ':':
|
|
|
|
c = nextc();
|
|
|
|
if (c == ':') {
|
2004-03-20 11:45:41 -05:00
|
|
|
if (IS_BEG() ||
|
2003-08-14 13:20:14 -04:00
|
|
|
lex_state == EXPR_CLASS || (IS_ARG() && space_seen)) {
|
1999-01-19 23:59:39 -05:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
return tCOLON3;
|
|
|
|
}
|
|
|
|
lex_state = EXPR_DOT;
|
|
|
|
return tCOLON2;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-06-01 02:47:32 -04:00
|
|
|
if (lex_state == EXPR_END || lex_state == EXPR_ENDARG || ISSPACE(c)) {
|
2002-10-23 06:17:30 -04:00
|
|
|
pushback(c);
|
1999-01-19 23:59:39 -05:00
|
|
|
lex_state = EXPR_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
return ':';
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2002-10-23 06:17:30 -04:00
|
|
|
switch (c) {
|
|
|
|
case '\'':
|
|
|
|
lex_strterm = NEW_STRTERM(str_ssym, c, 0);
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
lex_strterm = NEW_STRTERM(str_dsym, c, 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pushback(c);
|
|
|
|
break;
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
lex_state = EXPR_FNAME;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tSYMBEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '/':
|
2004-03-20 11:45:41 -05:00
|
|
|
if (IS_BEG()) {
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tREGEXP_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
if ((c = nextc()) == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id('/');
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-05-30 00:24:17 -04:00
|
|
|
pushback(c);
|
2001-05-30 05:12:34 -04:00
|
|
|
if (IS_ARG() && space_seen) {
|
2000-05-30 00:24:17 -04:00
|
|
|
if (!ISSPACE(c)) {
|
2000-12-12 02:42:35 -05:00
|
|
|
arg_ambiguous();
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tREGEXP_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
2002-02-19 00:39:06 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG; break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
return '/';
|
|
|
|
|
|
|
|
case '^':
|
2000-11-10 02:16:52 -05:00
|
|
|
if ((c = nextc()) == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id('^');
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-19 00:39:06 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG; break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
pushback(c);
|
2000-11-10 02:16:52 -05:00
|
|
|
return '^';
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case ';':
|
2001-05-30 05:12:34 -04:00
|
|
|
command_start = Qtrue;
|
|
|
|
case ',':
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
return c;
|
|
|
|
|
|
|
|
case '~':
|
1999-08-13 01:45:20 -04:00
|
|
|
if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
|
1998-01-16 07:13:05 -05:00
|
|
|
if ((c = nextc()) != '@') {
|
|
|
|
pushback(c);
|
|
|
|
}
|
|
|
|
}
|
2002-02-19 00:39:06 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG; break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
return '~';
|
|
|
|
|
|
|
|
case '(':
|
2001-05-30 05:12:34 -04:00
|
|
|
command_start = Qtrue;
|
2004-03-20 11:45:41 -05:00
|
|
|
if (IS_BEG()) {
|
1999-01-19 23:59:39 -05:00
|
|
|
c = tLPAREN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-05-30 05:12:34 -04:00
|
|
|
else if (space_seen) {
|
2003-01-30 23:00:17 -05:00
|
|
|
if (lex_state == EXPR_CMDARG) {
|
|
|
|
c = tLPAREN_ARG;
|
|
|
|
}
|
|
|
|
else if (lex_state == EXPR_ARG) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_warn0("don't put space before argument parentheses");
|
2003-10-14 22:27:56 -04:00
|
|
|
c = '(';
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-05-30 05:12:34 -04:00
|
|
|
COND_PUSH(0);
|
|
|
|
CMDARG_PUSH(0);
|
2000-05-30 00:24:17 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
return c;
|
|
|
|
|
|
|
|
case '[':
|
1999-08-13 01:45:20 -04:00
|
|
|
if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
|
2002-02-19 00:39:06 -05:00
|
|
|
lex_state = EXPR_ARG;
|
1998-01-16 07:13:05 -05:00
|
|
|
if ((c = nextc()) == ']') {
|
|
|
|
if ((c = nextc()) == '=') {
|
1999-01-19 23:59:39 -05:00
|
|
|
return tASET;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
1999-01-19 23:59:39 -05:00
|
|
|
return tAREF;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return '[';
|
|
|
|
}
|
2004-03-20 11:45:41 -05:00
|
|
|
else if (IS_BEG()) {
|
1999-01-19 23:59:39 -05:00
|
|
|
c = tLBRACK;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-05-30 05:12:34 -04:00
|
|
|
else if (IS_ARG() && space_seen) {
|
1999-01-19 23:59:39 -05:00
|
|
|
c = tLBRACK;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
lex_state = EXPR_BEG;
|
2001-05-30 05:12:34 -04:00
|
|
|
COND_PUSH(0);
|
|
|
|
CMDARG_PUSH(0);
|
1998-01-16 07:13:05 -05:00
|
|
|
return c;
|
|
|
|
|
|
|
|
case '{':
|
2002-07-25 23:13:06 -04:00
|
|
|
if (IS_ARG() || lex_state == EXPR_END)
|
|
|
|
c = '{'; /* block (primary) */
|
|
|
|
else if (lex_state == EXPR_ENDARG)
|
|
|
|
c = tLBRACE_ARG; /* block (expr) */
|
|
|
|
else
|
|
|
|
c = tLBRACE; /* hash */
|
2001-05-30 05:12:34 -04:00
|
|
|
COND_PUSH(0);
|
|
|
|
CMDARG_PUSH(0);
|
1998-01-16 07:13:05 -05:00
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
return c;
|
|
|
|
|
|
|
|
case '\\':
|
|
|
|
c = nextc();
|
|
|
|
if (c == '\n') {
|
|
|
|
space_seen = 1;
|
2004-09-19 23:03:12 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
ripper_dispatch_scan_event(parser, tSP);
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
goto retry; /* skip \\n */
|
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
return '\\';
|
|
|
|
|
|
|
|
case '%':
|
2004-03-20 11:45:41 -05:00
|
|
|
if (IS_BEG()) {
|
1998-01-16 07:13:05 -05:00
|
|
|
int term;
|
1999-01-19 23:59:39 -05:00
|
|
|
int paren;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
c = nextc();
|
|
|
|
quotation:
|
1999-01-19 23:59:39 -05:00
|
|
|
if (!ISALNUM(c)) {
|
1998-01-16 07:13:05 -05:00
|
|
|
term = c;
|
1999-01-19 23:59:39 -05:00
|
|
|
c = 'Q';
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
term = nextc();
|
2001-10-15 11:15:45 -04:00
|
|
|
if (ISALNUM(term) || ismbchar(term)) {
|
|
|
|
yyerror("unknown type of %string");
|
|
|
|
return 0;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
if (c == -1 || term == -1) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "unterminated quoted string meets end of file");
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
paren = term;
|
1998-01-16 07:13:05 -05:00
|
|
|
if (term == '(') term = ')';
|
|
|
|
else if (term == '[') term = ']';
|
|
|
|
else if (term == '{') term = '}';
|
|
|
|
else if (term == '<') term = '>';
|
1999-08-13 01:45:20 -04:00
|
|
|
else paren = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'Q':
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_dquote, term, paren);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tSTRING_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case 'q':
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_squote, term, paren);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tSTRING_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2002-06-26 04:01:00 -04:00
|
|
|
case 'W':
|
|
|
|
lex_strterm = NEW_STRTERM(str_dquote | STR_FUNC_QWORDS, term, paren);
|
|
|
|
do {c = nextc();} while (ISSPACE(c));
|
|
|
|
pushback(c);
|
|
|
|
return tWORDS_BEG;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
case 'w':
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_squote | STR_FUNC_QWORDS, term, paren);
|
|
|
|
do {c = nextc();} while (ISSPACE(c));
|
|
|
|
pushback(c);
|
|
|
|
return tQWORDS_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case 'x':
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_xquote, term, paren);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tXSTRING_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case 'r':
|
2002-06-26 04:01:00 -04:00
|
|
|
lex_strterm = NEW_STRTERM(str_regexp, term, paren);
|
2002-06-24 03:20:42 -04:00
|
|
|
return tREGEXP_BEG;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-10-23 06:17:30 -04:00
|
|
|
case 's':
|
|
|
|
lex_strterm = NEW_STRTERM(str_ssym, term, paren);
|
|
|
|
lex_state = EXPR_FNAME;
|
|
|
|
return tSYMBEG;
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
default:
|
1999-01-19 23:59:39 -05:00
|
|
|
yyerror("unknown type of %string");
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((c = nextc()) == '=') {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id('%');
|
2002-06-18 02:29:07 -04:00
|
|
|
lex_state = EXPR_BEG;
|
1999-01-19 23:59:39 -05:00
|
|
|
return tOP_ASGN;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-05-30 05:12:34 -04:00
|
|
|
if (IS_ARG() && space_seen && !ISSPACE(c)) {
|
1999-08-13 01:45:20 -04:00
|
|
|
goto quotation;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-02-19 00:39:06 -05:00
|
|
|
switch (lex_state) {
|
|
|
|
case EXPR_FNAME: case EXPR_DOT:
|
|
|
|
lex_state = EXPR_ARG; break;
|
|
|
|
default:
|
|
|
|
lex_state = EXPR_BEG; break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
pushback(c);
|
|
|
|
return '%';
|
|
|
|
|
|
|
|
case '$':
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
newtok();
|
|
|
|
c = nextc();
|
|
|
|
switch (c) {
|
1998-01-16 07:19:22 -05:00
|
|
|
case '_': /* $_: last read line string */
|
2000-09-15 02:00:30 -04:00
|
|
|
c = nextc();
|
|
|
|
if (is_identchar(c)) {
|
|
|
|
tokadd('$');
|
|
|
|
tokadd('_');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pushback(c);
|
|
|
|
c = '_';
|
2000-09-19 03:54:28 -04:00
|
|
|
/* fall through */
|
|
|
|
case '~': /* $~: match-data */
|
|
|
|
local_cnt(c);
|
1998-01-16 07:13:05 -05:00
|
|
|
/* fall through */
|
|
|
|
case '*': /* $*: argv */
|
|
|
|
case '$': /* $$: pid */
|
|
|
|
case '?': /* $?: last status */
|
|
|
|
case '!': /* $!: error string */
|
|
|
|
case '@': /* $@: error position */
|
|
|
|
case '/': /* $/: input record separator */
|
|
|
|
case '\\': /* $\: output record separator */
|
|
|
|
case ';': /* $;: field separator */
|
|
|
|
case ',': /* $,: output field separator */
|
|
|
|
case '.': /* $.: last read line number */
|
|
|
|
case '=': /* $=: ignorecase */
|
|
|
|
case ':': /* $:: load path */
|
|
|
|
case '<': /* $<: reading filename */
|
|
|
|
case '>': /* $>: default output handle */
|
|
|
|
case '\"': /* $": already loaded files */
|
|
|
|
tokadd('$');
|
|
|
|
tokadd(c);
|
|
|
|
tokfix();
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id(rb_intern(tok()));
|
1999-01-19 23:59:39 -05:00
|
|
|
return tGVAR;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '-':
|
|
|
|
tokadd('$');
|
|
|
|
tokadd(c);
|
|
|
|
c = nextc();
|
|
|
|
tokadd(c);
|
|
|
|
tokfix();
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id(rb_intern(tok()));
|
2004-10-31 01:22:58 -04:00
|
|
|
if (!is_global_id(yylval_id())) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "invalid global variable `%s'", rb_id2name(yylval.id));
|
2004-03-02 23:55:35 -05:00
|
|
|
return 0;
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
return tGVAR;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '&': /* $&: last match */
|
|
|
|
case '`': /* $`: string before last match */
|
|
|
|
case '\'': /* $': string after last match */
|
|
|
|
case '+': /* $+: string matches last paren. */
|
2004-10-31 01:22:58 -04:00
|
|
|
set_yylval_node(NEW_BACK_REF(c));
|
1999-01-19 23:59:39 -05:00
|
|
|
return tBACK_REF;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case '1': case '2': case '3':
|
|
|
|
case '4': case '5': case '6':
|
|
|
|
case '7': case '8': case '9':
|
2000-05-09 00:53:16 -04:00
|
|
|
tokadd('$');
|
2002-12-30 17:56:21 -05:00
|
|
|
do {
|
1998-01-16 07:13:05 -05:00
|
|
|
tokadd(c);
|
|
|
|
c = nextc();
|
2002-12-30 17:56:21 -05:00
|
|
|
} while (ISDIGIT(c));
|
1998-01-16 07:13:05 -05:00
|
|
|
pushback(c);
|
|
|
|
tokfix();
|
2004-10-31 01:22:58 -04:00
|
|
|
set_yylval_node(NEW_NTH_REF(atoi(tok()+1)));
|
1999-01-19 23:59:39 -05:00
|
|
|
return tNTH_REF;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
default:
|
|
|
|
if (!is_identchar(c)) {
|
|
|
|
pushback(c);
|
|
|
|
return '$';
|
|
|
|
}
|
|
|
|
case '0':
|
|
|
|
tokadd('$');
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '@':
|
|
|
|
c = nextc();
|
2000-02-18 01:59:36 -05:00
|
|
|
newtok();
|
|
|
|
tokadd('@');
|
|
|
|
if (c == '@') {
|
|
|
|
tokadd('@');
|
|
|
|
c = nextc();
|
|
|
|
}
|
2000-07-11 04:27:06 -04:00
|
|
|
if (ISDIGIT(c)) {
|
2002-06-12 23:55:44 -04:00
|
|
|
if (tokidx == 1) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c);
|
2002-06-12 23:55:44 -04:00
|
|
|
}
|
|
|
|
else {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "`@@%c' is not allowed as a class variable name", c);
|
2002-06-12 23:55:44 -04:00
|
|
|
}
|
2000-07-11 04:27:06 -04:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
if (!is_identchar(c)) {
|
|
|
|
pushback(c);
|
|
|
|
return '@';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2002-12-30 13:19:08 -05:00
|
|
|
case '_':
|
2002-12-30 17:56:21 -05:00
|
|
|
if (was_bol() && whole_match_p("__END__", 7, 0)) {
|
2002-12-30 13:19:08 -05:00
|
|
|
ruby__end__seen = 1;
|
|
|
|
lex_lastline = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifndef RIPPER
|
2002-12-30 13:19:08 -05:00
|
|
|
return -1;
|
2004-09-12 11:21:49 -04:00
|
|
|
#else
|
2004-09-19 23:03:12 -04:00
|
|
|
lex_goto_eol(parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
ripper_dispatch_scan_event(parser, k__END__);
|
|
|
|
return 0;
|
|
|
|
#endif
|
2002-12-30 13:19:08 -05:00
|
|
|
}
|
|
|
|
newtok();
|
|
|
|
break;
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
default:
|
2002-12-30 17:56:21 -05:00
|
|
|
if (!is_identchar(c)) {
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_compile_error(PARSER_ARG "Invalid char `\\%03o' in expression", c);
|
1998-01-16 07:13:05 -05:00
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
newtok();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-12-30 17:56:21 -05:00
|
|
|
do {
|
1998-01-16 07:13:05 -05:00
|
|
|
tokadd(c);
|
|
|
|
if (ismbchar(c)) {
|
1999-01-19 23:59:39 -05:00
|
|
|
int i, len = mbclen(c)-1;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
c = nextc();
|
|
|
|
tokadd(c);
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
c = nextc();
|
2002-12-30 17:56:21 -05:00
|
|
|
} while (is_identchar(c));
|
1999-08-13 01:45:20 -04:00
|
|
|
if ((c == '!' || c == '?') && is_identchar(tok()[0]) && !peek('=')) {
|
1998-01-16 07:13:05 -05:00
|
|
|
tokadd(c);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pushback(c);
|
|
|
|
}
|
|
|
|
tokfix();
|
|
|
|
|
|
|
|
{
|
2000-01-17 03:37:53 -05:00
|
|
|
int result = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
switch (tok()[0]) {
|
|
|
|
case '$':
|
|
|
|
lex_state = EXPR_END;
|
1999-01-19 23:59:39 -05:00
|
|
|
result = tGVAR;
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
case '@':
|
|
|
|
lex_state = EXPR_END;
|
2000-02-18 01:59:36 -05:00
|
|
|
if (tok()[1] == '@')
|
2000-03-23 03:37:35 -05:00
|
|
|
result = tCVAR;
|
2000-02-18 01:59:36 -05:00
|
|
|
else
|
|
|
|
result = tIVAR;
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
2001-09-05 02:54:57 -04:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
default:
|
2001-09-05 02:54:57 -04:00
|
|
|
if (toklast() == '!' || toklast() == '?') {
|
|
|
|
result = tFID;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (lex_state == EXPR_FNAME) {
|
|
|
|
if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
|
2002-09-23 11:48:42 -04:00
|
|
|
(!peek('=') || (lex_p + 1 < lex_pend && lex_p[1] == '>'))) {
|
2001-09-05 02:54:57 -04:00
|
|
|
result = tIDENTIFIER;
|
|
|
|
tokadd(c);
|
2003-05-21 12:01:49 -04:00
|
|
|
tokfix();
|
2001-09-05 02:54:57 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
pushback(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (result == 0 && ISUPPER(tok()[0])) {
|
|
|
|
result = tCONSTANT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
result = tIDENTIFIER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (lex_state != EXPR_DOT) {
|
2001-09-05 02:54:57 -04:00
|
|
|
struct kwtable *kw;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
/* See if it is a reserved word. */
|
|
|
|
kw = rb_reserved_word(tok(), toklen());
|
|
|
|
if (kw) {
|
2004-09-12 11:21:49 -04:00
|
|
|
enum lex_state_e state = lex_state;
|
1999-08-13 01:45:20 -04:00
|
|
|
lex_state = kw->state;
|
|
|
|
if (state == EXPR_FNAME) {
|
2004-09-12 11:21:49 -04:00
|
|
|
set_yylval_id(rb_intern(kw->name));
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2001-01-26 00:02:19 -05:00
|
|
|
if (kw->id[0] == kDO) {
|
|
|
|
if (COND_P()) return kDO_COND;
|
2003-01-30 23:00:17 -05:00
|
|
|
if (CMDARG_P() && state != EXPR_CMDARG)
|
2001-06-07 04:40:54 -04:00
|
|
|
return kDO_BLOCK;
|
2002-06-12 05:22:20 -04:00
|
|
|
if (state == EXPR_ENDARG)
|
|
|
|
return kDO_BLOCK;
|
2001-01-26 00:02:19 -05:00
|
|
|
return kDO;
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
2004-03-20 11:45:41 -05:00
|
|
|
if (state == EXPR_BEG || state == EXPR_TERNARY)
|
2001-05-02 00:22:21 -04:00
|
|
|
return kw->id[0];
|
|
|
|
else {
|
|
|
|
if (kw->id[0] != kw->id[1])
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
return kw->id[1];
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (lex_state == EXPR_BEG ||
|
2003-01-30 23:00:17 -05:00
|
|
|
lex_state == EXPR_ARG ||
|
|
|
|
lex_state == EXPR_CMDARG) {
|
2004-03-20 11:45:41 -05:00
|
|
|
if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) {
|
|
|
|
lex_state = EXPR_BEG;
|
|
|
|
nextc();
|
2004-10-31 01:22:58 -04:00
|
|
|
set_yylval_id(rb_intern(tok()));
|
2004-03-20 11:45:41 -05:00
|
|
|
return tLABEL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IS_BEG() ||
|
|
|
|
lex_state == EXPR_DOT ||
|
|
|
|
IS_ARG()) {
|
2003-01-30 23:00:17 -05:00
|
|
|
if (cmd_state) {
|
|
|
|
lex_state = EXPR_CMDARG;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lex_state = EXPR_ARG;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
}
|
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
{
|
|
|
|
ID ident = rb_intern(tok());
|
|
|
|
|
|
|
|
set_yylval_id(ident);
|
|
|
|
if (is_local_id(ident) && lvar_defined(ident)) {
|
|
|
|
lex_state = EXPR_END;
|
|
|
|
}
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
#if YYPURE
|
|
|
|
static int
|
|
|
|
yylex(lval, p)
|
|
|
|
void *lval, *p;
|
|
|
|
#else
|
|
|
|
yylex(p)
|
|
|
|
void *p;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
struct parser_params *parser = (struct parser_params*)p;
|
|
|
|
int t;
|
|
|
|
|
|
|
|
#if YYPURE
|
|
|
|
parser->parser_yylval = (union tmpyystype*)lval;
|
|
|
|
parser->parser_yylval->val = Qundef;
|
|
|
|
#endif
|
|
|
|
t = parser_yylex(parser);
|
|
|
|
#ifdef RIPPER
|
2004-09-20 03:59:30 -04:00
|
|
|
if (!NIL_P(parser->delayed)) {
|
|
|
|
ripper_dispatch_delayed_token(parser, t);
|
|
|
|
return t;
|
|
|
|
}
|
2004-09-20 01:51:13 -04:00
|
|
|
if (t != 0)
|
2004-09-19 23:03:12 -04:00
|
|
|
ripper_dispatch_scan_event(parser, t);
|
2004-09-17 05:24:13 -04:00
|
|
|
#endif
|
2004-09-19 23:03:12 -04:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifndef RIPPER
|
1998-01-16 07:13:05 -05:00
|
|
|
NODE*
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_node_newnode(type, a0, a1, a2)
|
1998-01-16 07:13:05 -05:00
|
|
|
enum node_type type;
|
2003-07-04 11:30:35 -04:00
|
|
|
VALUE a0, a1, a2;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
NODE *n = (NODE*)rb_newobj();
|
|
|
|
|
|
|
|
n->flags |= T_NODE;
|
|
|
|
nd_set_type(n, type);
|
1999-01-19 23:59:39 -05:00
|
|
|
nd_set_line(n, ruby_sourceline);
|
|
|
|
n->nd_file = ruby_sourcefile;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2003-07-04 11:30:35 -04:00
|
|
|
n->u1.value = a0;
|
|
|
|
n->u2.value = a1;
|
|
|
|
n->u3.value = a2;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static enum node_type
|
1998-01-16 07:13:05 -05:00
|
|
|
nodetype(node) /* for debug */
|
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
return (enum node_type)nd_type(node);
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static int
|
1998-01-16 07:13:05 -05:00
|
|
|
nodeline(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
return nd_line(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
static NODE*
|
|
|
|
newline_node(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
2004-01-21 11:47:23 -05:00
|
|
|
FL_SET(node, NODE_NEWLINE);
|
|
|
|
return node;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fixpos(node, orig)
|
|
|
|
NODE *node, *orig;
|
|
|
|
{
|
|
|
|
if (!node) return;
|
|
|
|
if (!orig) return;
|
2002-01-18 09:24:01 -05:00
|
|
|
if (orig == (NODE*)1) return;
|
1998-01-16 07:19:22 -05:00
|
|
|
node->nd_file = orig->nd_file;
|
1998-01-16 07:13:05 -05:00
|
|
|
nd_set_line(node, nd_line(orig));
|
|
|
|
}
|
|
|
|
|
2003-04-21 04:44:38 -04:00
|
|
|
static void
|
|
|
|
parser_warning(node, mesg)
|
|
|
|
NODE *node;
|
|
|
|
const char *mesg;
|
|
|
|
{
|
|
|
|
int line = ruby_sourceline;
|
|
|
|
ruby_sourceline = nd_line(node);
|
|
|
|
rb_warning(mesg);
|
|
|
|
ruby_sourceline = line;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
parser_warn(node, mesg)
|
|
|
|
NODE *node;
|
|
|
|
const char *mesg;
|
|
|
|
{
|
|
|
|
int line = ruby_sourceline;
|
|
|
|
ruby_sourceline = nd_line(node);
|
|
|
|
rb_warn(mesg);
|
|
|
|
ruby_sourceline = line;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static NODE*
|
|
|
|
block_append(head, tail)
|
|
|
|
NODE *head, *tail;
|
|
|
|
{
|
2004-02-02 21:23:20 -05:00
|
|
|
NODE *end, *h = head, *nd;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
if (tail == 0) return head;
|
|
|
|
|
2002-09-20 10:03:45 -04:00
|
|
|
if (h == 0) return tail;
|
|
|
|
switch (nd_type(h)) {
|
|
|
|
case NODE_LIT:
|
|
|
|
case NODE_STR:
|
2004-10-02 07:34:13 -04:00
|
|
|
case NODE_SELF:
|
|
|
|
case NODE_TRUE:
|
|
|
|
case NODE_FALSE:
|
|
|
|
case NODE_NIL:
|
2003-04-21 04:44:38 -04:00
|
|
|
parser_warning(h, "unused literal ignored");
|
2002-09-20 10:03:45 -04:00
|
|
|
return tail;
|
|
|
|
default:
|
2004-01-21 11:47:23 -05:00
|
|
|
h = end = NEW_BLOCK(head);
|
1998-01-16 07:13:05 -05:00
|
|
|
end->nd_end = end;
|
|
|
|
fixpos(end, head);
|
|
|
|
head = end;
|
2002-09-20 10:03:45 -04:00
|
|
|
break;
|
|
|
|
case NODE_BLOCK:
|
|
|
|
end = h->nd_end;
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2004-02-02 21:23:20 -05:00
|
|
|
nd = end->nd_head;
|
|
|
|
switch (nd_type(nd)) {
|
|
|
|
case NODE_RETURN:
|
|
|
|
case NODE_BREAK:
|
|
|
|
case NODE_NEXT:
|
|
|
|
case NODE_REDO:
|
|
|
|
case NODE_RETRY:
|
|
|
|
if (RTEST(ruby_verbose)) {
|
2003-04-21 04:44:38 -04:00
|
|
|
parser_warning(nd, "statement not reached");
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-02-02 21:23:20 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (nd_type(tail) != NODE_BLOCK) {
|
|
|
|
tail = NEW_BLOCK(tail);
|
|
|
|
tail->nd_end = tail;
|
|
|
|
}
|
|
|
|
end->nd_next = tail;
|
2004-01-21 11:47:23 -05:00
|
|
|
h->nd_end = tail->nd_end;
|
1998-01-16 07:13:05 -05:00
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
2002-07-26 02:12:39 -04:00
|
|
|
/* append item to the list */
|
1998-01-16 07:13:05 -05:00
|
|
|
static NODE*
|
2002-07-26 02:12:39 -04:00
|
|
|
list_append(list, item)
|
|
|
|
NODE *list, *item;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
NODE *last;
|
|
|
|
|
2002-07-26 02:12:39 -04:00
|
|
|
if (list == 0) return NEW_LIST(item);
|
2003-01-14 02:45:19 -05:00
|
|
|
if (list->nd_next) {
|
|
|
|
last = list->nd_next->nd_end;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
last = list;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2002-07-26 02:12:39 -04:00
|
|
|
list->nd_alen += 1;
|
2003-01-14 02:45:19 -05:00
|
|
|
last->nd_next = NEW_LIST(item);
|
|
|
|
list->nd_next->nd_end = last->nd_next;
|
2002-07-26 02:12:39 -04:00
|
|
|
return list;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2002-07-26 02:12:39 -04:00
|
|
|
/* concat two lists */
|
1998-01-16 07:13:05 -05:00
|
|
|
static NODE*
|
|
|
|
list_concat(head, tail)
|
|
|
|
NODE *head, *tail;
|
|
|
|
{
|
|
|
|
NODE *last;
|
|
|
|
|
2003-01-14 02:45:19 -05:00
|
|
|
if (head->nd_next) {
|
|
|
|
last = head->nd_next->nd_end;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
last = head;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
head->nd_alen += tail->nd_alen;
|
2003-01-14 02:45:19 -05:00
|
|
|
last->nd_next = tail;
|
|
|
|
if (tail->nd_next) {
|
|
|
|
head->nd_next->nd_end = tail->nd_next->nd_end;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
head->nd_next->nd_end = tail;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
2002-09-20 10:03:45 -04:00
|
|
|
/* concat two string literals */
|
2002-06-24 03:20:42 -04:00
|
|
|
static NODE *
|
2002-09-20 10:03:45 -04:00
|
|
|
literal_concat(head, tail)
|
2002-06-24 03:20:42 -04:00
|
|
|
NODE *head, *tail;
|
|
|
|
{
|
2002-09-20 10:03:45 -04:00
|
|
|
enum node_type htype;
|
2002-06-24 03:20:42 -04:00
|
|
|
|
|
|
|
if (!head) return tail;
|
|
|
|
if (!tail) return head;
|
|
|
|
|
2002-09-20 10:03:45 -04:00
|
|
|
htype = nd_type(head);
|
|
|
|
if (htype == NODE_EVSTR) {
|
|
|
|
NODE *node = NEW_DSTR(rb_str_new(0, 0));
|
2003-01-14 02:45:19 -05:00
|
|
|
head = list_append(node, head);
|
2002-09-20 10:03:45 -04:00
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
switch (nd_type(tail)) {
|
|
|
|
case NODE_STR:
|
2002-09-20 10:03:45 -04:00
|
|
|
if (htype == NODE_STR) {
|
2002-06-24 03:20:42 -04:00
|
|
|
rb_str_concat(head->nd_lit, tail->nd_lit);
|
|
|
|
rb_gc_force_recycle((VALUE)tail);
|
|
|
|
}
|
2002-09-20 10:03:45 -04:00
|
|
|
else {
|
|
|
|
list_append(head, tail);
|
|
|
|
}
|
2002-09-23 11:48:42 -04:00
|
|
|
break;
|
2002-06-24 03:20:42 -04:00
|
|
|
|
2002-09-20 10:03:45 -04:00
|
|
|
case NODE_DSTR:
|
|
|
|
if (htype == NODE_STR) {
|
|
|
|
rb_str_concat(head->nd_lit, tail->nd_lit);
|
|
|
|
tail->nd_lit = head->nd_lit;
|
|
|
|
rb_gc_force_recycle((VALUE)head);
|
|
|
|
head = tail;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nd_set_type(tail, NODE_ARRAY);
|
|
|
|
tail->nd_head = NEW_STR(tail->nd_lit);
|
|
|
|
list_concat(head, tail);
|
|
|
|
}
|
2002-09-23 11:48:42 -04:00
|
|
|
break;
|
2002-09-20 10:03:45 -04:00
|
|
|
|
|
|
|
case NODE_EVSTR:
|
|
|
|
if (htype == NODE_STR) {
|
|
|
|
nd_set_type(head, NODE_DSTR);
|
2004-05-18 01:00:58 -04:00
|
|
|
head->nd_alen = 1;
|
2002-09-20 10:03:45 -04:00
|
|
|
}
|
|
|
|
list_append(head, tail);
|
2002-09-23 11:48:42 -04:00
|
|
|
break;
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
2002-09-23 11:48:42 -04:00
|
|
|
return head;
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
|
2003-05-21 12:01:49 -04:00
|
|
|
static NODE *
|
|
|
|
evstr2dstr(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
if (nd_type(node) == NODE_EVSTR) {
|
|
|
|
node = list_append(NEW_DSTR(rb_str_new(0, 0)), node);
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2002-06-24 03:20:42 -04:00
|
|
|
static NODE *
|
2002-09-20 10:03:45 -04:00
|
|
|
new_evstr(node)
|
|
|
|
NODE *node;
|
2002-06-24 03:20:42 -04:00
|
|
|
{
|
2002-09-23 11:48:42 -04:00
|
|
|
NODE *head = node;
|
2002-06-24 03:20:42 -04:00
|
|
|
|
2002-09-20 10:03:45 -04:00
|
|
|
if (node) {
|
|
|
|
switch (nd_type(node)) {
|
|
|
|
case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
|
|
|
|
return node;
|
|
|
|
}
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
2002-09-23 11:48:42 -04:00
|
|
|
return NEW_EVSTR(head);
|
2002-06-24 03:20:42 -04:00
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static NODE *
|
2004-09-17 05:24:13 -04:00
|
|
|
call_op_gen(parser, recv, id, narg, arg1)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
NODE *recv;
|
|
|
|
ID id;
|
|
|
|
int narg;
|
|
|
|
NODE *arg1;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
value_expr(arg1);
|
1998-01-16 07:13:05 -05:00
|
|
|
if (narg == 1) {
|
|
|
|
value_expr(arg1);
|
2003-02-19 22:35:44 -05:00
|
|
|
arg1 = NEW_LIST(arg1);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2003-02-19 22:35:44 -05:00
|
|
|
else {
|
|
|
|
arg1 = 0;
|
|
|
|
}
|
|
|
|
return NEW_CALL(recv, id, arg1);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
static NODE*
|
2004-09-17 05:24:13 -04:00
|
|
|
match_op_gen(parser, node1, node2)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:19:22 -05:00
|
|
|
NODE *node1;
|
|
|
|
NODE *node2;
|
|
|
|
{
|
|
|
|
local_cnt('~');
|
|
|
|
|
2002-06-12 05:22:20 -04:00
|
|
|
value_expr(node1);
|
|
|
|
value_expr(node2);
|
|
|
|
if (node1) {
|
|
|
|
switch (nd_type(node1)) {
|
|
|
|
case NODE_DREGX:
|
|
|
|
case NODE_DREGX_ONCE:
|
1998-01-16 07:19:22 -05:00
|
|
|
return NEW_MATCH2(node1, node2);
|
2002-06-12 05:22:20 -04:00
|
|
|
|
|
|
|
case NODE_LIT:
|
|
|
|
if (TYPE(node1->nd_lit) == T_REGEXP) {
|
|
|
|
return NEW_MATCH2(node1, node2);
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-12 05:22:20 -04:00
|
|
|
if (node2) {
|
|
|
|
switch (nd_type(node2)) {
|
|
|
|
case NODE_DREGX:
|
|
|
|
case NODE_DREGX_ONCE:
|
1998-01-16 07:19:22 -05:00
|
|
|
return NEW_MATCH3(node2, node1);
|
2002-06-12 05:22:20 -04:00
|
|
|
|
|
|
|
case NODE_LIT:
|
|
|
|
if (TYPE(node2->nd_lit) == T_REGEXP) {
|
|
|
|
return NEW_MATCH3(node2, node1);
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static NODE*
|
2004-10-02 07:34:13 -04:00
|
|
|
gettable_gen(parser, id)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
ID id;
|
|
|
|
{
|
1998-01-16 07:19:22 -05:00
|
|
|
if (id == kSELF) {
|
1998-01-16 07:13:05 -05:00
|
|
|
return NEW_SELF();
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
else if (id == kNIL) {
|
1998-01-16 07:13:05 -05:00
|
|
|
return NEW_NIL();
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
else if (id == kTRUE) {
|
|
|
|
return NEW_TRUE();
|
|
|
|
}
|
|
|
|
else if (id == kFALSE) {
|
|
|
|
return NEW_FALSE();
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
else if (id == k__FILE__) {
|
2002-01-16 04:25:59 -05:00
|
|
|
return NEW_STR(rb_str_new2(ruby_sourcefile));
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
else if (id == k__LINE__) {
|
|
|
|
return NEW_LIT(INT2FIX(ruby_sourceline));
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
else if (is_local_id(id)) {
|
1999-01-19 23:59:39 -05:00
|
|
|
if (dyna_in_block() && rb_dvar_defined(id)) return NEW_DVAR(id);
|
1998-01-16 07:13:05 -05:00
|
|
|
if (local_id(id)) return NEW_LVAR(id);
|
|
|
|
/* method call without arguments */
|
2002-01-21 02:44:06 -05:00
|
|
|
#if 0
|
|
|
|
/* Rite will warn this */
|
|
|
|
rb_warn("ambiguous identifier; %s() or self.%s is better for method call",
|
|
|
|
rb_id2name(id), rb_id2name(id));
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
return NEW_VCALL(id);
|
|
|
|
}
|
|
|
|
else if (is_global_id(id)) {
|
|
|
|
return NEW_GVAR(id);
|
|
|
|
}
|
|
|
|
else if (is_instance_id(id)) {
|
|
|
|
return NEW_IVAR(id);
|
|
|
|
}
|
1999-12-14 01:50:43 -05:00
|
|
|
else if (is_const_id(id)) {
|
2000-03-23 03:37:35 -05:00
|
|
|
return NEW_CONST(id);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-03-23 03:37:35 -05:00
|
|
|
else if (is_class_id(id)) {
|
2000-08-28 22:52:41 -04:00
|
|
|
return NEW_CVAR(id);
|
2000-02-18 01:59:36 -05:00
|
|
|
}
|
2001-11-21 10:42:12 -05:00
|
|
|
rb_compile_error("identifier %s is not valid", rb_id2name(id));
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static NODE*
|
2004-09-17 05:24:13 -04:00
|
|
|
assignable_gen(parser, id, val)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
ID id;
|
|
|
|
NODE *val;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
value_expr(val);
|
1998-01-16 07:19:22 -05:00
|
|
|
if (id == kSELF) {
|
1998-01-16 07:13:05 -05:00
|
|
|
yyerror("Can't change the value of self");
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
else if (id == kNIL) {
|
1998-01-16 07:13:05 -05:00
|
|
|
yyerror("Can't assign to nil");
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
else if (id == kTRUE) {
|
|
|
|
yyerror("Can't assign to true");
|
|
|
|
}
|
|
|
|
else if (id == kFALSE) {
|
|
|
|
yyerror("Can't assign to false");
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
else if (id == k__FILE__) {
|
|
|
|
yyerror("Can't assign to __FILE__");
|
|
|
|
}
|
|
|
|
else if (id == k__LINE__) {
|
|
|
|
yyerror("Can't assign to __LINE__");
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
else if (is_local_id(id)) {
|
2000-01-31 22:12:21 -05:00
|
|
|
if (rb_dvar_curr(id)) {
|
2000-08-28 05:53:42 -04:00
|
|
|
return NEW_DASGN_CURR(id, val);
|
2000-01-31 22:12:21 -05:00
|
|
|
}
|
|
|
|
else if (rb_dvar_defined(id)) {
|
2000-08-28 05:53:42 -04:00
|
|
|
return NEW_DASGN(id, val);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
else if (local_id(id) || !dyna_in_block()) {
|
2000-08-28 05:53:42 -04:00
|
|
|
return NEW_LASGN(id, val);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else{
|
2000-01-31 22:12:21 -05:00
|
|
|
rb_dvar_push(id, Qnil);
|
2000-08-28 05:53:42 -04:00
|
|
|
return NEW_DASGN_CURR(id, val);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (is_global_id(id)) {
|
2000-08-28 05:53:42 -04:00
|
|
|
return NEW_GASGN(id, val);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else if (is_instance_id(id)) {
|
2000-08-28 05:53:42 -04:00
|
|
|
return NEW_IASGN(id, val);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-12-14 01:50:43 -05:00
|
|
|
else if (is_const_id(id)) {
|
2001-02-13 00:09:11 -05:00
|
|
|
if (in_def || in_single)
|
1999-12-14 01:50:43 -05:00
|
|
|
yyerror("dynamic constant assignment");
|
2003-02-19 22:35:44 -05:00
|
|
|
return NEW_CDECL(id, val, 0);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-03-23 03:37:35 -05:00
|
|
|
else if (is_class_id(id)) {
|
2002-02-13 04:01:11 -05:00
|
|
|
if (in_def || in_single) return NEW_CVASGN(id, val);
|
2000-08-28 05:53:42 -04:00
|
|
|
return NEW_CVDECL(id, val);
|
2000-02-18 01:59:36 -05:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
else {
|
2003-09-17 07:34:02 -04:00
|
|
|
rb_compile_error("identifier %s is not valid", rb_id2name(id));
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-08-28 05:53:42 -04:00
|
|
|
return 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
static NODE *
|
2004-09-17 05:24:13 -04:00
|
|
|
aryset_gen(parser, recv, idx)
|
|
|
|
struct parser_params *parser;
|
1999-08-13 01:45:20 -04:00
|
|
|
NODE *recv, *idx;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2003-02-19 22:35:44 -05:00
|
|
|
if (recv && nd_type(recv) == NODE_SELF)
|
|
|
|
recv = (NODE *)1;
|
|
|
|
else
|
|
|
|
value_expr(recv);
|
2002-12-19 04:20:20 -05:00
|
|
|
return NEW_ATTRASGN(recv, tASET, idx);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
ID
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_id_attrset(id)
|
1998-01-16 07:13:05 -05:00
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
id &= ~ID_SCOPE_MASK;
|
|
|
|
id |= ID_ATTRSET;
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static NODE *
|
2004-09-17 05:24:13 -04:00
|
|
|
attrset_gen(parser, recv, id)
|
|
|
|
struct parser_params *parser;
|
1999-08-13 01:45:20 -04:00
|
|
|
NODE *recv;
|
1998-01-16 07:13:05 -05:00
|
|
|
ID id;
|
|
|
|
{
|
2003-02-19 22:35:44 -05:00
|
|
|
if (recv && nd_type(recv) == NODE_SELF)
|
|
|
|
recv = (NODE *)1;
|
|
|
|
else
|
|
|
|
value_expr(recv);
|
2002-12-17 05:34:30 -05:00
|
|
|
return NEW_ATTRASGN(recv, rb_id_attrset(id), 0);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_backref_error(node)
|
1998-01-16 07:13:05 -05:00
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
switch (nd_type(node)) {
|
|
|
|
case NODE_NTH_REF:
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_compile_error("Can't set variable $%d", node->nd_nth);
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
case NODE_BACK_REF:
|
2002-12-31 22:24:29 -05:00
|
|
|
rb_compile_error("Can't set variable $%c", (int)node->nd_nth);
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
static NODE *
|
|
|
|
arg_concat(node1, node2)
|
|
|
|
NODE *node1;
|
|
|
|
NODE *node2;
|
|
|
|
{
|
2000-01-17 03:37:53 -05:00
|
|
|
if (!node2) return node1;
|
1999-08-13 01:45:20 -04:00
|
|
|
return NEW_ARGSCAT(node1, node2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static NODE *
|
|
|
|
arg_add(node1, node2)
|
|
|
|
NODE *node1;
|
|
|
|
NODE *node2;
|
|
|
|
{
|
|
|
|
if (!node1) return NEW_LIST(node2);
|
|
|
|
if (nd_type(node1) == NODE_ARRAY) {
|
|
|
|
return list_append(node1, node2);
|
|
|
|
}
|
|
|
|
else {
|
2000-01-17 03:37:53 -05:00
|
|
|
return NEW_ARGSPUSH(node1, node2);
|
1999-08-13 01:45:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static NODE*
|
2004-09-17 05:24:13 -04:00
|
|
|
node_assign_gen(parser, lhs, rhs)
|
|
|
|
struct parser_params *parser;
|
1999-08-13 01:45:20 -04:00
|
|
|
NODE *lhs, *rhs;
|
|
|
|
{
|
|
|
|
if (!lhs) return 0;
|
|
|
|
|
|
|
|
value_expr(rhs);
|
|
|
|
switch (nd_type(lhs)) {
|
|
|
|
case NODE_GASGN:
|
|
|
|
case NODE_IASGN:
|
|
|
|
case NODE_LASGN:
|
|
|
|
case NODE_DASGN:
|
2000-01-31 22:12:21 -05:00
|
|
|
case NODE_DASGN_CURR:
|
1999-08-13 01:45:20 -04:00
|
|
|
case NODE_MASGN:
|
1999-11-17 02:30:37 -05:00
|
|
|
case NODE_CDECL:
|
2000-03-23 03:37:35 -05:00
|
|
|
case NODE_CVDECL:
|
2000-11-21 09:26:25 -05:00
|
|
|
case NODE_CVASGN:
|
1999-08-13 01:45:20 -04:00
|
|
|
lhs->nd_value = rhs;
|
|
|
|
break;
|
|
|
|
|
2002-12-17 05:34:30 -05:00
|
|
|
case NODE_ATTRASGN:
|
1999-08-13 01:45:20 -04:00
|
|
|
case NODE_CALL:
|
|
|
|
lhs->nd_args = arg_add(lhs->nd_args, rhs);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* should not happen */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return lhs;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
value_expr_gen(parser, node)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
NODE *node;
|
|
|
|
{
|
2002-10-18 10:13:41 -04:00
|
|
|
int cond = 0;
|
|
|
|
|
2002-06-17 23:53:23 -04:00
|
|
|
while (node) {
|
|
|
|
switch (nd_type(node)) {
|
|
|
|
case NODE_DEFN:
|
|
|
|
case NODE_DEFS:
|
2003-04-21 04:44:38 -04:00
|
|
|
parser_warning(node, "void value expression");
|
2002-06-17 23:53:23 -04:00
|
|
|
return Qfalse;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-17 23:53:23 -04:00
|
|
|
case NODE_RETURN:
|
|
|
|
case NODE_BREAK:
|
|
|
|
case NODE_NEXT:
|
|
|
|
case NODE_REDO:
|
|
|
|
case NODE_RETRY:
|
2002-10-18 10:13:41 -04:00
|
|
|
if (!cond) yyerror("void value expression");
|
2002-06-17 23:53:23 -04:00
|
|
|
/* or "control never reach"? */
|
|
|
|
return Qfalse;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-17 23:53:23 -04:00
|
|
|
case NODE_BLOCK:
|
|
|
|
while (node->nd_next) {
|
|
|
|
node = node->nd_next;
|
|
|
|
}
|
|
|
|
node = node->nd_head;
|
|
|
|
break;
|
2000-05-17 00:38:19 -04:00
|
|
|
|
2002-06-17 23:53:23 -04:00
|
|
|
case NODE_BEGIN:
|
|
|
|
node = node->nd_body;
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-17 23:53:23 -04:00
|
|
|
case NODE_IF:
|
|
|
|
if (!value_expr(node->nd_body)) return Qfalse;
|
|
|
|
node = node->nd_else;
|
|
|
|
break;
|
2002-06-12 05:22:20 -04:00
|
|
|
|
2002-06-17 23:53:23 -04:00
|
|
|
case NODE_AND:
|
|
|
|
case NODE_OR:
|
2002-10-18 10:13:41 -04:00
|
|
|
cond = 1;
|
2002-06-17 23:53:23 -04:00
|
|
|
node = node->nd_2nd;
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-06-17 23:53:23 -04:00
|
|
|
default:
|
|
|
|
return Qtrue;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-06-17 23:53:23 -04:00
|
|
|
|
|
|
|
return Qtrue;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
static void
|
2004-09-17 05:24:13 -04:00
|
|
|
void_expr_gen(parser, node)
|
|
|
|
struct parser_params *parser;
|
1999-08-13 01:45:20 -04:00
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
char *useless = 0;
|
|
|
|
|
2002-04-11 06:03:01 -04:00
|
|
|
if (!RTEST(ruby_verbose)) return;
|
1999-08-13 01:45:20 -04:00
|
|
|
|
2003-04-19 14:17:59 -04:00
|
|
|
if (!node) return;
|
1999-08-13 01:45:20 -04:00
|
|
|
switch (nd_type(node)) {
|
|
|
|
case NODE_CALL:
|
|
|
|
switch (node->nd_mid) {
|
|
|
|
case '+':
|
|
|
|
case '-':
|
|
|
|
case '*':
|
|
|
|
case '/':
|
|
|
|
case '%':
|
|
|
|
case tPOW:
|
|
|
|
case tUPLUS:
|
|
|
|
case tUMINUS:
|
|
|
|
case '|':
|
|
|
|
case '^':
|
|
|
|
case '&':
|
|
|
|
case tCMP:
|
|
|
|
case '>':
|
|
|
|
case tGEQ:
|
|
|
|
case '<':
|
|
|
|
case tLEQ:
|
|
|
|
case tEQ:
|
|
|
|
case tNEQ:
|
|
|
|
useless = rb_id2name(node->nd_mid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NODE_LVAR:
|
|
|
|
case NODE_DVAR:
|
|
|
|
case NODE_GVAR:
|
|
|
|
case NODE_IVAR:
|
2000-03-23 03:37:35 -05:00
|
|
|
case NODE_CVAR:
|
1999-08-13 01:45:20 -04:00
|
|
|
case NODE_NTH_REF:
|
|
|
|
case NODE_BACK_REF:
|
|
|
|
useless = "a variable";
|
|
|
|
break;
|
2000-03-23 03:37:35 -05:00
|
|
|
case NODE_CONST:
|
1999-08-13 01:45:20 -04:00
|
|
|
case NODE_CREF:
|
|
|
|
useless = "a constant";
|
|
|
|
break;
|
|
|
|
case NODE_LIT:
|
|
|
|
case NODE_STR:
|
|
|
|
case NODE_DSTR:
|
|
|
|
case NODE_DREGX:
|
|
|
|
case NODE_DREGX_ONCE:
|
|
|
|
useless = "a literal";
|
|
|
|
break;
|
|
|
|
case NODE_COLON2:
|
|
|
|
case NODE_COLON3:
|
|
|
|
useless = "::";
|
|
|
|
break;
|
|
|
|
case NODE_DOT2:
|
|
|
|
useless = "..";
|
|
|
|
break;
|
|
|
|
case NODE_DOT3:
|
|
|
|
useless = "...";
|
|
|
|
break;
|
|
|
|
case NODE_SELF:
|
|
|
|
useless = "self";
|
|
|
|
break;
|
|
|
|
case NODE_NIL:
|
|
|
|
useless = "nil";
|
|
|
|
break;
|
|
|
|
case NODE_TRUE:
|
|
|
|
useless = "true";
|
|
|
|
break;
|
|
|
|
case NODE_FALSE:
|
|
|
|
useless = "false";
|
|
|
|
break;
|
|
|
|
case NODE_DEFINED:
|
|
|
|
useless = "defined?";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (useless) {
|
|
|
|
int line = ruby_sourceline;
|
|
|
|
|
|
|
|
ruby_sourceline = nd_line(node);
|
|
|
|
rb_warn("useless use of %s in void context", useless);
|
|
|
|
ruby_sourceline = line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-09-17 05:24:13 -04:00
|
|
|
void_stmts_gen(parser, node)
|
|
|
|
struct parser_params *parser;
|
1999-08-13 01:45:20 -04:00
|
|
|
NODE *node;
|
|
|
|
{
|
2002-04-11 06:03:01 -04:00
|
|
|
if (!RTEST(ruby_verbose)) return;
|
1999-08-13 01:45:20 -04:00
|
|
|
if (!node) return;
|
|
|
|
if (nd_type(node) != NODE_BLOCK) return;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (!node->nd_next) return;
|
|
|
|
void_expr(node->nd_head);
|
|
|
|
node = node->nd_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-18 10:13:41 -04:00
|
|
|
static NODE *
|
|
|
|
remove_begin(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
NODE **n = &node;
|
|
|
|
while (*n) {
|
2004-01-21 11:47:23 -05:00
|
|
|
if (nd_type(*n) != NODE_BEGIN) {
|
2002-10-18 10:13:41 -04:00
|
|
|
return node;
|
|
|
|
}
|
2004-01-21 11:47:23 -05:00
|
|
|
*n = (*n)->nd_body;
|
2002-10-18 10:13:41 -04:00
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2004-02-02 21:23:20 -05:00
|
|
|
static void
|
|
|
|
reduce_nodes(body)
|
|
|
|
NODE **body;
|
|
|
|
{
|
|
|
|
NODE *node = *body;
|
|
|
|
|
|
|
|
#define subnodes(n1, n2) \
|
|
|
|
((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
|
|
|
|
(!node->n2) ? (body = &node->n1, 1) : \
|
|
|
|
(reduce_nodes(&node->n1), body = &node->n2, 1))
|
|
|
|
|
|
|
|
while (node) {
|
|
|
|
switch (nd_type(node)) {
|
|
|
|
end:
|
|
|
|
case NODE_NIL:
|
|
|
|
*body = 0;
|
|
|
|
return;
|
|
|
|
case NODE_RETURN:
|
|
|
|
*body = node = node->nd_stts;
|
|
|
|
continue;
|
|
|
|
case NODE_BEGIN:
|
|
|
|
*body = node = node->nd_body;
|
|
|
|
continue;
|
|
|
|
case NODE_BLOCK:
|
|
|
|
body = &node->nd_end->nd_head;
|
|
|
|
break;
|
|
|
|
case NODE_IF:
|
|
|
|
if (subnodes(nd_body, nd_else)) break;
|
|
|
|
return;
|
|
|
|
case NODE_CASE:
|
|
|
|
body = &node->nd_body;
|
|
|
|
break;
|
|
|
|
case NODE_WHEN:
|
|
|
|
if (!subnodes(nd_body, nd_next)) goto end;
|
|
|
|
break;
|
|
|
|
case NODE_ENSURE:
|
|
|
|
if (!subnodes(nd_head, nd_resq)) goto end;
|
|
|
|
break;
|
|
|
|
case NODE_RESCUE:
|
|
|
|
if (!subnodes(nd_head, nd_resq)) goto end;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
node = *body;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef subnodes
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static int
|
2004-09-17 05:24:13 -04:00
|
|
|
assign_in_cond(parser, node)
|
|
|
|
struct parser_params *parser;
|
1999-01-19 23:59:39 -05:00
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
switch (nd_type(node)) {
|
|
|
|
case NODE_MASGN:
|
|
|
|
yyerror("multiple assignment in conditional");
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case NODE_LASGN:
|
|
|
|
case NODE_DASGN:
|
|
|
|
case NODE_GASGN:
|
|
|
|
case NODE_IASGN:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (nd_type(node->nd_value)) {
|
|
|
|
case NODE_LIT:
|
|
|
|
case NODE_STR:
|
|
|
|
case NODE_NIL:
|
|
|
|
case NODE_TRUE:
|
|
|
|
case NODE_FALSE:
|
|
|
|
/* reports always */
|
2003-04-21 04:44:38 -04:00
|
|
|
parser_warn(node->nd_value, "found = in conditional, should be ==");
|
1999-01-19 23:59:39 -05:00
|
|
|
return 1;
|
|
|
|
|
2000-10-10 03:03:36 -04:00
|
|
|
case NODE_DSTR:
|
|
|
|
case NODE_XSTR:
|
|
|
|
case NODE_DXSTR:
|
|
|
|
case NODE_EVSTR:
|
|
|
|
case NODE_DREGX:
|
1999-01-19 23:59:39 -05:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2001-02-08 04:19:27 -05:00
|
|
|
static int
|
|
|
|
e_option_supplied()
|
|
|
|
{
|
|
|
|
if (strcmp(ruby_sourcefile, "-e") == 0)
|
|
|
|
return Qtrue;
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2000-12-28 00:00:47 -05:00
|
|
|
static void
|
2003-04-21 04:44:38 -04:00
|
|
|
warn_unless_e_option(node, str)
|
|
|
|
NODE *node;
|
2000-12-28 00:00:47 -05:00
|
|
|
const char *str;
|
|
|
|
{
|
2003-04-21 04:44:38 -04:00
|
|
|
if (!e_option_supplied()) parser_warn(node, str);
|
2001-02-08 04:19:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-04-21 04:44:38 -04:00
|
|
|
warning_unless_e_option(node, str)
|
|
|
|
NODE *node;
|
2001-02-08 04:19:27 -05:00
|
|
|
const char *str;
|
|
|
|
{
|
2003-04-21 04:44:38 -04:00
|
|
|
if (!e_option_supplied()) parser_warning(node, str);
|
2000-12-28 00:00:47 -05:00
|
|
|
}
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
static NODE *cond0 _((struct parser_params*,NODE*));
|
2001-02-19 02:03:06 -05:00
|
|
|
|
|
|
|
static NODE*
|
2004-09-17 05:24:13 -04:00
|
|
|
range_op(parser, node)
|
|
|
|
struct parser_params *parser;
|
2001-02-19 02:03:06 -05:00
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
enum node_type type;
|
|
|
|
|
|
|
|
if (!e_option_supplied()) return node;
|
2002-06-12 05:22:20 -04:00
|
|
|
if (node == 0) return 0;
|
2001-02-19 02:03:06 -05:00
|
|
|
|
2002-06-17 23:53:23 -04:00
|
|
|
value_expr(node);
|
2004-09-17 05:24:13 -04:00
|
|
|
node = cond0(parser, node);
|
2001-02-19 02:03:06 -05:00
|
|
|
type = nd_type(node);
|
|
|
|
if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
|
2003-04-21 04:44:38 -04:00
|
|
|
warn_unless_e_option(node, "integer literal in conditional range");
|
2001-02-19 02:03:06 -05:00
|
|
|
return call_op(node,tEQ,1,NEW_GVAR(rb_intern("$.")));
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2003-04-17 01:22:40 -04:00
|
|
|
static int
|
|
|
|
literal_node(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
if (!node) return 1; /* same as NODE_NIL */
|
|
|
|
switch (nd_type(node)) {
|
|
|
|
case NODE_LIT:
|
|
|
|
case NODE_STR:
|
|
|
|
case NODE_DSTR:
|
|
|
|
case NODE_EVSTR:
|
|
|
|
case NODE_DREGX:
|
|
|
|
case NODE_DREGX_ONCE:
|
|
|
|
case NODE_DSYM:
|
|
|
|
return 2;
|
|
|
|
case NODE_TRUE:
|
|
|
|
case NODE_FALSE:
|
|
|
|
case NODE_NIL:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static NODE*
|
2004-09-17 05:24:13 -04:00
|
|
|
cond0(parser, node)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
NODE *node;
|
|
|
|
{
|
2004-07-14 10:51:42 -04:00
|
|
|
if (node == 0) return 0;
|
2004-09-17 05:24:13 -04:00
|
|
|
assign_in_cond(parser, node);
|
2001-08-05 23:05:23 -04:00
|
|
|
|
2004-07-14 10:51:42 -04:00
|
|
|
switch (nd_type(node)) {
|
2000-12-27 00:59:03 -05:00
|
|
|
case NODE_DSTR:
|
2003-04-17 01:22:40 -04:00
|
|
|
case NODE_EVSTR:
|
2001-03-13 00:45:13 -05:00
|
|
|
case NODE_STR:
|
2001-03-13 01:00:50 -05:00
|
|
|
rb_warn("string literal in condition");
|
2001-03-13 00:45:13 -05:00
|
|
|
break;
|
2001-02-08 04:19:27 -05:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
case NODE_DREGX:
|
|
|
|
case NODE_DREGX_ONCE:
|
2003-04-21 04:44:38 -04:00
|
|
|
warning_unless_e_option(node, "regex literal in condition");
|
1998-01-16 07:13:05 -05:00
|
|
|
local_cnt('_');
|
|
|
|
local_cnt('~');
|
1998-01-16 07:19:22 -05:00
|
|
|
return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2001-08-14 04:13:31 -04:00
|
|
|
case NODE_AND:
|
|
|
|
case NODE_OR:
|
2004-09-17 05:24:13 -04:00
|
|
|
node->nd_1st = cond0(parser, node->nd_1st);
|
|
|
|
node->nd_2nd = cond0(parser, node->nd_2nd);
|
2001-08-14 04:13:31 -04:00
|
|
|
break;
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
case NODE_DOT2:
|
|
|
|
case NODE_DOT3:
|
2004-09-17 05:24:13 -04:00
|
|
|
node->nd_beg = range_op(parser, node->nd_beg);
|
|
|
|
node->nd_end = range_op(parser, node->nd_end);
|
2004-07-14 10:51:42 -04:00
|
|
|
if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
|
|
|
|
else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
|
2001-09-20 02:23:50 -04:00
|
|
|
node->nd_cnt = local_append(internal_id());
|
2003-04-17 01:22:40 -04:00
|
|
|
if (!e_option_supplied()) {
|
|
|
|
int b = literal_node(node->nd_beg);
|
|
|
|
int e = literal_node(node->nd_end);
|
|
|
|
if ((b == 1 && e == 1) || (b + e >= 2 && RTEST(ruby_verbose))) {
|
2003-04-21 04:44:38 -04:00
|
|
|
parser_warn(node, "range literal in condition");
|
2003-04-17 01:22:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NODE_DSYM:
|
2003-04-21 04:44:38 -04:00
|
|
|
parser_warning(node, "literal in condition");
|
2000-12-28 00:00:47 -05:00
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
case NODE_LIT:
|
2001-02-19 02:03:06 -05:00
|
|
|
if (TYPE(node->nd_lit) == T_REGEXP) {
|
2003-04-21 04:44:38 -04:00
|
|
|
warn_unless_e_option(node, "regex literal in condition");
|
2000-12-27 00:59:03 -05:00
|
|
|
nd_set_type(node, NODE_MATCH);
|
1998-01-16 07:13:05 -05:00
|
|
|
local_cnt('_');
|
|
|
|
local_cnt('~');
|
|
|
|
}
|
2001-08-14 04:13:31 -04:00
|
|
|
else {
|
2003-04-21 04:44:38 -04:00
|
|
|
parser_warning(node, "literal in condition");
|
2001-08-14 04:13:31 -04:00
|
|
|
}
|
2002-06-05 02:10:57 -04:00
|
|
|
default:
|
|
|
|
break;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-12-27 00:59:03 -05:00
|
|
|
return node;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static NODE*
|
2004-09-17 05:24:13 -04:00
|
|
|
cond_gen(parser, node)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
NODE *node;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
if (node == 0) return 0;
|
2002-06-17 23:53:23 -04:00
|
|
|
value_expr(node);
|
2004-09-17 05:24:13 -04:00
|
|
|
return cond0(parser, node);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static NODE*
|
2004-09-17 05:24:13 -04:00
|
|
|
logop_gen(parser, type, left, right)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
enum node_type type;
|
|
|
|
NODE *left, *right;
|
|
|
|
{
|
|
|
|
value_expr(left);
|
2003-10-29 23:37:50 -05:00
|
|
|
if (left && nd_type(left) == type) {
|
2002-06-17 23:53:23 -04:00
|
|
|
NODE *node = left, *second;
|
|
|
|
while ((second = node->nd_2nd) != 0 && nd_type(second) == type) {
|
|
|
|
node = second;
|
|
|
|
}
|
2003-07-04 11:30:35 -04:00
|
|
|
node->nd_2nd = NEW_NODE(type, second, right, 0);
|
2002-06-17 23:53:23 -04:00
|
|
|
return left;
|
|
|
|
}
|
2003-07-04 11:30:35 -04:00
|
|
|
return NEW_NODE(type, left, right, 0);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
|
2003-03-20 02:03:22 -05:00
|
|
|
static int
|
|
|
|
cond_negative(nodep)
|
|
|
|
NODE **nodep;
|
|
|
|
{
|
|
|
|
NODE *c = *nodep;
|
|
|
|
|
|
|
|
if (!c) return 0;
|
|
|
|
switch (nd_type(c)) {
|
|
|
|
case NODE_NOT:
|
|
|
|
*nodep = c->nd_body;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-06-20 03:11:44 -04:00
|
|
|
static void
|
|
|
|
no_blockarg(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
if (node && nd_type(node) == NODE_BLOCK_PASS) {
|
|
|
|
rb_compile_error("block argument should not be given");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-05-30 05:12:34 -04:00
|
|
|
static NODE *
|
|
|
|
ret_args(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
if (node) {
|
2003-06-20 03:11:44 -04:00
|
|
|
no_blockarg(node);
|
2004-05-07 04:44:24 -04:00
|
|
|
if (nd_type(node) == NODE_ARRAY) {
|
|
|
|
if (node->nd_next == 0) {
|
|
|
|
node = node->nd_head;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nd_set_type(node, NODE_VALUES);
|
|
|
|
}
|
2003-06-20 03:11:44 -04:00
|
|
|
}
|
2004-05-07 04:44:24 -04:00
|
|
|
else if (nd_type(node) == NODE_SPLAT) {
|
2003-08-27 15:43:50 -04:00
|
|
|
node = NEW_SVALUE(node);
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
2003-06-20 03:11:44 -04:00
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static NODE *
|
|
|
|
new_yield(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
2003-10-29 12:47:24 -05:00
|
|
|
long state = Qtrue;
|
|
|
|
|
|
|
|
if (node) {
|
|
|
|
no_blockarg(node);
|
|
|
|
if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) {
|
|
|
|
node = node->nd_head;
|
|
|
|
state = Qfalse;
|
|
|
|
}
|
2004-01-21 11:47:23 -05:00
|
|
|
else if (node && nd_type(node) == NODE_SPLAT) {
|
2003-10-29 12:47:24 -05:00
|
|
|
state = Qtrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
state = Qfalse;
|
|
|
|
}
|
|
|
|
return NEW_YIELD(node, state);
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
|
|
|
|
2003-01-22 22:39:25 -05:00
|
|
|
static NODE*
|
|
|
|
negate_lit(node)
|
|
|
|
NODE *node;
|
|
|
|
{
|
|
|
|
switch (TYPE(node->nd_lit)) {
|
|
|
|
case T_FIXNUM:
|
|
|
|
node->nd_lit = LONG2FIX(-FIX2LONG(node->nd_lit));
|
|
|
|
break;
|
|
|
|
case T_BIGNUM:
|
|
|
|
node->nd_lit = rb_funcall(node->nd_lit,tUMINUS,0,0);
|
|
|
|
break;
|
|
|
|
case T_FLOAT:
|
|
|
|
RFLOAT(node->nd_lit)->value = -RFLOAT(node->nd_lit)->value;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static NODE *
|
|
|
|
arg_blk_pass(node1, node2)
|
|
|
|
NODE *node1;
|
|
|
|
NODE *node2;
|
|
|
|
{
|
|
|
|
if (node2) {
|
|
|
|
node2->nd_head = node1;
|
|
|
|
return node2;
|
|
|
|
}
|
|
|
|
return node1;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2001-05-30 05:12:34 -04:00
|
|
|
static NODE*
|
|
|
|
arg_prepend(node1, node2)
|
|
|
|
NODE *node1, *node2;
|
|
|
|
{
|
2003-12-10 21:39:59 -05:00
|
|
|
switch (nd_type(node2)) {
|
2001-05-30 05:12:34 -04:00
|
|
|
case NODE_ARRAY:
|
|
|
|
return list_concat(NEW_LIST(node1), node2);
|
|
|
|
|
2003-08-27 15:43:50 -04:00
|
|
|
case NODE_SPLAT:
|
2001-05-30 05:12:34 -04:00
|
|
|
return arg_concat(node1, node2->nd_head);
|
|
|
|
|
|
|
|
case NODE_BLOCK_PASS:
|
|
|
|
node2->nd_body = arg_prepend(node1, node2->nd_body);
|
|
|
|
return node2;
|
|
|
|
|
|
|
|
default:
|
2003-12-10 21:39:59 -05:00
|
|
|
rb_bug("unknown nodetype(%d) for arg_prepend", nd_type(node2));
|
2001-05-30 05:12:34 -04:00
|
|
|
}
|
|
|
|
return 0; /* not reached */
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static NODE*
|
|
|
|
new_call(r,m,a)
|
|
|
|
NODE *r;
|
|
|
|
ID m;
|
|
|
|
NODE *a;
|
|
|
|
{
|
|
|
|
if (a && nd_type(a) == NODE_BLOCK_PASS) {
|
|
|
|
a->nd_iter = NEW_CALL(r,m,a->nd_head);
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
return NEW_CALL(r,m,a);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static NODE*
|
|
|
|
new_fcall(m,a)
|
|
|
|
ID m;
|
|
|
|
NODE *a;
|
|
|
|
{
|
|
|
|
if (a && nd_type(a) == NODE_BLOCK_PASS) {
|
|
|
|
a->nd_iter = NEW_FCALL(m,a->nd_head);
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
return NEW_FCALL(m,a);
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-06-23 03:05:59 -04:00
|
|
|
static NODE*
|
|
|
|
new_super(a)
|
|
|
|
NODE *a;
|
|
|
|
{
|
|
|
|
if (a && nd_type(a) == NODE_BLOCK_PASS) {
|
|
|
|
a->nd_iter = NEW_SUPER(a->nd_head);
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
return NEW_SUPER(a);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static void
|
2004-10-02 07:34:13 -04:00
|
|
|
local_push_gen(parser, top)
|
|
|
|
struct parser_params *parser;
|
2002-03-19 04:03:11 -05:00
|
|
|
int top;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
struct local_vars *local;
|
|
|
|
|
|
|
|
local = ALLOC(struct local_vars);
|
|
|
|
local->prev = lvtbl;
|
|
|
|
local->nofree = 0;
|
|
|
|
local->cnt = 0;
|
|
|
|
local->tbl = 0;
|
|
|
|
local->dlev = 0;
|
2002-03-19 04:03:11 -05:00
|
|
|
local->dyna_vars = ruby_dyna_vars;
|
1998-01-16 07:13:05 -05:00
|
|
|
lvtbl = local;
|
2002-03-19 04:03:11 -05:00
|
|
|
if (!top) {
|
|
|
|
/* preserve reference for GC, but link should be cut. */
|
|
|
|
rb_dvar_push(0, (VALUE)ruby_dyna_vars);
|
|
|
|
ruby_dyna_vars->next = 0;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-10-02 07:34:13 -04:00
|
|
|
local_pop_gen(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
struct local_vars *local = lvtbl->prev;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (lvtbl->tbl) {
|
2004-10-02 07:34:13 -04:00
|
|
|
if (!lvtbl->nofree) xfree(lvtbl->tbl);
|
1999-01-19 23:59:39 -05:00
|
|
|
else lvtbl->tbl[0] = lvtbl->cnt;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-03-19 04:03:11 -05:00
|
|
|
ruby_dyna_vars = lvtbl->dyna_vars;
|
2004-10-02 07:34:13 -04:00
|
|
|
xfree(lvtbl);
|
1999-01-19 23:59:39 -05:00
|
|
|
lvtbl = local;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static ID*
|
2004-10-02 07:34:13 -04:00
|
|
|
local_tbl_gen(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
lvtbl->nofree = 1;
|
|
|
|
return lvtbl->tbl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2004-10-02 07:34:13 -04:00
|
|
|
local_append_gen(parser, id)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
if (lvtbl->tbl == 0) {
|
1999-01-19 23:59:39 -05:00
|
|
|
lvtbl->tbl = ALLOC_N(ID, 4);
|
1998-01-16 07:13:05 -05:00
|
|
|
lvtbl->tbl[0] = 0;
|
1999-01-19 23:59:39 -05:00
|
|
|
lvtbl->tbl[1] = '_';
|
|
|
|
lvtbl->tbl[2] = '~';
|
|
|
|
lvtbl->cnt = 2;
|
|
|
|
if (id == '_') return 0;
|
|
|
|
if (id == '~') return 1;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
REALLOC_N(lvtbl->tbl, ID, lvtbl->cnt+2);
|
|
|
|
}
|
|
|
|
|
|
|
|
lvtbl->tbl[lvtbl->cnt+1] = id;
|
|
|
|
return lvtbl->cnt++;
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static int
|
2004-10-02 07:34:13 -04:00
|
|
|
local_cnt_gen(parser, id)
|
|
|
|
struct parser_params *parser;
|
1999-01-19 23:59:39 -05:00
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
int cnt, max;
|
|
|
|
|
|
|
|
if (id == 0) return lvtbl->cnt;
|
|
|
|
|
1999-08-13 01:45:20 -04:00
|
|
|
for (cnt=1, max=lvtbl->cnt+1; cnt<max;cnt++) {
|
1999-01-19 23:59:39 -05:00
|
|
|
if (lvtbl->tbl[cnt] == id) return cnt-1;
|
|
|
|
}
|
|
|
|
return local_append(id);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static int
|
2004-10-02 07:34:13 -04:00
|
|
|
local_id_gen(parser, id)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
int i, max;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (lvtbl == 0) return Qfalse;
|
|
|
|
for (i=3, max=lvtbl->cnt+1; i<max; i++) {
|
|
|
|
if (lvtbl->tbl[i] == id) return Qtrue;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
return Qfalse;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-10-02 07:34:13 -04:00
|
|
|
top_local_init_gen(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2002-03-20 05:21:23 -05:00
|
|
|
local_push(1);
|
1999-01-19 23:59:39 -05:00
|
|
|
lvtbl->cnt = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
|
1998-01-16 07:13:05 -05:00
|
|
|
if (lvtbl->cnt > 0) {
|
1999-01-19 23:59:39 -05:00
|
|
|
lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+3);
|
|
|
|
MEMCPY(lvtbl->tbl, ruby_scope->local_tbl, ID, lvtbl->cnt+1);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
lvtbl->tbl = 0;
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
if (ruby_dyna_vars)
|
1998-01-16 07:13:05 -05:00
|
|
|
lvtbl->dlev = 1;
|
|
|
|
else
|
|
|
|
lvtbl->dlev = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-10-02 07:34:13 -04:00
|
|
|
top_local_setup_gen(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
int len = lvtbl->cnt;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (len > 0) {
|
1999-08-13 01:45:20 -04:00
|
|
|
i = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
if (i < len) {
|
2001-02-02 06:38:20 -05:00
|
|
|
if (i == 0 || (ruby_scope->flags & SCOPE_MALLOC) == 0) {
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE *vars = ALLOC_N(VALUE, len+1);
|
1999-01-19 23:59:39 -05:00
|
|
|
if (ruby_scope->local_vars) {
|
|
|
|
*vars++ = ruby_scope->local_vars[-1];
|
|
|
|
MEMCPY(vars, ruby_scope->local_vars, VALUE, i);
|
|
|
|
rb_mem_clear(vars+i, len-i);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
*vars++ = 0;
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_mem_clear(vars, len);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
ruby_scope->local_vars = vars;
|
2001-02-02 06:38:20 -05:00
|
|
|
ruby_scope->flags |= SCOPE_MALLOC;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE *vars = ruby_scope->local_vars-1;
|
1998-01-16 07:13:05 -05:00
|
|
|
REALLOC_N(vars, VALUE, len+1);
|
1999-01-19 23:59:39 -05:00
|
|
|
ruby_scope->local_vars = vars+1;
|
|
|
|
rb_mem_clear(ruby_scope->local_vars+i, len-i);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
if (ruby_scope->local_tbl && ruby_scope->local_vars[-1] == 0) {
|
2004-10-02 07:34:13 -04:00
|
|
|
xfree(ruby_scope->local_tbl);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
ruby_scope->local_vars[-1] = 0;
|
|
|
|
ruby_scope->local_tbl = local_tbl();
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
local_pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct RVarmap*
|
2004-10-02 07:34:13 -04:00
|
|
|
dyna_push_gen(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2000-01-31 22:12:21 -05:00
|
|
|
struct RVarmap* vars = ruby_dyna_vars;
|
|
|
|
|
|
|
|
rb_dvar_push(0, 0);
|
1998-01-16 07:13:05 -05:00
|
|
|
lvtbl->dlev++;
|
2000-01-31 22:12:21 -05:00
|
|
|
return vars;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-10-02 07:34:13 -04:00
|
|
|
dyna_pop_gen(parser, vars)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
struct RVarmap* vars;
|
|
|
|
{
|
|
|
|
lvtbl->dlev--;
|
1999-01-19 23:59:39 -05:00
|
|
|
ruby_dyna_vars = vars;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2004-10-02 07:34:13 -04:00
|
|
|
dyna_in_block_gen(parser)
|
|
|
|
struct parser_params *parser;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
return (lvtbl->dlev > 0);
|
|
|
|
}
|
|
|
|
|
2003-06-06 07:29:20 -04:00
|
|
|
static NODE *
|
2004-10-02 07:34:13 -04:00
|
|
|
dyna_init_gen(parser, node, pre)
|
|
|
|
struct parser_params *parser;
|
2003-06-06 07:29:20 -04:00
|
|
|
NODE *node;
|
|
|
|
struct RVarmap *pre;
|
|
|
|
{
|
|
|
|
struct RVarmap *post = ruby_dyna_vars;
|
|
|
|
NODE *var;
|
|
|
|
|
|
|
|
if (!node || !post || pre == post) return node;
|
|
|
|
for (var = 0; post != pre && post->id; post = post->next) {
|
|
|
|
var = NEW_DASGN_CURR(post->id, var);
|
|
|
|
}
|
|
|
|
return block_append(var, node);
|
|
|
|
}
|
|
|
|
|
2002-09-05 16:00:52 -04:00
|
|
|
void
|
|
|
|
rb_gc_mark_parser()
|
|
|
|
{
|
2002-09-05 23:09:07 -04:00
|
|
|
rb_gc_mark(ruby_debug_lines);
|
2002-09-05 16:00:52 -04:00
|
|
|
}
|
|
|
|
|
2004-09-21 20:19:15 -04:00
|
|
|
NODE*
|
|
|
|
rb_parser_append_print(node)
|
|
|
|
NODE *node;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2004-10-28 22:35:11 -04:00
|
|
|
NODE *prelude = 0;
|
2004-09-24 01:53:43 -04:00
|
|
|
|
2004-10-28 22:35:11 -04:00
|
|
|
if (node && (nd_type(node) == NODE_PRELUDE)) {
|
|
|
|
prelude = node;
|
2004-09-24 01:53:43 -04:00
|
|
|
node = node->nd_body;
|
|
|
|
}
|
|
|
|
node = block_append(node,
|
2004-09-21 20:19:15 -04:00
|
|
|
NEW_FCALL(rb_intern("print"),
|
|
|
|
NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
|
2004-09-24 01:53:43 -04:00
|
|
|
if (prelude) {
|
|
|
|
prelude->nd_body = node;
|
|
|
|
return prelude;
|
|
|
|
}
|
|
|
|
return node;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2004-09-21 20:19:15 -04:00
|
|
|
NODE *
|
|
|
|
rb_parser_while_loop(node, chop, split)
|
|
|
|
NODE *node;
|
1998-01-16 07:13:05 -05:00
|
|
|
int chop, split;
|
|
|
|
{
|
2004-10-28 22:35:11 -04:00
|
|
|
NODE *prelude = 0;
|
2004-09-24 01:53:43 -04:00
|
|
|
|
2004-10-28 22:35:11 -04:00
|
|
|
if (node && (nd_type(node) == NODE_PRELUDE)) {
|
|
|
|
prelude = node;
|
2004-09-24 01:53:43 -04:00
|
|
|
node = node->nd_body;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
if (split) {
|
2004-09-21 20:19:15 -04:00
|
|
|
node = block_append(NEW_GASGN(rb_intern("$F"),
|
|
|
|
NEW_CALL(NEW_GVAR(rb_intern("$_")),
|
|
|
|
rb_intern("split"), 0)),
|
|
|
|
node);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
if (chop) {
|
2004-09-21 20:19:15 -04:00
|
|
|
node = block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
|
|
|
|
rb_intern("chop!"), 0), node);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-09-24 01:53:43 -04:00
|
|
|
node = NEW_OPT_N(node);
|
|
|
|
if (prelude) {
|
|
|
|
prelude->nd_body = node;
|
|
|
|
return prelude;
|
|
|
|
}
|
|
|
|
return node;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static struct {
|
|
|
|
ID token;
|
|
|
|
char *name;
|
|
|
|
} op_tbl[] = {
|
2002-04-24 00:54:16 -04:00
|
|
|
{tDOT2, ".."},
|
|
|
|
{tDOT3, "..."},
|
|
|
|
{'+', "+"},
|
|
|
|
{'-', "-"},
|
|
|
|
{'+', "+(binary)"},
|
|
|
|
{'-', "-(binary)"},
|
|
|
|
{'*', "*"},
|
|
|
|
{'/', "/"},
|
|
|
|
{'%', "%"},
|
|
|
|
{tPOW, "**"},
|
|
|
|
{tUPLUS, "+@"},
|
|
|
|
{tUMINUS, "-@"},
|
|
|
|
{tUPLUS, "+(unary)"},
|
|
|
|
{tUMINUS, "-(unary)"},
|
|
|
|
{'|', "|"},
|
|
|
|
{'^', "^"},
|
|
|
|
{'&', "&"},
|
|
|
|
{tCMP, "<=>"},
|
|
|
|
{'>', ">"},
|
|
|
|
{tGEQ, ">="},
|
|
|
|
{'<', "<"},
|
|
|
|
{tLEQ, "<="},
|
|
|
|
{tEQ, "=="},
|
|
|
|
{tEQQ, "==="},
|
|
|
|
{tNEQ, "!="},
|
|
|
|
{tMATCH, "=~"},
|
|
|
|
{tNMATCH, "!~"},
|
|
|
|
{'!', "!"},
|
|
|
|
{'~', "~"},
|
|
|
|
{'!', "!(unary)"},
|
|
|
|
{'~', "~(unary)"},
|
|
|
|
{'!', "!@"},
|
|
|
|
{'~', "~@"},
|
|
|
|
{tAREF, "[]"},
|
|
|
|
{tASET, "[]="},
|
|
|
|
{tLSHFT, "<<"},
|
|
|
|
{tRSHFT, ">>"},
|
|
|
|
{tCOLON2, "::"},
|
|
|
|
{'`', "`"},
|
|
|
|
{0, 0}
|
1998-01-16 07:13:05 -05:00
|
|
|
};
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static st_table *sym_tbl;
|
|
|
|
static st_table *sym_rev_tbl;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
void
|
|
|
|
Init_sym()
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
sym_tbl = st_init_strtable_with_size(200);
|
|
|
|
sym_rev_tbl = st_init_numtable_with_size(200);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2002-12-24 03:53:56 -05:00
|
|
|
static ID last_id = tLAST_TOKEN;
|
2001-09-20 02:23:50 -04:00
|
|
|
|
|
|
|
static ID
|
|
|
|
internal_id()
|
|
|
|
{
|
|
|
|
return ID_INTERNAL | (++last_id << ID_SCOPE_SHIFT);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
ID
|
|
|
|
rb_intern(name)
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2001-06-05 03:50:59 -04:00
|
|
|
const char *m = name;
|
2000-05-22 03:29:50 -04:00
|
|
|
ID id;
|
1998-01-16 07:13:05 -05:00
|
|
|
int last;
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
if (st_lookup(sym_tbl, (st_data_t)name, (st_data_t *)&id))
|
1998-01-16 07:13:05 -05:00
|
|
|
return id;
|
|
|
|
|
2003-05-31 05:11:12 -04:00
|
|
|
last = strlen(name)-1;
|
1999-01-19 23:59:39 -05:00
|
|
|
id = 0;
|
2001-06-05 03:50:59 -04:00
|
|
|
switch (*name) {
|
1998-01-16 07:13:05 -05:00
|
|
|
case '$':
|
|
|
|
id |= ID_GLOBAL;
|
2001-06-05 03:50:59 -04:00
|
|
|
m++;
|
|
|
|
if (!is_identchar(*m)) m++;
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
case '@':
|
2001-06-05 03:50:59 -04:00
|
|
|
if (name[1] == '@') {
|
|
|
|
m++;
|
2000-03-23 03:37:35 -05:00
|
|
|
id |= ID_CLASS;
|
2001-06-05 03:50:59 -04:00
|
|
|
}
|
|
|
|
else {
|
2000-02-18 01:59:36 -05:00
|
|
|
id |= ID_INSTANCE;
|
2001-06-05 03:50:59 -04:00
|
|
|
}
|
|
|
|
m++;
|
1998-01-16 07:13:05 -05:00
|
|
|
break;
|
|
|
|
default:
|
1999-01-19 23:59:39 -05:00
|
|
|
if (name[0] != '_' && !ISALPHA(name[0]) && !ismbchar(name[0])) {
|
2001-06-05 03:50:59 -04:00
|
|
|
/* operators */
|
1998-01-16 07:13:05 -05:00
|
|
|
int i;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
for (i=0; op_tbl[i].token; i++) {
|
|
|
|
if (*op_tbl[i].name == *name &&
|
|
|
|
strcmp(op_tbl[i].name, name) == 0) {
|
|
|
|
id = op_tbl[i].token;
|
|
|
|
goto id_regist;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
if (name[last] == '=') {
|
|
|
|
/* attribute assignment */
|
|
|
|
char *buf = ALLOCA_N(char,last+1);
|
|
|
|
|
|
|
|
strncpy(buf, name, last);
|
|
|
|
buf[last] = '\0';
|
|
|
|
id = rb_intern(buf);
|
2002-12-24 03:53:56 -05:00
|
|
|
if (id > tLAST_TOKEN && !is_attrset_id(id)) {
|
1999-01-19 23:59:39 -05:00
|
|
|
id = rb_id_attrset(id);
|
|
|
|
goto id_regist;
|
|
|
|
}
|
1999-10-12 00:53:36 -04:00
|
|
|
id = ID_ATTRSET;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
else if (ISUPPER(name[0])) {
|
1999-12-14 01:50:43 -05:00
|
|
|
id = ID_CONST;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
1999-01-19 23:59:39 -05:00
|
|
|
id = ID_LOCAL;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2003-07-01 06:03:04 -04:00
|
|
|
while (m <= name + last && is_identchar(*m)) {
|
|
|
|
m += mbclen(*m);
|
2001-06-05 03:50:59 -04:00
|
|
|
}
|
|
|
|
if (*m) id = ID_JUNK;
|
1999-01-19 23:59:39 -05:00
|
|
|
id |= ++last_id << ID_SCOPE_SHIFT;
|
|
|
|
id_regist:
|
|
|
|
name = strdup(name);
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
st_add_direct(sym_tbl, (st_data_t)name, id);
|
|
|
|
st_add_direct(sym_rev_tbl, id, (st_data_t)name);
|
1998-01-16 07:13:05 -05:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
rb_id2name(id)
|
|
|
|
ID id;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-12-24 03:53:56 -05:00
|
|
|
if (id < tLAST_TOKEN) {
|
1998-01-16 07:13:05 -05:00
|
|
|
int i = 0;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
for (i=0; op_tbl[i].token; i++) {
|
|
|
|
if (op_tbl[i].token == id)
|
|
|
|
return op_tbl[i].name;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
if (st_lookup(sym_rev_tbl, id, (st_data_t *)&name))
|
1999-01-19 23:59:39 -05:00
|
|
|
return name;
|
|
|
|
|
|
|
|
if (is_attrset_id(id)) {
|
2000-06-05 04:46:59 -04:00
|
|
|
ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-06-05 04:46:59 -04:00
|
|
|
again:
|
|
|
|
name = rb_id2name(id2);
|
|
|
|
if (name) {
|
|
|
|
char *buf = ALLOCA_N(char, strlen(name)+2);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-06-05 04:46:59 -04:00
|
|
|
strcpy(buf, name);
|
1998-01-16 07:13:05 -05:00
|
|
|
strcat(buf, "=");
|
|
|
|
rb_intern(buf);
|
|
|
|
return rb_id2name(id);
|
|
|
|
}
|
2000-06-05 04:46:59 -04:00
|
|
|
if (is_local_id(id2)) {
|
|
|
|
id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
|
|
|
|
goto again;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
return 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2001-05-02 00:22:21 -04:00
|
|
|
static int
|
|
|
|
symbols_i(key, value, ary)
|
|
|
|
char *key;
|
|
|
|
ID value;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
|
|
|
rb_ary_push(ary, ID2SYM(value));
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* Symbol.all_symbols => array
|
|
|
|
*
|
|
|
|
* Returns an array of all the symbols currently in Ruby's symbol
|
|
|
|
* table.
|
|
|
|
*
|
|
|
|
* Symbol.all_symbols.size #=> 903
|
|
|
|
* Symbol.all_symbols[1,20] #=> [:floor, :ARGV, :Binding, :symlink,
|
|
|
|
* :chown, :EOFError, :$;, :String,
|
|
|
|
* :LOCK_SH, :"setuid?", :$<,
|
|
|
|
* :default_proc, :compact, :extend,
|
|
|
|
* :Tms, :getwd, :$=, :ThreadGroup,
|
|
|
|
* :wait2, :$>]
|
|
|
|
*/
|
|
|
|
|
2001-05-02 00:22:21 -04:00
|
|
|
VALUE
|
|
|
|
rb_sym_all_symbols()
|
|
|
|
{
|
|
|
|
VALUE ary = rb_ary_new2(sym_tbl->num_entries);
|
|
|
|
|
|
|
|
st_foreach(sym_tbl, symbols_i, ary);
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
1999-11-17 02:30:37 -05:00
|
|
|
int
|
|
|
|
rb_is_const_id(id)
|
|
|
|
ID id;
|
|
|
|
{
|
1999-12-14 01:50:43 -05:00
|
|
|
if (is_const_id(id)) return Qtrue;
|
|
|
|
return Qfalse;
|
1999-11-17 02:30:37 -05:00
|
|
|
}
|
|
|
|
|
2000-02-18 01:59:36 -05:00
|
|
|
int
|
2000-03-23 03:37:35 -05:00
|
|
|
rb_is_class_id(id)
|
2000-02-18 01:59:36 -05:00
|
|
|
ID id;
|
|
|
|
{
|
2000-03-23 03:37:35 -05:00
|
|
|
if (is_class_id(id)) return Qtrue;
|
2000-02-18 01:59:36 -05:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
int
|
|
|
|
rb_is_instance_id(id)
|
|
|
|
ID id;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
if (is_instance_id(id)) return Qtrue;
|
|
|
|
return Qfalse;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2001-09-20 02:23:50 -04:00
|
|
|
int
|
|
|
|
rb_is_local_id(id)
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
if (is_local_id(id)) return Qtrue;
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2002-10-23 06:17:30 -04:00
|
|
|
int
|
|
|
|
rb_is_junk_id(id)
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
if (is_junk_id(id)) return Qtrue;
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static void
|
|
|
|
special_local_set(c, val)
|
|
|
|
char c;
|
|
|
|
VALUE val;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
int cnt;
|
2004-10-02 07:34:13 -04:00
|
|
|
struct parser_params *parser = parser_new();
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
top_local_init();
|
|
|
|
cnt = local_cnt(c);
|
|
|
|
top_local_setup();
|
1999-01-19 23:59:39 -05:00
|
|
|
ruby_scope->local_vars[cnt] = val;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_backref_get()
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2001-09-20 02:23:50 -04:00
|
|
|
VALUE *var = rb_svar(1);
|
|
|
|
if (var) {
|
|
|
|
return *var;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
return Qnil;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_backref_set(val)
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE val;
|
|
|
|
{
|
2001-09-20 02:23:50 -04:00
|
|
|
VALUE *var = rb_svar(1);
|
|
|
|
if (var) {
|
|
|
|
*var = val;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
special_local_set('~', val);
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_lastline_get()
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2001-09-20 02:23:50 -04:00
|
|
|
VALUE *var = rb_svar(0);
|
|
|
|
if (var) {
|
|
|
|
return *var;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
return Qnil;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_lastline_set(val)
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE val;
|
|
|
|
{
|
2001-09-20 02:23:50 -04:00
|
|
|
VALUE *var = rb_svar(0);
|
|
|
|
if (var) {
|
|
|
|
*var = val;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
special_local_set('_', val);
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2004-09-12 11:21:49 -04:00
|
|
|
#endif /* !RIPPER */
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
static void
|
|
|
|
parser_initialize(parser)
|
|
|
|
struct parser_params *parser;
|
|
|
|
{
|
|
|
|
parser->result = Qnil;
|
|
|
|
parser->toplevel_p = Qtrue;
|
|
|
|
parser->parsing_thread = Qnil;
|
|
|
|
|
2004-09-21 20:19:15 -04:00
|
|
|
#ifndef RIPPER
|
|
|
|
parser->parser_eval_tree_begin = 0;
|
|
|
|
parser->parser_eval_tree = 0;
|
|
|
|
#endif
|
2004-09-17 05:24:13 -04:00
|
|
|
parser->parser_lex_strterm = 0;
|
|
|
|
parser->parser_cond_stack = 0;
|
|
|
|
parser->parser_cmdarg_stack = 0;
|
|
|
|
parser->parser_class_nest = 0;
|
|
|
|
parser->parser_in_single = 0;
|
|
|
|
parser->parser_in_def = 0;
|
|
|
|
parser->parser_in_defined = 0;
|
|
|
|
parser->parser_compile_for_eval = 0;
|
|
|
|
parser->parser_cur_mid = 0;
|
|
|
|
parser->parser_tokenbuf = NULL;
|
|
|
|
parser->parser_tokidx = 0;
|
|
|
|
parser->parser_toksiz = 0;
|
|
|
|
parser->parser_heredoc_end = 0;
|
|
|
|
parser->parser_command_start = Qtrue;
|
|
|
|
parser->parser_lex_pbeg = 0;
|
|
|
|
parser->parser_lex_p = 0;
|
|
|
|
parser->parser_lex_pend = 0;
|
2004-10-02 07:34:13 -04:00
|
|
|
parser->parser_lvtbl = 0;
|
2004-09-19 23:03:12 -04:00
|
|
|
#ifdef RIPPER
|
2004-09-20 03:59:30 -04:00
|
|
|
parser->parser_ruby_sourcefile = Qnil;
|
|
|
|
parser->delayed = Qnil;
|
2004-09-19 23:03:12 -04:00
|
|
|
#endif
|
2004-09-17 05:24:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-09-21 20:19:15 -04:00
|
|
|
parser_mark(ptr)
|
2004-09-17 05:24:13 -04:00
|
|
|
void *ptr;
|
|
|
|
{
|
|
|
|
struct parser_params *p = (struct parser_params*)ptr;
|
|
|
|
|
|
|
|
rb_gc_mark(p->result);
|
|
|
|
rb_gc_mark(p->parsing_thread);
|
|
|
|
rb_gc_mark((VALUE)p->parser_lex_strterm);
|
|
|
|
/*rb_gc_mark(p->parser_cur_mid);*/
|
|
|
|
rb_gc_mark(p->parser_lex_input);
|
|
|
|
rb_gc_mark(p->parser_lex_lastline);
|
|
|
|
#ifdef RIPPER
|
|
|
|
rb_gc_mark(p->parser_ruby_sourcefile);
|
2004-09-19 23:03:12 -04:00
|
|
|
rb_gc_mark(p->delayed);
|
2004-09-21 20:19:15 -04:00
|
|
|
#else
|
|
|
|
rb_gc_mark((VALUE)p->parser_eval_tree_begin) ;
|
|
|
|
rb_gc_mark((VALUE)p->parser_eval_tree) ;
|
2004-09-17 05:24:13 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-09-21 20:19:15 -04:00
|
|
|
parser_free(ptr)
|
2004-09-17 05:24:13 -04:00
|
|
|
void *ptr;
|
|
|
|
{
|
|
|
|
struct parser_params *p = (struct parser_params*)ptr;
|
2004-10-02 07:34:13 -04:00
|
|
|
struct local_vars *local, *prev;
|
2004-09-17 05:24:13 -04:00
|
|
|
|
|
|
|
if (p->parser_tokenbuf) {
|
2004-10-02 07:34:13 -04:00
|
|
|
xfree(p->parser_tokenbuf);
|
|
|
|
}
|
|
|
|
for (local = p->parser_lvtbl; local; local = prev) {
|
|
|
|
if (local->tbl && !local->nofree)
|
|
|
|
xfree(local->tbl);
|
|
|
|
prev = local->prev;
|
|
|
|
xfree(local);
|
2004-09-17 05:24:13 -04:00
|
|
|
}
|
2004-10-02 07:34:13 -04:00
|
|
|
xfree(p);
|
2004-09-17 05:24:13 -04:00
|
|
|
}
|
|
|
|
|
2004-09-20 01:40:23 -04:00
|
|
|
#ifndef RIPPER
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *
|
|
|
|
parser_new()
|
|
|
|
{
|
|
|
|
struct parser_params *p;
|
|
|
|
|
|
|
|
p = ALLOC_N(struct parser_params, 1);
|
|
|
|
MEMZERO(p, struct parser_params, 1);
|
2004-09-21 20:19:15 -04:00
|
|
|
p->value = Data_Wrap_Struct(rb_cData, parser_mark, parser_free, p);
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_initialize(p);
|
|
|
|
return p;
|
|
|
|
}
|
2004-09-20 01:40:23 -04:00
|
|
|
#endif
|
2004-09-17 05:24:13 -04:00
|
|
|
|
2004-09-12 11:21:49 -04:00
|
|
|
#ifdef RIPPER
|
|
|
|
#ifdef RIPPER_DEBUG
|
|
|
|
extern int rb_is_pointer_to_heap _((VALUE));
|
|
|
|
|
2004-10-19 21:38:04 -04:00
|
|
|
/* :nodoc: */
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_validate_object(self, x)
|
|
|
|
VALUE self, x;
|
|
|
|
{
|
|
|
|
if (x == Qfalse) return x;
|
|
|
|
if (x == Qtrue) return x;
|
|
|
|
if (x == Qnil) return x;
|
|
|
|
if (x == Qundef)
|
|
|
|
rb_raise(rb_eArgError, "Qundef given");
|
|
|
|
if (FIXNUM_P(x)) return x;
|
|
|
|
if (SYMBOL_P(x)) return x;
|
|
|
|
if (!rb_is_pointer_to_heap(x))
|
|
|
|
rb_raise(rb_eArgError, "invalid pointer: 0x%x", x);
|
|
|
|
switch (TYPE(x)) {
|
|
|
|
case T_STRING:
|
|
|
|
case T_OBJECT:
|
|
|
|
case T_ARRAY:
|
|
|
|
case T_BIGNUM:
|
|
|
|
case T_FLOAT:
|
|
|
|
return x;
|
|
|
|
case T_NODE:
|
|
|
|
rb_raise(rb_eArgError, "NODE given: 0x%x", x);
|
|
|
|
default:
|
|
|
|
rb_raise(rb_eArgError, "wrong type of ruby object: 0x%x (%s)",
|
|
|
|
x, rb_obj_classname(x));
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define validate(x)
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_dispatch0(parser, mid)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
ID mid;
|
|
|
|
{
|
|
|
|
return rb_funcall(parser->value, mid, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_dispatch1(parser, mid, a)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
ID mid;
|
|
|
|
VALUE a;
|
|
|
|
{
|
|
|
|
validate(a);
|
|
|
|
return rb_funcall(parser->value, mid, 1, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_dispatch2(parser, mid, a, b)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
ID mid;
|
|
|
|
VALUE a, b;
|
|
|
|
{
|
|
|
|
validate(a);
|
|
|
|
validate(b);
|
|
|
|
return rb_funcall(parser->value, mid, 2, a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_dispatch3(parser, mid, a, b, c)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
ID mid;
|
|
|
|
VALUE a, b, c;
|
|
|
|
{
|
|
|
|
validate(a);
|
|
|
|
validate(b);
|
|
|
|
validate(c);
|
|
|
|
return rb_funcall(parser->value, mid, 3, a, b, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_dispatch4(parser, mid, a, b, c, d)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
ID mid;
|
|
|
|
VALUE a, b, c, d;
|
|
|
|
{
|
|
|
|
validate(a);
|
|
|
|
validate(b);
|
|
|
|
validate(c);
|
|
|
|
validate(d);
|
|
|
|
return rb_funcall(parser->value, mid, 4, a, b, c, d);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_dispatch5(parser, mid, a, b, c, d, e)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
ID mid;
|
|
|
|
VALUE a, b, c, d, e;
|
|
|
|
{
|
|
|
|
validate(a);
|
|
|
|
validate(b);
|
|
|
|
validate(c);
|
|
|
|
validate(d);
|
|
|
|
validate(e);
|
|
|
|
return rb_funcall(parser->value, mid, 5, a, b, c, d, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct kw_assoc {
|
|
|
|
ID id;
|
|
|
|
const char *name;
|
|
|
|
} keyword_to_name[] = {
|
|
|
|
{kCLASS, "class"},
|
|
|
|
{kMODULE, "module"},
|
|
|
|
{kDEF, "def"},
|
|
|
|
{kUNDEF, "undef"},
|
|
|
|
{kBEGIN, "begin"},
|
|
|
|
{kRESCUE, "rescue"},
|
|
|
|
{kENSURE, "ensure"},
|
|
|
|
{kEND, "end"},
|
|
|
|
{kIF, "if"},
|
|
|
|
{kUNLESS, "unless"},
|
|
|
|
{kTHEN, "then"},
|
|
|
|
{kELSIF, "elsif"},
|
|
|
|
{kELSE, "else"},
|
|
|
|
{kCASE, "case"},
|
|
|
|
{kWHEN, "when"},
|
|
|
|
{kWHILE, "while"},
|
|
|
|
{kUNTIL, "until"},
|
|
|
|
{kFOR, "for"},
|
|
|
|
{kBREAK, "break"},
|
|
|
|
{kNEXT, "next"},
|
|
|
|
{kREDO, "redo"},
|
|
|
|
{kRETRY, "retry"},
|
|
|
|
{kIN, "in"},
|
|
|
|
{kDO, "do"},
|
|
|
|
{kDO_COND, "do"},
|
|
|
|
{kDO_BLOCK, "do"},
|
|
|
|
{kRETURN, "return"},
|
|
|
|
{kYIELD, "yield"},
|
|
|
|
{kSUPER, "super"},
|
|
|
|
{kSELF, "self"},
|
|
|
|
{kNIL, "nil"},
|
|
|
|
{kTRUE, "true"},
|
|
|
|
{kFALSE, "false"},
|
|
|
|
{kAND, "and"},
|
|
|
|
{kOR, "or"},
|
|
|
|
{kNOT, "not"},
|
|
|
|
{kIF_MOD, "if"},
|
|
|
|
{kUNLESS_MOD, "unless"},
|
|
|
|
{kWHILE_MOD, "while"},
|
|
|
|
{kUNTIL_MOD, "until"},
|
|
|
|
{kRESCUE_MOD, "rescue"},
|
|
|
|
{kALIAS, "alias"},
|
|
|
|
{kDEFINED, "defined"},
|
|
|
|
{klBEGIN, "BEGIN"},
|
|
|
|
{klEND, "END"},
|
|
|
|
{k__LINE__, "__LINE__"},
|
|
|
|
{k__FILE__, "__FILE__"},
|
|
|
|
{0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char*
|
|
|
|
keyword_id_to_str(id)
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
struct kw_assoc *a;
|
|
|
|
|
|
|
|
for (a = keyword_to_name; a->id; a++) {
|
|
|
|
if (a->id == id)
|
|
|
|
return a->name;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_id2sym(id)
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
char buf[8];
|
|
|
|
|
|
|
|
if (id <= 256) {
|
|
|
|
buf[0] = id;
|
|
|
|
buf[1] = '\0';
|
|
|
|
return ID2SYM(rb_intern(buf));
|
|
|
|
}
|
|
|
|
if ((name = keyword_id_to_str(id))) {
|
|
|
|
return ID2SYM(rb_intern(name));
|
|
|
|
}
|
|
|
|
switch (id) {
|
|
|
|
case tOROP:
|
|
|
|
name = "||";
|
|
|
|
break;
|
|
|
|
case tANDOP:
|
|
|
|
name = "&&";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
name = rb_id2name(id);
|
|
|
|
if (!name) {
|
|
|
|
rb_bug("cannot convert ID to string: %ld", (unsigned long)id);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ID2SYM(rb_intern(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_intern(s)
|
|
|
|
const char *s;
|
|
|
|
{
|
|
|
|
return ID2SYM(rb_intern(s));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_STDARG_PROTOTYPES
|
|
|
|
# include <stdarg.h>
|
|
|
|
# define va_init_list(a,b) va_start(a,b)
|
|
|
|
#else
|
|
|
|
# include <varargs.h>
|
|
|
|
# define va_init_list(a,b) va_start(a)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void
|
|
|
|
#ifdef HAVE_STDARG_PROTOTYPES
|
2004-09-17 05:24:13 -04:00
|
|
|
ripper_compile_error(struct parser_params *parser, const char *fmt, ...)
|
2004-09-12 11:21:49 -04:00
|
|
|
#else
|
2004-09-17 05:24:13 -04:00
|
|
|
ripper_compile_error(parser, fmt, va_alist)
|
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
const char *fmt;
|
|
|
|
va_dcl
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_init_list(args, fmt);
|
|
|
|
vsnprintf(buf, BUFSIZ, fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
rb_funcall(parser->value, rb_intern("compile_error"), 1, rb_str_new2(buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ripper_warn0(parser, fmt)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
const char *fmt;
|
|
|
|
{
|
|
|
|
rb_funcall(parser->value, rb_intern("warn"), 1, rb_str_new2(fmt));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ripper_warnI(parser, fmt, a)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
const char *fmt;
|
|
|
|
int a;
|
|
|
|
{
|
|
|
|
rb_funcall(parser->value, rb_intern("warn"), 2,
|
|
|
|
rb_str_new2(fmt), INT2NUM(a));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ripper_warnS(parser, fmt, str)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
const char *fmt;
|
|
|
|
const char *str;
|
|
|
|
{
|
|
|
|
rb_funcall(parser->value, rb_intern("warn"), 2,
|
|
|
|
rb_str_new2(fmt), rb_str_new2(str));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ripper_warning0(parser, fmt)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
const char *fmt;
|
|
|
|
{
|
|
|
|
rb_funcall(parser->value, rb_intern("warning"), 1, rb_str_new2(fmt));
|
|
|
|
}
|
|
|
|
|
2004-09-17 07:38:49 -04:00
|
|
|
static VALUE ripper_lex_get_generic _((struct parser_params *, VALUE));
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_lex_get_generic(parser, src)
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
VALUE src;
|
|
|
|
{
|
|
|
|
return rb_funcall(src, ripper_id_gets, 0);
|
|
|
|
}
|
|
|
|
|
2004-10-29 04:19:50 -04:00
|
|
|
static VALUE ripper_s_allocate _((VALUE));
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_s_allocate(klass)
|
|
|
|
VALUE klass;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *p;
|
2004-09-12 11:21:49 -04:00
|
|
|
VALUE self;
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
p = ALLOC_N(struct parser_params, 1);
|
|
|
|
MEMZERO(p, struct parser_params, 1);
|
2004-09-21 20:19:15 -04:00
|
|
|
self = Data_Wrap_Struct(klass, parser_mark, parser_free, p);
|
2004-09-12 11:21:49 -04:00
|
|
|
p->value = self;
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
obj_respond_to(obj, mid)
|
|
|
|
VALUE obj, mid;
|
|
|
|
{
|
|
|
|
VALUE st;
|
|
|
|
|
|
|
|
st = rb_funcall(obj, rb_intern("respond_to?"), 2, mid, Qfalse);
|
|
|
|
return RTEST(st);
|
|
|
|
}
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
#define ripper_initialized_p(r) ((r)->parser_lex_input != 0)
|
2004-09-12 11:21:49 -04:00
|
|
|
|
2004-09-14 09:11:29 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* Ripper.new(src, filename="(ripper)", lineno=1) -> ripper
|
|
|
|
*
|
|
|
|
* Create a new Ripper object.
|
|
|
|
* _src_ must be a String, a IO, or an Object which has #gets method.
|
|
|
|
*
|
|
|
|
* This method does not starts parsing.
|
|
|
|
* See also Ripper#parse and Ripper.parse.
|
|
|
|
*/
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_initialize(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
VALUE src, fname, lineno;
|
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
Data_Get_Struct(self, struct parser_params, parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
|
|
|
|
if (obj_respond_to(src, ID2SYM(ripper_id_gets))) {
|
2004-09-17 05:24:13 -04:00
|
|
|
parser->parser_lex_gets = ripper_lex_get_generic;
|
2004-09-12 11:21:49 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
StringValue(src);
|
2004-09-17 05:24:13 -04:00
|
|
|
parser->parser_lex_gets = lex_get_str;
|
2004-09-12 11:21:49 -04:00
|
|
|
}
|
2004-09-17 05:24:13 -04:00
|
|
|
parser->parser_lex_input = src;
|
2004-09-12 11:21:49 -04:00
|
|
|
parser->eofp = Qfalse;
|
|
|
|
if (NIL_P(fname)) {
|
|
|
|
fname = rb_str_new2("(ripper)");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
StringValue(fname);
|
|
|
|
}
|
2004-09-17 05:24:13 -04:00
|
|
|
parser_initialize(parser);
|
|
|
|
parser->parser_ruby_sourcefile = fname;
|
|
|
|
parser->parser_ruby_sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
|
|
|
|
parser->parser_ruby__end__seen = 0;
|
2004-09-12 11:21:49 -04:00
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2004-09-14 09:11:29 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* Ripper.yydebug -> true or false
|
|
|
|
*
|
|
|
|
* Get yydebug.
|
|
|
|
*/
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_s_get_yydebug(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return ripper_yydebug ? Qtrue : Qfalse;
|
|
|
|
}
|
|
|
|
|
2004-09-14 09:11:29 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* Ripper.yydebug = flag
|
|
|
|
*
|
|
|
|
* Set yydebug.
|
|
|
|
*/
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_s_set_yydebug(self, flag)
|
|
|
|
VALUE self, flag;
|
|
|
|
{
|
|
|
|
ripper_yydebug = RTEST(flag);
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern VALUE rb_thread_pass _((void));
|
|
|
|
|
|
|
|
struct ripper_args {
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_parse0(parser_v)
|
|
|
|
VALUE parser_v;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
Data_Get_Struct(parser_v, struct parser_params, parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
ripper_yyparse((void*)parser);
|
|
|
|
return parser->result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ripper_ensure(parser_v)
|
|
|
|
VALUE parser_v;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
Data_Get_Struct(parser_v, struct parser_params, parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
parser->parsing_thread = Qnil;
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2004-09-14 09:11:29 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* ripper#parse
|
|
|
|
*
|
|
|
|
* Start parsing and returns the value of the root action.
|
|
|
|
*/
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_parse(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
Data_Get_Struct(self, struct parser_params, parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
if (!ripper_initialized_p(parser)) {
|
|
|
|
rb_raise(rb_eArgError, "method called for uninitialized object");
|
|
|
|
}
|
|
|
|
if (!NIL_P(parser->parsing_thread)) {
|
|
|
|
if (parser->parsing_thread == rb_thread_current())
|
|
|
|
rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
|
|
|
|
else
|
|
|
|
rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
|
|
|
|
}
|
|
|
|
parser->parsing_thread = rb_thread_current();
|
|
|
|
rb_ensure(ripper_parse0, self, ripper_ensure, self);
|
|
|
|
|
|
|
|
return parser->result;
|
|
|
|
}
|
|
|
|
|
2004-09-14 09:11:29 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* ripper#column -> Integer
|
|
|
|
*
|
|
|
|
* Return column number of current parsing line.
|
|
|
|
* This number starts from 0.
|
|
|
|
*/
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_column(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-19 23:03:12 -04:00
|
|
|
long col;
|
2004-09-12 11:21:49 -04:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
Data_Get_Struct(self, struct parser_params, parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
if (!ripper_initialized_p(parser)) {
|
|
|
|
rb_raise(rb_eArgError, "method called for uninitialized object");
|
|
|
|
}
|
|
|
|
if (NIL_P(parser->parsing_thread)) return Qnil;
|
2004-09-20 00:23:18 -04:00
|
|
|
col = parser->tokp - parser->parser_lex_pbeg;
|
2004-09-19 23:03:12 -04:00
|
|
|
return LONG2NUM(col);
|
2004-09-12 11:21:49 -04:00
|
|
|
}
|
|
|
|
|
2004-09-14 09:11:29 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* ripper#lineno -> Integer
|
|
|
|
*
|
|
|
|
* Return line number of current parsing line.
|
|
|
|
* This number starts from 1.
|
|
|
|
*/
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_lineno(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
2004-09-17 05:24:13 -04:00
|
|
|
struct parser_params *parser;
|
2004-09-12 11:21:49 -04:00
|
|
|
|
2004-09-17 05:24:13 -04:00
|
|
|
Data_Get_Struct(self, struct parser_params, parser);
|
2004-09-12 11:21:49 -04:00
|
|
|
if (!ripper_initialized_p(parser)) {
|
|
|
|
rb_raise(rb_eArgError, "method called for uninitialized object");
|
|
|
|
}
|
|
|
|
if (NIL_P(parser->parsing_thread)) return Qnil;
|
2004-09-17 05:24:13 -04:00
|
|
|
return INT2NUM(parser->parser_ruby_sourceline);
|
2004-09-12 11:21:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef RIPPER_DEBUG
|
2004-10-19 21:38:04 -04:00
|
|
|
/* :nodoc: */
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_assert_Qundef(self, obj, msg)
|
|
|
|
VALUE self, obj, msg;
|
|
|
|
{
|
|
|
|
StringValue(msg);
|
|
|
|
if (obj == Qundef) {
|
|
|
|
rb_raise(rb_eArgError, RSTRING(msg)->ptr);
|
|
|
|
}
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2004-10-19 21:38:04 -04:00
|
|
|
/* :nodoc: */
|
2004-09-12 11:21:49 -04:00
|
|
|
static VALUE
|
|
|
|
ripper_value(self, obj)
|
|
|
|
VALUE self, obj;
|
|
|
|
{
|
|
|
|
return ULONG2NUM(obj);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
|
|
|
Init_ripper()
|
|
|
|
{
|
|
|
|
VALUE Ripper;
|
|
|
|
|
|
|
|
Ripper = rb_define_class("Ripper", rb_cObject);
|
|
|
|
rb_define_const(Ripper, "Version", rb_str_new2(RIPPER_VERSION));
|
|
|
|
rb_define_singleton_method(Ripper, "yydebug", ripper_s_get_yydebug, 0);
|
|
|
|
rb_define_singleton_method(Ripper, "yydebug=", ripper_s_set_yydebug, 1);
|
|
|
|
rb_define_alloc_func(Ripper, ripper_s_allocate);
|
|
|
|
rb_define_method(Ripper, "initialize", ripper_initialize, -1);
|
|
|
|
rb_define_method(Ripper, "parse", ripper_parse, 0);
|
|
|
|
rb_define_method(Ripper, "column", ripper_column, 0);
|
|
|
|
rb_define_method(Ripper, "lineno", ripper_lineno, 0);
|
|
|
|
#ifdef RIPPER_DEBUG
|
|
|
|
rb_define_method(rb_mKernel, "assert_Qundef", ripper_assert_Qundef, 2);
|
|
|
|
rb_define_method(rb_mKernel, "rawVALUE", ripper_value, 1);
|
|
|
|
rb_define_method(rb_mKernel, "validate_object", ripper_validate_object, 1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ripper_id_gets = rb_intern("gets");
|
|
|
|
ripper_init_eventids1();
|
|
|
|
ripper_init_eventids2();
|
|
|
|
/* ensure existing in symbol table */
|
|
|
|
rb_intern("||");
|
|
|
|
rb_intern("&&");
|
|
|
|
}
|
|
|
|
#endif /* RIPPER */
|