Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Lexer refactoring.

This patch transforms lexer from module level functions that
operate with module-level variables to a normal JavaScript
object with its own state and so on. This means that we don't
need to explicitly reset variables between executions since
`new Lexer(...)` guarantees that the state will be new on every
run.

Also Lexer is an EventEmitter so we don't need to pass warningAt,
errorAt and quit functions. We just need to subscribe to the
warning, error and fatal Lexer events and call appropriate
functions from our handlers (see jshint.js for an example).
  • Loading branch information...
commit 5d32e6f1aa9955c4ff6f485b56e1fd75ec5d3c46 1 parent aafef94
@valueof valueof authored
Showing with 400 additions and 164 deletions.
  1. +21 −11 src/stable/jshint.js
  2. +379 −153 src/stable/lex.js
View
32 src/stable/jshint.js
@@ -30,12 +30,12 @@
/*jshint quotmark:double */
-var _ = require("underscore");
-var vars = require("../shared/vars.js");
+var _ = require("underscore");
+var vars = require("../shared/vars.js");
var messages = require("../shared/messages.js");
-var lex = require("./lex.js").lex;
-var reg = require("./reg.js");
-var state = require("./state.js").state;
+var Lexer = require("./lex.js").Lexer;
+var reg = require("./reg.js");
+var state = require("./state.js").state;
// We build the application inside a function so that we produce only a single
// global variable. That function will be invoked immediately, and its return
@@ -198,6 +198,7 @@ var JSHINT = (function () {
inblock,
indent,
lookahead,
+ lex,
member,
membersOnly,
noreach,
@@ -3161,12 +3162,21 @@ loop:
state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
- lex.init(s,
- { // Functions
- warningAt: warningAt,
- errorAt: errorAt,
- quit: quit
- });
+ lex = new Lexer(s);
+
+ lex.on("warning", function (ev) {
+ warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
+ });
+
+ lex.on("error", function (ev) {
+ errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
+ });
+
+ lex.on("fatal", function (ev) {
+ quit(ev.line, ev.from);
+ });
+
+ lex.start();
// Check options
for (var name in o) {
View
532 src/stable/lex.js
@@ -4,9 +4,10 @@
"use strict";
-var _ = require("underscore");
-var reg = require("./reg.js");
-var state = require("./state.js").state;
+var _ = require("underscore");
+var events = require("events");
+var reg = require("./reg.js");
+var state = require("./state.js").state;
// Helper functions
@@ -21,32 +22,29 @@ function isDigit(str) {
var Lexer = function (source) {
var lines = source;
-
+
if (typeof lines === "string") {
lines = lines
.replace(/\r\n/g, "\n")
.replace(/\r/g, "\n")
.split("\n");
}
-
+
// If the first line is a shebang (#!), make it a blank and move on.
// Shebangs are used by Node scripts.
if (lines[0] && lines[0].substr(0, 2) === "#!") {
lines[0] = "";
}
-
+
this.emitter = new events.EventEmitter();
this.source = source;
this.lines = lines;
this.line = 0;
this.character = 1;
this.input = null;
-
- this.nextLine();
-
this.from = 1;
- this.preref = true;
-
+ this.prereg = true;
+
for (var i = 0; i < state.option.indent; i += 1) {
state.tab += " ";
}
@@ -59,30 +57,44 @@ Lexer.prototype = {
this._lines = state.lines;
return this._lines;
},
-
+
set lines(val) {
this._lines = val;
state.lines = this._lines;
},
-
+
on: function (names, listener) {
names.split(" ").forEach(function (name) {
this.emitter.on(name, listener);
}.bind(this));
},
-
+
trigger: function () {
this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
},
-
+
+ start: function () {
+ this.nextLine();
+ },
+
lintName: function (name) {
if (!state.option.proto && name === "__proto__") {
- this.trigger("warning", { code: "W103", line: line, character: from, data: [ name ] });
+ this.trigger("warning", {
+ code: "W103",
+ line: this.line,
+ character: this.from,
+ data: [ name ]
+ });
return;
}
if (!state.option.iterator && name === "__iterator__") {
- this.trigger("warning", { code: "W104", line: line, character: from, data: [ name ] });
+ this.trigger("warning", {
+ code: "W104",
+ line: this.line,
+ character: this.from,
+ data: [ name ]
+ });
return;
}
@@ -100,8 +112,8 @@ Lexer.prototype = {
this.trigger("warning", {
code: "W105",
- line: line,
- character: from,
+ line: this.line,
+ character: this.from,
data: [ "dangling '_'", name ]
});
@@ -115,21 +127,21 @@ Lexer.prototype = {
if (name.replace(/^_+/, "").indexOf("_") > -1 && !name.match(/^[A-Z0-9_]*$/)) {
this.trigger("warning", {
code: "W106",
- line: line,
- character: from,
- data: [ value ]
+ line: this.line,
+ character: this.from,
+ data: [ name ]
});
}
}
},
-
+
nextLine: function () {
if (this.line >= this.lines.length) {
return false;
}
-
+
this.character = 1;
- this.input = state.lines[line];
+ this.input = this.lines[this.line];
this.line += 1;
// If smartstate.tabs option is used check for spaces followed by tabs only.
@@ -150,7 +162,7 @@ Lexer.prototype = {
if (at >= 0) {
this.trigger("warning", { code: "W099", line: this.line, character: at + 1 });
}
-
+
// Replace tabs with spaces.
this.input = this.input.replace(/\t/g, state.tab);
@@ -185,7 +197,7 @@ Lexer.prototype = {
*/
create: function (type, value) {
var token;
-
+
switch (true) {
case type === "(range)":
token = { type: type };
@@ -202,7 +214,7 @@ Lexer.prototype = {
if (type === "(string)" || type === "(range)") {
if (!state.option.scripturl && reg.javascriptURL.test(value)) {
- this.trigger("warning", { code: "W107", line: this.line, character: from });
+ this.trigger("warning", { code: "W107", line: this.line, character: this.from });
}
}
@@ -219,12 +231,12 @@ Lexer.prototype = {
var id = token.id;
if (id !== "(endline)") {
this.prereg = id && (("(,=:[!&|?{};".indexOf(id.charAt(id.length - 1)) >= 0) ||
- id === "return" || i === "case");
+ id === "return" || id === "case");
}
-
+
return token;
},
-
+
range: function (begin, end) {
var chr, value = "";
this.from = this.character;
@@ -232,9 +244,9 @@ Lexer.prototype = {
if (this.input.charAt(0) !== begin) {
this.trigger("error", {
code: "E004",
- line: line,
- character: character,
- data: [ begin, input.charAt(0) ]
+ line: this.line,
+ character: this.character,
+ data: [ begin, this.input.charAt(0) ]
});
}
@@ -245,7 +257,12 @@ Lexer.prototype = {
switch (chr) {
case "":
- this.trigger("error", { code: "E013", line: line, character: character, data: [ c ] });
+ this.trigger("error", {
+ code: "E013",
+ line: this.line,
+ character: this.character,
+ data: [ chr ]
+ });
break;
case end:
this.input = this.input.slice(1);
@@ -254,9 +271,9 @@ Lexer.prototype = {
case "\\":
this.trigger("warning", {
code: "W052",
- line: line,
- character: character,
- data: [ c ]
+ line: this.line,
+ character: this.character,
+ data: [ chr ]
});
}
@@ -272,27 +289,33 @@ Lexer.prototype = {
token: function () {
var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n;
- function match(x) {
- var r = x.exec(input), r1;
+ // This function must be bound to 'this'.
+ var match = function (x) {
+ var r = x.exec(this.input), r1;
if (r) {
l = r[0].length;
r1 = r[1];
c = r1.charAt(0);
- input = input.substr(l);
- from = character + l - r1.length;
- character += l;
+ this.input = this.input.substr(l);
+ this.from = this.character + l - r1.length;
+ this.character += l;
return r1;
}
- }
+ }.bind(this);
- function string(x) {
+ // This function must be bound to 'this'.
+ var string = function (x) { /*jshint validthis:true */
var c, j, r = "", allowNewLine = false;
// In JSON mode all strings must use double-quote.
if (state.jsonMode && x !== "\"") {
- warningAt("W108", line, character);
+ this.trigger("warning", {
+ code: "W108",
+ line: this.line,
+ character: this.character
+ });
}
// Option 'quotmark' helps you to enforce one particular
@@ -319,49 +342,67 @@ Lexer.prototype = {
}
if (code) {
- warningAt(code, line, character);
+ this.trigger("warning", {
+ code: code,
+ line: this.line,
+ character: this.character
+ });
}
}
- function esc(n) {
- var i = parseInt(input.substr(j + 1, n), 16);
+ // This function must be bound to 'this'.
+ var esc = function (n) {
+ var i = parseInt(this.input.substr(j + 1, n), 16);
j += n;
// Warn about unnecessary escapements.
if (i >= 32 && i <= 126 && i !== 34 && i !== 92 && i !== 39) {
- warningAt("W111", line, character);
+ this.trigger("warning", {
+ code: "W111",
+ line: this.line,
+ character: this.character
+ });
}
- character += n;
+ this.character += n;
c = String.fromCharCode(i);
- }
+ }.bind(this);
j = 0;
for (;;) {
- while (j >= input.length) { // What is this? j >= input.length?
+ while (j >= this.input.length) { // What is this? j >= this.input.length?
j = 0;
- var cl = line;
- var cf = from;
+ var cl = this.line;
+ var cf = this.from;
- if (!nextLine()) {
+ if (!this.nextLine()) {
// Display an error about an unclosed string.
- errorAt("E044", cl, cf);
+ this.trigger("error", {
+ code: "E044",
+ line: cl,
+ character: cf
+ });
return;
}
if (allowNewLine) {
allowNewLine = false;
} else {
- warningAt("W112", cl, cf); // Warn about an unclosed string.
+ // Warn about an unclosed string.
+ this.trigger("warning", {
+ code: "W112",
+ line: cl,
+ character: cf
+ });
}
}
- c = input.charAt(j);
+ c = this.input.charAt(j);
if (c === x) {
- character += 1;
- input = input.substr(j + 1);
+ this.character += 1;
+ this.input = this.input.substr(j + 1);
return this.create("(string)", r, x);
}
@@ -371,12 +412,17 @@ Lexer.prototype = {
}
// Warn about a control character in a string.
- warningAt("W113", line, character + j, input.slice(0, j));
+ this.trigger("warning", {
+ code: "W113",
+ line: this.line,
+ character: this.character + j,
+ data: [ this.input.slice(0, j) ]
+ });
} else if (c === "\\") {
j += 1;
- character += 1;
- c = input.charAt(j);
- n = input.charAt(j + 1);
+ this.character += 1;
+ c = this.input.charAt(j);
+ n = this.input.charAt(j + 1);
switch (c) {
case "\\":
@@ -385,7 +431,12 @@ Lexer.prototype = {
break;
case "\'":
if (state.jsonMode) {
- warningAt("W114", line, character, "\\'");
+ this.trigger("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.character,
+ data: [ "\\'" ]
+ });
}
break;
case "b":
@@ -411,7 +462,11 @@ Lexer.prototype = {
// where 'n' is the token next to 'c'
if (n >= 0 && n <= 7 && state.directive["use strict"]) {
- warningAt("W115", line, character);
+ this.trigger("warning", {
+ code: "W115",
+ line: this.line,
+ character: this.character
+ });
}
break;
@@ -420,14 +475,24 @@ Lexer.prototype = {
break;
case "v":
if (state.jsonMode) {
- warningAt("W114", line, character, "\\v");
+ this.trigger("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.character,
+ data: [ "\\v" ]
+ });
}
c = "\v";
break;
case "x":
if (state.jsonMode) {
- warningAt("W114", line, character, "\\x-");
+ this.trigger("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.character,
+ data: [ "\\x-" ]
+ });
}
esc(2);
@@ -439,36 +504,48 @@ Lexer.prototype = {
allowNewLine = true;
if (state.option.multistr) {
if (state.jsonMode) {
- warningAt("W116", line, character);
+ this.trigger("warning", {
+ code: "W116",
+ line: this.line,
+ character: this.character
+ });
}
c = "";
- character -= 1;
+ this.character -= 1;
break;
}
- warningAt("W117", line, character);
+ this.trigger("warning", {
+ code: "W117",
+ line: this.line,
+ character: this.character
+ });
break;
case "!":
- if (input.charAt(j - 2) === "<")
+ if (this.input.charAt(j - 2) === "<")
break;
/*falls through*/
default:
// Weird escapement, warn about that.
- warningAt("W118", line, character);
+ this.trigger("warning", {
+ code: "W118",
+ line: this.line,
+ character: this.character
+ });
}
}
r += c;
- character += 1;
+ this.character += 1;
j += 1;
}
- }
+ }.bind(this);
for (;;) {
- if (!input) {
- return this.create(nextLine() ? "(endline)" : "(end)", "");
+ if (!this.input) {
+ return this.create(this.nextLine() ? "(endline)" : "(end)", "");
}
t = match(reg.token);
@@ -478,14 +555,19 @@ Lexer.prototype = {
c = "";
// Reducing input for?
- while (input && input < "!") {
- input = input.substr(1);
+ while (this.input && this.input < "!") {
+ this.input = this.input.substr(1);
}
- if (input) {
+ if (this.input) {
// Unexpected character.
- errorAt("E014", line, character, input.substr(0, 1));
- input = "";
+ this.trigger("error", {
+ code: "E014",
+ line: this.line,
+ character: this.character,
+ data: [ this.input.substr(0, 1) ]
+ });
+ this.input = "";
}
} else {
@@ -502,11 +584,21 @@ Lexer.prototype = {
// Check if this number is invalid.
if (!isFinite(Number(t))) {
- warningAt("W119", line, character, t);
+ this.trigger("warning", {
+ code: "W119",
+ line: this.line,
+ character: this.character,
+ data: [ t ]
+ });
}
- if (isAlpha(input.substr(0, 1))) {
- warningAt("W013", line, character, t);
+ if (isAlpha(this.input.substr(0, 1))) {
+ this.trigger("warning", {
+ code: "W013",
+ line: this.line,
+ character: this.character,
+ data: [ t ]
+ });
}
if (c === "0") {
@@ -514,16 +606,31 @@ Lexer.prototype = {
if (isDigit(d)) {
// Check for leading zeroes.
if (state.tokens.curr.id !== ".") {
- warningAt("W120", line, character, t);
+ this.trigger("warning", {
+ code: "W120",
+ line: this.line,
+ character: this.character,
+ data: [ t ]
+ });
}
} else if (state.jsonMode && (d === "x" || d === "X")) {
- warningAt("W114", line, character, "0x-");
+ this.trigger("warning", {
+ code: "W114",
+ line: this.line,
+ character: this.character,
+ data: [ "0x-" ]
+ });
}
}
if (t.substr(t.length - 1) === ".") {
// Warn about a trailing decimal point.
- warningAt("W121", line, character, t);
+ this.trigger("warning", {
+ code: "W121",
+ line: this.line,
+ character: this.character,
+ data: [ t ]
+ });
}
return this.create("(number)", t);
@@ -540,7 +647,7 @@ Lexer.prototype = {
// Single line comment
case "//":
- input = "";
+ this.input = "";
state.tokens.curr.comment = true;
break;
@@ -548,18 +655,22 @@ Lexer.prototype = {
case "/*":
for (;;) {
- i = input.search(reg.starSlash);
+ i = this.input.search(reg.starSlash);
if (i >= 0) {
break;
}
// Is this comment unclosed?
- if (!nextLine()) {
- errorAt("E015", line, character);
+ if (!this.nextLine()) {
+ this.trigger("error", {
+ code: "E015",
+ line: this.line,
+ character: this.character
+ });
}
}
- input = input.substr(i + 2);
+ this.input = this.input.substr(i + 2);
state.tokens.curr.comment = true;
break;
@@ -574,9 +685,9 @@ Lexer.prototype = {
return {
value: t,
type: "special",
- line: line,
- character: character,
- from: from
+ line: this.line,
+ character: this.character,
+ from: this.from
};
case "":
@@ -586,30 +697,47 @@ Lexer.prototype = {
case "/":
// Warn about '/=' (it can be confused with /= operator.
- if (input.charAt(0) === "=") {
- errorAt("E016", line, from);
+ if (this.input.charAt(0) === "=") {
+ this.trigger("error", {
+ code: "E016",
+ line: this.line,
+ character: this.from
+ });
}
- if (prereg) {
+ if (this.prereg) {
depth = 0;
captures = 0;
l = 0;
for (;;) {
b = true;
- c = input.charAt(l);
+ c = this.input.charAt(l);
l += 1;
switch (c) {
case "":
// Fatal: unclosed regular expression.
- errorAt("E017", line, from);
- return quit("Stopping.", line, from);
+ this.trigger("error", {
+ code: "E017",
+ line: this.line,
+ character: this.from
+ });
+
+ return void this.trigger("fatal", {
+ line: this.line,
+ from: this.from
+ });
case "/":
// Check that all regexp groups were terminated.
if (depth > 0) {
- warningAt("W122", line, from + l, depth);
+ this.trigger("warning", {
+ code: "W122",
+ line: this.line,
+ character: this.from + l,
+ data: [ depth ]
+ });
}
- c = input.substr(0, l - 1);
+ c = this.input.substr(0, l - 1);
q = {
g: true,
@@ -617,29 +745,42 @@ Lexer.prototype = {
m: true
};
- while (q[input.charAt(l)] === true) {
- q[input.charAt(l)] = false;
+ while (q[this.input.charAt(l)] === true) {
+ q[this.input.charAt(l)] = false;
l += 1;
}
- character += l;
- input = input.substr(l);
- q = input.charAt(0);
+ this.character += l;
+ this.input = this.input.substr(l);
+ q = this.input.charAt(0);
if (q === "/" || q === "*") {
- errorAt("E018", line, from);
+ this.trigger("error", {
+ code: "E018",
+ line: this.line,
+ character: this.from
+ });
}
return this.create("(regexp)", c);
case "\\":
- c = input.charAt(l);
+ c = this.input.charAt(l);
if (c < " ") {
// Unexpected control character.
- warningAt("W123", line, from + l);
+ this.trigger("warning", {
+ code: "W123",
+ line: this.line,
+ character: this.from + l
+ });
} else if (c === "<") {
// Unexpected escaped character.
- warningAt("W124", line, from + l, c);
+ this.trigger("warning", {
+ code: "W124",
+ line: this.line,
+ character: this.from + l,
+ data: [ c ]
+ });
}
l += 1;
@@ -647,16 +788,21 @@ Lexer.prototype = {
case "(":
depth += 1;
b = false;
- if (input.charAt(l) === "?") {
+ if (this.input.charAt(l) === "?") {
l += 1;
- switch (input.charAt(l)) {
+ switch (this.input.charAt(l)) {
case ":":
case "=":
case "!":
l += 1;
break;
default:
- warningAt("W132", line, from + l, ":", input.charAt(l));
+ this.trigger("warning", {
+ code: "W132",
+ line: this.line,
+ character: this.from + l,
+ data: [ ":", this.input.charAt(l) ]
+ });
}
} else {
captures += 1;
@@ -668,42 +814,66 @@ Lexer.prototype = {
case ")":
if (depth === 0) {
// Warn about unexpected paren.
- warningAt("W125", line, from + l, ")");
+ this.trigger("warning", {
+ code: "W125",
+ line: this.line,
+ character: this.from + l,
+ data: [ ")" ]
+ });
} else {
depth -= 1;
}
break;
case " ":
q = 1;
- while (input.charAt(l) === " ") {
+ while (this.input.charAt(l) === " ") {
l += 1;
q += 1;
}
if (q > 1) {
- warningAt("W126", line, from + l, q);
+ this.trigger("warning", {
+ code: "W126",
+ line: this.line,
+ character: this.from + l,
+ data: [ q ]
+ });
}
break;
case "[":
- c = input.charAt(l);
+ c = this.input.charAt(l);
if (c === "^") {
l += 1;
- if (input.charAt(l) === "]") {
- errorAt("E019", line, from + l, "^");
+ if (this.input.charAt(l) === "]") {
+ this.trigger("error", {
+ code: "E019",
+ line: this.line,
+ character: this.from + l,
+ data: [ "^" ]
+ });
}
}
if (c === "]") {
- warningAt("W127", line, from + l - 1);
+ this.trigger("warning", {
+ code: "W127",
+ line: this.line,
+ character: this.from + l - 1
+ });
}
isLiteral = false;
isInRange = false;
klass:
do {
- c = input.charAt(l);
+ c = this.input.charAt(l);
l += 1;
switch (c) {
case "[":
case "^":
- warningAt("W125", line, from + l, c);
+ this.trigger("warning", {
+ code: "W125",
+ line: this.line,
+ character: this.from + l,
+ data: [ c ]
+ });
if (isInRange) {
isInRange = false;
@@ -718,28 +888,47 @@ klass:
isInRange = true;
} else if (isInRange) {
isInRange = false;
- } else if (input.charAt(l) === "]") {
+ } else if (this.input.charAt(l) === "]") {
isInRange = true;
} else {
if (state.option.regexdash !== (l === 2 || (l === 3 &&
- input.charAt(1) === "^"))) {
- warningAt("W125", line, from + l - 1, "-");
+ this.input.charAt(1) === "^"))) {
+ this.trigger("warning", {
+ code: "W125",
+ line: this.line,
+ character: this.from + l - 1,
+ data: [ "-" ]
+ });
}
isLiteral = true;
}
break;
case "]":
if (isInRange && !state.option.regexdash) {
- warningAt("W125", line, from + l - 1, "-");
+ this.trigger("warning", {
+ code: "W125",
+ line: this.line,
+ character: this.from + l - 1,
+ data: [ "-" ]
+ });
}
break klass;
case "\\":
- c = input.charAt(l);
+ c = this.input.charAt(l);
if (c < " ") {
- warningAt("W123", line, from + l);
+ this.trigger("warning", {
+ code: "W123",
+ line: this.line,
+ character: this.from + l
+ });
} else if (c === "<") {
- warningAt("W124", line, from + l, c);
+ this.trigger("warning", {
+ code: "W124",
+ line: this.line,
+ character: this.from + l,
+ data: [ c ]
+ });
}
l += 1;
@@ -747,7 +936,12 @@ klass:
// \w, \s and \d are never part of a character range
if (/[wsd]/i.test(c)) {
if (isInRange) {
- warningAt("W125", line, from + l, "-");
+ this.trigger("warning", {
+ code: "W125",
+ line: this.line,
+ character: this.from + l,
+ data: [ "-" ]
+ });
isInRange = false;
}
isLiteral = false;
@@ -758,7 +952,12 @@ klass:
}
break;
case "/":
- warningAt("W128", line, from + l - 1, "/");
+ this.trigger("warning", {
+ code: "W128",
+ line: this.line,
+ character: this.from + l - 1,
+ data: [ "/" ]
+ });
if (isInRange) {
isInRange = false;
@@ -785,7 +984,12 @@ klass:
break;
case ".":
if (state.option.regexp) {
- warningAt("W129", line, from + l, c);
+ this.trigger("warning", {
+ code: "W129",
+ line: this.line,
+ character: this.from + l,
+ data: [ c ]
+ });
}
break;
case "]":
@@ -794,30 +998,40 @@ klass:
case "}":
case "+":
case "*":
- warningAt("W125", line, from + l, c);
+ this.trigger("warning", {
+ code: "W125",
+ line: this.line,
+ character: this.from + l,
+ data: [ c ]
+ });
}
if (b) {
- switch (input.charAt(l)) {
+ switch (this.input.charAt(l)) {
case "?":
case "+":
case "*":
l += 1;
- if (input.charAt(l) === "?") {
+ if (this.input.charAt(l) === "?") {
l += 1;
}
break;
case "{":
l += 1;
- c = input.charAt(l);
+ c = this.input.charAt(l);
if (c < "0" || c > "9") {
- warningAt("W130", line, from + l, c);
+ this.trigger("warning", {
+ code: "W130",
+ line: this.line,
+ character: this.from + l,
+ data: [ c ]
+ });
break; // No reason to continue checking numbers.
}
l += 1;
low = +c;
for (;;) {
- c = input.charAt(l);
+ c = this.input.charAt(l);
if (c < "0" || c > "9") {
break;
}
@@ -828,12 +1042,12 @@ klass:
if (c === ",") {
l += 1;
high = Infinity;
- c = input.charAt(l);
+ c = this.input.charAt(l);
if (c >= "0" && c <= "9") {
l += 1;
high = +c;
for (;;) {
- c = input.charAt(l);
+ c = this.input.charAt(l);
if (c < "0" || c > "9") {
break;
}
@@ -842,23 +1056,33 @@ klass:
}
}
}
- if (input.charAt(l) !== "}") {
- warningAt("W132", line, from + l, "}", c);
+ if (this.input.charAt(l) !== "}") {
+ this.trigger("warning", {
+ code: "W132",
+ line: this.line,
+ character: this.from + l,
+ data: [ "}", c ]
+ });
} else {
l += 1;
}
- if (input.charAt(l) === "?") {
+ if (this.input.charAt(l) === "?") {
l += 1;
}
if (low > high) {
- warningAt("W131", line, from + l, low, high);
+ this.trigger("warning", {
+ code: "W131",
+ line: this.line,
+ character: this.from + l,
+ data: [ low, high ]
+ });
}
}
}
}
- c = input.substr(0, l - 1);
- character += l;
- input = input.substr(l);
+ c = this.input.substr(0, l - 1);
+ this.character += l;
+ this.input = this.input.substr(l);
return this.create("(regexp)", c);
}
return this.create("(punctuator)", t);
@@ -872,5 +1096,7 @@ klass:
}
}
}
- }
-};
+ }
+};
+
+exports.Lexer = Lexer;
Please sign in to comment.
Something went wrong with that request. Please try again.