00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ruby/ruby.h"
00015
00016 #ifndef FALSE
00017 #define FALSE 0
00018 #endif
00019 #ifndef TRUE
00020 #define TRUE 1
00021 #endif
00022
00023
00024
00025
00026
00027 #define RACC_VERSION "1.4.5"
00028
00029 #define DEFAULT_TOKEN -1
00030 #define ERROR_TOKEN 1
00031 #define FINAL_TOKEN 0
00032
00033 #define vDEFAULT_TOKEN INT2FIX(DEFAULT_TOKEN)
00034 #define vERROR_TOKEN INT2FIX(ERROR_TOKEN)
00035 #define vFINAL_TOKEN INT2FIX(FINAL_TOKEN)
00036
00037
00038
00039
00040
00041 static VALUE RaccBug;
00042 static VALUE CparseParams;
00043
00044 static ID id_yydebug;
00045 static ID id_nexttoken;
00046 static ID id_onerror;
00047 static ID id_noreduce;
00048 static ID id_errstatus;
00049
00050 static ID id_d_shift;
00051 static ID id_d_reduce;
00052 static ID id_d_accept;
00053 static ID id_d_read_token;
00054 static ID id_d_next_state;
00055 static ID id_d_e_pop;
00056
00057
00058
00059
00060
00061
00062 #ifndef ID2SYM
00063 # define ID2SYM(i) ULONG2NUM(i)
00064 #endif
00065 #ifndef SYM2ID
00066 # define SYM2ID(v) ((ID)NUM2ULONG(v))
00067 #endif
00068 #ifndef SYMBOL_P
00069 # define SYMBOL_P(v) FIXNUM_P(v)
00070 #endif
00071 #ifndef LONG2NUM
00072 # define LONG2NUM(i) INT2NUM(i)
00073 #endif
00074
00075 static ID value_to_id _((VALUE v));
00076 static inline long num_to_long _((VALUE n));
00077
00078 static ID
00079 value_to_id(VALUE v)
00080 {
00081 if (! SYMBOL_P(v)) {
00082 rb_raise(rb_eTypeError, "not symbol");
00083 }
00084 return SYM2ID(v);
00085 }
00086
00087 static inline long
00088 num_to_long(VALUE n)
00089 {
00090 return NUM2LONG(n);
00091 }
00092
00093 #define AREF(s, idx) \
00094 ((0 <= idx && idx < RARRAY_LEN(s)) ? RARRAY_PTR(s)[idx] : Qnil)
00095
00096
00097
00098
00099
00100 static VALUE get_stack_tail _((VALUE stack, long len));
00101 static void cut_stack_tail _((VALUE stack, long len));
00102
00103 static VALUE
00104 get_stack_tail(VALUE stack, long len)
00105 {
00106 if (len < 0) return Qnil;
00107 if (len > RARRAY_LEN(stack)) len = RARRAY_LEN(stack);
00108 return rb_ary_new4(len, RARRAY_PTR(stack) + RARRAY_LEN(stack) - len);
00109 }
00110
00111 static void
00112 cut_stack_tail(VALUE stack, long len)
00113 {
00114 while (len > 0) {
00115 rb_ary_pop(stack);
00116 len--;
00117 }
00118 }
00119
00120 #define STACK_INIT_LEN 64
00121 #define NEW_STACK() rb_ary_new2(STACK_INIT_LEN)
00122 #define PUSH(s, i) rb_ary_store(s, RARRAY_LEN(s), i)
00123 #define POP(s) rb_ary_pop(s)
00124 #define LAST_I(s) \
00125 ((RARRAY_LEN(s) > 0) ? RARRAY_PTR(s)[RARRAY_LEN(s) - 1] : Qnil)
00126 #define GET_TAIL(s, len) get_stack_tail(s, len)
00127 #define CUT_TAIL(s, len) cut_stack_tail(s, len)
00128
00129
00130
00131
00132
00133 struct cparse_params {
00134 VALUE value_v;
00135
00136 VALUE parser;
00137
00138 int lex_is_iterator;
00139 VALUE lexer;
00140 ID lexmid;
00141
00142
00143
00144
00145 VALUE action_table;
00146 VALUE action_check;
00147 VALUE action_default;
00148 VALUE action_pointer;
00149
00150 VALUE goto_table;
00151 VALUE goto_check;
00152 VALUE goto_default;
00153 VALUE goto_pointer;
00154
00155 long nt_base;
00156 VALUE reduce_table;
00157 VALUE token_table;
00158
00159
00160 VALUE state;
00161 long curstate;
00162 VALUE vstack;
00163 VALUE tstack;
00164 VALUE t;
00165 long shift_n;
00166 long reduce_n;
00167 long ruleno;
00168
00169 long errstatus;
00170 long nerr;
00171
00172 int use_result_var;
00173
00174 VALUE retval;
00175 long fin;
00176 #define CP_FIN_ACCEPT 1
00177 #define CP_FIN_EOT 2
00178 #define CP_FIN_CANTPOP 3
00179
00180 int debug;
00181 int sys_debug;
00182
00183 long i;
00184 };
00185
00186
00187
00188
00189
00190 static VALUE racc_cparse _((VALUE parser, VALUE arg, VALUE sysdebug));
00191 static VALUE racc_yyparse _((VALUE parser, VALUE lexer, VALUE lexmid,
00192 VALUE arg, VALUE sysdebug));
00193
00194 static void call_lexer _((struct cparse_params *v));
00195 static VALUE lexer_i _((VALUE block_args, VALUE data, VALUE self));
00196
00197 static VALUE assert_array _((VALUE a));
00198 static long assert_integer _((VALUE n));
00199 static VALUE assert_hash _((VALUE h));
00200 static VALUE initialize_params _((VALUE vparams, VALUE parser, VALUE arg,
00201 VALUE lexer, VALUE lexmid));
00202 static void cparse_params_mark _((void *ptr));
00203
00204 static void parse_main _((struct cparse_params *v,
00205 VALUE tok, VALUE val, int resume));
00206 static void extract_user_token _((struct cparse_params *v,
00207 VALUE block_args, VALUE *tok, VALUE *val));
00208 static void shift _((struct cparse_params* v, long act, VALUE tok, VALUE val));
00209 static int reduce _((struct cparse_params* v, long act));
00210 static VALUE reduce0 _((VALUE block_args, VALUE data, VALUE self));
00211
00212 #ifdef DEBUG
00213 # define D_puts(msg) if (v->sys_debug) puts(msg)
00214 # define D_printf(fmt,arg) if (v->sys_debug) printf(fmt,arg)
00215 #else
00216 # define D_puts(msg)
00217 # define D_printf(fmt,arg)
00218 #endif
00219
00220 static VALUE
00221 racc_cparse(VALUE parser, VALUE arg, VALUE sysdebug)
00222 {
00223 volatile VALUE vparams;
00224 struct cparse_params *v;
00225
00226 vparams = Data_Make_Struct(CparseParams, struct cparse_params,
00227 cparse_params_mark, -1, v);
00228 D_puts("starting cparse");
00229 v->sys_debug = RTEST(sysdebug);
00230 vparams = initialize_params(vparams, parser, arg, Qnil, Qnil);
00231 v->lex_is_iterator = FALSE;
00232 parse_main(v, Qnil, Qnil, 0);
00233
00234 return v->retval;
00235 }
00236
00237 static VALUE
00238 racc_yyparse(VALUE parser, VALUE lexer, VALUE lexmid, VALUE arg, VALUE sysdebug)
00239 {
00240 volatile VALUE vparams;
00241 struct cparse_params *v;
00242
00243 vparams = Data_Make_Struct(CparseParams, struct cparse_params,
00244 cparse_params_mark, -1, v);
00245 v->sys_debug = RTEST(sysdebug);
00246 D_puts("start C yyparse");
00247 vparams = initialize_params(vparams, parser, arg, lexer, lexmid);
00248 v->lex_is_iterator = TRUE;
00249 D_puts("params initialized");
00250 parse_main(v, Qnil, Qnil, 0);
00251 call_lexer(v);
00252 if (!v->fin) {
00253 rb_raise(rb_eArgError, "%s() is finished before EndOfToken",
00254 rb_id2name(v->lexmid));
00255 }
00256
00257 return v->retval;
00258 }
00259
00260 #ifdef HAVE_RB_BLOCK_CALL
00261 static void
00262 call_lexer(struct cparse_params *v)
00263 {
00264 rb_block_call(v->lexer, v->lexmid, 0, NULL, lexer_i, v->value_v);
00265 }
00266 #else
00267 static VALUE
00268 lexer_iter(VALUE data)
00269 {
00270 struct cparse_params *v;
00271
00272 Data_Get_Struct(data, struct cparse_params, v);
00273 rb_funcall(v->lexer, v->lexmid, 0);
00274 return Qnil;
00275 }
00276
00277 static void
00278 call_lexer(struct cparse_params *v)
00279 {
00280 rb_iterate(lexer_iter, v->value_v, lexer_i, v->value_v);
00281 }
00282 #endif
00283
00284 static VALUE
00285 lexer_i(VALUE block_args, VALUE data, VALUE self)
00286 {
00287 struct cparse_params *v;
00288 VALUE tok, val;
00289
00290 Data_Get_Struct(data, struct cparse_params, v);
00291 if (v->fin)
00292 rb_raise(rb_eArgError, "extra token after EndOfToken");
00293 extract_user_token(v, block_args, &tok, &val);
00294 parse_main(v, tok, val, 1);
00295 if (v->fin && v->fin != CP_FIN_ACCEPT)
00296 rb_iter_break();
00297 return Qnil;
00298 }
00299
00300 static VALUE
00301 assert_array(VALUE a)
00302 {
00303 Check_Type(a, T_ARRAY);
00304 return a;
00305 }
00306
00307 static VALUE
00308 assert_hash(VALUE h)
00309 {
00310 Check_Type(h, T_HASH);
00311 return h;
00312 }
00313
00314 static long
00315 assert_integer(VALUE n)
00316 {
00317 return NUM2LONG(n);
00318 }
00319
00320 static VALUE
00321 initialize_params(VALUE vparams, VALUE parser, VALUE arg, VALUE lexer, VALUE lexmid)
00322 {
00323 struct cparse_params *v;
00324
00325 Data_Get_Struct(vparams, struct cparse_params, v);
00326 v->value_v = vparams;
00327 v->parser = parser;
00328 v->lexer = lexer;
00329 if (! NIL_P(lexmid))
00330 v->lexmid = value_to_id(lexmid);
00331
00332 v->debug = RTEST(rb_ivar_get(parser, id_yydebug));
00333
00334 Check_Type(arg, T_ARRAY);
00335 if (!(13 <= RARRAY_LEN(arg) && RARRAY_LEN(arg) <= 14))
00336 rb_raise(RaccBug, "[Racc Bug] wrong arg.size %ld", RARRAY_LEN(arg));
00337 v->action_table = assert_array (RARRAY_PTR(arg)[ 0]);
00338 v->action_check = assert_array (RARRAY_PTR(arg)[ 1]);
00339 v->action_default = assert_array (RARRAY_PTR(arg)[ 2]);
00340 v->action_pointer = assert_array (RARRAY_PTR(arg)[ 3]);
00341 v->goto_table = assert_array (RARRAY_PTR(arg)[ 4]);
00342 v->goto_check = assert_array (RARRAY_PTR(arg)[ 5]);
00343 v->goto_default = assert_array (RARRAY_PTR(arg)[ 6]);
00344 v->goto_pointer = assert_array (RARRAY_PTR(arg)[ 7]);
00345 v->nt_base = assert_integer(RARRAY_PTR(arg)[ 8]);
00346 v->reduce_table = assert_array (RARRAY_PTR(arg)[ 9]);
00347 v->token_table = assert_hash (RARRAY_PTR(arg)[10]);
00348 v->shift_n = assert_integer(RARRAY_PTR(arg)[11]);
00349 v->reduce_n = assert_integer(RARRAY_PTR(arg)[12]);
00350 if (RARRAY_LEN(arg) > 13) {
00351 v->use_result_var = RTEST(RARRAY_PTR(arg)[13]);
00352 }
00353 else {
00354 v->use_result_var = TRUE;
00355 }
00356
00357 v->tstack = v->debug ? NEW_STACK() : Qnil;
00358 v->vstack = NEW_STACK();
00359 v->state = NEW_STACK();
00360 v->curstate = 0;
00361 PUSH(v->state, INT2FIX(0));
00362 v->t = INT2FIX(FINAL_TOKEN + 1);
00363 v->nerr = 0;
00364 v->errstatus = 0;
00365 rb_ivar_set(parser, id_errstatus, LONG2NUM(v->errstatus));
00366
00367 v->retval = Qnil;
00368 v->fin = 0;
00369
00370 v->lex_is_iterator = FALSE;
00371
00372 rb_iv_set(parser, "@vstack", v->vstack);
00373 if (v->debug) {
00374 rb_iv_set(parser, "@tstack", v->tstack);
00375 }
00376 else {
00377 rb_iv_set(parser, "@tstack", Qnil);
00378 }
00379
00380 return vparams;
00381 }
00382
00383 static void
00384 cparse_params_mark(void *ptr)
00385 {
00386 struct cparse_params *v = (struct cparse_params*)ptr;
00387
00388 rb_gc_mark(v->value_v);
00389 rb_gc_mark(v->parser);
00390 rb_gc_mark(v->lexer);
00391 rb_gc_mark(v->action_table);
00392 rb_gc_mark(v->action_check);
00393 rb_gc_mark(v->action_default);
00394 rb_gc_mark(v->action_pointer);
00395 rb_gc_mark(v->goto_table);
00396 rb_gc_mark(v->goto_check);
00397 rb_gc_mark(v->goto_default);
00398 rb_gc_mark(v->goto_pointer);
00399 rb_gc_mark(v->reduce_table);
00400 rb_gc_mark(v->token_table);
00401 rb_gc_mark(v->state);
00402 rb_gc_mark(v->vstack);
00403 rb_gc_mark(v->tstack);
00404 rb_gc_mark(v->t);
00405 rb_gc_mark(v->retval);
00406 }
00407
00408 static void
00409 extract_user_token(struct cparse_params *v, VALUE block_args,
00410 VALUE *tok, VALUE *val)
00411 {
00412 if (NIL_P(block_args)) {
00413
00414 *tok = Qfalse;
00415 *val = rb_str_new("$", 1);
00416 return;
00417 }
00418
00419 if (TYPE(block_args) != T_ARRAY) {
00420 rb_raise(rb_eTypeError,
00421 "%s() %s %s (must be Array[2])",
00422 v->lex_is_iterator ? rb_id2name(v->lexmid) : "next_token",
00423 v->lex_is_iterator ? "yielded" : "returned",
00424 rb_class2name(CLASS_OF(block_args)));
00425 }
00426 if (RARRAY_LEN(block_args) != 2) {
00427 rb_raise(rb_eArgError,
00428 "%s() %s wrong size of array (%ld for 2)",
00429 v->lex_is_iterator ? rb_id2name(v->lexmid) : "next_token",
00430 v->lex_is_iterator ? "yielded" : "returned",
00431 RARRAY_LEN(block_args));
00432 }
00433 *tok = AREF(block_args, 0);
00434 *val = AREF(block_args, 1);
00435 }
00436
00437 #define SHIFT(v,act,tok,val) shift(v,act,tok,val)
00438 #define REDUCE(v,act) do {\
00439 switch (reduce(v,act)) { \
00440 case 0: \
00441 break; \
00442 case 1: \
00443 goto user_yyerror; \
00444 case 2: \
00445 D_puts("u accept"); \
00446 goto accept; \
00447 default: \
00448 break; \
00449 } \
00450 } while (0)
00451
00452 static void
00453 parse_main(struct cparse_params *v, VALUE tok, VALUE val, int resume)
00454 {
00455 long i;
00456 long act;
00457 VALUE act_value;
00458 int read_next = 1;
00459 VALUE tmp;
00460
00461 if (resume)
00462 goto resume;
00463
00464 while (1) {
00465 D_puts("");
00466 D_puts("---- enter new loop ----");
00467 D_puts("");
00468
00469 D_printf("(act) k1=%ld\n", v->curstate);
00470 tmp = AREF(v->action_pointer, v->curstate);
00471 if (NIL_P(tmp)) goto notfound;
00472 D_puts("(act) pointer[k1] ok");
00473 i = NUM2LONG(tmp);
00474
00475 D_printf("read_next=%d\n", read_next);
00476 if (read_next && (v->t != vFINAL_TOKEN)) {
00477 if (v->lex_is_iterator) {
00478 D_puts("resuming...");
00479 if (v->fin) rb_raise(rb_eArgError, "token given after EOF");
00480 v->i = i;
00481 return;
00482 resume:
00483 D_puts("resumed");
00484 i = v->i;
00485 }
00486 else {
00487 D_puts("next_token");
00488 tmp = rb_funcall(v->parser, id_nexttoken, 0);
00489 extract_user_token(v, tmp, &tok, &val);
00490 }
00491
00492 v->t = rb_hash_aref(v->token_table, tok);
00493 if (NIL_P(v->t)) {
00494 v->t = vERROR_TOKEN;
00495 }
00496 D_printf("(act) t(k2)=%ld\n", NUM2LONG(v->t));
00497 if (v->debug) {
00498 rb_funcall(v->parser, id_d_read_token,
00499 3, v->t, tok, val);
00500 }
00501 }
00502 read_next = 0;
00503
00504 i += NUM2LONG(v->t);
00505 D_printf("(act) i=%ld\n", i);
00506 if (i < 0) goto notfound;
00507
00508 act_value = AREF(v->action_table, i);
00509 if (NIL_P(act_value)) goto notfound;
00510 act = NUM2LONG(act_value);
00511 D_printf("(act) table[i]=%ld\n", act);
00512
00513 tmp = AREF(v->action_check, i);
00514 if (NIL_P(tmp)) goto notfound;
00515 if (NUM2LONG(tmp) != v->curstate) goto notfound;
00516 D_printf("(act) check[i]=%ld\n", NUM2LONG(tmp));
00517
00518 D_puts("(act) found");
00519 act_fixed:
00520 D_printf("act=%ld\n", act);
00521 goto handle_act;
00522
00523 notfound:
00524 D_puts("(act) not found: use default");
00525 act_value = AREF(v->action_default, v->curstate);
00526 act = NUM2LONG(act_value);
00527 goto act_fixed;
00528
00529
00530 handle_act:
00531 if (act > 0 && act < v->shift_n) {
00532 D_puts("shift");
00533 if (v->errstatus > 0) {
00534 v->errstatus--;
00535 rb_ivar_set(v->parser, id_errstatus, LONG2NUM(v->errstatus));
00536 }
00537 SHIFT(v, act, v->t, val);
00538 read_next = 1;
00539 }
00540 else if (act < 0 && act > -(v->reduce_n)) {
00541 D_puts("reduce");
00542 REDUCE(v, act);
00543 }
00544 else if (act == -(v->reduce_n)) {
00545 goto error;
00546 error_recovered:
00547 ;
00548 }
00549 else if (act == v->shift_n) {
00550 D_puts("accept");
00551 goto accept;
00552 }
00553 else {
00554 rb_raise(RaccBug, "[Racc Bug] unknown act value %ld", act);
00555 }
00556
00557 if (v->debug) {
00558 rb_funcall(v->parser, id_d_next_state,
00559 2, LONG2NUM(v->curstate), v->state);
00560 }
00561 }
00562
00563
00564
00565 accept:
00566 if (v->debug) rb_funcall(v->parser, id_d_accept, 0);
00567 v->retval = RARRAY_PTR(v->vstack)[0];
00568 v->fin = CP_FIN_ACCEPT;
00569 return;
00570
00571
00572 error:
00573 D_printf("error detected, status=%ld\n", v->errstatus);
00574 if (v->errstatus == 0) {
00575 v->nerr++;
00576 rb_funcall(v->parser, id_onerror,
00577 3, v->t, val, v->vstack);
00578 }
00579 user_yyerror:
00580 if (v->errstatus == 3) {
00581 if (v->t == vFINAL_TOKEN) {
00582 v->retval = Qfalse;
00583 v->fin = CP_FIN_EOT;
00584 return;
00585 }
00586 read_next = 1;
00587 }
00588 v->errstatus = 3;
00589 rb_ivar_set(v->parser, id_errstatus, LONG2NUM(v->errstatus));
00590
00591
00592 D_printf("(err) k1=%ld\n", v->curstate);
00593 D_printf("(err) k2=%d (error)\n", ERROR_TOKEN);
00594 while (1) {
00595 tmp = AREF(v->action_pointer, v->curstate);
00596 if (NIL_P(tmp)) goto error_pop;
00597 D_puts("(err) pointer[k1] ok");
00598
00599 i = NUM2LONG(tmp) + ERROR_TOKEN;
00600 D_printf("(err) i=%ld\n", i);
00601 if (i < 0) goto error_pop;
00602
00603 act_value = AREF(v->action_table, i);
00604 if (NIL_P(act_value)) {
00605 D_puts("(err) table[i] == nil");
00606 goto error_pop;
00607 }
00608 act = NUM2LONG(act_value);
00609 D_printf("(err) table[i]=%ld\n", act);
00610
00611 tmp = AREF(v->action_check, i);
00612 if (NIL_P(tmp)) {
00613 D_puts("(err) check[i] == nil");
00614 goto error_pop;
00615 }
00616 if (NUM2LONG(tmp) != v->curstate) {
00617 D_puts("(err) check[i] != k1");
00618 goto error_pop;
00619 }
00620
00621 D_puts("(err) found: can handle error token");
00622 break;
00623
00624 error_pop:
00625 D_puts("(err) act not found: can't handle error token; pop");
00626
00627 if (RARRAY_LEN(v->state) <= 1) {
00628 v->retval = Qnil;
00629 v->fin = CP_FIN_CANTPOP;
00630 return;
00631 }
00632 POP(v->state);
00633 POP(v->vstack);
00634 v->curstate = num_to_long(LAST_I(v->state));
00635 if (v->debug) {
00636 POP(v->tstack);
00637 rb_funcall(v->parser, id_d_e_pop,
00638 3, v->state, v->tstack, v->vstack);
00639 }
00640 }
00641
00642
00643 if (act > 0 && act < v->shift_n) {
00644 D_puts("e shift");
00645 SHIFT(v, act, ERROR_TOKEN, val);
00646 }
00647 else if (act < 0 && act > -(v->reduce_n)) {
00648 D_puts("e reduce");
00649 REDUCE(v, act);
00650 }
00651 else if (act == v->shift_n) {
00652 D_puts("e accept");
00653 goto accept;
00654 }
00655 else {
00656 rb_raise(RaccBug, "[Racc Bug] unknown act value %ld", act);
00657 }
00658 goto error_recovered;
00659 }
00660
00661 static void
00662 shift(struct cparse_params *v, long act, VALUE tok, VALUE val)
00663 {
00664 PUSH(v->vstack, val);
00665 if (v->debug) {
00666 PUSH(v->tstack, tok);
00667 rb_funcall(v->parser, id_d_shift,
00668 3, tok, v->tstack, v->vstack);
00669 }
00670 v->curstate = act;
00671 PUSH(v->state, LONG2NUM(v->curstate));
00672 }
00673
00674 static int
00675 reduce(struct cparse_params *v, long act)
00676 {
00677 VALUE code;
00678 v->ruleno = -act * 3;
00679 code = rb_catch("racc_jump", reduce0, v->value_v);
00680 v->errstatus = num_to_long(rb_ivar_get(v->parser, id_errstatus));
00681 return NUM2INT(code);
00682 }
00683
00684 static VALUE
00685 reduce0(VALUE val, VALUE data, VALUE self)
00686 {
00687 struct cparse_params *v;
00688 VALUE reduce_to, reduce_len, method_id;
00689 long len;
00690 ID mid;
00691 VALUE tmp, tmp_t = Qundef, tmp_v = Qundef;
00692 long i, k1, k2;
00693 VALUE goto_state;
00694
00695 Data_Get_Struct(data, struct cparse_params, v);
00696 reduce_len = RARRAY_PTR(v->reduce_table)[v->ruleno];
00697 reduce_to = RARRAY_PTR(v->reduce_table)[v->ruleno+1];
00698 method_id = RARRAY_PTR(v->reduce_table)[v->ruleno+2];
00699 len = NUM2LONG(reduce_len);
00700 mid = value_to_id(method_id);
00701
00702
00703 if (len == 0) {
00704 tmp = Qnil;
00705 if (mid != id_noreduce)
00706 tmp_v = rb_ary_new();
00707 if (v->debug)
00708 tmp_t = rb_ary_new();
00709 }
00710 else {
00711 if (mid != id_noreduce) {
00712 tmp_v = GET_TAIL(v->vstack, len);
00713 tmp = RARRAY_PTR(tmp_v)[0];
00714 }
00715 else {
00716 tmp = RARRAY_PTR(v->vstack)[ RARRAY_LEN(v->vstack) - len ];
00717 }
00718 CUT_TAIL(v->vstack, len);
00719 if (v->debug) {
00720 tmp_t = GET_TAIL(v->tstack, len);
00721 CUT_TAIL(v->tstack, len);
00722 }
00723 CUT_TAIL(v->state, len);
00724 }
00725 if (mid != id_noreduce) {
00726 if (v->use_result_var) {
00727 tmp = rb_funcall(v->parser, mid,
00728 3, tmp_v, v->vstack, tmp);
00729 }
00730 else {
00731 tmp = rb_funcall(v->parser, mid,
00732 2, tmp_v, v->vstack);
00733 }
00734 }
00735
00736
00737 PUSH(v->vstack, tmp);
00738 if (v->debug) {
00739 PUSH(v->tstack, reduce_to);
00740 rb_funcall(v->parser, id_d_reduce,
00741 4, tmp_t, reduce_to, v->tstack, v->vstack);
00742 }
00743
00744
00745 if (RARRAY_LEN(v->state) == 0)
00746 rb_raise(RaccBug, "state stack unexpectedly empty");
00747 k2 = num_to_long(LAST_I(v->state));
00748 k1 = num_to_long(reduce_to) - v->nt_base;
00749 D_printf("(goto) k1=%ld\n", k1);
00750 D_printf("(goto) k2=%ld\n", k2);
00751
00752 tmp = AREF(v->goto_pointer, k1);
00753 if (NIL_P(tmp)) goto notfound;
00754
00755 i = NUM2LONG(tmp) + k2;
00756 D_printf("(goto) i=%ld\n", i);
00757 if (i < 0) goto notfound;
00758
00759 goto_state = AREF(v->goto_table, i);
00760 if (NIL_P(goto_state)) {
00761 D_puts("(goto) table[i] == nil");
00762 goto notfound;
00763 }
00764 D_printf("(goto) table[i]=%ld (goto_state)\n", NUM2LONG(goto_state));
00765
00766 tmp = AREF(v->goto_check, i);
00767 if (NIL_P(tmp)) {
00768 D_puts("(goto) check[i] == nil");
00769 goto notfound;
00770 }
00771 if (tmp != LONG2NUM(k1)) {
00772 D_puts("(goto) check[i] != table[i]");
00773 goto notfound;
00774 }
00775 D_printf("(goto) check[i]=%ld\n", NUM2LONG(tmp));
00776
00777 D_puts("(goto) found");
00778 transit:
00779 PUSH(v->state, goto_state);
00780 v->curstate = NUM2LONG(goto_state);
00781 return INT2FIX(0);
00782
00783 notfound:
00784 D_puts("(goto) not found: use default");
00785
00786 goto_state = AREF(v->goto_default, k1);
00787 goto transit;
00788 }
00789
00790
00791
00792
00793
00794 void
00795 Init_cparse(void)
00796 {
00797 VALUE Racc, Parser;
00798 ID id_racc = rb_intern("Racc");
00799
00800 if (rb_const_defined(rb_cObject, id_racc)) {
00801 Racc = rb_const_get(rb_cObject, id_racc);
00802 Parser = rb_const_get_at(Racc, rb_intern("Parser"));
00803 }
00804 else {
00805 Racc = rb_define_module("Racc");
00806 Parser = rb_define_class_under(Racc, "Parser", rb_cObject);
00807 }
00808 rb_define_private_method(Parser, "_racc_do_parse_c", racc_cparse, 2);
00809 rb_define_private_method(Parser, "_racc_yyparse_c", racc_yyparse, 4);
00810 rb_define_const(Parser, "Racc_Runtime_Core_Version_C",
00811 rb_str_new2(RACC_VERSION));
00812 rb_define_const(Parser, "Racc_Runtime_Core_Id_C",
00813 rb_str_new2("$originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $"));
00814
00815 CparseParams = rb_define_class_under(Racc, "CparseParams", rb_cObject);
00816
00817 RaccBug = rb_eRuntimeError;
00818
00819 id_yydebug = rb_intern("@yydebug");
00820 id_nexttoken = rb_intern("next_token");
00821 id_onerror = rb_intern("on_error");
00822 id_noreduce = rb_intern("_reduce_none");
00823 id_errstatus = rb_intern("@racc_error_status");
00824
00825 id_d_shift = rb_intern("racc_shift");
00826 id_d_reduce = rb_intern("racc_reduce");
00827 id_d_accept = rb_intern("racc_accept");
00828 id_d_read_token = rb_intern("racc_read_token");
00829 id_d_next_state = rb_intern("racc_next_state");
00830 id_d_e_pop = rb_intern("racc_e_pop");
00831 }
00832