Add Save() and SavedLiteral() matchers. Add badpenny grammar.
This commit is contained in:
47
static/grammars/badpenny.js
Normal file
47
static/grammars/badpenny.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
badpenny = rr.Parser({
|
||||||
|
'container': rr.Node('container',
|
||||||
|
rr.Save('tagname',
|
||||||
|
rr.Sequence(
|
||||||
|
rr.Literal('{{('),
|
||||||
|
rr.SingleLineText(),
|
||||||
|
rr.Literal('}}')),
|
||||||
|
rr.Sequence(
|
||||||
|
rr.Literal('{{('),
|
||||||
|
rr.SavedLiteral('tagname'),
|
||||||
|
rr.Literal('}}'),
|
||||||
|
rr.MultiLineText(),
|
||||||
|
rr.Literal('{{)'),
|
||||||
|
rr.SavedLiteral('tagname'),
|
||||||
|
rr.Literal('}}')))),
|
||||||
|
|
||||||
|
'repeated': rr.Node('repeated',
|
||||||
|
rr.Save('tagname',
|
||||||
|
rr.Sequence(
|
||||||
|
rr.Literal('{{['),
|
||||||
|
rr.SingleLineText(),
|
||||||
|
rr.Literal('}}')),
|
||||||
|
rr.Sequence(
|
||||||
|
rr.Literal('{{['),
|
||||||
|
rr.SavedLiteral('tagname'),
|
||||||
|
rr.Literal('}}'),
|
||||||
|
rr.MultiLineText(),
|
||||||
|
rr.Literal('{{]'),
|
||||||
|
rr.SavedLiteral('tagname'),
|
||||||
|
rr.Literal('}}')))),
|
||||||
|
|
||||||
|
'value': rr.Node('value', rr.Sequence(
|
||||||
|
rr.Literal('{{'),
|
||||||
|
rr.SingleLineText(),
|
||||||
|
rr.Literal('}}'))),
|
||||||
|
|
||||||
|
'chunk': rr.Or(
|
||||||
|
rr.Ref('container'),
|
||||||
|
rr.Ref('repeated'),
|
||||||
|
rr.Ref('value'),
|
||||||
|
rr.MultiLineText()),
|
||||||
|
|
||||||
|
'main': rr.Node('badpenny', rr.Sequence(
|
||||||
|
rr.ZeroOrMore(rr.Ref('chunk')),
|
||||||
|
rr.EndOfText()))
|
||||||
|
}, [
|
||||||
|
]);
|
||||||
@@ -468,6 +468,100 @@ rr.Ref.cache_ = {};
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @param {rr.typeMatcher} child
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
rr.Save_ = function(key, child) {
|
||||||
|
this.key_ = key;
|
||||||
|
this.child_ = child;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {rr.Context} context
|
||||||
|
* @return {rr.typeIterator}
|
||||||
|
*/
|
||||||
|
rr.Save_.prototype.match = function(context) {
|
||||||
|
var iterator = this.child_.match(context);
|
||||||
|
return {
|
||||||
|
'next': function() {
|
||||||
|
var next = iterator.next();
|
||||||
|
if (next['done']) {
|
||||||
|
return { 'done': true };
|
||||||
|
}
|
||||||
|
var value = '';
|
||||||
|
var nodes = next['value']['nodes'];
|
||||||
|
for (var i = 0; i < nodes.length; i++) {
|
||||||
|
value += nodes[i].textContent;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
'done': false,
|
||||||
|
'value': {
|
||||||
|
'context': context.saveValue(this.key_, value),
|
||||||
|
'nodes': []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}.bind(this)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} key
|
||||||
|
* @param {rr.typeMatcher} saveChild
|
||||||
|
* @param {rr.typeMatcher} matchChild
|
||||||
|
* @return {rr.SequentialPair_}
|
||||||
|
*/
|
||||||
|
rr.Save = function(key, saveChild, matchChild) {
|
||||||
|
return new rr.SequentialPair_(new rr.Save_(key, saveChild), matchChild);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
rr.SavedLiteral_ = function(key) {
|
||||||
|
this.key_ = key;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {rr.Context} context
|
||||||
|
* @return {rr.typeIterator}
|
||||||
|
*/
|
||||||
|
rr.SavedLiteral_.prototype.match = function(context) {
|
||||||
|
var literal = rr.Literal(context.getValue(this.key_));
|
||||||
|
return literal.match(context);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} key
|
||||||
|
* @return {rr.SavedLiteral_}
|
||||||
|
*/
|
||||||
|
rr.SavedLiteral = function(key) {
|
||||||
|
return (rr.SavedLiteral.cache_[key] ||
|
||||||
|
(rr.SavedLiteral.cache_[key] = new rr.SavedLiteral_(key)));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Object.<string, rr.SavedLiteral_>}
|
||||||
|
* @const
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
rr.SavedLiteral.cache_ = {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
*
|
*
|
||||||
@@ -771,7 +865,7 @@ rr.ExtractElement = function(nodeName) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} parentName
|
* @param {string} parentName
|
||||||
* @param {string} childNames
|
* @param {Array.<string>} childNames
|
||||||
* @return {rr.typeFilter}
|
* @return {rr.typeFilter}
|
||||||
*/
|
*/
|
||||||
rr.GroupSiblings = function(parentName, childNames) {
|
rr.GroupSiblings = function(parentName, childNames) {
|
||||||
@@ -885,11 +979,14 @@ rr.ApplyFilters = function(node, filters) {
|
|||||||
* @param {Object.<string, rr.typeMatcher>} rules
|
* @param {Object.<string, rr.typeMatcher>} rules
|
||||||
* @param {string} input
|
* @param {string} input
|
||||||
* @param {number=} opt_inputIndex
|
* @param {number=} opt_inputIndex
|
||||||
|
* @param {Object.<string, string>=} opt_savedValues
|
||||||
*/
|
*/
|
||||||
rr.Context = function(rules, input, opt_inputIndex) {
|
rr.Context = function(rules, input, opt_inputIndex, opt_savedValues) {
|
||||||
this.rules = rules;
|
this.rules = rules;
|
||||||
this.input = input;
|
this.input = input;
|
||||||
this.inputIndex = opt_inputIndex || 0;
|
this.inputIndex = opt_inputIndex || 0;
|
||||||
|
this.savedValues = /** @type {Object.<string, string>} */ (
|
||||||
|
JSON.parse(JSON.stringify(opt_savedValues || {})));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -897,7 +994,8 @@ rr.Context = function(rules, input, opt_inputIndex) {
|
|||||||
* @return {rr.Context}
|
* @return {rr.Context}
|
||||||
*/
|
*/
|
||||||
rr.Context.prototype.copy = function() {
|
rr.Context.prototype.copy = function() {
|
||||||
return new rr.Context(this.rules, this.input, this.inputIndex);
|
return new rr.Context(
|
||||||
|
this.rules, this.input, this.inputIndex, this.savedValues);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -965,6 +1063,27 @@ rr.Context.prototype.advance = function(numChars) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} key
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
rr.Context.prototype.getValue = function(key) {
|
||||||
|
return this.savedValues[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} key
|
||||||
|
* @param {string} value
|
||||||
|
* @return {rr.Context}
|
||||||
|
*/
|
||||||
|
rr.Context.prototype.saveValue = function(key, value) {
|
||||||
|
var context = this.copy();
|
||||||
|
context.savedValues[key] = value;
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
<div id="qunit-fixture"></div>
|
<div id="qunit-fixture"></div>
|
||||||
<script src="https://code.jquery.com/qunit/qunit-git.js"></script>
|
<script src="https://code.jquery.com/qunit/qunit-git.js"></script>
|
||||||
<script src="/recentrunes/static/recentrunes.js" charset="UTF-8"></script>
|
<script src="/recentrunes/static/recentrunes.js" charset="UTF-8"></script>
|
||||||
|
<script src="/recentrunes/static/grammars/badpenny.js" charset="UTF-8"></script>
|
||||||
<script src="/recentrunes/static/grammars/mediawiki.js" charset="UTF-8"></script>
|
<script src="/recentrunes/static/grammars/mediawiki.js" charset="UTF-8"></script>
|
||||||
<script src="test.js" charset="UTF-8"></script>
|
<script src="test.js" charset="UTF-8"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -106,3 +106,23 @@ QUnit.test('Figure', function(assert) {
|
|||||||
|
|
||||||
assert.equal(mediawiki.parseFromString(content).innerHTML, expected);
|
assert.equal(mediawiki.parseFromString(content).innerHTML, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
QUnit.module('badpenny');
|
||||||
|
|
||||||
|
QUnit.test('Base', function(assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
var content = [
|
||||||
|
'foo{{value1}}bar',
|
||||||
|
'foo{{(container}}contents{{)nottheend}}more contents{{)container}}bar',
|
||||||
|
'foo{{[repeated}}testing{{]notthis}}{{)repeated}}zig{{]repeated}}bar'
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
var expected = [
|
||||||
|
'foo<value>value1</value>bar\n',
|
||||||
|
'foo<container>contents{{)nottheend}}more contents</container>bar\n',
|
||||||
|
'foo<repeated>testing{{]notthis}}{{)repeated}}zig</repeated>bar'
|
||||||
|
].join('');
|
||||||
|
|
||||||
|
assert.equal(badpenny.parseFromString(content).innerHTML, expected);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user