diff --git a/grammars/mediawiki.js b/grammars/mediawiki.js
index fe374e1..4f35db1 100644
--- a/grammars/mediawiki.js
+++ b/grammars/mediawiki.js
@@ -1,4 +1,4 @@
-var mediawiki = {
+var mediawiki = rr.Parser({
'list-blockquote1': rr.Node('blockquote', rr.Sequence(
rr.StartOfLine(),
rr.Literal(': '),
@@ -290,12 +290,9 @@ var mediawiki = {
rr.Sequence(rr.EndOfLine(), rr.Literal('\n')),
rr.EndOfText()))),
- 'wikidoc': rr.Node('wikidoc', rr.Sequence(
+ 'main': rr.Node('wikidoc', rr.Sequence(
rr.ZeroOrMore(rr.Ref('paragraph')),
rr.EndOfText()))
-};
-
-
-var mediawiki_filters = {
+}, {
'bi': rr.SplitTagAndNest('b', 'i')
-};
+});
diff --git a/recentrunes.js b/recentrunes.js
index 0647545..34a66e1 100644
--- a/recentrunes.js
+++ b/recentrunes.js
@@ -4,6 +4,12 @@ var rr = {};
/* ============ typedefs ============ */
+/**
+ * @typedef {function(Node)}
+ */
+rr.typeFilter;
+
+
/**
* @typedef {{done: boolean,
* value: *}}
@@ -716,10 +722,14 @@ rr.SingleLineText = function() {
-/* ============ Filters ============ */
+/* ============ Filter factories ============ */
-rr.SplitTagAndNest = function() {
+/**
+ * @param {...string} var_args
+ * @return {rr.typeFilter}
+ */
+rr.SplitTagAndNest = function(var_args) {
var hierarchy = Array.prototype.slice.call(arguments);
return function(node) {
var outerNode, innerNode;
@@ -744,7 +754,6 @@ rr.SplitTagAndNest = function() {
/* ============ Scaffolding ============ */
-
/**
* @param {Node} node
* @param {Object.} filters
@@ -766,12 +775,12 @@ rr.ApplyFilters = function(node, filters) {
*
* @param {Object.} rules
* @param {string} input
- * @param {number} inputIndex
+ * @param {number=} opt_inputIndex
*/
-rr.Context = function(rules, input, inputIndex) {
+rr.Context = function(rules, input, opt_inputIndex) {
this.rules = rules;
this.input = input;
- this.inputIndex = inputIndex || 0;
+ this.inputIndex = opt_inputIndex || 0;
};
@@ -845,3 +854,44 @@ rr.Context.prototype.advance = function(numChars) {
context.inputIndex += numChars;
return context;
};
+
+
+
+/**
+ * @constructor
+ *
+ * @param {Object.} rules
+ * @param {Object.} filters
+ * @private
+ */
+rr.Parser_ = function(rules, filters) {
+ this.rules_ = rules;
+ this.filters_ = filters;
+};
+
+
+/**
+ * @param {string} input
+ * @return {?Node}
+ */
+rr.Parser_.prototype.parseFromString = function(input) {
+ var context = new rr.Context(this.rules_, input);
+ var iterable = context.rules['main'].match(context);
+ var next = iterable.next();
+ if (next['done']) {
+ return null;
+ }
+ var rootNode = next['value']['nodes'][0];
+ rr.ApplyFilters(rootNode, this.filters_);
+ return rootNode;
+};
+
+
+/**
+ * @param {Object.} rules
+ * @param {Object.} filters
+ * @return {rr.Parser_}
+ */
+rr.Parser = function(rules, filters) {
+ return new rr.Parser_(rules, filters);
+};
diff --git a/test.js b/test.js
index 279e886..bb45546 100644
--- a/test.js
+++ b/test.js
@@ -59,11 +59,7 @@ QUnit.test('Base', function(assert) {
'
'
].join('');
- var context = new rr.Context(mediawiki, content);
- var iterable = context.rules['wikidoc'].match(context);
- var rootNode = iterable.next().value.nodes[0];
- rr.ApplyFilters(rootNode, mediawiki_filters);
- assert.equal(rootNode.innerHTML, expected);
+ assert.equal(mediawiki.parseFromString(content).innerHTML, expected);
});
QUnit.test('singleline-wikichunk', function(assert) {
@@ -78,9 +74,7 @@ QUnit.test('singleline-wikichunk', function(assert) {
'Header 3 with italics
'
].join('');
- var context = new rr.Context(mediawiki, content);
- var iterable = context.rules['wikidoc'].match(context);
- assert.equal(iterable.next().value.nodes[0].innerHTML, expected);
+ assert.equal(mediawiki.parseFromString(content).innerHTML, expected);
});
QUnit.test('Link', function(assert) {
@@ -94,9 +88,7 @@ QUnit.test('Link', function(assert) {
'Test text with formatting'
].join('');
- var context = new rr.Context(mediawiki, content);
- var iterable = context.rules['wikidoc'].match(context);
- assert.equal(iterable.next().value.nodes[0].innerHTML, expected);
+ assert.equal(mediawiki.parseFromString(content).innerHTML, expected);
});
QUnit.test('Image', function(assert) {
@@ -110,7 +102,5 @@ QUnit.test('Image', function(assert) {
'Test image with formatting'
].join('');
- var context = new rr.Context(mediawiki, content);
- var iterable = context.rules['wikidoc'].match(context);
- assert.equal(iterable.next().value.nodes[0].innerHTML, expected);
+ assert.equal(mediawiki.parseFromString(content).innerHTML, expected);
});