ruby-changes:56143
From: Hiroshi <ko1@a...>
Date: Wed, 19 Jun 2019 18:27:26 +0900 (JST)
Subject: [ruby-changes:56143] Hiroshi SHIBATA: 1a2546c2be (trunk): Backport racc-1.4.15 from upstream.
https://git.ruby-lang.org/ruby.git/commit/?id=1a2546c2be From 1a2546c2be839baa7d0a50dc056d4d6987d26852 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA <hsbt@r...> Date: Mon, 13 May 2019 21:25:22 +0900 Subject: Backport racc-1.4.15 from upstream. diff --git a/ext/racc/cparse.c b/ext/racc/cparse.c new file mode 100644 index 0000000..cc0e865 --- /dev/null +++ b/ext/racc/cparse.c @@ -0,0 +1,861 @@ https://github.com/ruby/ruby/blob/trunk/ext/racc/cparse.c#L1 +/* + + cparse.c -- Racc Runtime Core + + Copyright (c) 1999-2006 Minero Aoki + + This library is free software. + You can distribute/modify this program under the same terms of ruby. + + $originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $ + +*/ + +#include <ruby.h> + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +/* ----------------------------------------------------------------------- + Important Constants +----------------------------------------------------------------------- */ + +#define RACC_VERSION "1.4.15" + +#define DEFAULT_TOKEN -1 +#define ERROR_TOKEN 1 +#define FINAL_TOKEN 0 + +#define vDEFAULT_TOKEN INT2FIX(DEFAULT_TOKEN) +#define vERROR_TOKEN INT2FIX(ERROR_TOKEN) +#define vFINAL_TOKEN INT2FIX(FINAL_TOKEN) + +/* ----------------------------------------------------------------------- + File Local Variables +----------------------------------------------------------------------- */ + +static VALUE RaccBug; +static VALUE CparseParams; + +static ID id_yydebug; +static ID id_nexttoken; +static ID id_onerror; +static ID id_noreduce; +static ID id_errstatus; + +static ID id_d_shift; +static ID id_d_reduce; +static ID id_d_accept; +static ID id_d_read_token; +static ID id_d_next_state; +static ID id_d_e_pop; + +/* ----------------------------------------------------------------------- + Utils +----------------------------------------------------------------------- */ + +/* For backward compatibility */ +#ifndef ID2SYM +# define ID2SYM(i) ULONG2NUM(i) +#endif +#ifndef SYM2ID +# define SYM2ID(v) ((ID)NUM2ULONG(v)) +#endif +#ifndef SYMBOL_P +# define SYMBOL_P(v) FIXNUM_P(v) +#endif +#ifndef LONG2NUM +# define LONG2NUM(i) INT2NUM(i) +#endif + +#ifndef HAVE_RB_ARY_SUBSEQ +# define rb_ary_subseq(ary, beg, len) rb_ary_new4(len, RARRAY_PTR(ary) + beg) +#endif + +static ID value_to_id _((VALUE v)); +static inline long num_to_long _((VALUE n)); + +static ID +value_to_id(VALUE v) +{ + if (! SYMBOL_P(v)) { + rb_raise(rb_eTypeError, "not symbol"); + } + return SYM2ID(v); +} + +static inline long +num_to_long(VALUE n) +{ + return NUM2LONG(n); +} + +#define AREF(s, idx) \ + ((0 <= idx && idx < RARRAY_LEN(s)) ? rb_ary_entry(s, idx) : Qnil) + +/* ----------------------------------------------------------------------- + Parser Stack Interfaces +----------------------------------------------------------------------- */ + +static VALUE get_stack_tail _((VALUE stack, long len)); +static void cut_stack_tail _((VALUE stack, long len)); + +static VALUE +get_stack_tail(VALUE stack, long len) +{ + if (len < 0) return Qnil; /* system error */ + if (len > RARRAY_LEN(stack)) len = RARRAY_LEN(stack); + return rb_ary_subseq(stack, RARRAY_LEN(stack) - len, len); +} + +static void +cut_stack_tail(VALUE stack, long len) +{ + while (len > 0) { + rb_ary_pop(stack); + len--; + } +} + +#define STACK_INIT_LEN 64 +#define NEW_STACK() rb_ary_new2(STACK_INIT_LEN) +#define PUSH(s, i) rb_ary_store(s, RARRAY_LEN(s), i) +#define POP(s) rb_ary_pop(s) +#define LAST_I(s) \ + ((RARRAY_LEN(s) > 0) ? rb_ary_entry(s, RARRAY_LEN(s) - 1) : Qnil) +#define GET_TAIL(s, len) get_stack_tail(s, len) +#define CUT_TAIL(s, len) cut_stack_tail(s, len) + +/* ----------------------------------------------------------------------- + struct cparse_params +----------------------------------------------------------------------- */ + +struct cparse_params { + VALUE value_v; /* VALUE version of this struct */ + + VALUE parser; /* parser object */ + + int lex_is_iterator; + VALUE lexer; /* scanner object */ + ID lexmid; /* name of scanner method (must be an iterator) */ + + /* State transition tables (immutable) + Data structure is from Dragon Book 4.9 */ + /* action table */ + VALUE action_table; + VALUE action_check; + VALUE action_default; + VALUE action_pointer; + /* goto table */ + VALUE goto_table; + VALUE goto_check; + VALUE goto_default; + VALUE goto_pointer; + + long nt_base; /* NonTerminal BASE index */ + VALUE reduce_table; /* reduce data table */ + VALUE token_table; /* token conversion table */ + + /* parser stacks and parameters */ + VALUE state; + long curstate; + VALUE vstack; + VALUE tstack; + VALUE t; + long shift_n; + long reduce_n; + long ruleno; + + long errstatus; /* nonzero in error recovering mode */ + long nerr; /* number of error */ + + int use_result_var; + + VALUE retval; /* return value of parser routine */ + long fin; /* parse result status */ +#define CP_FIN_ACCEPT 1 +#define CP_FIN_EOT 2 +#define CP_FIN_CANTPOP 3 + + int debug; /* user level debug */ + int sys_debug; /* system level debug */ + + long i; /* table index */ +}; + +/* ----------------------------------------------------------------------- + Parser Main Routines +----------------------------------------------------------------------- */ + +static VALUE racc_cparse _((VALUE parser, VALUE arg, VALUE sysdebug)); +static VALUE racc_yyparse _((VALUE parser, VALUE lexer, VALUE lexmid, + VALUE arg, VALUE sysdebug)); + +static void call_lexer _((struct cparse_params *v)); +static VALUE lexer_i _((RB_BLOCK_CALL_FUNC_ARGLIST(block_args, data))); + +static VALUE assert_array _((VALUE a)); +static long assert_integer _((VALUE n)); +static VALUE assert_hash _((VALUE h)); +static VALUE initialize_params _((VALUE vparams, VALUE parser, VALUE arg, + VALUE lexer, VALUE lexmid)); +static void cparse_params_mark _((void *ptr)); +static size_t cparse_params_memsize _((const void *ptr)); + +static void parse_main _((struct cparse_params *v, + VALUE tok, VALUE val, int resume)); +static void extract_user_token _((struct cparse_params *v, + VALUE block_args, VALUE *tok, VALUE *val)); +static void shift _((struct cparse_params* v, long act, VALUE tok, VALUE val)); +static int reduce _((struct cparse_params* v, long act)); +static VALUE reduce0 _((VALUE block_args, VALUE data, VALUE self)); + +#ifdef DEBUG +# define D_puts(msg) if (v->sys_debug) puts(msg) +# define D_printf(fmt,arg) if (v->sys_debug) printf(fmt,arg) +#else +# define D_puts(msg) +# define D_printf(fmt,arg) +#endif + +#undef RUBY_UNTYPED_DATA_WARNING +#define RUBY_UNTYPED_DATA_WARNING 1 + +static const rb_data_type_t cparse_params_type = { + "racc/cparse", + { + cparse_params_mark, + RUBY_TYPED_DEFAULT_FREE, + cparse_params_memsize, + }, +#ifdef RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, + RUBY_TYPED_FREE_IMMEDIATELY, +#endif +}; + +static VALUE +racc_cparse(VALUE parser, VALUE arg, VALUE sysdebug) +{ + VALUE vparams; + struct cparse_params *v; + + vparams = TypedData_Make_Struct(CparseParams, struct cparse_params, + &cparse_params_type, v); + D_puts("starting cparse"); + v->sys_debug = RTEST(sysdebug); + vparams = initialize_params(vparams, parser, arg, Qnil, Qnil); + v->lex_is_iterator = FALSE; + parse_main(v, Qnil, Qnil, 0); + + RB_GC_GUARD(vparams); + return v->retval; +} + +static VALUE +racc_yyparse(VALUE parser, VALUE lexer, VALUE lexmid, VALUE arg, VALUE sysdebug) +{ + VALUE vparams; + struct cparse_params *v; + + vparams = TypedData_Make_Struct(CparseParams, struct cparse_params, + &cparse_params_type, v); + v->sys_debug = RTEST(sysdebug); + D_puts("start C yyparse"); + vparams = initialize_params(vparams, parser, arg, lexer, lexmid); + v->lex_is_iterator = TRUE; + D_puts("params initialized"); + parse_main(v, Qnil, Qnil, 0); + call_lexer(v); + if (!v->fin) { + rb_raise(rb_eArgError, "%s() is finished before EndOfToken", + rb_id2name(v->lexmid)); + } + + RB_GC_GUARD(vparams); + return v->retval; +} + +#ifdef HAVE_RB_BLOCK_CALL +static void +call_lexer(struct cparse_params *v) +{ + rb_block_call(v->lexer, v->lexmid, 0, NULL, lexer_i, v->value_v); +} +#else +static VALUE +lexer_iter(VALUE data) +{ + struct cparse_params *v = rb_check_typeddata(data, &cparse_params_type); + + rb_funcall(v->lexer, v->lexmid, 0); + return Qnil; +} + +static void +call_lexer(struct cparse_params *v) +{ + rb_iterate(lexer_iter, v->value_v, lexer_i, v->value_v); +} +#endif + +static VALUE +lexer_i(RB_BLOCK_CALL_FUNC_ARGLIST(block_args, data)) +{ + struct cparse_params *v = rb_check_typeddata(data, &cparse_params_type); + VALUE tok, val; + + if (v->fin) + rb_raise(rb_eArgError, "extra token after EndOfToken"); + extract_user_token(v, block_args, &tok, &val); + parse_main(v, tok, val, 1); + if (v->fin && v->fin != CP_FIN_ACCEPT) + rb_iter_break(); + return Qnil; +} + +static VALUE +assert_array(VALUE a) +{ + Check_Type(a, T_ARRAY); + return a; +} + +static VALUE +assert_hash(VALUE h) +{ + Check_Type(h, T_HASH); + return h; +} + +static long +assert_integer(VALUE n) +{ + return NUM2LONG(n); +} + +static VALUE +initialize_params(VALUE vparams, VALUE parser, VALUE arg, VALUE lexer, VALUE lexmid) +{ + struct cparse_params *v = rb_check_typeddata(vparams, &cparse_params_type); + + v->value_v = vparams; + v->parser = parser; + (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/