@rescript/std
Version:
The motiviation of this repo is that when ReScript users want to share their library with JS users, the JS users don't need have ReScript toolchain installed, this makes sharing code with JS users easier (more details on that topic can be found in our [Ex
302 lines (292 loc) • 11 kB
JavaScript
'use strict';
/***********************************************************************/
/* */
/* Objective Caml */
/* */
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
/* */
/* Copyright 1996 Institut National de Recherche en Informatique et */
/* en Automatique. All rights reserved. This file is distributed */
/* under the terms of the GNU Library General Public License, with */
/* the special exception on linking described in file ../LICENSE. */
/* */
/***********************************************************************/
/* $Id: parsing.c 8983 2008-08-06 09:38:25Z xleroy $ */
/* The PDA automaton for parsers generated by camlyacc */
/* The pushdown automata */
/**
* caml_lex_array("abcd")
* [25185, 25699]
* @param s
* @returns {any[]}
* TODO: duplicated with module {!Caml_lex}
*/
function caml_lex_array(s) {
var l = s.length / 2;
var a = new Array(l);
for (var i = 0; i < l; i++)
a[i] = (s.charCodeAt(2 * i) | (s.charCodeAt(2 * i + 1) << 8)) << 16 >> 16;
return a;
}
/**
* Note that TS enum is not friendly to Closure compiler
* @enum{number}
*/
var Automata = {
START: 0,
LOOP: 6,
TOKEN_READ: 1,
TEST_SHIFT: 7,
ERROR_DETECTED: 5,
SHIFT: 8,
SHIFT_RECOVER: 9,
STACK_GROWN_1: 2,
REDUCE: 10,
STACK_GROWN_2: 3,
SEMANTIC_ACTION_COMPUTED: 4
};
/**
* @enum{number}
*/
var Result = {
READ_TOKEN: 0,
RAISE_PARSE_ERROR: 1,
GROW_STACKS_1: 2,
GROW_STACKS_2: 3,
COMPUTE_SEMANTIC_ACTION: 4,
CALL_ERROR_FUNCTION: 5
};
var PARSER_TRACE = false;
;
var parse_engine = (function (tables /* parser_table */, env /* parser_env */, cmd /* parser_input*/, arg /* Obj.t*/) {
var ERRCODE = 256;
//var START = 0;
//var TOKEN_READ = 1;
//var STACKS_GROWN_1 = 2;
//var STACKS_GROWN_2 = 3;
//var SEMANTIC_ACTION_COMPUTED = 4;
//var ERROR_DETECTED = 5;
//var loop = 6;
//var testshift = 7;
//var shift = 8;
//var shift_recover = 9;
//var reduce = 10;
// Parsing.parser_env
var env_s_stack = 's_stack'; // array
var env_v_stack = 'v_stack'; // array
var env_symb_start_stack = 'symb_start_stack'; // array
var env_symb_end_stack = 'symb_end_stack'; // array
var env_stacksize = 'stacksize';
var env_stackbase = 'stackbase';
var env_curr_char = 'curr_char';
var env_lval = 'lval'; // Obj.t
var env_symb_start = 'symb_start'; // position
var env_symb_end = 'symb_end'; // position
var env_asp = 'asp';
var env_rule_len = 'rule_len';
var env_rule_number = 'rule_number';
var env_sp = 'sp';
var env_state = 'state';
var env_errflag = 'errflag';
// Parsing.parse_tables
// var _tbl_actions = 1;
var tbl_transl_const = 'transl_const'; // array
var tbl_transl_block = 'transl_block'; // array
var tbl_lhs = 'lhs';
var tbl_len = 'len';
var tbl_defred = 'defred';
var tbl_dgoto = 'dgoto';
var tbl_sindex = 'sindex';
var tbl_rindex = 'rindex';
var tbl_gindex = 'gindex';
var tbl_tablesize = 'tablesize';
var tbl_table = 'table';
var tbl_check = 'check';
// var _tbl_error_function = 14;
// var _tbl_names_const = 15;
// var _tbl_names_block = 16;
if (!tables.preprocessed) {
tables.defred = caml_lex_array(tables[tbl_defred]);
tables.sindex = caml_lex_array(tables[tbl_sindex]);
tables.check = caml_lex_array(tables[tbl_check]);
tables.rindex = caml_lex_array(tables[tbl_rindex]);
tables.table = caml_lex_array(tables[tbl_table]);
tables.len = caml_lex_array(tables[tbl_len]);
tables.lhs = caml_lex_array(tables[tbl_lhs]);
tables.gindex = caml_lex_array(tables[tbl_gindex]);
tables.dgoto = caml_lex_array(tables[tbl_dgoto]);
tables.preprocessed = true;
}
var res;
var n, n1, n2, state1;
// RESTORE
var sp = env[env_sp];
var state = env[env_state];
var errflag = env[env_errflag];
exit: for (;;) {
//console.error("State", Automata[cmd]);
switch (cmd) {
case Automata.START:
state = 0;
errflag = 0;
// Fall through
case Automata.LOOP:
n = tables.defred[state];
if (n != 0) {
cmd = Automata.REDUCE;
break;
}
if (env[env_curr_char] >= 0) {
cmd = Automata.TEST_SHIFT;
break;
}
res = Result.READ_TOKEN;
break exit;
/* The ML code calls the lexer and updates */
/* symb_start and symb_end */
case Automata.TOKEN_READ:
if (typeof arg !== 'number') {
env[env_curr_char] = tables[tbl_transl_block][arg.TAG | 0 /* + 1 */];
env[env_lval] = arg._0; // token carries payload
}
else {
env[env_curr_char] = tables[tbl_transl_const][arg /* + 1 */];
env[env_lval] = 0; // const token
}
if (PARSER_TRACE) {
console.error("State %d, read token", state, arg);
}
// Fall through
case Automata.TEST_SHIFT:
n1 = tables.sindex[state];
n2 = n1 + env[env_curr_char];
if (n1 != 0 && n2 >= 0 && n2 <= tables[tbl_tablesize] &&
tables.check[n2] == env[env_curr_char]) {
cmd = Automata.SHIFT;
break;
}
n1 = tables.rindex[state];
n2 = n1 + env[env_curr_char];
if (n1 != 0 && n2 >= 0 && n2 <= tables[tbl_tablesize] &&
tables.check[n2] == env[env_curr_char]) {
n = tables.table[n2];
cmd = Automata.REDUCE;
break;
}
if (errflag <= 0) {
res = Result.CALL_ERROR_FUNCTION;
break exit;
}
// Fall through
/* The ML code calls the error function */
case Automata.ERROR_DETECTED:
if (errflag < 3) {
errflag = 3;
for (;;) {
state1 = env[env_s_stack][sp /* + 1*/];
n1 = tables.sindex[state1];
n2 = n1 + ERRCODE;
if (n1 != 0 && n2 >= 0 && n2 <= tables[tbl_tablesize] &&
tables.check[n2] == ERRCODE) {
cmd = Automata.SHIFT_RECOVER;
break;
}
else {
if (sp <= env[env_stackbase])
return Result.RAISE_PARSE_ERROR;
/* The ML code raises Parse_error */
sp--;
}
}
}
else {
if (env[env_curr_char] == 0)
return Result.RAISE_PARSE_ERROR;
/* The ML code raises Parse_error */
env[env_curr_char] = -1;
cmd = Automata.LOOP;
break;
}
// Fall through
case Automata.SHIFT:
env[env_curr_char] = -1;
if (errflag > 0)
errflag--;
// Fall through
case Automata.SHIFT_RECOVER:
if (PARSER_TRACE) {
console.error("State %d: shift to state %d", state, tables.table[n2]);
}
state = tables.table[n2];
sp++;
if (sp >= env[env_stacksize]) {
res = Result.GROW_STACKS_1;
break exit;
}
// Fall through
/* The ML code resizes the stacks */
case Automata.STACK_GROWN_1:
env[env_s_stack][sp /* + 1 */] = state;
env[env_v_stack][sp /* + 1 */] = env[env_lval];
env[env_symb_start_stack][sp /* + 1 */] = env[env_symb_start];
env[env_symb_end_stack][sp /* + 1 */] = env[env_symb_end];
cmd = Automata.LOOP;
break;
case Automata.REDUCE:
if (PARSER_TRACE) {
console.error("State %d : reduce by rule %d", state, n);
}
var m = tables.len[n];
env[env_asp] = sp;
env[env_rule_number] = n;
env[env_rule_len] = m;
sp = sp - m + 1;
m = tables.lhs[n];
state1 = env[env_s_stack][sp - 1]; //
n1 = tables.gindex[m];
n2 = n1 + state1;
if (n1 != 0 && n2 >= 0 && n2 <= tables[tbl_tablesize] &&
tables.check[n2] == state1)
state = tables.table[n2];
else
state = tables.dgoto[m];
if (sp >= env[env_stacksize]) {
res = Result.GROW_STACKS_2;
break exit;
}
// Fall through
/* The ML code resizes the stacks */
case Automata.STACK_GROWN_2:
res = Result.COMPUTE_SEMANTIC_ACTION;
break exit;
/* The ML code calls the semantic action */
case Automata.SEMANTIC_ACTION_COMPUTED:
env[env_s_stack][sp /* + 1 */] = state;
env[env_v_stack][sp /* + 1*/] = arg;
var asp = env[env_asp];
env[env_symb_end_stack][sp /* + 1*/] = env[env_symb_end_stack][asp /* + 1*/];
if (sp > asp) {
/* This is an epsilon production. Take symb_start equal to symb_end. */
env[env_symb_start_stack][sp /* + 1*/] = env[env_symb_end_stack][asp /*+ 1*/];
}
cmd = Automata.LOOP;
break;
/* Should not happen */
default:
return Result.RAISE_PARSE_ERROR;
}
}
// SAVE
env[env_sp] = sp;
env[env_state] = state;
env[env_errflag] = errflag;
return res;
});
var set_parser_trace = (function (v) {
var old = PARSER_TRACE;
PARSER_TRACE = v;
return old;
});
exports.parse_engine = parse_engine;
exports.set_parser_trace = set_parser_trace;
/* Not a pure module */