Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

clarinet.js 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. ;(function (clarinet) {
  2. "use strict";
  3. // non node-js needs to set clarinet debug on root
  4. var env =(typeof process === 'object' && process.env)
  5. ? process.env
  6. : self;
  7. clarinet.parser = function (opt) { return new CParser(opt);};
  8. clarinet.CParser = CParser;
  9. clarinet.CStream = CStream;
  10. clarinet.createStream = createStream;
  11. clarinet.MAX_BUFFER_LENGTH = 64 * 1024;
  12. clarinet.DEBUG = (env.CDEBUG==='debug');
  13. clarinet.INFO = (env.CDEBUG==='debug' || env.CDEBUG==='info');
  14. clarinet.EVENTS =
  15. [ "value"
  16. , "string"
  17. , "key"
  18. , "openobject"
  19. , "closeobject"
  20. , "openarray"
  21. , "closearray"
  22. , "error"
  23. , "end"
  24. , "ready"
  25. ];
  26. var buffers = {
  27. textNode: undefined,
  28. numberNode: ""
  29. }
  30. , streamWraps = clarinet.EVENTS.filter(function (ev) {
  31. return ev !== "error" && ev !== "end";
  32. })
  33. , S = 0
  34. , Stream
  35. ;
  36. clarinet.STATE =
  37. { BEGIN : S++
  38. , VALUE : S++ // general stuff
  39. , OPEN_OBJECT : S++ // {
  40. , CLOSE_OBJECT : S++ // }
  41. , OPEN_ARRAY : S++ // [
  42. , CLOSE_ARRAY : S++ // ]
  43. , TEXT_ESCAPE : S++ // \ stuff
  44. , STRING : S++ // ""
  45. , BACKSLASH : S++
  46. , END : S++ // No more stack
  47. , OPEN_KEY : S++ // , "a"
  48. , CLOSE_KEY : S++ // :
  49. , TRUE : S++ // r
  50. , TRUE2 : S++ // u
  51. , TRUE3 : S++ // e
  52. , FALSE : S++ // a
  53. , FALSE2 : S++ // l
  54. , FALSE3 : S++ // s
  55. , FALSE4 : S++ // e
  56. , NULL : S++ // u
  57. , NULL2 : S++ // l
  58. , NULL3 : S++ // l
  59. , NUMBER_DECIMAL_POINT : S++ // .
  60. , NUMBER_DIGIT : S++ // [0-9]
  61. };
  62. for (var s_ in clarinet.STATE) clarinet.STATE[clarinet.STATE[s_]] = s_;
  63. // switcharoo
  64. S = clarinet.STATE;
  65. const Char = {
  66. tab : 0x09, // \t
  67. lineFeed : 0x0A, // \n
  68. carriageReturn : 0x0D, // \r
  69. space : 0x20, // " "
  70. doubleQuote : 0x22, // "
  71. plus : 0x2B, // +
  72. comma : 0x2C, // ,
  73. minus : 0x2D, // -
  74. period : 0x2E, // .
  75. _0 : 0x30, // 0
  76. _9 : 0x39, // 9
  77. colon : 0x3A, // :
  78. E : 0x45, // E
  79. openBracket : 0x5B, // [
  80. backslash : 0x5C, // \
  81. closeBracket : 0x5D, // ]
  82. a : 0x61, // a
  83. b : 0x62, // b
  84. e : 0x65, // e
  85. f : 0x66, // f
  86. l : 0x6C, // l
  87. n : 0x6E, // n
  88. r : 0x72, // r
  89. s : 0x73, // s
  90. t : 0x74, // t
  91. u : 0x75, // u
  92. openBrace : 0x7B, // {
  93. closeBrace : 0x7D, // }
  94. }
  95. if (!Object.create) {
  96. Object.create = function (o) {
  97. function f () { this["__proto__"] = o; }
  98. f.prototype = o;
  99. return new f;
  100. };
  101. }
  102. if (!Object.getPrototypeOf) {
  103. Object.getPrototypeOf = function (o) {
  104. return o["__proto__"];
  105. };
  106. }
  107. if (!Object.keys) {
  108. Object.keys = function (o) {
  109. var a = [];
  110. for (var i in o) if (o.hasOwnProperty(i)) a.push(i);
  111. return a;
  112. };
  113. }
  114. function checkBufferLength (parser) {
  115. var maxAllowed = Math.max(clarinet.MAX_BUFFER_LENGTH, 10)
  116. , maxActual = 0
  117. ;
  118. for (var buffer in buffers) {
  119. var len = parser[buffer] === undefined ? 0 : parser[buffer].length;
  120. if (len > maxAllowed) {
  121. switch (buffer) {
  122. case "text":
  123. closeText(parser);
  124. break;
  125. default:
  126. error(parser, "Max buffer length exceeded: "+ buffer);
  127. }
  128. }
  129. maxActual = Math.max(maxActual, len);
  130. }
  131. parser.bufferCheckPosition = (clarinet.MAX_BUFFER_LENGTH - maxActual)
  132. + parser.position;
  133. }
  134. function clearBuffers (parser) {
  135. for (var buffer in buffers) {
  136. parser[buffer] = buffers[buffer];
  137. }
  138. }
  139. var stringTokenPattern = /[\\"\n]/g;
  140. function CParser (opt) {
  141. if (!(this instanceof CParser)) return new CParser (opt);
  142. var parser = this;
  143. clearBuffers(parser);
  144. parser.bufferCheckPosition = clarinet.MAX_BUFFER_LENGTH;
  145. parser.q = parser.c = parser.p = "";
  146. parser.opt = opt || {};
  147. parser.closed = parser.closedRoot = parser.sawRoot = false;
  148. parser.tag = parser.error = null;
  149. parser.state = S.BEGIN;
  150. parser.stack = new Array();
  151. // mostly just for error reporting
  152. parser.position = parser.column = 0;
  153. parser.line = 1;
  154. parser.slashed = false;
  155. parser.unicodeI = 0;
  156. parser.unicodeS = null;
  157. parser.depth = 0;
  158. emit(parser, "onready");
  159. }
  160. CParser.prototype =
  161. { end : function () { end(this); }
  162. , write : write
  163. , resume : function () { this.error = null; return this; }
  164. , close : function () { return this.write(null); }
  165. };
  166. try { Stream = require("stream").Stream; }
  167. catch (ex) { Stream = function () {}; }
  168. function createStream (opt) { return new CStream(opt); }
  169. function CStream (opt) {
  170. if (!(this instanceof CStream)) return new CStream(opt);
  171. this._parser = new CParser(opt);
  172. this.writable = true;
  173. this.readable = true;
  174. //var Buffer = this.Buffer || function Buffer () {}; // if we don't have Buffers, fake it so we can do `var instanceof Buffer` and not throw an error
  175. this.bytes_remaining = 0; // number of bytes remaining in multi byte utf8 char to read after split boundary
  176. this.bytes_in_sequence = 0; // bytes in multi byte utf8 char to read
  177. this.temp_buffs = { "2": new Buffer(2), "3": new Buffer(3), "4": new Buffer(4) }; // for rebuilding chars split before boundary is reached
  178. this.string = '';
  179. var me = this;
  180. Stream.apply(me);
  181. this._parser.onend = function () { me.emit("end"); };
  182. this._parser.onerror = function (er) {
  183. me.emit("error", er);
  184. me._parser.error = null;
  185. };
  186. streamWraps.forEach(function (ev) {
  187. Object.defineProperty(me, "on" + ev,
  188. { get : function () { return me._parser["on" + ev]; }
  189. , set : function (h) {
  190. if (!h) {
  191. me.removeAllListeners(ev);
  192. me._parser["on"+ev] = h;
  193. return h;
  194. }
  195. me.on(ev, h);
  196. }
  197. , enumerable : true
  198. , configurable : false
  199. });
  200. });
  201. }
  202. CStream.prototype = Object.create(Stream.prototype,
  203. { constructor: { value: CStream } });
  204. CStream.prototype.write = function (data) {
  205. data = new Buffer(data);
  206. for (var i = 0; i < data.length; i++) {
  207. var n = data[i];
  208. // check for carry over of a multi byte char split between data chunks
  209. // & fill temp buffer it with start of this data chunk up to the boundary limit set in the last iteration
  210. if (this.bytes_remaining > 0) {
  211. for (var j = 0; j < this.bytes_remaining; j++) {
  212. this.temp_buffs[this.bytes_in_sequence][this.bytes_in_sequence - this.bytes_remaining + j] = data[j];
  213. }
  214. this.string = this.temp_buffs[this.bytes_in_sequence].toString();
  215. this.bytes_in_sequence = this.bytes_remaining = 0;
  216. // move iterator forward by number of byte read during sequencing
  217. i = i + j - 1;
  218. // pass data to parser and move forward to parse rest of data
  219. this._parser.write(this.string);
  220. this.emit("data", this.string);
  221. continue;
  222. }
  223. // if no remainder bytes carried over, parse multi byte (>=128) chars one at a time
  224. if (this.bytes_remaining === 0 && n >= 128) {
  225. if ((n >= 194) && (n <= 223)) this.bytes_in_sequence = 2;
  226. if ((n >= 224) && (n <= 239)) this.bytes_in_sequence = 3;
  227. if ((n >= 240) && (n <= 244)) this.bytes_in_sequence = 4;
  228. if ((this.bytes_in_sequence + i) > data.length) { // if bytes needed to complete char fall outside data length, we have a boundary split
  229. for (var k = 0; k <= (data.length - 1 - i); k++) {
  230. this.temp_buffs[this.bytes_in_sequence][k] = data[i + k]; // fill temp data of correct size with bytes available in this chunk
  231. }
  232. this.bytes_remaining = (i + this.bytes_in_sequence) - data.length;
  233. // immediately return as we need another chunk to sequence the character
  234. return true;
  235. } else {
  236. this.string = data.slice(i, (i + this.bytes_in_sequence)).toString();
  237. i = i + this.bytes_in_sequence - 1;
  238. this._parser.write(this.string);
  239. this.emit("data", this.string);
  240. continue;
  241. }
  242. }
  243. // is there a range of characters that are immediately parsable?
  244. for (var p = i; p < data.length; p++) {
  245. if (data[p] >= 128) break;
  246. }
  247. this.string = data.slice(i, p).toString();
  248. this._parser.write(this.string);
  249. this.emit("data", this.string);
  250. i = p - 1;
  251. // handle any remaining characters using multibyte logic
  252. continue;
  253. }
  254. };
  255. CStream.prototype.end = function (chunk) {
  256. if (chunk && chunk.length) this._parser.write(chunk.toString());
  257. this._parser.end();
  258. return true;
  259. };
  260. CStream.prototype.on = function (ev, handler) {
  261. var me = this;
  262. if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) {
  263. me._parser["on"+ev] = function () {
  264. var args = arguments.length === 1 ? [arguments[0]]
  265. : Array.apply(null, arguments);
  266. args.splice(0, 0, ev);
  267. me.emit.apply(me, args);
  268. };
  269. }
  270. return Stream.prototype.on.call(me, ev, handler);
  271. };
  272. CStream.prototype.destroy = function () {
  273. clearBuffers(this._parser);
  274. this.emit("close");
  275. };
  276. function emit(parser, event, data) {
  277. if(clarinet.INFO) console.log('-- emit', event, data);
  278. if (parser[event]) parser[event](data);
  279. }
  280. function emitNode(parser, event, data) {
  281. closeValue(parser);
  282. emit(parser, event, data);
  283. }
  284. function closeValue(parser, event) {
  285. parser.textNode = textopts(parser.opt, parser.textNode);
  286. if (parser.textNode !== undefined) {
  287. emit(parser, (event ? event : "onvalue"), parser.textNode);
  288. }
  289. parser.textNode = undefined;
  290. }
  291. function closeNumber(parser) {
  292. if (parser.numberNode)
  293. emit(parser, "onvalue", parseFloat(parser.numberNode));
  294. parser.numberNode = "";
  295. }
  296. function textopts (opt, text) {
  297. if (text === undefined) {
  298. return text;
  299. }
  300. if (opt.trim) text = text.trim();
  301. if (opt.normalize) text = text.replace(/\s+/g, " ");
  302. return text;
  303. }
  304. function error (parser, er) {
  305. closeValue(parser);
  306. er += "\nLine: "+parser.line+
  307. "\nColumn: "+parser.column+
  308. "\nChar: "+parser.c;
  309. er = new Error(er);
  310. parser.error = er;
  311. emit(parser, "onerror", er);
  312. return parser;
  313. }
  314. function end(parser) {
  315. if (parser.state !== S.VALUE || parser.depth !== 0)
  316. error(parser, "Unexpected end");
  317. closeValue(parser);
  318. parser.c = "";
  319. parser.closed = true;
  320. emit(parser, "onend");
  321. CParser.call(parser, parser.opt);
  322. return parser;
  323. }
  324. function isWhitespace(c) {
  325. return c === Char.carriageReturn || c === Char.lineFeed || c === Char.space || c === Char.tab;
  326. }
  327. function write (chunk) {
  328. var parser = this;
  329. if (this.error) throw this.error;
  330. if (parser.closed) return error(parser,
  331. "Cannot write after close. Assign an onready handler.");
  332. if (chunk === null) return end(parser);
  333. var i = 0, c = chunk.charCodeAt(0), p = parser.p;
  334. if (clarinet.DEBUG) console.log('write -> [' + chunk + ']');
  335. while (c) {
  336. p = c;
  337. parser.c = c = chunk.charCodeAt(i++);
  338. // if chunk doesnt have next, like streaming char by char
  339. // this way we need to check if previous is really previous
  340. // if not we need to reset to what the parser says is the previous
  341. // from buffer
  342. if(p !== c ) parser.p = p;
  343. else p = parser.p;
  344. if(!c) break;
  345. if (clarinet.DEBUG) console.log(i,c,clarinet.STATE[parser.state]);
  346. parser.position ++;
  347. if (c === Char.lineFeed) {
  348. parser.line ++;
  349. parser.column = 0;
  350. } else parser.column ++;
  351. switch (parser.state) {
  352. case S.BEGIN:
  353. if (c === Char.openBrace) parser.state = S.OPEN_OBJECT;
  354. else if (c === Char.openBracket) parser.state = S.OPEN_ARRAY;
  355. else if (!isWhitespace(c))
  356. error(parser, "Non-whitespace before {[.");
  357. continue;
  358. case S.OPEN_KEY:
  359. case S.OPEN_OBJECT:
  360. if (isWhitespace(c)) continue;
  361. if(parser.state === S.OPEN_KEY) parser.stack.push(S.CLOSE_KEY);
  362. else {
  363. if(c === Char.closeBrace) {
  364. emit(parser, 'onopenobject');
  365. this.depth++;
  366. emit(parser, 'oncloseobject');
  367. this.depth--;
  368. parser.state = parser.stack.pop() || S.VALUE;
  369. continue;
  370. } else parser.stack.push(S.CLOSE_OBJECT);
  371. }
  372. if(c === Char.doubleQuote) parser.state = S.STRING;
  373. else error(parser, "Malformed object key should start with \"");
  374. continue;
  375. case S.CLOSE_KEY:
  376. case S.CLOSE_OBJECT:
  377. if (isWhitespace(c)) continue;
  378. var event = (parser.state === S.CLOSE_KEY) ? 'key' : 'object';
  379. if(c === Char.colon) {
  380. if(parser.state === S.CLOSE_OBJECT) {
  381. parser.stack.push(S.CLOSE_OBJECT);
  382. closeValue(parser, 'onopenobject');
  383. this.depth++;
  384. } else closeValue(parser, 'onkey');
  385. parser.state = S.VALUE;
  386. } else if (c === Char.closeBrace) {
  387. emitNode(parser, 'oncloseobject');
  388. this.depth--;
  389. parser.state = parser.stack.pop() || S.VALUE;
  390. } else if(c === Char.comma) {
  391. if(parser.state === S.CLOSE_OBJECT)
  392. parser.stack.push(S.CLOSE_OBJECT);
  393. closeValue(parser);
  394. parser.state = S.OPEN_KEY;
  395. } else error(parser, 'Bad object');
  396. continue;
  397. case S.OPEN_ARRAY: // after an array there always a value
  398. case S.VALUE:
  399. if (isWhitespace(c)) continue;
  400. if(parser.state===S.OPEN_ARRAY) {
  401. emit(parser, 'onopenarray');
  402. this.depth++;
  403. parser.state = S.VALUE;
  404. if(c === Char.closeBracket) {
  405. emit(parser, 'onclosearray');
  406. this.depth--;
  407. parser.state = parser.stack.pop() || S.VALUE;
  408. continue;
  409. } else {
  410. parser.stack.push(S.CLOSE_ARRAY);
  411. }
  412. }
  413. if(c === Char.doubleQuote) parser.state = S.STRING;
  414. else if(c === Char.openBrace) parser.state = S.OPEN_OBJECT;
  415. else if(c === Char.openBracket) parser.state = S.OPEN_ARRAY;
  416. else if(c === Char.t) parser.state = S.TRUE;
  417. else if(c === Char.f) parser.state = S.FALSE;
  418. else if(c === Char.n) parser.state = S.NULL;
  419. else if(c === Char.minus) { // keep and continue
  420. parser.numberNode += "-";
  421. } else if(Char._0 <= c && c <= Char._9) {
  422. parser.numberNode += String.fromCharCode(c);
  423. parser.state = S.NUMBER_DIGIT;
  424. } else error(parser, "Bad value");
  425. continue;
  426. case S.CLOSE_ARRAY:
  427. if(c === Char.comma) {
  428. parser.stack.push(S.CLOSE_ARRAY);
  429. closeValue(parser, 'onvalue');
  430. parser.state = S.VALUE;
  431. } else if (c === Char.closeBracket) {
  432. emitNode(parser, 'onclosearray');
  433. this.depth--;
  434. parser.state = parser.stack.pop() || S.VALUE;
  435. } else if (isWhitespace(c))
  436. continue;
  437. else error(parser, 'Bad array');
  438. continue;
  439. case S.STRING:
  440. if (parser.textNode === undefined) {
  441. parser.textNode = "";
  442. }
  443. // thanks thejh, this is an about 50% performance improvement.
  444. var starti = i-1
  445. , slashed = parser.slashed
  446. , unicodeI = parser.unicodeI
  447. ;
  448. STRING_BIGLOOP: while (true) {
  449. if (clarinet.DEBUG)
  450. console.log(i,c,clarinet.STATE[parser.state]
  451. ,slashed);
  452. // zero means "no unicode active". 1-4 mean "parse some more". end after 4.
  453. while (unicodeI > 0) {
  454. parser.unicodeS += String.fromCharCode(c);
  455. c = chunk.charCodeAt(i++);
  456. parser.position++;
  457. if (unicodeI === 4) {
  458. // TODO this might be slow? well, probably not used too often anyway
  459. parser.textNode += String.fromCharCode(parseInt(parser.unicodeS, 16));
  460. unicodeI = 0;
  461. starti = i-1;
  462. } else {
  463. unicodeI++;
  464. }
  465. // we can just break here: no stuff we skipped that still has to be sliced out or so
  466. if (!c) break STRING_BIGLOOP;
  467. }
  468. if (c === Char.doubleQuote && !slashed) {
  469. parser.state = parser.stack.pop() || S.VALUE;
  470. parser.textNode += chunk.substring(starti, i-1);
  471. parser.position += i - 1 - starti;
  472. break;
  473. }
  474. if (c === Char.backslash && !slashed) {
  475. slashed = true;
  476. parser.textNode += chunk.substring(starti, i-1);
  477. parser.position += i - 1 - starti;
  478. c = chunk.charCodeAt(i++);
  479. parser.position++;
  480. if (!c) break;
  481. }
  482. if (slashed) {
  483. slashed = false;
  484. if (c === Char.n) { parser.textNode += '\n'; }
  485. else if (c === Char.r) { parser.textNode += '\r'; }
  486. else if (c === Char.t) { parser.textNode += '\t'; }
  487. else if (c === Char.f) { parser.textNode += '\f'; }
  488. else if (c === Char.b) { parser.textNode += '\b'; }
  489. else if (c === Char.u) {
  490. // \uxxxx. meh!
  491. unicodeI = 1;
  492. parser.unicodeS = '';
  493. } else {
  494. parser.textNode += String.fromCharCode(c);
  495. }
  496. c = chunk.charCodeAt(i++);
  497. parser.position++;
  498. starti = i-1;
  499. if (!c) break;
  500. else continue;
  501. }
  502. stringTokenPattern.lastIndex = i;
  503. var reResult = stringTokenPattern.exec(chunk);
  504. if (reResult === null) {
  505. i = chunk.length+1;
  506. parser.textNode += chunk.substring(starti, i-1);
  507. parser.position += i - 1 - starti;
  508. break;
  509. }
  510. i = reResult.index+1;
  511. c = chunk.charCodeAt(reResult.index);
  512. if (!c) {
  513. parser.textNode += chunk.substring(starti, i-1);
  514. parser.position += i - 1 - starti;
  515. break;
  516. }
  517. }
  518. parser.slashed = slashed;
  519. parser.unicodeI = unicodeI;
  520. continue;
  521. case S.TRUE:
  522. if (c === Char.r) parser.state = S.TRUE2;
  523. else error(parser, 'Invalid true started with t'+ c);
  524. continue;
  525. case S.TRUE2:
  526. if (c === Char.u) parser.state = S.TRUE3;
  527. else error(parser, 'Invalid true started with tr'+ c);
  528. continue;
  529. case S.TRUE3:
  530. if(c === Char.e) {
  531. emit(parser, "onvalue", true);
  532. parser.state = parser.stack.pop() || S.VALUE;
  533. } else error(parser, 'Invalid true started with tru'+ c);
  534. continue;
  535. case S.FALSE:
  536. if (c === Char.a) parser.state = S.FALSE2;
  537. else error(parser, 'Invalid false started with f'+ c);
  538. continue;
  539. case S.FALSE2:
  540. if (c === Char.l) parser.state = S.FALSE3;
  541. else error(parser, 'Invalid false started with fa'+ c);
  542. continue;
  543. case S.FALSE3:
  544. if (c === Char.s) parser.state = S.FALSE4;
  545. else error(parser, 'Invalid false started with fal'+ c);
  546. continue;
  547. case S.FALSE4:
  548. if (c === Char.e) {
  549. emit(parser, "onvalue", false);
  550. parser.state = parser.stack.pop() || S.VALUE;
  551. } else error(parser, 'Invalid false started with fals'+ c);
  552. continue;
  553. case S.NULL:
  554. if (c === Char.u) parser.state = S.NULL2;
  555. else error(parser, 'Invalid null started with n'+ c);
  556. continue;
  557. case S.NULL2:
  558. if (c === Char.l) parser.state = S.NULL3;
  559. else error(parser, 'Invalid null started with nu'+ c);
  560. continue;
  561. case S.NULL3:
  562. if(c === Char.l) {
  563. emit(parser, "onvalue", null);
  564. parser.state = parser.stack.pop() || S.VALUE;
  565. } else error(parser, 'Invalid null started with nul'+ c);
  566. continue;
  567. case S.NUMBER_DECIMAL_POINT:
  568. if(c === Char.period) {
  569. parser.numberNode += ".";
  570. parser.state = S.NUMBER_DIGIT;
  571. } else error(parser, 'Leading zero not followed by .');
  572. continue;
  573. case S.NUMBER_DIGIT:
  574. if(Char._0 <= c && c <= Char._9) parser.numberNode += String.fromCharCode(c);
  575. else if (c === Char.period) {
  576. if(parser.numberNode.indexOf('.')!==-1)
  577. error(parser, 'Invalid number has two dots');
  578. parser.numberNode += ".";
  579. } else if (c === Char.e || c === Char.E) {
  580. if(parser.numberNode.indexOf('e')!==-1 ||
  581. parser.numberNode.indexOf('E')!==-1 )
  582. error(parser, 'Invalid number has two exponential');
  583. parser.numberNode += "e";
  584. } else if (c === Char.plus || c === Char.minus) {
  585. if(!(p === Char.e || p === Char.E))
  586. error(parser, 'Invalid symbol in number');
  587. parser.numberNode += String.fromCharCode(c);
  588. } else {
  589. closeNumber(parser);
  590. i--; // go back one
  591. parser.state = parser.stack.pop() || S.VALUE;
  592. }
  593. continue;
  594. default:
  595. error(parser, "Unknown state: " + parser.state);
  596. }
  597. }
  598. if (parser.position >= parser.bufferCheckPosition)
  599. checkBufferLength(parser);
  600. return parser;
  601. }
  602. })(typeof exports === "undefined" ? clarinet = {} : exports);