665 lines
18 KiB
JavaScript
665 lines
18 KiB
JavaScript
'use strict';
|
|
|
|
var Char = require("./char.js");
|
|
var List = require("./list.js");
|
|
var Bytes = require("./bytes.js");
|
|
var Stream = require("./stream.js");
|
|
var Hashtbl = require("./hashtbl.js");
|
|
var Caml_bytes = require("./caml_bytes.js");
|
|
var Caml_format = require("./caml_format.js");
|
|
var Caml_string = require("./caml_string.js");
|
|
var Caml_js_exceptions = require("./caml_js_exceptions.js");
|
|
|
|
var initial_buffer = Caml_bytes.create(32);
|
|
|
|
var buffer = {
|
|
contents: initial_buffer
|
|
};
|
|
|
|
var bufpos = {
|
|
contents: 0
|
|
};
|
|
|
|
function reset_buffer(param) {
|
|
buffer.contents = initial_buffer;
|
|
bufpos.contents = 0;
|
|
}
|
|
|
|
function store(c) {
|
|
if (bufpos.contents >= buffer.contents.length) {
|
|
var newbuffer = Caml_bytes.create((bufpos.contents << 1));
|
|
Bytes.blit(buffer.contents, 0, newbuffer, 0, bufpos.contents);
|
|
buffer.contents = newbuffer;
|
|
}
|
|
Caml_bytes.set(buffer.contents, bufpos.contents, c);
|
|
bufpos.contents = bufpos.contents + 1 | 0;
|
|
}
|
|
|
|
function get_string(param) {
|
|
var s = Bytes.sub_string(buffer.contents, 0, bufpos.contents);
|
|
buffer.contents = initial_buffer;
|
|
return s;
|
|
}
|
|
|
|
function make_lexer(keywords) {
|
|
var kwd_table = Hashtbl.create(undefined, 17);
|
|
List.iter((function (s) {
|
|
Hashtbl.add(kwd_table, s, {
|
|
TAG: /* Kwd */0,
|
|
_0: s
|
|
});
|
|
}), keywords);
|
|
var ident_or_keyword = function (id) {
|
|
try {
|
|
return Hashtbl.find(kwd_table, id);
|
|
}
|
|
catch (raw_exn){
|
|
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
if (exn.RE_EXN_ID === "Not_found") {
|
|
return {
|
|
TAG: /* Ident */1,
|
|
_0: id
|
|
};
|
|
}
|
|
throw exn;
|
|
}
|
|
};
|
|
var keyword_or_error = function (c) {
|
|
var s = Caml_string.make(1, c);
|
|
try {
|
|
return Hashtbl.find(kwd_table, s);
|
|
}
|
|
catch (raw_exn){
|
|
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
if (exn.RE_EXN_ID === "Not_found") {
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "Illegal character " + s,
|
|
Error: new Error()
|
|
};
|
|
}
|
|
throw exn;
|
|
}
|
|
};
|
|
var next_token = function (strm__) {
|
|
while(true) {
|
|
var c = Stream.peek(strm__);
|
|
if (c === undefined) {
|
|
return ;
|
|
}
|
|
var exit = 0;
|
|
if (c < 124) {
|
|
if (c > 122 || c < 65) {
|
|
if (c >= 123) {
|
|
exit = 1;
|
|
} else {
|
|
switch (c) {
|
|
case 9 :
|
|
case 10 :
|
|
case 12 :
|
|
case 13 :
|
|
case 26 :
|
|
case 32 :
|
|
Stream.junk(strm__);
|
|
continue ;
|
|
case 34 :
|
|
Stream.junk(strm__);
|
|
reset_buffer(undefined);
|
|
return {
|
|
TAG: /* String */4,
|
|
_0: string(strm__)
|
|
};
|
|
case 39 :
|
|
Stream.junk(strm__);
|
|
var c$1;
|
|
try {
|
|
c$1 = $$char(strm__);
|
|
}
|
|
catch (raw_exn){
|
|
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
if (exn.RE_EXN_ID === Stream.Failure) {
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
}
|
|
throw exn;
|
|
}
|
|
var match = Stream.peek(strm__);
|
|
if (match !== undefined) {
|
|
if (match !== 39) {
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
}
|
|
Stream.junk(strm__);
|
|
return {
|
|
TAG: /* Char */5,
|
|
_0: c$1
|
|
};
|
|
}
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
case 40 :
|
|
Stream.junk(strm__);
|
|
var match$1 = Stream.peek(strm__);
|
|
if (match$1 === 42) {
|
|
Stream.junk(strm__);
|
|
comment(strm__);
|
|
return next_token(strm__);
|
|
} else {
|
|
return keyword_or_error(/* '(' */40);
|
|
}
|
|
case 45 :
|
|
Stream.junk(strm__);
|
|
var c$2 = Stream.peek(strm__);
|
|
if (c$2 !== undefined && !(c$2 > 57 || c$2 < 48)) {
|
|
Stream.junk(strm__);
|
|
reset_buffer(undefined);
|
|
store(/* '-' */45);
|
|
store(c$2);
|
|
return number(strm__);
|
|
} else {
|
|
reset_buffer(undefined);
|
|
store(/* '-' */45);
|
|
return ident2(strm__);
|
|
}
|
|
case 48 :
|
|
case 49 :
|
|
case 50 :
|
|
case 51 :
|
|
case 52 :
|
|
case 53 :
|
|
case 54 :
|
|
case 55 :
|
|
case 56 :
|
|
case 57 :
|
|
exit = 4;
|
|
break;
|
|
case 0 :
|
|
case 1 :
|
|
case 2 :
|
|
case 3 :
|
|
case 4 :
|
|
case 5 :
|
|
case 6 :
|
|
case 7 :
|
|
case 8 :
|
|
case 11 :
|
|
case 14 :
|
|
case 15 :
|
|
case 16 :
|
|
case 17 :
|
|
case 18 :
|
|
case 19 :
|
|
case 20 :
|
|
case 21 :
|
|
case 22 :
|
|
case 23 :
|
|
case 24 :
|
|
case 25 :
|
|
case 27 :
|
|
case 28 :
|
|
case 29 :
|
|
case 30 :
|
|
case 31 :
|
|
case 41 :
|
|
case 44 :
|
|
case 46 :
|
|
case 59 :
|
|
exit = 1;
|
|
break;
|
|
case 33 :
|
|
case 35 :
|
|
case 36 :
|
|
case 37 :
|
|
case 38 :
|
|
case 42 :
|
|
case 43 :
|
|
case 47 :
|
|
case 58 :
|
|
case 60 :
|
|
case 61 :
|
|
case 62 :
|
|
case 63 :
|
|
case 64 :
|
|
exit = 3;
|
|
break;
|
|
|
|
}
|
|
}
|
|
} else {
|
|
switch (c) {
|
|
case 92 :
|
|
case 94 :
|
|
exit = 3;
|
|
break;
|
|
case 95 :
|
|
exit = 2;
|
|
break;
|
|
case 91 :
|
|
case 93 :
|
|
case 96 :
|
|
exit = 1;
|
|
break;
|
|
default:
|
|
exit = 2;
|
|
}
|
|
}
|
|
} else {
|
|
exit = c >= 127 ? (
|
|
c > 255 || c < 192 ? 1 : 2
|
|
) : (
|
|
c !== 125 ? 3 : 1
|
|
);
|
|
}
|
|
switch (exit) {
|
|
case 1 :
|
|
Stream.junk(strm__);
|
|
return keyword_or_error(c);
|
|
case 2 :
|
|
Stream.junk(strm__);
|
|
reset_buffer(undefined);
|
|
store(c);
|
|
while(true) {
|
|
var c$3 = Stream.peek(strm__);
|
|
if (c$3 === undefined) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
if (c$3 >= 91) {
|
|
if (c$3 > 122 || c$3 < 95) {
|
|
if (c$3 > 255 || c$3 < 192) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
|
|
} else if (c$3 === 96) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
|
|
} else if (c$3 >= 48) {
|
|
if (!(c$3 > 64 || c$3 < 58)) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
|
|
} else if (c$3 !== 39) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
Stream.junk(strm__);
|
|
store(c$3);
|
|
continue ;
|
|
};
|
|
case 3 :
|
|
Stream.junk(strm__);
|
|
reset_buffer(undefined);
|
|
store(c);
|
|
return ident2(strm__);
|
|
case 4 :
|
|
Stream.junk(strm__);
|
|
reset_buffer(undefined);
|
|
store(c);
|
|
return number(strm__);
|
|
|
|
}
|
|
};
|
|
};
|
|
var ident2 = function (strm__) {
|
|
while(true) {
|
|
var c = Stream.peek(strm__);
|
|
if (c === undefined) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
if (c >= 94) {
|
|
if (c > 125 || c < 95) {
|
|
if (c >= 127) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
|
|
} else if (c !== 124) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
|
|
} else if (c >= 65) {
|
|
if (c !== 92) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
|
|
} else {
|
|
if (c < 33) {
|
|
return ident_or_keyword(get_string(undefined));
|
|
}
|
|
switch (c) {
|
|
case 34 :
|
|
case 39 :
|
|
case 40 :
|
|
case 41 :
|
|
case 44 :
|
|
case 46 :
|
|
case 48 :
|
|
case 49 :
|
|
case 50 :
|
|
case 51 :
|
|
case 52 :
|
|
case 53 :
|
|
case 54 :
|
|
case 55 :
|
|
case 56 :
|
|
case 57 :
|
|
case 59 :
|
|
return ident_or_keyword(get_string(undefined));
|
|
case 33 :
|
|
case 35 :
|
|
case 36 :
|
|
case 37 :
|
|
case 38 :
|
|
case 42 :
|
|
case 43 :
|
|
case 45 :
|
|
case 47 :
|
|
case 58 :
|
|
case 60 :
|
|
case 61 :
|
|
case 62 :
|
|
case 63 :
|
|
case 64 :
|
|
break;
|
|
|
|
}
|
|
}
|
|
Stream.junk(strm__);
|
|
store(c);
|
|
continue ;
|
|
};
|
|
};
|
|
var number = function (strm__) {
|
|
while(true) {
|
|
var c = Stream.peek(strm__);
|
|
if (c !== undefined) {
|
|
if (c >= 58) {
|
|
if (!(c !== 69 && c !== 101)) {
|
|
Stream.junk(strm__);
|
|
store(/* 'E' */69);
|
|
return exponent_part(strm__);
|
|
}
|
|
|
|
} else if (c !== 46) {
|
|
if (c >= 48) {
|
|
Stream.junk(strm__);
|
|
store(c);
|
|
continue ;
|
|
}
|
|
|
|
} else {
|
|
Stream.junk(strm__);
|
|
store(/* '.' */46);
|
|
while(true) {
|
|
var c$1 = Stream.peek(strm__);
|
|
if (c$1 !== undefined) {
|
|
if (c$1 > 101 || c$1 < 69) {
|
|
if (!(c$1 > 57 || c$1 < 48)) {
|
|
Stream.junk(strm__);
|
|
store(c$1);
|
|
continue ;
|
|
}
|
|
|
|
} else if (c$1 > 100 || c$1 < 70) {
|
|
Stream.junk(strm__);
|
|
store(/* 'E' */69);
|
|
return exponent_part(strm__);
|
|
}
|
|
|
|
}
|
|
return {
|
|
TAG: /* Float */3,
|
|
_0: Caml_format.float_of_string(get_string(undefined))
|
|
};
|
|
};
|
|
}
|
|
}
|
|
return {
|
|
TAG: /* Int */2,
|
|
_0: Caml_format.int_of_string(get_string(undefined))
|
|
};
|
|
};
|
|
};
|
|
var exponent_part = function (strm__) {
|
|
var c = Stream.peek(strm__);
|
|
if (c !== undefined && !(c !== 43 && c !== 45)) {
|
|
Stream.junk(strm__);
|
|
store(c);
|
|
return end_exponent_part(strm__);
|
|
} else {
|
|
return end_exponent_part(strm__);
|
|
}
|
|
};
|
|
var end_exponent_part = function (strm__) {
|
|
while(true) {
|
|
var c = Stream.peek(strm__);
|
|
if (c === undefined) {
|
|
return {
|
|
TAG: /* Float */3,
|
|
_0: Caml_format.float_of_string(get_string(undefined))
|
|
};
|
|
}
|
|
if (c > 57 || c < 48) {
|
|
return {
|
|
TAG: /* Float */3,
|
|
_0: Caml_format.float_of_string(get_string(undefined))
|
|
};
|
|
}
|
|
Stream.junk(strm__);
|
|
store(c);
|
|
continue ;
|
|
};
|
|
};
|
|
var string = function (strm__) {
|
|
while(true) {
|
|
var c = Stream.peek(strm__);
|
|
if (c !== undefined) {
|
|
if (c !== 34) {
|
|
if (c !== 92) {
|
|
Stream.junk(strm__);
|
|
store(c);
|
|
continue ;
|
|
}
|
|
Stream.junk(strm__);
|
|
var c$1;
|
|
try {
|
|
c$1 = $$escape(strm__);
|
|
}
|
|
catch (raw_exn){
|
|
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
if (exn.RE_EXN_ID === Stream.Failure) {
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
}
|
|
throw exn;
|
|
}
|
|
store(c$1);
|
|
continue ;
|
|
}
|
|
Stream.junk(strm__);
|
|
return get_string(undefined);
|
|
}
|
|
throw {
|
|
RE_EXN_ID: Stream.Failure,
|
|
Error: new Error()
|
|
};
|
|
};
|
|
};
|
|
var $$char = function (strm__) {
|
|
var c = Stream.peek(strm__);
|
|
if (c !== undefined) {
|
|
if (c !== 92) {
|
|
Stream.junk(strm__);
|
|
return c;
|
|
}
|
|
Stream.junk(strm__);
|
|
try {
|
|
return $$escape(strm__);
|
|
}
|
|
catch (raw_exn){
|
|
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
if (exn.RE_EXN_ID === Stream.Failure) {
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
}
|
|
throw exn;
|
|
}
|
|
} else {
|
|
throw {
|
|
RE_EXN_ID: Stream.Failure,
|
|
Error: new Error()
|
|
};
|
|
}
|
|
};
|
|
var $$escape = function (strm__) {
|
|
var c1 = Stream.peek(strm__);
|
|
if (c1 !== undefined) {
|
|
if (c1 >= 58) {
|
|
switch (c1) {
|
|
case 110 :
|
|
Stream.junk(strm__);
|
|
return /* '\n' */10;
|
|
case 114 :
|
|
Stream.junk(strm__);
|
|
return /* '\r' */13;
|
|
case 111 :
|
|
case 112 :
|
|
case 113 :
|
|
case 115 :
|
|
Stream.junk(strm__);
|
|
return c1;
|
|
case 116 :
|
|
Stream.junk(strm__);
|
|
return /* '\t' */9;
|
|
default:
|
|
Stream.junk(strm__);
|
|
return c1;
|
|
}
|
|
} else {
|
|
if (c1 >= 48) {
|
|
Stream.junk(strm__);
|
|
var c2 = Stream.peek(strm__);
|
|
if (c2 !== undefined) {
|
|
if (c2 > 57 || c2 < 48) {
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
}
|
|
Stream.junk(strm__);
|
|
var c3 = Stream.peek(strm__);
|
|
if (c3 !== undefined) {
|
|
if (c3 > 57 || c3 < 48) {
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
}
|
|
Stream.junk(strm__);
|
|
return Char.chr((Math.imul(c1 - 48 | 0, 100) + Math.imul(c2 - 48 | 0, 10) | 0) + (c3 - 48 | 0) | 0);
|
|
}
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
}
|
|
throw {
|
|
RE_EXN_ID: Stream.$$Error,
|
|
_1: "",
|
|
Error: new Error()
|
|
};
|
|
}
|
|
Stream.junk(strm__);
|
|
return c1;
|
|
}
|
|
} else {
|
|
throw {
|
|
RE_EXN_ID: Stream.Failure,
|
|
Error: new Error()
|
|
};
|
|
}
|
|
};
|
|
var comment = function (strm__) {
|
|
while(true) {
|
|
var match = Stream.peek(strm__);
|
|
if (match !== undefined) {
|
|
switch (match) {
|
|
case 40 :
|
|
Stream.junk(strm__);
|
|
var match$1 = Stream.peek(strm__);
|
|
if (match$1 !== undefined) {
|
|
if (match$1 !== 42) {
|
|
Stream.junk(strm__);
|
|
return comment(strm__);
|
|
} else {
|
|
Stream.junk(strm__);
|
|
comment(strm__);
|
|
return comment(strm__);
|
|
}
|
|
}
|
|
throw {
|
|
RE_EXN_ID: Stream.Failure,
|
|
Error: new Error()
|
|
};
|
|
case 41 :
|
|
Stream.junk(strm__);
|
|
continue ;
|
|
case 42 :
|
|
Stream.junk(strm__);
|
|
while(true) {
|
|
var match$2 = Stream.peek(strm__);
|
|
if (match$2 !== undefined) {
|
|
if (match$2 !== 41) {
|
|
if (match$2 !== 42) {
|
|
Stream.junk(strm__);
|
|
return comment(strm__);
|
|
}
|
|
Stream.junk(strm__);
|
|
continue ;
|
|
}
|
|
Stream.junk(strm__);
|
|
return ;
|
|
}
|
|
throw {
|
|
RE_EXN_ID: Stream.Failure,
|
|
Error: new Error()
|
|
};
|
|
};
|
|
default:
|
|
Stream.junk(strm__);
|
|
continue ;
|
|
}
|
|
} else {
|
|
throw {
|
|
RE_EXN_ID: Stream.Failure,
|
|
Error: new Error()
|
|
};
|
|
}
|
|
};
|
|
};
|
|
return function (input) {
|
|
return Stream.from(function (_count) {
|
|
return next_token(input);
|
|
});
|
|
};
|
|
}
|
|
|
|
exports.make_lexer = make_lexer;
|
|
/* No side effect */
|