diff options
author | Benoit Giannangeli <benoit.giannangeli@boursorama.fr> | 2017-02-27 08:46:56 +0100 |
---|---|---|
committer | Benoit Giannangeli <benoit.giannangeli@boursorama.fr> | 2017-02-27 14:19:05 +0100 |
commit | 5a47025d64f013975051473c1115ff70c0281785 (patch) | |
tree | 2a79b29beea6d4571993783cef523c38568c2742 /src/lobject.js | |
parent | 94a301a27a8a75c4684790a99a898262b8354f68 (diff) | |
download | fengari-5a47025d64f013975051473c1115ff70c0281785.tar.gz fengari-5a47025d64f013975051473c1115ff70c0281785.tar.bz2 fengari-5a47025d64f013975051473c1115ff70c0281785.zip |
lexing
Diffstat (limited to 'src/lobject.js')
-rw-r--r-- | src/lobject.js | 133 |
1 files changed, 124 insertions, 9 deletions
diff --git a/src/lobject.js b/src/lobject.js index 086af00..93e23c2 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -1,8 +1,11 @@ -/*jshint esversion: 6 */ + /*jshint esversion: 6 */ "use strict"; -const CT = require('./lua.js').constant_types; -const UpVal = require('./lfunc.js').UpVal; +const assert = require('assert'); + +const ljstype = require('./ljstype.js'); +const CT = require('./lua.js').constant_types; +const UpVal = require('./lfunc.js').UpVal; class TValue { @@ -223,7 +226,7 @@ const luaO_chunkid = function(source, bufflen) { let nli = source.indexOf('\n'); /* find first new line (if any) */ let nl = nli ? source.slice(nli) : null; out = `${PRE}`; /* add prefix */ - bufflen -= PRE.length - RETS.length; - POS.length + 1; /* save space for prefix+suffix+'\0' */ + bufflen -= PRE.length + RETS.length + POS.length + 1; /* save space for prefix+suffix+'\0' */ if (l < bufflen && nl === null) { /* small one-line source? */ out += `${source}`; /* keep it */ } else { @@ -237,8 +240,120 @@ const luaO_chunkid = function(source, bufflen) { return out; }; -module.exports.LClosure = LClosure; -module.exports.CClosure = CClosure; -module.exports.TValue = TValue; -module.exports.Table = Table; -module.exports.luaO_chunkid = luaO_chunkid;
\ No newline at end of file +const luaO_hexavalue = function(c) { + if (ljstype.lisdigit(c)) return c.charCodeAt(0) - '0'.charCodeAt(0); + else return (c.toLowerCase().charCodeAt(0) - 'a'.charCodeAt(0)) + 10; +}; + +const UTF8BUFFSZ = 8; + +const luaO_utf8desc = function(buff, x) { + let n = 1; /* number of bytes put in buffer (backwards) */ + assert(x <= 0x10FFFF); + if (x < 0x80) /* ascii? */ + buff[UTF8BUFFSZ - 1] = String.fromCharCode(x); + else { /* need continuation bytes */ + let mfb = 0x3f; /* maximum that fits in first byte */ + do { + buff[UTF8BUFFSZ - (n++)] = String.fromCharCode(0x80 | (x & 0x3f)); + x >>= 6; /* remove added bits */ + mfb >>= 1; /* now there is one less bit available in first byte */ + } while (x > mfb); /* still needs continuation byte? */ + buff[UTF8BUFFSZ - n] = String.fromCharCode((~mfb << 1) | x); /* add first byte */ + } + return n; +}; + +const l_str2dloc = function(s, result, mode) { + result[0] = mode === 'x' ? parseInt(s, '16') : parseInt(s); + if (isNaN(result[0])) return null; /* nothing recognized? */ + while (ljstype.lisspace(result[0])) result[0] = result[0].slice(1); /* skip trailing spaces */ + return result[0] === '\0' ? result : null; /* OK if no trailing characters */ +}; + +const l_str2d = function(s) { + let result = [null, null]; + let pidx = /[.xXnN]/g.exec(s).index; + let pmode = pidx ? s.slice(pidx) : null; + let mode = pmode ? pmode.toLowerCase() : 0; + if (mode === 'n') /* reject 'inf' and 'nan' */ + return null; + let end = l_str2dloc(s, result, mode)[0]; /* try to convert */ + if (end === null) { /* failed? may be a different locale */ + throw new Error("Locale not available to handle number"); // TODO + } + return [end, result[1]]; +}; + +const MAXBY10 = Number.MAX_SAFE_INTEGER / 10; +const MAXLASTD = Number.MAX_SAFE_INTEGER % 10; + +const l_str2int = function(s) { + let result = [null, null]; + let a = 0; + let empty = true; + let neg; + + while (ljstype.lisspace(s.charAt(0))) s = s.slice(1); /* skip initial spaces */ + neg = s.charAt(0) === '-'; + + if (neg || s.charAt(0) === '+') + s = s.slice(1); + + if (s[0] === '0' && (s[1] === 'x' || s[1] === 'X')) { /* hex? */ + s = s.slice(2); /* skip '0x' */ + + for (; ljstype.lisxdigit(s); s = s.slice(1)) { + a = a * 16 + luaO_hexavalue(s); + empty = false; + } + } else { /* decimal */ + for (; ljstype.lisdigit(s); s = s.slice(1)) { + let d = parseInt(s.charAt(0)); + if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ + return null; /* do not accept it (as integer) */ + a = a * 10 + d; + empty = false; + } + } + + while (ljstype.lisspace(s.charAt(0))) s = s.slice(1); /* skip trailing spaces */ + + if (empty || s.charAt(0) !== "") return null; /* something wrong in the numeral */ + else { + result[1] = neg ? -a : a; + result[0] = s; + return result; + } +}; + +const luaO_str2num = function(s) { + let s2i = l_str2int(s); + let e = s2i[0]; + let i = s2i[1]; + + let o; + if (e !== null) /* try as an integer */ + o = new TValue(CT.LUA_TNUMINT, i); + else { /* else try as a float */ + s2i = l_str2d(s); + e = s2i[0]; + i = s2i[1]; + + if (e !== null) { + o = new TValue(CT.LUA_TNUMFLT, i); + } else + return false; /* conversion failed */ + return (e - s) + 1; // TODO: wrong + } +}; + +module.exports.CClosure = CClosure; +module.exports.LClosure = LClosure; +module.exports.TValue = TValue; +module.exports.Table = Table; +module.exports.UTF8BUFFSZ = UTF8BUFFSZ; +module.exports.luaO_chunkid = luaO_chunkid; +module.exports.luaO_hexavalue = luaO_hexavalue; +module.exports.luaO_str2num = luaO_str2num; +module.exports.luaO_utf8desc = luaO_utf8desc;
\ No newline at end of file |