Checkin before I destroy everything.

This commit is contained in:
Ian Gulliver
2014-06-26 19:41:23 -07:00
parent 18476a1468
commit 8d445df2c4
3 changed files with 162 additions and 90 deletions

View File

@@ -11,16 +11,16 @@ var mediawiki = {
'nowiki': [rr.Literal('<nowiki>'), rr.MultiLineText(), rr.Literal('</nowiki>')], 'nowiki': [rr.Literal('<nowiki>'), rr.MultiLineText(), rr.Literal('</nowiki>')],
'text': [rr.MultiLineText()], 'text': [rr.MultiLineText()],
'wikichunk': [rr.Or( 'wikichunk': [rr.Or(
'b', // 'b',
'del', // 'del',
'h2', // 'h2',
'h3', 'h3',
'h4', // 'h4',
'h5', // 'h5',
'h6', // 'h6',
'hr', // 'hr',
'i', // 'i',
'nowiki', // 'nowiki',
'text' 'text'
)], )],
'wikidoc': [rr.ZeroOrMore('wikichunk')], 'wikidoc': [rr.ZeroOrMore('wikichunk')],

View File

@@ -6,16 +6,18 @@ rr.Literal_ = function(value) {
this.value_ = value; this.value_ = value;
}; };
rr.Literal_.prototype.match = function(input) { rr.Literal_.prototype.match = function(context) {
if (input.slice(0, this.value_.length) == this.value_) { if (context.stringAfter(this.value_.length) == this.value_) {
return [this.value_.length, null]; context.advance(this.value_.length);
return [];
} else { } else {
return null; return null;
} }
}; };
rr.Literal_.prototype.search = function(input) { rr.Literal_.prototype.search = function(context) {
var index = input.indexOf(this.value_); console.log(context.stringAfter());
var index = context.stringAfter().indexOf(this.value_);
if (index == -1) { if (index == -1) {
return null; return null;
} else { } else {
@@ -39,8 +41,8 @@ rr.Ref_.prototype.minimize = function(parser) {
return parser.minimize(this.key_); return parser.minimize(this.key_);
}; };
rr.Ref_.prototype.match = function(input, fullInput, inputIndex, parser) { rr.Ref_.prototype.match = function(context) {
return parser.parse(this.key_, input); return context.parser.parse(this.key_, context);
}; };
rr.Ref = function(key) { rr.Ref = function(key) {
@@ -54,26 +56,27 @@ rr.Ref.cache = {};
rr.EndOfLine_ = function() { rr.EndOfLine_ = function() {
}; };
rr.EndOfLine_.prototype.match = function(input, fullInput, inputIndex) { rr.EndOfLine_.prototype.match = function(context) {
if (input.length == 0) { if (context.atEnd()) {
return [0, null]; return [];
} }
if (input[0] == '\n') { if (context.stringAfter(1) == '\n') {
return [1, null]; context.advance(1);
return [];
} }
if (inputIndex > 0 && fullInput[inputIndex - 1] == '\n') { if (context.stringBefore(1) == '\n') {
return [0, null]; return [];
} }
return null; return null;
}; };
rr.EndOfLine_.prototype.search = function(input, fullInput, inputIndex) { rr.EndOfLine_.prototype.search = function(context) {
if (input.length == 0) { if (context.atEnd()) {
return 0; return 0;
} }
var loc = input.indexOf('\n'); var loc = context.stringAfter().indexOf('\n');
if (loc == -1) { if (loc == -1) {
return input.length; return context.remaining();
} else { } else {
return loc; return loc;
} }
@@ -89,16 +92,16 @@ rr.EndOfLine.cache = new rr.EndOfLine_();
rr.EndOfText_ = function() { rr.EndOfText_ = function() {
}; };
rr.EndOfText_.prototype.match = function(input) { rr.EndOfText_.prototype.match = function(context) {
if (input.length) { if (context.atEnd()) {
return null; return null;
} else { } else {
return [0, null]; return [];
} }
}; };
rr.EndOfText_.prototype.search = function(input) { rr.EndOfText_.prototype.search = function(context) {
return input.length; return context.remaining();
}; };
rr.EndOfText = function() { rr.EndOfText = function() {
@@ -115,8 +118,10 @@ rr.MultiLineText_.prototype.minimize = function() {
return true; return true;
}; };
rr.MultiLineText_.prototype.match = function(input) { rr.MultiLineText_.prototype.match = function(context) {
return [input.length, document.createTextNode(input)]; var ret = [document.createTextNode(context.stringAfter())];
context.advance(context.remaining());
return ret;
}; };
rr.MultiLineText = function() { rr.MultiLineText = function() {
@@ -135,15 +140,15 @@ rr.Or_.prototype.minimize = function(parser) {
var option = this.options_[i]; var option = this.options_[i];
if (parser.minimize(option)) { if (parser.minimize(option)) {
return true; return true;
}; }
} }
return false; return false;
}; };
rr.Or_.prototype.match = function(input, fullInput, inputIndex, parser) { rr.Or_.prototype.match = function(context) {
for (var i = 0; i < this.options_.length; i++) { for (var i = 0; i < this.options_.length; i++) {
var option = this.options_[i]; var option = this.options_[i];
var result = parser.parse(option, input); var result = context.parser.parse(option, context);
if (result) { if (result) {
return result; return result;
} }
@@ -164,13 +169,14 @@ rr.SingleLineText_.prototype.minimize = function() {
return true; return true;
} }
rr.SingleLineText_.prototype.match = function(input) { rr.SingleLineText_.prototype.match = function(context) {
var newLine = input.indexOf('\n'); var newLine = context.stringAfter().indexOf('\n');
if (newLine == -1) { if (newLine == -1) {
return [input.length, document.createTextNode(input)]; newLine = context.remaining();
} else {
return [newLine, document.createTextNode(input.slice(0, newLine))];
} }
var ret = [document.createTextNode(context.stringAfter(newLine))];
context.advance(newLine);
return ret;
}; };
rr.SingleLineText = function() { rr.SingleLineText = function() {
@@ -183,24 +189,25 @@ rr.SingleLineText.cache = new rr.SingleLineText_();
rr.StartOfLine_ = function() { rr.StartOfLine_ = function() {
}; };
rr.StartOfLine_.prototype.match = function(input, fullInput, inputIndex) { rr.StartOfLine_.prototype.match = function(context) {
if (inputIndex == 0) { if (context.atStart()) {
return [0, null]; return [];
} }
if (input[0] == '\n') { if (context.stringAfter(1) == '\n') {
return [1, null]; context.advance(1);
return [];
} }
if (fullInput[inputIndex - 1] == '\n') { if (context.stringBefore(1) == '\n') {
return [0, null]; return [];
} }
return null; return null;
}; };
rr.StartOfLine_.prototype.search = function(input, fullInput, inputIndex) { rr.StartOfLine_.prototype.search = function(context) {
if (inputIndex == 0) { if (context.atStart()) {
return 0; return 0;
} }
var loc = input.indexOf('\n'); var loc = context.stringAfter().indexOf('\n');
if (loc == -1) { if (loc == -1) {
return null; return null;
} }
@@ -222,20 +229,18 @@ rr.ZeroOrMore_.prototype.minimize = function(parser) {
return parser.minimize(this.key_); return parser.minimize(this.key_);
}; };
rr.ZeroOrMore_.prototype.match = function(input, fullInput, inputIndex, parser) { rr.ZeroOrMore_.prototype.match = function(context) {
var ret = document.createElement('group'); var ret = [];
var parseIndex = 0; while (context.inputIndex < context.input.length) {
while (parseIndex < input.length - 1) { var result = context.parser.parse(this.key_, context);
var result = parser.parse(this.key_, input.slice(parseIndex));
if (!result) { if (!result) {
break; break;
} }
parseIndex += result[0]; result.forEach(function(child) {
if (result[1]) { ret.push(child);
ret.appendChild(result[1]); });
}
}; };
return [parseIndex, ret]; return ret;
}; };
rr.ZeroOrMore = function(key) { rr.ZeroOrMore = function(key) {
@@ -245,11 +250,68 @@ rr.ZeroOrMore = function(key) {
rr.ZeroOrMore.cache = {}; rr.ZeroOrMore.cache = {};
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;
};
var RecentRunes = function(dictionary) { var RecentRunes = function(dictionary) {
this.dictionary_ = dictionary; this.dictionary_ = dictionary;
}; };
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;
}
};
RecentRunes.prototype.minimize = function(nodeType) { RecentRunes.prototype.minimize = function(nodeType) {
var rules = this.dictionary_[nodeType]; var rules = this.dictionary_[nodeType];
for (var i = 0; i < rules.length; i++) { for (var i = 0; i < rules.length; i++) {
@@ -260,12 +322,14 @@ RecentRunes.prototype.minimize = function(nodeType) {
return false; return false;
}; };
RecentRunes.prototype.parse = function(nodeType, input) { RecentRunes.prototype.parse = function(nodeType, origContext) {
var context = origContext.copy();
var ret = document.createElement(nodeType); var ret = document.createElement(nodeType);
var rules = this.dictionary_[nodeType]; var rules = this.dictionary_[nodeType];
var inputIndex = 0; rules = [];
var lastRuleMinimize = false; var lastRuleMinimize = false;
for (var i = 0; i < rules.length; i++) { for (var i = 0; i < rules.length; i++) {
console.log('nodeType:', nodeType, 'rule:', i);
var rule = rules[i]; var rule = rules[i];
if (rule.minimize && rule.minimize(this)) { if (rule.minimize && rule.minimize(this)) {
if (lastRuleMinimize) { if (lastRuleMinimize) {
@@ -277,47 +341,54 @@ RecentRunes.prototype.parse = function(nodeType, input) {
} }
if (lastRuleMinimize) { if (lastRuleMinimize) {
// Check if this rule can find a match in the string // Check if this rule can find a match in the string
var loc = rule.search(input.slice(inputIndex)); var loc = rule.search(context);
if (loc == null) { if (loc == null) {
console.log('search fail');
return null; return null;
} }
// Check if the previous rule will match the interim data // Check if the previous rule will match the interim data
var prevMatch = lastRuleMinimize.match( var prevContext = context.copy();
input.slice(inputIndex, inputIndex + loc), prevContext.truncate(loc);
input, inputIndex, this); var prevMatch = lastRuleMinimize.match(prevContext);
if (!prevMatch || prevMatch[0] != loc) { if (!prevMatch) {
console.log('prevMatch fail');
return null; return null;
}; };
inputIndex += prevMatch[0]; context.advance(prevContext.inputIndex - context.inputIndex);
if (prevMatch[1]) { prevMatch.forEach(function(child) {
ret.appendChild(prevMatch[1]); ret.appendChild(child);
} });
lastRuleMinimize = false; lastRuleMinimize = false;
} }
var match = rule.match( console.log(context);
input.slice(inputIndex), input, inputIndex, this); var match = rule.match(context);
if (!match) { if (!match) {
console.log('rule fail');
return null; return null;
} }
inputIndex += match[0]; match.forEach(function(child) {
if (match[1]) { ret.appendChild(child);
ret.appendChild(match[1]); });
}
}; };
if (lastRuleMinimize) { if (lastRuleMinimize) {
var lastMatch = lastRuleMinimize.match( var prevContext = context.copy();
input.slice(inputIndex), input, inputIndex, this); prevContext.truncate(loc);
var lastMatch = lastRuleMinimize.match(prevContext);
if (!lastMatch) { if (!lastMatch) {
return null; return null;
} }
inputIndex += lastMatch[0]; context.advance(prevContext.inputIndex - context.inputIndex);
if (lastMatch[1]) { lastMatch.forEach(function(child) {
ret.appendChild(lastMatch[1]); ret.appendChild(child);
} });
} }
return [inputIndex, ret]; console.log('nodeType:', nodeType, 'context:', context);
origContext.advance(context.inputIndex - origContext.inputIndex);
return [ret];
}; };

View File

@@ -1,11 +1,12 @@
test('Simple', function() { asyncTest('Simple', function() {
expect(0); // expect(1);
var parser = new RecentRunes(mediawiki); var parser = new RecentRunes(mediawiki);
var result = parser.parse('wikidoc', console.log('foo');
var result = parser.parseString('wikidoc',
'=== Heading ===\n\ '=== Heading ===\n\
This is a wiki doc.\n\ This is a wiki doc.\n\
How about some <b>bold and <i>bold italic</i></b>.\n\ How about some <b>bold and <i>bold italic</i></b>.\n\
I would also love some <nowiki>nowiki <b>foo</b></nowiki>'); I would also love some <nowiki>nowiki <b>foo</b></nowiki>');
console.log(result); console.log(result);
document.body.appendChild(result[1]); document.body.appendChild(result);
}); });