'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 */