From f8de5bcb16aea8682409e3ab261cc14ef77ecd40 Mon Sep 17 00:00:00 2001 From: Luke Page Date: Sun, 15 Mar 2015 10:24:41 +0000 Subject: [PATCH] replace simple regex's with simple string comparisons --- lib/less/parser/parser-input.js | 60 ++++++++------------------------- lib/less/parser/parser.js | 20 ++++++----- 2 files changed, 25 insertions(+), 55 deletions(-) diff --git a/lib/less/parser/parser-input.js b/lib/less/parser/parser-input.js index e7990681..db35f34f 100644 --- a/lib/less/parser/parser-input.js +++ b/lib/less/parser/parser-input.js @@ -29,56 +29,11 @@ module.exports = function() { parserInput.forget = function() { saveStack.pop(); }; - function sync() { - if (parserInput.i > currentPos) { - current = current.slice(parserInput.i - currentPos); - currentPos = parserInput.i; - } - } parserInput.isWhitespace = function (offset) { var pos = parserInput.i + (offset || 0), code = input.charCodeAt(pos); return (code === CHARCODE_SPACE || code === CHARCODE_CR || code === CHARCODE_TAB || code === CHARCODE_LF); }; - // - // Parse from a token, regexp or string, and move forward if match - // - parserInput.$ = function(tok) { - var tokType = typeof tok, - match, length; - - // Either match a single character in the input, - // or match a regexp in the current chunk (`current`). - // - if (tokType === "string") { - if (input.charAt(parserInput.i) !== tok) { - return null; - } - skipWhitespace(1); - return tok; - } - - // regexp - sync(); - if (! (match = tok.exec(current))) { - return null; - } - - length = match[0].length; - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - skipWhitespace(length); - - if (typeof match === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - }; // Specialization of $(tok) parserInput.$re = function(tok) { @@ -86,6 +41,7 @@ module.exports = function() { current = current.slice(parserInput.i - currentPos); currentPos = parserInput.i; } + var m = tok.exec(current); if (!m) { return null; @@ -99,7 +55,6 @@ module.exports = function() { return m.length === 1 ? m[0] : m; }; - // Specialization of $(tok) parserInput.$char = function(tok) { if (input.charAt(parserInput.i) !== tok) { return null; @@ -108,6 +63,19 @@ module.exports = function() { return tok; }; + parserInput.$str = function(tok) { + var tokLength = tok.length; + + for (var i = 0; i < tokLength; i++) { + if (input.charAt(parserInput.i + i) !== tok.charAt(i)) { + return null; + } + } + + skipWhitespace(tokLength); + return tok; + }; + var CHARCODE_SPACE = 32, CHARCODE_TAB = 9, CHARCODE_LF = 10, diff --git a/lib/less/parser/parser.js b/lib/less/parser/parser.js index 1c292ab6..c363b188 100644 --- a/lib/less/parser/parser.js +++ b/lib/less/parser/parser.js @@ -43,7 +43,7 @@ var Parser = function Parser(context, imports, fileInfo) { function expect(arg, msg, index) { // some older browsers return typeof 'function' for RegExp - var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : parserInput.$(arg); + var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : parserInput.$re(arg); if (result) { return result; } @@ -411,7 +411,7 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.autoCommentAbsorb = false; - if (parserInput.currentChar() !== 'u' || !parserInput.$re(/^url\(/)) { + if (!parserInput.$str("url(")) { parserInput.autoCommentAbsorb = true; return; } @@ -549,7 +549,9 @@ var Parser = function Parser(context, imports, fileInfo) { extend: function(isRule) { var elements, e, index = parserInput.i, option, extendList, extend; - if (!(isRule ? parserInput.$re(/^&:extend\(/) : parserInput.$re(/^:extend\(/))) { return; } + if (!parserInput.$str(isRule ? "&:extend(" : ":extend(")) { + return; + } do { option = null; @@ -811,7 +813,7 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.commentStore.length = 0; - if (parserInput.$re(/^when/)) { // Guard + if (parserInput.$str("when")) { // Guard cond = expect(parsers.conditions, 'expected condition'); } @@ -960,7 +962,7 @@ var Parser = function Parser(context, imports, fileInfo) { selector: function (isLess) { var index = parserInput.i, elements, extendList, c, e, allExtends, when, condition; - while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$re(/^when/))) || (e = this.element())) { + while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str("when"))) || (e = this.element())) { if (when) { condition = expect(this.conditions, 'expected condition'); } else if (condition) { @@ -1165,7 +1167,7 @@ var Parser = function Parser(context, imports, fileInfo) { if ((path = this.entities.quoted() || this.entities.url())) { features = this.mediaFeatures(); - if (!parserInput.$(';')) { + if (!parserInput.$char(';')) { parserInput.i = index; error("missing semi-colon or unrecognised media features on import"); } @@ -1273,7 +1275,7 @@ var Parser = function Parser(context, imports, fileInfo) { debugInfo = getDebugInfo(parserInput.i); } - if (parserInput.$re(/^@media/)) { + if (parserInput.$str("@media")) { features = this.mediaFeatures(); rules = this.block(); @@ -1511,7 +1513,7 @@ var Parser = function Parser(context, imports, fileInfo) { var entities = this.entities, index = parserInput.i, negate = false, a, b, c, op; - if (parserInput.$re(/^not/)) { negate = true; } + if (parserInput.$str("not")) { negate = true; } expectChar('('); a = this.addition() || entities.keyword() || entities.quoted(); if (a) { @@ -1527,7 +1529,7 @@ var Parser = function Parser(context, imports, fileInfo) { c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); } expectChar(')'); - return parserInput.$re(/^and/) ? new(tree.Condition)('and', c, this.condition()) : c; + return parserInput.$str("and") ? new(tree.Condition)('and', c, this.condition()) : c; } },