PEG.buildParser reports missing referenced rules.

redux
David Majda 15 years ago
parent 6bbd88088b
commit 3a65316416

@ -38,6 +38,9 @@ PEG.buildParser = function(grammar, startRule) {
throw new PEG.Grammar.GrammarError("Grammar must be object or string.");
}
for (var key in ast) {
ast[key].checkReferencedRulesExist(ast);
}
if (ast[startRule] === undefined) {
throw new PEG.Grammar.GrammarError("Missing \"" + startRule + "\" rule.");
}
@ -97,6 +100,46 @@ PEG.Grammar.Action = function(expression, action) {
this._action = action;
};
/* ===== Referenced Rule Existence Checks ===== */
PEG.Grammar.Rule.prototype.checkReferencedRulesExist = function(grammar) {
this._expression.checkReferencedRulesExist(grammar);
};
PEG.Grammar.Literal.prototype.checkReferencedRulesExist = function(grammar) {};
PEG.Grammar.Any.prototype.checkReferencedRulesExist = function(grammar) {};
PEG.Grammar.Sequence.prototype.checkReferencedRulesExist = function(grammar) {
PEG.ArrayUtils.each(this._elements, function(element) {
element.checkReferencedRulesExist(grammar);
});
};
PEG.Grammar.Choice.prototype.checkReferencedRulesExist = function(grammar) {
PEG.ArrayUtils.each(this._alternatives, function(alternative) {
alternative.checkReferencedRulesExist(grammar);
});
};
PEG.Grammar.ZeroOrMore.prototype.checkReferencedRulesExist = function(grammar) {
this._element.checkReferencedRulesExist(grammar);
};
PEG.Grammar.NotPredicate.prototype.checkReferencedRulesExist = function(grammar) {
this._expression.checkReferencedRulesExist(grammar);
};
PEG.Grammar.RuleRef.prototype.checkReferencedRulesExist = function(grammar) {
if (grammar[this._name] === undefined) {
throw new PEG.Grammar.GrammarError("Referenced rule \"" + this._name + "\" does not exist.");
}
};
PEG.Grammar.Action.prototype.checkReferencedRulesExist = function(grammar) {
this._expression.checkReferencedRulesExist(grammar);
};
/* ===== PEG.Compiler ===== */
PEG.Compiler = {

@ -113,6 +113,24 @@ test("buildParser reports missing start rule", function() {
throws(function() { PEG.buildParser({}); }, PEG.Grammar.GrammarError);
});
test("buildParser reports missing referenced rules", function() {
var grammars = [
'start: missing',
'start: missing "a" "b"',
'start: "a" "b" missing',
'start: missing | "a" | "b"',
'start: "a" | "b" | missing',
'start: missing*',
'start: !missing',
'start: &missing',
'start: missing { }'
];
PEG.ArrayUtils.each(grammars, function(grammar) {
throws(function() { PEG.buildParser(grammar); }, PEG.Grammar.GrammarError);
});
});
test("buildParser allows custom start rule", function() {
var parser = PEG.buildParser('s: "abcd"', "s");
parses(parser, "abcd", "abcd");

Loading…
Cancel
Save