peasy
Version:
an easy but powerful parser
603 lines (571 loc) • 15.7 kB
JavaScript
var exports, module, require;
(function(require, exports, module) {var ts;if (typeof window === 'object') { ts = twoside('peasy/peasy.js'), require = ts.require, exports = ts.exports, module = ts.module;} // wrap line by gulp-twoside for providing twoside module;
var Parser,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
__slice = [].slice;
exports.Parser = exports.BaseParser = Parser = (function() {
function Parser() {
var base, self;
self = this;
base = this.base = {};
this.ruleIndex = 0;
base.parse = this.parse = function(data, root, cur) {
if (root == null) {
root = self.root;
}
if (cur == null) {
cur = 0;
}
self.data = data;
self.cur = cur;
self.ruleStack = {};
self.cache = {};
return root();
};
base.rec = this.rec = function(rule) {
var tag;
tag = self.ruleIndex++;
return function() {
var cache, callStack, m, result, ruleStack, start, _base;
ruleStack = self.ruleStack;
cache = (_base = self.cache)[tag] != null ? _base[tag] : _base[tag] = {};
start = self.cur;
callStack = ruleStack[start] != null ? ruleStack[start] : ruleStack[start] = [];
if (__indexOf.call(callStack, tag) < 0) {
callStack.push(tag);
m = cache[start] != null ? cache[start] : cache[start] = [void 0, start];
while (1) {
self.cur = start;
result = rule();
if (!result) {
result = m[0];
self.cur = m[1];
break;
} else if (m[1] === self.cur) {
m[0] = result;
break;
} else {
m[0] = result;
m[1] = self.cur;
}
}
callStack.pop();
return result;
} else {
m = cache[start];
self.cur = m[1];
return m[0];
}
};
};
base.memo = this.memo = function(rule) {
var tag;
tag = self.ruleIndex++;
return (function(_this) {
return function() {
var cache, m, result, start, _base;
cache = (_base = self.cache)[tag] != null ? _base[tag] : _base[tag] = {};
start = self.cur;
m = cache[start];
if (m) {
self.cur = m[1];
return m[0];
} else {
result = rule();
self.cache[tag][start] = [result, self.cur];
return result;
}
};
})(this);
};
base.orp = this.orp = function() {
var item, items;
items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
items = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
if ((typeof item) === 'string') {
_results.push(self.literal(item));
} else {
_results.push(item);
}
}
return _results;
})();
return (function(_this) {
return function() {
var result, start, _i, _len;
start = self.cur;
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
self.cur = start;
if (result = item()) {
return result;
}
}
};
})(this);
};
base.andp = this.andp = function() {
var item, items;
items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
items = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
if ((typeof item) === 'string') {
_results.push(self.literal(item));
} else {
_results.push(item);
}
}
return _results;
})();
return function() {
var result, _i, _len;
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
if (!(result = item())) {
return;
}
}
return result;
};
};
base.notp = this.notp = function(item) {
if ((typeof item) === 'string') {
item = self.literal(item);
}
return function() {
return !item();
};
};
base.may = this.may = function(item) {
if ((typeof item) === 'string') {
item = self.literal(item);
}
return (function(_this) {
return function() {
var start, x;
start = self.cur;
if (x = item()) {
return x;
} else {
self.cur = start;
return true;
}
};
})(this);
};
base.any = this.any = function(item) {
if ((typeof item) === 'string') {
item = self.literal(item);
}
return (function(_this) {
return function() {
var result, x;
result = [];
while ((x = item())) {
result.push(x);
}
return result;
};
})(this);
};
base.some = this.some = function(item) {
if ((typeof item) === 'string') {
item = self.literal(item);
}
return function() {
var result, x;
if (!(x = item())) {
return;
}
result = [x];
while ((x = item())) {
result.push(x);
}
return result;
};
};
base.times = this.times = function(item, n) {
if ((typeof item) === 'string') {
item = self.literal(item);
}
return function() {
var i, x;
i = 0;
while (i++ < n) {
if (x = item()) {
result.push(x);
} else {
return;
}
}
return result;
};
};
base.list = this.list = function(item, separator) {
if (separator == null) {
separator = self.spaces;
}
if ((typeof item) === 'string') {
item = self.literal(item);
}
if ((typeof separator) === 'string') {
separator = self.literal(separator);
}
return function() {
var result, x;
if (!(x = item())) {
return;
}
result = [x];
while (separator() && (x = item())) {
result.push(x);
}
return result;
};
};
base.listn = this.listn = function(item, n, separator) {
if (separator == null) {
separator = self.spaces;
}
if ((typeof item) === 'string') {
item = self.literal(item);
}
if ((typeof separator) === 'string') {
separator = self.literal(separator);
}
return function() {
var i, result, x;
if (!(x = item())) {
return;
}
result = [x];
i = 1;
while (i++ < n) {
if (separator() && (x = item())) {
result.push(x);
} else {
return;
}
}
return result;
};
};
base.follow = this.follow = function(item) {
if ((typeof item) === 'string') {
item = self.literal(item);
}
return (function(_this) {
return function() {
var start, x;
start = self.cur;
x = item();
self.cur = start;
return x;
};
})(this);
};
base.literal = this.literal = function(string) {
return function() {
var len, start, stop;
len = string.length;
start = self.cur;
if (self.data.slice(start, stop = start + len) === string) {
self.cur = stop;
return true;
}
};
};
base['char'] = this['char'] = function(c) {
return function() {
if (self.data[self.cur] === c) {
self.cur++;
return c;
}
};
};
base.wrap = this.wrap = function(item, left, right) {
if (left == null) {
left = self.spaces;
}
if (right == null) {
right = self.spaces;
}
if ((typeof item) === 'string') {
item = self.literal(item);
}
return function() {
var result;
if (left() && (result = item() && right())) {
return result;
}
};
};
base.spaces = this.spaces = function() {
var c, cur, data, len;
data = self.data;
len = 0;
cur = self.cur;
while (1) {
if ((c = data[cur++]) && (c === ' ' || c === '\t')) {
len++;
} else {
break;
}
}
self.cur += len;
return len + 1;
};
base.spaces1 = this.spaces1 = function() {
var c, cur, data, len;
data = self.data;
cur = self.cur;
len = 0;
while (1) {
if ((c = data[cur++]) && (c === ' ' || c === '\t')) {
lent++;
} else {
break;
}
}
self.cur += len;
return len;
};
base.eoi = this.eoi = function() {
return self.cur === self.data.length;
};
base.identifierLetter = this.identifierLetter = function() {
var c;
c = self.data[self.cur];
if (c === '$' || c === '_' || ('a' <= c && c < 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')) {
self.cur++;
return true;
}
};
base.followIdentifierLetter = this.followIdentifierLetter = function() {
var c;
c = self.data[self.cur];
return (c === '$' || c === '_' || ('a' <= c && c < 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')) && c;
};
base.digit = this.digit = function() {
var c;
c = self.data[self.cur];
if (('0' <= c && c <= '9')) {
self.cur++;
return c;
}
};
base.letter = this.letter = function() {
var c;
c = self.data[self.cur];
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
self.cur++;
return c;
}
};
base.lower = this.lower = function() {
var c;
c = self.data[self.cur];
if (('a' <= c && c <= 'z')) {
self.cur++;
return c;
}
};
base.upper = this.upper = function() {
var c;
c = self.data[self.cur];
if (('A' <= c && c <= 'Z')) {
self.cur++;
return c;
}
};
base.identifier = this.identifier = function() {
var c, cur, data, start;
data = self.data;
start = cur = self.cur;
c = data[cur];
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c === '$' || c === '_') {
cur++;
} else {
return;
}
while (1) {
c = data[cur];
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c === '$' || c === '_') {
cur++;
} else {
break;
}
}
self.cur = cur;
return data.slice(start, cur);
};
base.number = this.number = function() {
var c, cur, data;
data = self.data;
cur = self.cur;
c = data[cur];
if (('0' <= c && c <= '9')) {
cur++;
} else {
return;
}
while (1) {
c = data[cur];
if (('0' <= c && c <= '9')) {
cur++;
} else {
break;
}
}
self.cur = cur;
return data.slice(start, cur);
};
base.string = this.string = function() {
var c, c1, cur, quote, start, text, wrap;
text = self.data;
start = cur = self.cur;
c = text[cur];
if (c === '"') {
quote = c;
wrap = '"';
} else if (c === "'") {
quote = c;
wrap = "'";
} else {
return;
}
cur++;
while (1) {
c = text[cur];
if (c === '\n' || c === '\r') {
self.error('new line is forbidden in single line string.');
} else if (c === '\\') {
c1 = text[cur + 1];
if (c1 === '\n' || c1 === '\r') {
self.error('new line is forbidden in single line string.');
} else if (!c1) {
self.error('unexpect end of input, string is not closed');
} else {
cur += 2;
}
} else if (c === quote) {
self.cur = cur + 1;
return eval(wrap + text.slice(start, +cur + 1 || 9e9) + wrap);
} else if (!c) {
self.error('new line is forbidden in string.');
} else {
cur++;
}
}
};
base.select = this.select = function(item, actions) {
var action, defaultAction;
console.log('select');
action = actions[item];
if (action) {
return action();
}
defaultAction = actions['default'] || actions[''];
if (defaultAction) {
return defaultAction();
}
};
base.selectp = this.selectp = function(item, actions) {
return function() {
var test;
test = item();
if (test) {
return self.select(actions);
}
};
};
}
return Parser;
})();
exports.debugging = false;
exports.testing = false;
exports.debug = function(message) {
if (exports.debugging) {
return console.log(message);
}
};
exports.warn = function(message) {
if (exports.debugging || exports.testing) {
return console.log(message);
}
};
/* some utilities for parsing */
exports.Charset = function(string) {
var x, _i, _len;
for (_i = 0, _len = string.length; _i < _len; _i++) {
x = string[_i];
this[x] = true;
}
return this;
};
exports.Charset.prototype.contain = function(ch) {
return this.hasOwnProperty(ch);
};
exports.charset = function(string) {
return new exports.Charset(string);
};
exports.inCharset = function(ch, chars) {
exports.warn('peasy.inCharset(char, set) is deprecated, use set.contain(char) instead.');
return chars.hasOwnProperty(ch);
};
exports.in_ = exports.inCharset;
exports.isdigit = function(c) {
return ('0' <= c && c <= '9');
};
exports.isletter = function(c) {
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
};
exports.islower = function(c) {
return ('a' <= c && c <= 'z');
};
exports.isupper = function(c) {
return ('A' <= c && c <= 'Z');
};
exports.isIdentifierLetter = function(c) {
return c === '$' || c === '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9');
};
exports.digits = '0123456789';
exports.lowers = 'abcdefghijklmnopqrstuvwxyz';
exports.uppers = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
exports.letters = exports.lowers + exports.uppers;
exports.letterDigits = exports.letterDigits;
// code from lodash.undscore.js
exports.extend = function (object) {
if (!object) {
return object;
}
for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
var iterable = arguments[argsIndex];
if (iterable) {
for (var key in iterable) {
object[key] = iterable[key];
}
}
}
return object;
}
exports.isArray = function(value) {
return value && typeof value == 'object' && typeof value.length == 'number' &&
toString.call(value) == arrayClass || false;
};
exports.isObject = function (value) {
// check if the value is the ECMAScript language type of Object
// http://es5.github.io/#x8
// and avoid a V8 bug
// http://code.google.com/p/v8/issues/detail?id=2291
return !!(value && objectTypes[typeof value]);
}
;
})(require, exports, module);// wrap line by gulp-twoside