Files
recentrunes/recentrunes.js

395 lines
8.3 KiB
JavaScript
Raw Normal View History

2014-05-20 11:46:57 -07:00
var rr = {};
2014-05-20 16:40:35 -07:00
2014-05-20 11:46:57 -07:00
rr.Literal_ = function(value) {
2014-05-20 12:49:30 -07:00
this.value_ = value;
};
2014-06-26 19:41:23 -07:00
rr.Literal_.prototype.match = function(context) {
if (context.stringAfter(this.value_.length) == this.value_) {
context.advance(this.value_.length);
return [];
2014-05-20 12:49:30 -07:00
} else {
return null;
}
};
2014-06-26 19:41:23 -07:00
rr.Literal_.prototype.search = function(context) {
console.log(context.stringAfter());
var index = context.stringAfter().indexOf(this.value_);
2014-05-20 12:49:30 -07:00
if (index == -1) {
return null;
} else {
return index;
}
2014-05-20 11:46:57 -07:00
};
rr.Literal = function(value) {
return (rr.Literal.cache[value] ||
(rr.Literal.cache[value] = new rr.Literal_(value)));
};
rr.Literal.cache = {};
2014-05-20 16:40:35 -07:00
2014-05-20 11:46:57 -07:00
rr.Ref_ = function(key) {
2014-05-20 12:49:30 -07:00
this.key_ = key;
2014-05-20 11:46:57 -07:00
};
2014-05-20 16:40:35 -07:00
rr.Ref_.prototype.minimize = function(parser) {
return parser.minimize(this.key_);
};
2014-06-26 19:41:23 -07:00
rr.Ref_.prototype.match = function(context) {
return context.parser.parse(this.key_, context);
2014-05-20 16:40:35 -07:00
};
2014-05-20 11:46:57 -07:00
rr.Ref = function(key) {
return (rr.Ref.cache[key] ||
(rr.Ref.cache[key] = new rr.Ref_(key)));
};
rr.Ref.cache = {};
2014-05-20 16:40:35 -07:00
2014-05-20 11:46:57 -07:00
rr.EndOfLine_ = function() {
};
2014-06-26 19:41:23 -07:00
rr.EndOfLine_.prototype.match = function(context) {
if (context.atEnd()) {
return [];
2014-05-20 16:40:35 -07:00
}
2014-06-26 19:41:23 -07:00
if (context.stringAfter(1) == '\n') {
context.advance(1);
return [];
2014-05-20 16:40:35 -07:00
}
2014-06-26 19:41:23 -07:00
if (context.stringBefore(1) == '\n') {
return [];
2014-05-20 16:40:35 -07:00
}
return null;
};
2014-06-26 19:41:23 -07:00
rr.EndOfLine_.prototype.search = function(context) {
if (context.atEnd()) {
2014-05-20 16:40:35 -07:00
return 0;
}
2014-06-26 19:41:23 -07:00
var loc = context.stringAfter().indexOf('\n');
2014-05-20 16:40:35 -07:00
if (loc == -1) {
2014-06-26 19:41:23 -07:00
return context.remaining();
2014-05-20 16:40:35 -07:00
} else {
return loc;
}
};
2014-05-20 11:46:57 -07:00
rr.EndOfLine = function() {
return rr.EndOfLine.cache;
2014-05-20 16:40:35 -07:00
};
2014-05-20 11:46:57 -07:00
rr.EndOfLine.cache = new rr.EndOfLine_();
2014-05-20 16:40:35 -07:00
rr.EndOfText_ = function() {
};
2014-06-26 19:41:23 -07:00
rr.EndOfText_.prototype.match = function(context) {
if (context.atEnd()) {
2014-05-20 16:40:35 -07:00
return null;
} else {
2014-06-26 19:41:23 -07:00
return [];
2014-05-20 16:40:35 -07:00
}
};
2014-06-26 19:41:23 -07:00
rr.EndOfText_.prototype.search = function(context) {
return context.remaining();
2014-05-20 16:40:35 -07:00
};
rr.EndOfText = function() {
return rr.EndOfText.cache;
};
rr.EndOfText.cache = new rr.EndOfText_();
2014-05-20 11:46:57 -07:00
rr.MultiLineText_ = function() {
};
2014-05-20 16:40:35 -07:00
rr.MultiLineText_.prototype.minimize = function() {
return true;
};
2014-06-26 19:41:23 -07:00
rr.MultiLineText_.prototype.match = function(context) {
var ret = [document.createTextNode(context.stringAfter())];
context.advance(context.remaining());
return ret;
2014-05-20 16:40:35 -07:00
};
2014-05-20 12:49:30 -07:00
2014-05-20 11:46:57 -07:00
rr.MultiLineText = function() {
return rr.MultiLineText.cache;
};
rr.MultiLineText.cache = new rr.MultiLineText_();
2014-05-20 16:40:35 -07:00
2014-05-20 11:46:57 -07:00
rr.Or_ = function(options) {
2014-05-20 12:49:30 -07:00
this.options_ = options;
2014-05-20 11:46:57 -07:00
};
2014-05-20 16:40:35 -07:00
rr.Or_.prototype.minimize = function(parser) {
for (var i = 0; i < this.options_.length; i++) {
var option = this.options_[i];
if (parser.minimize(option)) {
return true;
2014-06-26 19:41:23 -07:00
}
2014-05-20 16:40:35 -07:00
}
return false;
};
2014-06-26 19:41:23 -07:00
rr.Or_.prototype.match = function(context) {
2014-05-20 16:40:35 -07:00
for (var i = 0; i < this.options_.length; i++) {
var option = this.options_[i];
2014-06-26 19:41:23 -07:00
var result = context.parser.parse(option, context);
2014-05-20 16:40:35 -07:00
if (result) {
return result;
}
}
return null;
};
2014-05-20 11:46:57 -07:00
rr.Or = function() {
return new rr.Or_(arguments);
};
2014-05-20 16:40:35 -07:00
2014-05-20 11:46:57 -07:00
rr.SingleLineText_ = function() {
};
2014-05-20 16:40:35 -07:00
rr.SingleLineText_.prototype.minimize = function() {
return true;
}
2014-05-20 12:49:30 -07:00
2014-06-26 19:41:23 -07:00
rr.SingleLineText_.prototype.match = function(context) {
var newLine = context.stringAfter().indexOf('\n');
2014-05-20 12:49:30 -07:00
if (newLine == -1) {
2014-06-26 19:41:23 -07:00
newLine = context.remaining();
2014-05-20 12:49:30 -07:00
}
2014-06-26 19:41:23 -07:00
var ret = [document.createTextNode(context.stringAfter(newLine))];
context.advance(newLine);
return ret;
2014-05-20 12:49:30 -07:00
};
2014-05-20 11:46:57 -07:00
rr.SingleLineText = function() {
return rr.SingleLineText.cache;
};
rr.SingleLineText.cache = new rr.SingleLineText_();
2014-05-20 16:40:35 -07:00
2014-05-20 11:46:57 -07:00
rr.StartOfLine_ = function() {
};
2014-06-26 19:41:23 -07:00
rr.StartOfLine_.prototype.match = function(context) {
if (context.atStart()) {
return [];
2014-05-20 16:40:35 -07:00
}
2014-06-26 19:41:23 -07:00
if (context.stringAfter(1) == '\n') {
context.advance(1);
return [];
2014-05-20 16:40:35 -07:00
}
2014-06-26 19:41:23 -07:00
if (context.stringBefore(1) == '\n') {
return [];
2014-05-20 16:40:35 -07:00
}
return null;
};
2014-06-26 19:41:23 -07:00
rr.StartOfLine_.prototype.search = function(context) {
if (context.atStart()) {
2014-05-20 16:40:35 -07:00
return 0;
}
2014-06-26 19:41:23 -07:00
var loc = context.stringAfter().indexOf('\n');
2014-05-20 16:40:35 -07:00
if (loc == -1) {
return null;
}
return loc + 1;
};
2014-05-20 11:46:57 -07:00
rr.StartOfLine = function() {
return rr.StartOfLine.cache;
};
rr.StartOfLine.cache = new rr.StartOfLine_();
2014-05-20 12:49:30 -07:00
2014-05-20 16:40:35 -07:00
rr.ZeroOrMore_ = function(key) {
this.key_ = key;
2014-05-20 11:46:57 -07:00
};
2014-05-20 16:40:35 -07:00
rr.ZeroOrMore_.prototype.minimize = function(parser) {
return parser.minimize(this.key_);
};
2014-05-20 11:46:57 -07:00
2014-06-26 19:41:23 -07:00
rr.ZeroOrMore_.prototype.match = function(context) {
var ret = [];
while (context.inputIndex < context.input.length) {
var result = context.parser.parse(this.key_, context);
2014-05-20 16:40:35 -07:00
if (!result) {
break;
}
2014-06-26 19:41:23 -07:00
result.forEach(function(child) {
ret.push(child);
});
2014-05-20 16:40:35 -07:00
};
2014-06-26 19:41:23 -07:00
return ret;
2014-05-20 11:46:57 -07:00
};
rr.ZeroOrMore = function(key) {
return (rr.ZeroOrMore.cache[key] ||
(rr.ZeroOrMore.cache[key] = new rr.ZeroOrMore_(key)));
};
rr.ZeroOrMore.cache = {};
2014-06-26 19:41:23 -07:00
rr.Context = function(parser, input, inputIndex) {
this.parser = parser;
this.input = input;
this.inputIndex = inputIndex || 0;
};
rr.Context.prototype.copy = function() {
return new rr.Context(this.parser, this.input, this.inputIndex);
};
rr.Context.prototype.truncate = function(numChars) {
this.input = this.input.slice(this.inputIndex, this.inputIndex + numChars);
};
rr.Context.prototype.stringAfter = function(numChars) {
if (numChars == null) {
numChars = this.remaining();
}
return this.input.slice(this.inputIndex, this.inputIndex + numChars);
};
rr.Context.prototype.stringBefore = function(numChars) {
var start = this.inputIndex - numChars;
if (start < 0) {
numChars += start;
start = 0;
}
return this.input.slice(start, numChars);
};
rr.Context.prototype.atStart = function() {
return this.inputIndex == 0;
};
rr.Context.prototype.atEnd = function() {
return this.inputIndex == this.input.length;
};
rr.Context.prototype.remaining = function() {
return this.input.length - this.inputIndex;
};
rr.Context.prototype.advance = function(numChars) {
console.log('advance', numChars);
this.inputIndex += numChars;
};
2014-05-20 16:40:35 -07:00
2014-05-20 11:46:57 -07:00
var RecentRunes = function(dictionary) {
this.dictionary_ = dictionary;
};
2014-06-26 19:41:23 -07:00
RecentRunes.prototype.parseString = function(nodeType, input) {
var context = new rr.Context(this, input);
var ret = this.parse(nodeType, context);
if (ret) {
return ret[0];
} else {
return null;
}
};
2014-05-20 16:40:35 -07:00
RecentRunes.prototype.minimize = function(nodeType) {
var rules = this.dictionary_[nodeType];
for (var i = 0; i < rules.length; i++) {
if (rules.minimize && rules.minimize(this)) {
return true;
}
}
return false;
};
2014-06-26 19:41:23 -07:00
RecentRunes.prototype.parse = function(nodeType, origContext) {
var context = origContext.copy();
2014-05-20 12:49:30 -07:00
var ret = document.createElement(nodeType);
var rules = this.dictionary_[nodeType];
2014-06-26 19:41:23 -07:00
rules = [];
2014-05-20 12:49:30 -07:00
var lastRuleMinimize = false;
for (var i = 0; i < rules.length; i++) {
2014-06-26 19:41:23 -07:00
console.log('nodeType:', nodeType, 'rule:', i);
2014-05-20 12:49:30 -07:00
var rule = rules[i];
2014-05-20 16:40:35 -07:00
if (rule.minimize && rule.minimize(this)) {
2014-05-20 12:49:30 -07:00
if (lastRuleMinimize) {
// Two minimize rules in a row is ambiguous
return null;
}
2014-05-20 16:40:35 -07:00
lastRuleMinimize = rule;
2014-05-20 12:49:30 -07:00
continue;
}
if (lastRuleMinimize) {
// Check if this rule can find a match in the string
2014-06-26 19:41:23 -07:00
var loc = rule.search(context);
2014-05-20 12:49:30 -07:00
if (loc == null) {
2014-06-26 19:41:23 -07:00
console.log('search fail');
2014-05-20 12:49:30 -07:00
return null;
}
// Check if the previous rule will match the interim data
2014-06-26 19:41:23 -07:00
var prevContext = context.copy();
prevContext.truncate(loc);
var prevMatch = lastRuleMinimize.match(prevContext);
if (!prevMatch) {
console.log('prevMatch fail');
2014-05-20 12:49:30 -07:00
return null;
};
2014-06-26 19:41:23 -07:00
context.advance(prevContext.inputIndex - context.inputIndex);
prevMatch.forEach(function(child) {
ret.appendChild(child);
});
2014-05-20 16:40:35 -07:00
lastRuleMinimize = false;
2014-05-20 12:49:30 -07:00
}
2014-06-26 19:41:23 -07:00
console.log(context);
var match = rule.match(context);
2014-05-20 12:49:30 -07:00
if (!match) {
2014-06-26 19:41:23 -07:00
console.log('rule fail');
2014-05-20 12:49:30 -07:00
return null;
}
2014-06-26 19:41:23 -07:00
match.forEach(function(child) {
ret.appendChild(child);
});
2014-05-20 12:49:30 -07:00
};
2014-05-20 16:40:35 -07:00
if (lastRuleMinimize) {
2014-06-26 19:41:23 -07:00
var prevContext = context.copy();
prevContext.truncate(loc);
var lastMatch = lastRuleMinimize.match(prevContext);
if (!lastMatch) {
2014-05-20 16:40:35 -07:00
return null;
}
2014-06-26 19:41:23 -07:00
context.advance(prevContext.inputIndex - context.inputIndex);
lastMatch.forEach(function(child) {
ret.appendChild(child);
});
2014-05-20 16:40:35 -07:00
}
2014-06-26 19:41:23 -07:00
console.log('nodeType:', nodeType, 'context:', context);
origContext.advance(context.inputIndex - origContext.inputIndex);
return [ret];
2014-05-20 11:46:57 -07:00
};