Skip to content

Commit

Permalink
Rewrite parser_input to not use String.substring
Browse files Browse the repository at this point in the history
Instead use RegExp.matchAsPrefix(...) - which was optimized on the bleeding edge
Dart VM to perform a sticky match.

Benchmark (bleeding edge Dart VM x64): 48xx ms -> 7xx ms (almost 7x).
  • Loading branch information
mraleph committed Nov 18, 2016
1 parent 7246fe9 commit 626137c
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 454 deletions.
33 changes: 17 additions & 16 deletions lib/src/parser/entities.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Entities {
// },
}

static final RegExp _keywordRegEx = new RegExp(r'^[_A-Za-z-][_A-Za-z0-9-]*', caseSensitive: true);
static final RegExp _keywordRegEx = new RegExp(r'[_A-Za-z-][_A-Za-z0-9-]*', caseSensitive: true);
///
/// A catch-all word, such as:
///
Expand All @@ -81,7 +81,8 @@ class Entities {
// },
}

static final _callRegExp = new RegExp(r'^([\w-]+|%|progid:[\w\.]+)\(', caseSensitive: true);
static final _callRegExp = new RegExp(r'([\w-]+|%|progid:[\w\.]+)\(', caseSensitive: true);
static final _reCallUrl = new RegExp(r'url\(', caseSensitive: false);
///
/// A function call
///
Expand All @@ -100,7 +101,7 @@ class Entities {
int index = parserInput.i;

// http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
if (parserInput.peek(new RegExp(r'^url\(', caseSensitive: false))) return null;
if (parserInput.peek(_reCallUrl)) return null;

parserInput.save();

Expand Down Expand Up @@ -199,8 +200,8 @@ class Entities {
// }
}

static final _alphaRegExp1 = new RegExp(r'^\opacity=', caseSensitive: false);
static final _alphaRegExp2 = new RegExp(r'^\d+', caseSensitive: true);
static final _alphaRegExp1 = new RegExp(r'\opacity=', caseSensitive: false);
static final _alphaRegExp2 = new RegExp(r'\d+', caseSensitive: true);
///
/// IE's alpha function
///
Expand Down Expand Up @@ -285,7 +286,7 @@ class Entities {
// }
}

static final _assignmentRegExp = new RegExp(r'^\w+(?=\s?=)', caseSensitive: false);
static final _assignmentRegExp = new RegExp(r'\w+(?=\s?=)', caseSensitive: false);
///
/// Assignments are argument entities for calls.
/// They are present in ie filter properties as shown below.
Expand Down Expand Up @@ -340,7 +341,7 @@ class Entities {
// },
}

static final _urlRegExp = new RegExp(r'''^(?:(?:\\[\(\)'"])|[^\(\)'"])+''', caseSensitive: true);
static final _urlRegExp = new RegExp(r'''(?:(?:\\[\(\)'"])|[^\(\)'"])+''', caseSensitive: true);
///
/// Parse url() tokens
///
Expand Down Expand Up @@ -395,7 +396,7 @@ class Entities {
// },
}

static final _variableRegExp = new RegExp(r'^@@?[\w-]+', caseSensitive: true);
static final _variableRegExp = new RegExp(r'@@?[\w-]+', caseSensitive: true);
///
/// A Variable entity, such as `@fink`, in
///
Expand Down Expand Up @@ -424,7 +425,7 @@ class Entities {
// }
}

static final _variableCurlyRegExp = new RegExp(r'^@\{([\w-]+)\}', caseSensitive: true);
static final _variableCurlyRegExp = new RegExp(r'@\{([\w-]+)\}', caseSensitive: true);
///
/// A variable entity using the protective {} e.g. @{var}
///
Expand All @@ -447,9 +448,9 @@ class Entities {
// }
}

static final _colorRegExp1 = new RegExp(r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})', caseSensitive: true);
static final _colorRegExp1 = new RegExp(r'#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})', caseSensitive: true);

static final _colorRegExp2 = new RegExp(r'^#([\w]+).*');
static final _colorRegExp2 = new RegExp(r'#([\w]+).*');
static final _colorRegExp3 = new RegExp(r'^[A-Fa-f0-9]+$');

///
Expand All @@ -463,11 +464,11 @@ class Entities {
Match rgb;

if (parserInput.currentChar() == '#'
&& (rgb = parserInput.$reMatchRegExp(_colorRegExp1)) != null) {
&& (rgb = parserInput.$reMatch(_colorRegExp1)) != null) {

// strip colons, brackets, whitespaces and other characters that should not
// definitely be part of color string
Match colorCandidateMatch = _colorRegExp2.firstMatch(rgb.input);
Match colorCandidateMatch = _colorRegExp2.matchAsPrefix(rgb.input, rgb.start);
String colorCandidateString = colorCandidateMatch[1];

// verify if candidate consists only of allowed HEX characters
Expand Down Expand Up @@ -495,7 +496,7 @@ class Entities {
// },
}

static final _dimensionRegExp = new RegExp(r'^([+-]?\d*\.?\d+)(%|[a-z]+)?', caseSensitive: false);
static final _dimensionRegExp = new RegExp(r'([+-]?\d*\.?\d+)(%|[a-z]+)?', caseSensitive: false);
///
/// A Dimension, that is, a number and a unit
///
Expand All @@ -521,7 +522,7 @@ class Entities {
// }
}

static final _unicodeDescriptorRegExp = new RegExp(r'^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?', caseSensitive: true);
static final _unicodeDescriptorRegExp = new RegExp(r'U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?', caseSensitive: true);

///
/// A unicode descriptor, as is used in unicode-range
Expand All @@ -545,7 +546,7 @@ class Entities {
// }
}

static final _javascriptRegExp = new RegExp(r'^[^`]*`', caseSensitive: true);
static final _javascriptRegExp = new RegExp(r'[^`]*`', caseSensitive: true);

///
/// JavaScript code to be evaluated
Expand Down
7 changes: 4 additions & 3 deletions lib/src/parser/mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Mixin {
}


static final _callRegExp = new RegExp(r'^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+', caseSensitive: true);
static final _callRegExp = new RegExp(r'[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+', caseSensitive: true);

///
/// A Mixin call, with an optional argument list
Expand Down Expand Up @@ -337,7 +337,7 @@ class Mixin {
// },
}

static final _definitionRegExp = new RegExp(r'^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(', caseSensitive: true);
static final _definitionRegExp = new RegExp(r'([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(', caseSensitive: true);

///
/// A Mixin definition, with a list of parameters
Expand All @@ -358,6 +358,7 @@ class Mixin {
/// Once we've got our params list, and a closing `)`, we parse
/// the `{...}` block.
///
static final _reDefinition = new RegExp(r'[^{]*\}');
MixinDefinition definition() {
Condition cond;
int index = parserInput.i; //not in original
Expand All @@ -366,7 +367,7 @@ class Mixin {
List<Node> ruleset;
bool variadic = false;

if ((parserInput.currentChar() != '.' && parserInput.currentChar() != '#') || parserInput.peek(new RegExp(r'^[^{]*\}'))) return null;
if ((parserInput.currentChar() != '.' && parserInput.currentChar() != '#') || parserInput.peek(_reDefinition)) return null;

parserInput.save();

Expand Down
Loading

0 comments on commit 626137c

Please sign in to comment.