Start of an actual parser.

This commit is contained in:
Ian Gulliver
2014-05-20 12:49:30 -07:00
parent 2bf3c67aa7
commit bbabf59505
2 changed files with 88 additions and 0 deletions

View File

@@ -1,6 +1,24 @@
var rr = {}; var rr = {};
rr.Literal_ = function(value) { rr.Literal_ = function(value) {
this.value_ = value;
};
rr.Literal_.prototype.match = function(input) {
if (input.slice(0, this.value_.length) == this.value_) {
return [this.value_.length, null];
} else {
return null;
}
};
rr.Literal_.prototype.search = function(input) {
var index = input.indexOf(this.value_);
if (index == -1) {
return null;
} else {
return index;
}
}; };
rr.Literal = function(value) { rr.Literal = function(value) {
@@ -11,6 +29,7 @@ rr.Literal.cache = {};
rr.Ref_ = function(key) { rr.Ref_ = function(key) {
this.key_ = key;
}; };
rr.Ref = function(key) { rr.Ref = function(key) {
@@ -32,6 +51,8 @@ rr.EndOfLine.cache = new rr.EndOfLine_();
rr.MultiLineText_ = function() { rr.MultiLineText_ = function() {
}; };
rr.MultiLineText_.prototype.minimize = true;
rr.MultiLineText = function() { rr.MultiLineText = function() {
return rr.MultiLineText.cache; return rr.MultiLineText.cache;
}; };
@@ -39,6 +60,7 @@ rr.MultiLineText.cache = new rr.MultiLineText_();
rr.Or_ = function(options) { rr.Or_ = function(options) {
this.options_ = options;
}; };
rr.Or = function() { rr.Or = function() {
@@ -49,6 +71,17 @@ rr.Or = function() {
rr.SingleLineText_ = function() { rr.SingleLineText_ = function() {
}; };
rr.SingleLineText_.prototype.minimize = true;
rr.SingleLineText_.prototype.match = function(input) {
var newLine = input.indexOf('\n');
if (newLine == -1) {
return [input.length, document.createTextNode(input)];
} else {
return [newLine, document.createTextNode(input.slice(0, newLine))];
}
};
rr.SingleLineText = function() { rr.SingleLineText = function() {
return rr.SingleLineText.cache; return rr.SingleLineText.cache;
}; };
@@ -67,6 +100,8 @@ rr.StartOfLine.cache = new rr.StartOfLine_();
rr.WordText_ = function() { rr.WordText_ = function() {
}; };
rr.WordText_.prototype.minimize = true;
rr.WordText = function() { rr.WordText = function() {
return rr.WordText.cache; return rr.WordText.cache;
}; };
@@ -74,6 +109,7 @@ rr.WordText.cache = new rr.WordText_();
rr.ZeroOrMore_ = function(key) { rr.ZeroOrMore_ = function(key) {
this.key_ = key;
}; };
rr.ZeroOrMore = function(key) { rr.ZeroOrMore = function(key) {
@@ -88,4 +124,46 @@ var RecentRunes = function(dictionary) {
}; };
RecentRunes.prototype.parse = function(nodeType, input) { RecentRunes.prototype.parse = function(nodeType, input) {
var ret = document.createElement(nodeType);
var rules = this.dictionary_[nodeType];
var inputIndex = 0;
var lastRuleMinimize = false;
for (var i = 0; i < rules.length; i++) {
var rule = rules[i];
if (rule.minimize) {
if (lastRuleMinimize) {
// Two minimize rules in a row is ambiguous
return null;
}
lastRuleMinimize = true;
continue;
}
if (lastRuleMinimize) {
// Check if this rule can find a match in the string
var loc = rule.search(input.slice(inputIndex));
if (loc == null) {
return null;
}
// Check if the previous rule will match the interim data
var prevMatch = rules[i - 1].match(
input.slice(inputIndex, inputIndex + loc));
if (!prevMatch) {
return null;
};
inputIndex += prevMatch[0];
if (prevMatch[1]) {
ret.appendChild(prevMatch[1]);
}
}
var match = rule.match(input.slice(inputIndex));
if (!match) {
return null;
}
inputIndex += match[0];
if (match[1]) {
ret.appendChild(match[1]);
}
};
return [inputIndex, ret];
}; };

10
test.js
View File

@@ -0,0 +1,10 @@
test('Simple', function() {
expect(0);
var grammar = {
'rule1': [rr.Literal('=== '), rr.SingleLineText(), rr.Literal(' ===')],
'rule2': [rr.SingleLineText(), rr.Literal('=')],
};
var parser = new RecentRunes(grammar);
console.log(parser.parse('rule1', '=== bar ==='));
console.log(parser.parse('rule2', 'foo=\nbar='));
});