Create a Parser object that can package up rules and filters.

This commit is contained in:
Ian Gulliver
2014-06-30 23:14:20 -07:00
parent 241a27c9c1
commit dfb1e07f46
3 changed files with 64 additions and 27 deletions

View File

@@ -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')
};
});

View File

@@ -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.<string, rr.typeFilter>} filters
@@ -766,12 +775,12 @@ rr.ApplyFilters = function(node, filters) {
*
* @param {Object.<string, rr.typeMatcher>} 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.<string, rr.typeMatcher>} rules
* @param {Object.<string, rr.typeFilter>} 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.<string, rr.typeMatcher>} rules
* @param {Object.<string, rr.typeFilter>} filters
* @return {rr.Parser_}
*/
rr.Parser = function(rules, filters) {
return new rr.Parser_(rules, filters);
};

18
test.js
View File

@@ -59,11 +59,7 @@ QUnit.test('Base', function(assert) {
'</pre></p>'
].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) {
'<h3>Header 3 <i>with italics</i></h3></p>'
].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 <i>with formatting</i></a></p>'
].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) {
'<caption>Test image <i>with formatting</i></caption></imgtemp></p>'
].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);
});