Skip to content

Instantly share code, notes, and snippets.

@gmac
Last active December 17, 2015 17:28
Show Gist options
  • Save gmac/5645879 to your computer and use it in GitHub Desktop.
Save gmac/5645879 to your computer and use it in GitHub Desktop.
Simple lexical analysis for a JavaScript expression. Written as a prototype for pre-parsing JavaScript bindings (Epoxy.js). Will alphabetically sort the order of object property lists while removing all non-string whitespace. Example expression: 'text: all("a", "x", "c"), css:{fontWeight:"bold", color:["#f00, \\"#fee", "#00f"]}, html:firstName'
function parseBindings(bindings, sorted) {
var attrs = [];
var token = '';
bindings += ',';
for (var i = 0, len = bindings.length; i < len; i++) {
var c = bindings.charAt(i);
// Comma: chunk off tokens at list delimiter.
if (c == ',') {
attrs.push(token);
token = '';
continue;
}
// Space: skip whitespace.
if (c == ' ') {
continue;
}
// String: open at quote character, close at unescaped match.
if (c == "'" || c == '"') {
var string = '';
for (i = i+1; i < len; i++) {
var q = bindings.charAt(i);
if (q == c) break;
if (q == '\\') q = bindings.charAt(i+=1);
string += q;
}
c = c + string + c;
}
// Block: chunk out block scope and parse it.
else if (c == '{' || c == '[' || c == '(') {
var opener = c;
var closer = c == '{' ? '}' : c == '[' ? ']' : ')';
var io = i;
var ic = i;
while (io >= i && io <= ic) {
io = bindings.indexOf(opener, io+1);
ic = bindings.indexOf(closer, ic+1);
}
c = opener + parseBindings(bindings.slice(i+1, ic), c == '{') + closer;
i = ic;
}
token += c;
}
if (sorted) attrs.sort();
return attrs.join(',');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment