Skip to content

Commit

Permalink
hacky tokenizer is much simpler
Browse files Browse the repository at this point in the history
  • Loading branch information
James Halliday committed May 13, 2013
1 parent d6d6416 commit 7e91b18
Showing 1 changed file with 35 additions and 39 deletions.
74 changes: 35 additions & 39 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,27 @@ var CONTROL = '(?:' + [
].join('|') + ')';
var META = '|&;()<> \\t';

exports.parse = function parse (s, env) {
var TOKEN = '';
for (var i = 0; i < 4; i++) {
TOKEN += (Math.pow(16,8)*Math.random()).toString(16);
}

exports.parse = function (s, env) {
var mapped = parse(s, env);
if (typeof env !== 'function') return mapped;
return mapped.reduce(function (acc, s) {
var xs = s.split(RegExp('(' + TOKEN + '.*?' + TOKEN + ')', 'g'));
if (xs.length === 1) return acc.concat(xs[0]);
return acc.concat(xs.filter(Boolean).map(function (x) {
if (RegExp('^' + TOKEN).test(x)) {
return JSON.parse(x.split(TOKEN)[1]);
}
else return x;
}));
}, []);
};

function parse (s, env) {
var chunker = new RegExp([
'([\'"])((\\\\\\1|[^\\1])*?)\\1', // quotes
'(\\\\[' + META + ']|[^\\s' + META + '])+', // barewords
Expand All @@ -29,49 +49,19 @@ exports.parse = function parse (s, env) {
var match = s.match(chunker);
if (!match) return [];
if (!env) env = {};
return [].concat.apply([], match.map(function (s) {
return match.map(function (s) {
if (/^'/.test(s)) {
return s
.replace(/^'|'$/g, '')
.replace(/\\(["'\\$`(){}!#&*|])/g, '$1')
;
}
else if (/^"/.test(s) && typeof env === 'function') {
var res = [];
s = s.replace(/^"|"$/g, '');

var begin = 0, bracket = false;
for (var i = 0; i < s.length; i++) {
if (s.charAt(i) !== '$' || s.charAt(i-1) === '\\') continue;
if (s.charAt(i+1) === '{') {
i ++;
bracket = true;
}
if (/^[*@#?$!0_-]$/.test(s.charAt(i+1))
&& (!bracket || (bracket && s.charAt(i+2) === '}'))) {
res.push(s.slice(begin, i));
var r = env(s.charAt(i+1));
if (typeof r === 'object') res.push(r);
else res[res.length-1] += r;
i ++;
if (bracket) i++;
begin = i + 1;
continue;
}
for (var j=i+1; j < s.length && /\w/.test(s.charAt(j)); j++);
if (j-(i+1) > 1) {
res.push(s.slice(begin, i));
var r = env(s.slice(i+1, j));
if (typeof r === 'object') res.push(r);
else res[res.length-1] += r;
begin = j;
}
}
res.push(s.slice(begin));
return res.map(function (c) {
if (typeof c === 'object') return c;
return c.replace(/\\([ "'\\$`(){}!#&*|])/g, '$1');
});
return s.replace(/^"|"$/g, '')
.replace(/(^|[^\\])\$(\w+|[*@#?$!0_-])/g, getVar)
.replace(/(^|[^\\])\${(\w+|[*@#?$!0_-])}/g, getVar)
.replace(/\\([ "'\\$`(){}!#&*|])/g, '$1')
;
}
else if (/^"/.test(s)) {
return s.replace(/^"|"$/g, '')
Expand All @@ -90,9 +80,15 @@ exports.parse = function parse (s, env) {
return parse('"' + s + '"', env);
}
);
}));
});

function getVar (_, pre, key) {
return pre + String(env[key] || '');
var r = typeof env === 'function' ? env(key) : env[key];
if (r === undefined) r = '';

if (typeof r === 'object') {
return pre + TOKEN + JSON.stringify(r) + TOKEN;
}
else return pre + r;
}
};

0 comments on commit 7e91b18

Please sign in to comment.