diff options
-rw-r--r-- | byterun/lexing.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/byterun/lexing.c b/byterun/lexing.c new file mode 100644 index 000000000..fa275eb99 --- /dev/null +++ b/byterun/lexing.c @@ -0,0 +1,90 @@ +/***********************************************************************/ +/* */ +/* Caml Special Light */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1995 Institut National de Recherche en Informatique et */ +/* Automatique. Distributed only by permission. */ +/* */ +/***********************************************************************/ + +/* $Id$ */ + +/* The table-driven automaton for lexers generated by camllex. */ + +#include "mlvalues.h" +#include "stacks.h" +#include "str.h" + +struct lexer_buffer { + value refill_buff; + value lex_buffer; + value lex_buffer_len; + value lex_abs_pos; + value lex_start_pos; + value lex_curr_pos; + value lex_last_pos; +}; + +struct lexing_table { + value lex_base; + value lex_backtrk; + value lex_default; + value lex_trans; + value lex_check; +}; + +#ifdef BIG_ENDIAN +#define Short(tbl,n) \ + (*((unsigned char *)((tbl) + (n) * sizeof(short))) + \ + (*((schar *)((tbl) + (n) * sizeof(short) + 1)) << 8)) +#else +#define Short(tbl,n) (((short *)(tbl))[n]) +#endif + +value lex_engine(tbl, start_state, lexbuf) /* ML */ + struct lexing_table * tbl; + value start_state; + struct lexer_buffer * lexbuf; +{ + int state, last_action, base, backtrk, c; + + state = Int_val(start_state); + lexbuf->lex_last_pos = lexbuf->lex_start_pos = lexbuf->lex_curr_pos; + last_action = -1; + while(1) { + /* Lookup base address or action number for current state */ + base = Short(tbl->lex_base, state); + if (base < 0) return Val_int(-base-1); + /* See if it's a backtrack point */ + backtrk = Short(tbl->lex_backtrk, state); + if (backtrk >= 0) { + lexbuf->lex_last_pos = lexbuf->lex_curr_pos; + last_action = backtrk; + } + /* Read next input char */ + if (lexbuf->lex_curr_pos >= lexbuf->lex_buffer_len) { + Push_roots (r, 2); + r[0] = (value) tbl; + r[1] = (value) lexbuf; + callback(lexbuf->refill_buff, (value) lexbuf); + tbl = (struct lexing_table *) r[0]; + lexbuf = (struct lexer_buffer *) r[1]; + Pop_roots (); + } + c = Byte_u(lexbuf->lex_buffer, Long_val(lexbuf->lex_curr_pos)); + lexbuf->lex_curr_pos += 2; + /* Determine next state */ + if (Short(tbl->lex_check, base + c) == state) + state = Short(tbl->lex_trans, base + c); + else + state = Short(tbl->lex_default, state); + /* If no transition on this char, return to last backtrack point */ + if (state < 0) { + lexbuf->lex_curr_pos = lexbuf->lex_last_pos; + return Val_int(last_action); + } + } +} + |