js303/bower_components/emblem/lib/preprocessor.js
2015-01-14 20:12:11 +01:00

196 lines
5.4 KiB
JavaScript

var Emblem, Preprocessor, StringScanner;
StringScanner = require('StringScanner');
Emblem = require('./emblem');
Emblem.Preprocessor = Preprocessor = (function() {
var DEDENT, INDENT, TERM, UNMATCHED_DEDENT, anyWhitespaceAndNewlinesTouchingEOF, any_whitespaceFollowedByNewlines_, processInput, ws;
ws = '\\t\\x0B\\f \\xA0\\u1680\\u180E\\u2000-\\u200A\\u202F\\u205F\\u3000\\uFEFF';
INDENT = '\uEFEF';
DEDENT = '\uEFFE';
UNMATCHED_DEDENT = '\uEFEE';
TERM = '\uEFFF';
anyWhitespaceAndNewlinesTouchingEOF = RegExp("[" + ws + "\\r?\\n]*$");
any_whitespaceFollowedByNewlines_ = RegExp("(?:[" + ws + "]*\\r?\\n)+");
function Preprocessor() {
this.base = null;
this.indents = [];
this.context = [];
this.context.peek = function() {
if (this.length) {
return this[this.length - 1];
} else {
return null;
}
};
this.context.err = function(c) {
throw new Error("Unexpected " + c);
};
this.output = '';
this.context.observe = function(c) {
var top;
top = this.peek();
switch (c) {
case INDENT:
this.push(c);
break;
case DEDENT:
if (top !== INDENT) {
this.err(c);
}
this.pop();
break;
case '\r':
if (top !== '/') {
this.err(c);
}
this.pop();
break;
case '\n':
if (top !== '/') {
this.err(c);
}
this.pop();
break;
case '/':
this.push(c);
break;
case 'end-\\':
if (top !== '\\') {
this.err(c);
}
this.pop();
break;
default:
throw new Error("undefined token observed: " + c);
}
return this;
};
if (this.StringScanner) {
this.ss = new this.StringScanner('');
} else if (Emblem.StringScanner) {
this.ss = new Emblem.StringScanner('');
} else {
this.ss = new StringScanner('');
}
}
Preprocessor.prototype.p = function(s) {
if (s) {
this.output += s;
}
return s;
};
Preprocessor.prototype.scan = function(r) {
return this.p(this.ss.scan(r));
};
Preprocessor.prototype.discard = function(r) {
return this.ss.scan(r);
};
processInput = function(isEnd) {
return function(data) {
var b, d, indent, s;
if (!isEnd) {
this.ss.concat(data);
this.discard(any_whitespaceFollowedByNewlines_);
}
while (!this.ss.eos()) {
switch (this.context.peek()) {
case null:
case INDENT:
if (this.ss.bol() || this.discard(any_whitespaceFollowedByNewlines_)) {
if (this.discard(RegExp("[" + ws + "]*\\r?\\n"))) {
this.p("" + TERM + "\n");
continue;
}
if (this.base != null) {
if ((this.discard(this.base)) == null) {
throw new Error("inconsistent base indentation");
}
} else {
b = this.discard(RegExp("[" + ws + "]*"));
this.base = RegExp("" + b);
}
if (this.indents.length === 0) {
if (this.ss.check(RegExp("[" + ws + "]+"))) {
this.p(INDENT);
this.context.observe(INDENT);
this.indents.push(this.scan(RegExp("([" + ws + "]+)")));
}
} else {
indent = this.indents[this.indents.length - 1];
if (d = this.ss.check(RegExp("(" + indent + ")"))) {
this.discard(d);
if (this.ss.check(RegExp("([" + ws + "]+)"))) {
this.p(INDENT);
this.context.observe(INDENT);
this.indents.push(d + this.scan(RegExp("([" + ws + "]+)")));
}
} else {
while (this.indents.length) {
indent = this.indents[this.indents.length - 1];
if (this.discard(RegExp("(?:" + indent + ")"))) {
break;
}
this.context.observe(DEDENT);
this.p(DEDENT);
this.indents.pop();
}
if (s = this.discard(RegExp("[" + ws + "]+"))) {
this.output = this.output.slice(0, -1);
this.output += UNMATCHED_DEDENT;
this.p(INDENT);
this.context.observe(INDENT);
this.indents.push(s);
}
}
}
}
this.scan(/[^\r\n]+/);
if (this.discard(/\r?\n/)) {
this.p("" + TERM + "\n");
}
}
}
if (isEnd) {
this.scan(anyWhitespaceAndNewlinesTouchingEOF);
while (this.context.length && INDENT === this.context.peek()) {
this.context.observe(DEDENT);
this.p(DEDENT);
}
if (this.context.length) {
throw new Error('Unclosed ' + (this.context.peek()) + ' at EOF');
}
}
};
};
Preprocessor.prototype.processData = processInput(false);
Preprocessor.prototype.processEnd = processInput(true);
Preprocessor.processSync = function(input) {
var pre;
input += "\n";
pre = new Preprocessor;
pre.processData(input);
pre.processEnd();
return pre.output;
};
return Preprocessor;
})();