Test Failed
Push — master ( c267c9...24f501 )
by
unknown
11:19
created

tokenizr.js ➔ _callSuper   A

Complexity

Conditions 3

Size

Total Lines 1
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 1
c 0
b 0
f 0
dl 0
loc 1
rs 10
1
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Tokenizr = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){
0 ignored issues
show
Unused Code introduced by
The variable define seems to be never used. Consider removing it.
Loading history...
2
"use strict";
3
4
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
5
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
0 ignored issues
show
Coding Style introduced by
Consider using undefined instead of void(0). It is equivalent and more straightforward to read.
Loading history...
6
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
0 ignored issues
show
Coding Style introduced by
Consider using undefined instead of void(0). It is equivalent and more straightforward to read.
Loading history...
7
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
8
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
9
function _construct(t, e, r) { if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments); var o = [null]; o.push.apply(o, e); var p = new (t.bind.apply(t, o))(); return r && _setPrototypeOf(p, r.prototype), p; }
10
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
Unused Code introduced by
The variable _isNativeReflectConstruct seems to be never used. Consider removing it.
Loading history...
11
function _isNativeFunction(fn) { try { return Function.toString.call(fn).indexOf("[native code]") !== -1; } catch (e) { return typeof fn === "function"; } }
12
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
13
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
14
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
0 ignored issues
show
Comprehensibility introduced by
It seems like you are trying to overwrite a function name here. _typeof is already defined in line 14 as a function. While this will work, it can be very confusing.
Loading history...
Unused Code introduced by
The expression "@babel/helpers - typeof" has no effects. Consider removing it.
Loading history...
15
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
17
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
18
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
19
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
0 ignored issues
show
Coding Style introduced by
Consider using undefined instead of void(0). It is equivalent and more straightforward to read.
Loading history...
20
/*
21
**  Tokenizr -- String Tokenization Library
22
**  Copyright (c) 2015-2024 Dr. Ralf S. Engelschall <[email protected]>
23
**
24
**  Permission is hereby granted, free of charge, to any person obtaining
25
**  a copy of this software and associated documentation files (the
26
**  "Software"), to deal in the Software without restriction, including
27
**  without limitation the rights to use, copy, modify, merge, publish,
28
**  distribute, sublicense, and/or sell copies of the Software, and to
29
**  permit persons to whom the Software is furnished to do so, subject to
30
**  the following conditions:
31
**
32
**  The above copyright notice and this permission notice shall be included
33
**  in all copies or substantial portions of the Software.
34
**
35
**  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
36
**  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37
**  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
38
**  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
39
**  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
40
**  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
41
**  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42
*/
43
44
/*  utility function: create a source excerpt  */
45
var excerpt = function excerpt(txt, o) {
46
  var l = txt.length;
47
  var b = o - 20;
48
  if (b < 0) b = 0;
49
  var e = o + 20;
50
  if (e > l) e = l;
51
  var hex = function hex(ch) {
52
    return ch.charCodeAt(0).toString(16).toUpperCase();
53
  };
54
  var extract = function extract(txt, pos, len) {
55
    return txt.substr(pos, len).replace(/\\/g, "\\\\").replace(/\x08/g, "\\b").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\f/g, "\\f").replace(/\r/g, "\\r").replace(/[\x00-\x07\x0B\x0E\x0F]/g, function (ch) {
56
      return "\\x0" + hex(ch);
57
    }).replace(/[\x10-\x1F\x80-\xFF]/g, function (ch) {
58
      return "\\x" + hex(ch);
59
    }).replace(/[\u0100-\u0FFF]/g, function (ch) {
60
      return "\\u0" + hex(ch);
61
    }).replace(/[\u1000-\uFFFF]/g, function (ch) {
62
      return "\\u" + hex(ch);
63
    });
64
  };
65
  return {
66
    prologTrunc: b > 0,
67
    prologText: extract(txt, b, o - b),
68
    tokenText: extract(txt, o, 1),
69
    epilogText: extract(txt, o + 1, e - (o + 1)),
70
    epilogTrunc: e < l
71
  };
72
};
73
74
/*  internal helper class for token representation  */
75
var Token = /*#__PURE__*/function () {
76
  function Token(type, value, text) {
77
    var pos = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
78
    var line = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
79
    var column = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
80
    _classCallCheck(this, Token);
81
    this.type = type;
82
    this.value = value;
83
    this.text = text;
84
    this.pos = pos;
85
    this.line = line;
86
    this.column = column;
87
  }
88
  return _createClass(Token, [{
89
    key: "toString",
90
    value: function toString() {
91
      var colorize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function (type, text) {
92
        return text;
93
      };
94
      return "".concat(colorize("type", this.type), " ") + "(value: ".concat(colorize("value", JSON.stringify(this.value)), ", ") + "text: ".concat(colorize("text", JSON.stringify(this.text)), ", ") + "pos: ".concat(colorize("pos", this.pos), ", ") + "line: ".concat(colorize("line", this.line), ", ") + "column: ".concat(colorize("column", this.column), ")");
95
    }
96
  }, {
97
    key: "isA",
98
    value: function isA(type, value) {
99
      if (type !== this.type) return false;
100
      if (arguments.length === 2 && value !== this.value) return false;
101
      return true;
102
    }
103
  }]);
104
}();
105
/*  internal helper class for tokenization error reporting  */
106
var ParsingError = /*#__PURE__*/function (_Error) {
107
  /*  construct and initialize object  */
108
  function ParsingError(message, pos, line, column, input) {
109
    var _this;
110
    _classCallCheck(this, ParsingError);
111
    _this = _callSuper(this, ParsingError, [message]);
112
    _this.name = "ParsingError";
113
    _this.message = message;
114
    _this.pos = pos;
115
    _this.line = line;
116
    _this.column = column;
117
    _this.input = input;
118
    return _this;
119
  }
120
121
  /*  render a useful string representation  */
122
  _inherits(ParsingError, _Error);
123
  return _createClass(ParsingError, [{
124
    key: "toString",
125
    value: function toString() {
126
      var l = excerpt(this.input, this.pos);
127
      var prefix1 = "line ".concat(this.line, " (column ").concat(this.column, "): ");
128
      var prefix2 = "";
129
      for (var i = 0; i < prefix1.length + l.prologText.length; i++) prefix2 += " ";
130
      var msg = "Parsing Error: " + this.message + "\n" + prefix1 + l.prologText + l.tokenText + l.epilogText + "\n" + prefix2 + "^";
131
      return msg;
132
    }
133
  }]);
134
}( /*#__PURE__*/_wrapNativeSuper(Error));
135
/*  internal helper class for action context  */
136
var ActionContext = /*#__PURE__*/function () {
137
  /*  construct and initialize the object  */
138
  function ActionContext(tokenizr) {
139
    _classCallCheck(this, ActionContext);
140
    this._tokenizr = tokenizr;
141
    this._data = {};
142
    this._repeat = false;
143
    this._reject = false;
144
    this._ignore = false;
145
    this._match = null;
146
  }
147
148
  /*  store and retrieve user data attached to context  */
149
  return _createClass(ActionContext, [{
150
    key: "data",
151
    value: function data(key, value) {
152
      var valueOld = this._data[key];
153
      if (arguments.length === 2) this._data[key] = value;
154
      return valueOld;
155
    }
156
157
    /*  retrieve information of current matching  */
158
  }, {
159
    key: "info",
160
    value: function info() {
161
      return {
162
        line: this._tokenizr._line,
163
        column: this._tokenizr._column,
164
        pos: this._tokenizr._pos,
165
        len: this._match[0].length
166
      };
167
    }
168
169
    /*  pass-through functions to attached tokenizer  */
170
  }, {
171
    key: "push",
172
    value: function push() {
173
      var _this$_tokenizr;
174
      (_this$_tokenizr = this._tokenizr).push.apply(_this$_tokenizr, arguments);
175
      return this;
176
    }
177
  }, {
178
    key: "pop",
179
    value: function pop() {
180
      var _this$_tokenizr2;
181
      return (_this$_tokenizr2 = this._tokenizr).pop.apply(_this$_tokenizr2, arguments);
182
    }
183
  }, {
184
    key: "state",
185
    value: function state() {
186
      var _this$_tokenizr4;
187
      if (arguments.length > 0) {
188
        var _this$_tokenizr3;
189
        (_this$_tokenizr3 = this._tokenizr).state.apply(_this$_tokenizr3, arguments);
190
        return this;
191
      } else return (_this$_tokenizr4 = this._tokenizr).state.apply(_this$_tokenizr4, arguments);
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
192
    }
193
  }, {
194
    key: "tag",
195
    value: function tag() {
196
      var _this$_tokenizr5;
197
      (_this$_tokenizr5 = this._tokenizr).tag.apply(_this$_tokenizr5, arguments);
198
      return this;
199
    }
200
  }, {
201
    key: "tagged",
202
    value: function tagged() {
203
      var _this$_tokenizr6;
204
      return (_this$_tokenizr6 = this._tokenizr).tagged.apply(_this$_tokenizr6, arguments);
205
    }
206
  }, {
207
    key: "untag",
208
    value: function untag() {
209
      var _this$_tokenizr7;
210
      (_this$_tokenizr7 = this._tokenizr).untag.apply(_this$_tokenizr7, arguments);
211
      return this;
212
    }
213
214
    /*  mark current matching to be repeated from scratch  */
215
  }, {
216
    key: "repeat",
217
    value: function repeat() {
218
      this._tokenizr._log("    REPEAT");
219
      this._repeat = true;
220
      return this;
221
    }
222
223
    /*  mark current matching to be rejected  */
224
  }, {
225
    key: "reject",
226
    value: function reject() {
227
      this._tokenizr._log("    REJECT");
228
      this._reject = true;
229
      return this;
230
    }
231
232
    /*  mark current matching to be ignored  */
233
  }, {
234
    key: "ignore",
235
    value: function ignore() {
236
      this._tokenizr._log("    IGNORE");
237
      this._ignore = true;
238
      return this;
239
    }
240
241
    /*  accept current matching as a new token  */
242
  }, {
243
    key: "accept",
244
    value: function accept(type, value) {
245
      if (arguments.length < 2) value = this._match[0];
246
      this._tokenizr._log("    ACCEPT: type: ".concat(type, ", value: ") + "".concat(JSON.stringify(value), " (").concat(_typeof(value), "), text: \"").concat(this._match[0], "\""));
247
      this._tokenizr._pending.push(new Token(type, value, this._match[0], this._tokenizr._pos, this._tokenizr._line, this._tokenizr._column));
248
      return this;
249
    }
250
251
    /*  immediately stop tokenization  */
252
  }, {
253
    key: "stop",
254
    value: function stop() {
255
      this._tokenizr._stopped = true;
256
      return this;
257
    }
258
  }]);
259
}();
260
/*  external API class  */
261
var Tokenizr = /*#__PURE__*/function () {
262
  /*  construct and initialize the object  */
263
  function Tokenizr() {
264
    _classCallCheck(this, Tokenizr);
265
    this._before = null;
266
    this._after = null;
267
    this._finish = null;
268
    this._rules = [];
269
    this._debug = false;
270
    this.reset();
271
  }
272
273
  /*  reset the internal state  */
274
  return _createClass(Tokenizr, [{
275
    key: "reset",
276
    value: function reset() {
277
      this._input = "";
278
      this._len = 0;
279
      this._eof = false;
280
      this._pos = 0;
281
      this._line = 1;
282
      this._column = 1;
283
      this._state = ["default"];
284
      this._tag = {};
285
      this._transaction = [];
286
      this._pending = [];
287
      this._stopped = false;
288
      this._ctx = new ActionContext(this);
289
      return this;
290
    }
291
292
    /*  create an error message for the current position  */
293
  }, {
294
    key: "error",
295
    value: function error(message) {
296
      return new ParsingError(message, this._pos, this._line, this._column, this._input);
297
    }
298
299
    /*  configure debug operation  */
300
  }, {
301
    key: "debug",
302
    value: function debug(_debug) {
303
      this._debug = _debug;
304
      return this;
305
    }
306
307
    /*  output a debug message  */
308
  }, {
309
    key: "_log",
310
    value: function _log(msg) {
311
      /* eslint no-console: off */
312
      if (this._debug) console.log("tokenizr: ".concat(msg));
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
313
    }
314
315
    /*  provide (new) input string to tokenize  */
316
  }, {
317
    key: "input",
318
    value: function input(_input) {
319
      /*  sanity check arguments  */
320
      if (typeof _input !== "string") throw new Error("parameter \"input\" not a String");
321
322
      /*  reset state and store new input  */
323
      this.reset();
324
      this._input = _input;
325
      this._len = _input.length;
326
      return this;
327
    }
328
329
    /*  push state  */
330
  }, {
331
    key: "push",
332
    value: function push(state) {
333
      /*  sanity check arguments  */
334
      if (arguments.length !== 1) throw new Error("invalid number of arguments");
335
      if (typeof state !== "string") throw new Error("parameter \"state\" not a String");
336
337
      /*  push new state  */
338
      this._log("    STATE (PUSH): " + "old: <".concat(this._state[this._state.length - 1], ">, ") + "new: <".concat(state, ">"));
339
      this._state.push(state);
340
      return this;
341
    }
342
343
    /*  pop state  */
344
  }, {
345
    key: "pop",
346
    value: function pop() {
347
      /*  sanity check arguments  */
348
      if (arguments.length !== 0) throw new Error("invalid number of arguments");
349
      if (this._state.length < 2) throw new Error("no more custom states to pop");
350
351
      /*  pop old state  */
352
      this._log("    STATE (POP): " + "old: <".concat(this._state[this._state.length - 1], ">, ") + "new: <".concat(this._state[this._state.length - 2], ">"));
353
      return this._state.pop();
354
    }
355
356
    /*  get/set state  */
357
  }, {
358
    key: "state",
359
    value: function state(_state) {
360
      if (arguments.length === 1) {
361
        /*  sanity check arguments  */
362
        if (typeof _state !== "string") throw new Error("parameter \"state\" not a String");
363
364
        /*  change current state  */
365
        this._log("    STATE (SET): " + "old: <".concat(this._state[this._state.length - 1], ">, ") + "new: <".concat(_state, ">"));
366
        this._state[this._state.length - 1] = _state;
367
        return this;
368
      } else if (arguments.length === 0) return this._state[this._state.length - 1];else throw new Error("invalid number of arguments");
369
    }
370
371
    /*  set a tag  */
372
  }, {
373
    key: "tag",
374
    value: function tag(_tag) {
375
      /*  sanity check arguments  */
376
      if (arguments.length !== 1) throw new Error("invalid number of arguments");
377
      if (typeof _tag !== "string") throw new Error("parameter \"tag\" not a String");
378
379
      /*  set tag  */
380
      this._log("    TAG (ADD): ".concat(_tag));
381
      this._tag[_tag] = true;
382
      return this;
383
    }
384
385
    /*  check whether tag is set  */
386
  }, {
387
    key: "tagged",
388
    value: function tagged(tag) {
389
      /*  sanity check arguments  */
390
      if (arguments.length !== 1) throw new Error("invalid number of arguments");
391
      if (typeof tag !== "string") throw new Error("parameter \"tag\" not a String");
392
393
      /*  set tag  */
394
      return this._tag[tag] === true;
395
    }
396
397
    /*  unset a tag  */
398
  }, {
399
    key: "untag",
400
    value: function untag(tag) {
401
      /*  sanity check arguments  */
402
      if (arguments.length !== 1) throw new Error("invalid number of arguments");
403
      if (typeof tag !== "string") throw new Error("parameter \"tag\" not a String");
404
405
      /*  delete tag  */
406
      this._log("    TAG (DEL): ".concat(tag));
407
      delete this._tag[tag];
408
      return this;
409
    }
410
411
    /*  configure a tokenization before-rule callback  */
412
  }, {
413
    key: "before",
414
    value: function before(action) {
415
      this._before = action;
416
      return this;
417
    }
418
419
    /*  configure a tokenization after-rule callback  */
420
  }, {
421
    key: "after",
422
    value: function after(action) {
423
      this._after = action;
424
      return this;
425
    }
426
427
    /*  configure a tokenization finish callback  */
428
  }, {
429
    key: "finish",
430
    value: function finish(action) {
431
      this._finish = action;
432
      return this;
433
    }
434
435
    /*  configure a tokenization rule  */
436
  }, {
437
    key: "rule",
438
    value: function rule(state, pattern, action) {
439
      var name = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "unknown";
440
      /*  support optional states  */
441
      if (arguments.length === 2 && typeof pattern === "function") {
442
        var _ref = [state, pattern];
443
        pattern = _ref[0];
444
        action = _ref[1];
445
        state = "*";
446
      } else if (arguments.length === 3 && typeof pattern === "function") {
447
        var _ref2 = [state, pattern, action];
448
        pattern = _ref2[0];
449
        action = _ref2[1];
450
        name = _ref2[2];
451
        state = "*";
452
      }
453
454
      /*  sanity check arguments  */
455
      if (typeof state !== "string") throw new Error("parameter \"state\" not a String");
456
      if (!(_typeof(pattern) === "object" && pattern instanceof RegExp)) throw new Error("parameter \"pattern\" not a RegExp");
457
      if (typeof action !== "function") throw new Error("parameter \"action\" not a Function");
458
      if (typeof name !== "string") throw new Error("parameter \"name\" not a String");
459
460
      /*  post-process state  */
461
      state = state.split(/\s*,\s*/g).map(function (entry) {
462
        var items = entry.split(/\s+/g);
463
        var states = items.filter(function (item) {
464
          return item.match(/^#/) === null;
465
        });
466
        var tags = items.filter(function (item) {
467
          return item.match(/^#/) !== null;
468
        }).map(function (tag) {
469
          return tag.replace(/^#/, "");
470
        });
471
        if (states.length !== 1) throw new Error("exactly one state required");
472
        return {
473
          state: states[0],
474
          tags: tags
475
        };
476
      });
477
478
      /*  post-process pattern  */
479
      var flags = "g"; /* ECMAScript <= 5 */
480
      try {
481
        var regexp = new RegExp("", "y");
482
        if (typeof regexp.sticky === "boolean") flags = "y"; /* ECMAScript >= 2015 */
483
      } catch (ex) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
484
        /*  no-op  */
485
      }
486
      if (typeof pattern.multiline === "boolean" && pattern.multiline) flags += "m";
487
      if (typeof pattern.dotAll === "boolean" && pattern.dotAll) flags += "s";
488
      if (typeof pattern.ignoreCase === "boolean" && pattern.ignoreCase) flags += "i";
489
      if (typeof pattern.unicode === "boolean" && pattern.unicode) flags += "u";
490
      pattern = new RegExp(pattern.source, flags);
491
492
      /*  store rule  */
493
      this._log("rule: configure rule (state: ".concat(state, ", pattern: ").concat(pattern.source, ")"));
494
      this._rules.push({
495
        state: state,
496
        pattern: pattern,
497
        action: action,
498
        name: name
499
      });
500
      return this;
501
    }
502
503
    /*  progress the line/column counter  */
504
  }, {
505
    key: "_progress",
506
    value: function _progress(from, until) {
507
      var line = this._line;
508
      var column = this._column;
509
      var s = this._input;
510
      for (var i = from; i < until; i++) {
511
        var c = s.charAt(i);
512
        if (c === "\r") this._column = 1;else if (c === "\n") {
513
          this._line++;
514
          this._column = 1;
515
        } else if (c === "\t") this._column += 8 - this._column % 8;else this._column++;
516
      }
517
      this._log("    PROGRESS: characters: ".concat(until - from, ", ") + "from: <line ".concat(line, ", column ").concat(column, ">, ") + "to: <line ".concat(this._line, ", column ").concat(this._column, ">"));
518
    }
519
520
    /*  determine and provide the next token  */
521
  }, {
522
    key: "_tokenize",
523
    value: function _tokenize() {
524
      var _this2 = this;
525
      /*  helper function for finishing parsing  */
526
      var finish = function finish() {
527
        if (!_this2._eof) {
528
          if (_this2._finish !== null) _this2._finish.call(_this2._ctx, _this2._ctx);
529
          _this2._eof = true;
530
          _this2._pending.push(new Token("EOF", "", "", _this2._pos, _this2._line, _this2._column));
531
        }
532
      };
533
534
      /*  tokenize only as long as we were not stopped and there is input left  */
535
      if (this._stopped || this._pos >= this._len) {
536
        finish();
537
        return;
538
      }
539
540
      /*  loop...  */
541
      var continued = true;
542
      while (continued) {
543
        continued = false;
544
545
        /*  some optional debugging context  */
546
        if (this._debug) {
547
          var e = excerpt(this._input, this._pos);
548
          var tags = Object.keys(this._tag).map(function (tag) {
549
            return "#".concat(tag);
550
          }).join(" ");
551
          this._log("INPUT: state: <".concat(this._state[this._state.length - 1], ">, tags: <").concat(tags, ">, text: ") + (e.prologTrunc ? "..." : "\"") + "".concat(e.prologText, "<").concat(e.tokenText, ">").concat(e.epilogText) + (e.epilogTrunc ? "..." : "\"") + ", at: <line ".concat(this._line, ", column ").concat(this._column, ">"));
552
        }
553
554
        /*  iterate over all rules...  */
555
        for (var i = 0; i < this._rules.length; i++) {
556
          if (this._debug) {
557
            var state = this._rules[i].state.map(function (item) {
558
              var output = item.state;
559
              if (item.tags.length > 0) output += " " + item.tags.map(function (tag) {
560
                return "#".concat(tag);
561
              }).join(" ");
562
              return output;
563
            }).join(", ");
564
            this._log("  RULE: state(s): <".concat(state, ">, ") + "pattern: ".concat(this._rules[i].pattern.source));
565
          }
566
567
          /*  one of rule's states (and all of its tags) has to match  */
568
          var matches = false;
569
          var states = this._rules[i].state.map(function (item) {
570
            return item.state;
571
          });
572
          var idx = states.indexOf("*");
573
          if (idx < 0) idx = states.indexOf(this._state[this._state.length - 1]);
574
          if (idx >= 0) {
575
            matches = true;
576
            var _tags = this._rules[i].state[idx].tags;
577
            _tags = _tags.filter(function (tag) {
578
              return !_this2._tag[tag];
579
            });
580
            if (_tags.length > 0) matches = false;
581
          }
582
          if (!matches) continue;
583
584
          /*  match pattern at the last position  */
585
          this._rules[i].pattern.lastIndex = this._pos;
586
          var found = this._rules[i].pattern.exec(this._input);
0 ignored issues
show
Unused Code introduced by
The assignment to variable found seems to be never used. Consider removing it.
Loading history...
587
          this._rules[i].pattern.lastIndex = this._pos;
588
          if ((found = this._rules[i].pattern.exec(this._input)) !== null && found.index === this._pos) {
589
            if (this._debug) this._log("    MATCHED: " + JSON.stringify(found));
590
591
            /*  pattern found, so give action a chance to operate
592
                on it and act according to its results  */
593
            this._ctx._match = found;
594
            this._ctx._repeat = false;
595
            this._ctx._reject = false;
596
            this._ctx._ignore = false;
597
            if (this._before !== null) this._before.call(this._ctx, this._ctx, found, this._rules[i]);
598
            this._rules[i].action.call(this._ctx, this._ctx, found);
599
            if (this._after !== null) this._after.call(this._ctx, this._ctx, found, this._rules[i]);
600
            if (this._ctx._reject) /*  reject current action, continue matching  */
601
              continue;else if (this._ctx._repeat) {
0 ignored issues
show
Unused Code introduced by
This continue has no effect on the loop flow and can be removed.
Loading history...
602
              /*  repeat matching from scratch  */
603
              continued = true;
604
              break;
605
            } else if (this._ctx._ignore) {
606
              /*  ignore token  */
607
              this._progress(this._pos, this._rules[i].pattern.lastIndex);
608
              this._pos = this._rules[i].pattern.lastIndex;
609
              if (this._pos >= this._len) {
610
                finish();
611
                return;
612
              }
613
              continued = true;
614
              break;
615
            } else if (this._pending.length > 0) {
616
              /*  accept token(s)  */
617
              this._progress(this._pos, this._rules[i].pattern.lastIndex);
618
              this._pos = this._rules[i].pattern.lastIndex;
619
              if (this._pos >= this._len) finish();
620
              return;
621
            } else throw new Error("action of pattern \"" + this._rules[i].pattern.source + "\" neither rejected nor accepted any token(s)");
622
          }
623
        }
624
      }
625
626
      /*  no pattern matched at all  */
627
      throw this.error("token not recognized");
628
    }
629
630
    /*  determine and return next token  */
631
  }, {
632
    key: "token",
633
    value: function token() {
634
      /*  if no more tokens are pending, try to determine a new one  */
635
      if (this._pending.length === 0) this._tokenize();
636
637
      /*  return now potentially pending token  */
638
      if (this._pending.length > 0) {
639
        var token = this._pending.shift();
640
        if (this._transaction.length > 0) this._transaction[0].push(token);
641
        this._log("TOKEN: ".concat(token.toString()));
642
        return token;
643
      }
644
645
      /*  no more tokens  */
646
      return null;
647
    }
648
649
    /*  determine and return all tokens  */
650
  }, {
651
    key: "tokens",
652
    value: function tokens() {
653
      var result = [];
654
      var token;
655
      while ((token = this.token()) !== null) result.push(token);
656
      return result;
657
    }
658
659
    /*  peek at the next token or token at particular offset  */
660
  }, {
661
    key: "peek",
662
    value: function peek(offset) {
663
      if (typeof offset === "undefined") offset = 0;
664
665
      /*  if no more tokens are pending, try to determine new ones  */
666
      if (offset >= this._pending.length) {
667
        if (this._pending.length === 0) this._tokenize();
668
        for (var i = 0; i < offset - this._pending.length; i++) this._tokenize();
669
      }
670
      if (offset >= this._pending.length) throw new Error("not enough tokens available for peek operation");
671
      this._log("PEEK: ".concat(this._pending[offset].toString()));
672
      return this._pending[offset];
673
    }
674
675
    /*  skip one or more tokens  */
676
  }, {
677
    key: "skip",
678
    value: function skip(len) {
679
      if (typeof len === "undefined") len = 1;
680
      for (var i = 0; i < this._pending.length + len; i++) this._tokenize();
681
      if (len > this._pending.length) throw new Error("not enough tokens available for skip operation");
682
      while (len-- > 0) this.token();
683
      return this;
684
    }
685
686
    /*  consume the current token (by expecting it to be a particular symbol)  */
687
  }, {
688
    key: "consume",
689
    value: function consume(type, value) {
690
      var _this3 = this;
691
      for (var i = 0; i < this._pending.length + 1; i++) this._tokenize();
692
      if (this._pending.length === 0) throw new Error("not enough tokens available for consume operation");
693
      var token = this.token();
694
      this._log("CONSUME: ".concat(token.toString()));
695
      var raiseError = function raiseError() {
696
        throw new ParsingError("expected: <type: ".concat(type, ", value: ").concat(JSON.stringify(value), " (").concat(_typeof(value), ")>, ") + "found: <type: ".concat(token.type, ", value: ").concat(JSON.stringify(token.value), " (").concat(_typeof(token.value), ")>"), token.pos, token.line, token.column, _this3._input);
697
      };
698
      if (arguments.length === 2 && !token.isA(type, value)) raiseError(JSON.stringify(value), _typeof(value));else if (!token.isA(type)) raiseError("*", "any");
0 ignored issues
show
Bug introduced by
The call to raiseError seems to have too many arguments starting with JSON.stringify(value).
Loading history...
699
      return token;
700
    }
701
702
    /*  open tokenization transaction  */
703
  }, {
704
    key: "begin",
705
    value: function begin() {
706
      this._log("BEGIN: level ".concat(this._transaction.length));
707
      this._transaction.unshift([]);
708
      return this;
709
    }
710
711
    /*  determine depth of still open tokenization transaction  */
712
  }, {
713
    key: "depth",
714
    value: function depth() {
715
      if (this._transaction.length === 0) throw new Error("cannot determine depth -- no active transaction");
716
      return this._transaction[0].length;
717
    }
718
719
    /*  close (successfully) tokenization transaction  */
720
  }, {
721
    key: "commit",
722
    value: function commit() {
723
      if (this._transaction.length === 0) throw new Error("cannot commit transaction -- no active transaction");
724
725
      /*  remove current transaction  */
726
      var committed = this._transaction.shift();
727
728
      /*  in case we were a nested transaction, still remember the tokens  */
729
      if (this._transaction.length > 0) this._transaction[0] = this._transaction[0].concat(committed);
730
      this._log("COMMIT: level ".concat(this._transaction.length));
731
      return this;
732
    }
733
734
    /*  close (unsuccessfully) tokenization transaction  */
735
  }, {
736
    key: "rollback",
737
    value: function rollback() {
738
      if (this._transaction.length === 0) throw new Error("cannot rollback transaction -- no active transaction");
739
740
      /*  remove current transaction  */
741
      var rolledback = this._transaction.shift();
742
743
      /*  make the tokens available again, as new pending tokens  */
744
      this._pending = rolledback.concat(this._pending);
745
      this._log("ROLLBACK: level ".concat(this._transaction.length));
746
      return this;
747
    }
748
749
    /*  execute multiple alternative callbacks  */
750
  }, {
751
    key: "alternatives",
752
    value: function alternatives() {
753
      var result = null;
754
      var depths = [];
755
      for (var _len = arguments.length, _alternatives = new Array(_len), _key = 0; _key < _len; _key++) {
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
756
        _alternatives[_key] = arguments[_key];
757
      }
758
      for (var i = 0; i < _alternatives.length; i++) {
759
        try {
760
          this.begin();
761
          result = _alternatives[i].call(this);
762
          this.commit();
763
          break;
764
        } catch (ex) {
765
          this._log("EXCEPTION: ".concat(ex.toString()));
766
          depths.push({
767
            ex: ex,
768
            depth: this.depth()
769
          });
770
          this.rollback();
771
          continue;
0 ignored issues
show
Unused Code introduced by
This continue has no effect on the loop flow and can be removed.
Loading history...
772
        }
773
      }
774
      if (result === null && depths.length > 0) {
775
        depths = depths.sort(function (a, b) {
776
          return a.depth - b.depth;
777
        });
778
        throw depths[0].ex;
779
      }
780
      return result;
781
    }
782
  }]);
783
}();
784
/*  expose the utility classes, too  */
785
Tokenizr.Token = Token;
786
Tokenizr.ParsingError = ParsingError;
787
Tokenizr.ActionContext = ActionContext;
788
789
/*  export the API class  */
790
module.exports = Tokenizr;
791
792
},{}]},{},[1])(1)
793
});
794