Checks refactoring
Changed two things: 1. Checks are run in |PEG.Compiler.compileParser|, not in |PEG.buildParser|. 2. Checks are extracted into separate functions.
This commit is contained in:
parent
85930cbcfe
commit
6f2a188efc
|
@ -23,19 +23,10 @@ function nop() {}
|
||||||
PEG.buildParser = function(grammar, startRule) {
|
PEG.buildParser = function(grammar, startRule) {
|
||||||
startRule = startRule || "start";
|
startRule = startRule || "start";
|
||||||
|
|
||||||
var ast = PEG.grammarParser.parse(grammar);
|
return PEG.Compiler.compileParser(
|
||||||
|
PEG.grammarParser.parse(grammar),
|
||||||
for (var rule in ast) {
|
startRule
|
||||||
ast[rule].checkReferencedRulesExist(ast);
|
);
|
||||||
}
|
|
||||||
if (ast[startRule] === undefined) {
|
|
||||||
throw new PEG.Grammar.GrammarError("Missing \"" + startRule + "\" rule.");
|
|
||||||
}
|
|
||||||
for (var rule in ast) {
|
|
||||||
ast[rule].checkNoLeftRecursion(ast, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PEG.Compiler.compileParser(ast, startRule);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ===== PEG.ArrayUtils ===== */
|
/* ===== PEG.ArrayUtils ===== */
|
||||||
|
@ -462,18 +453,57 @@ PEG.Compiler = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generates a parser from a specified grammar and start rule.
|
* Checks made on the grammar AST before compilation. Each check is a function
|
||||||
|
* that is passed the AST and start rule and does not return anything. If the
|
||||||
|
* check passes, the function does not do anything special, otherwise it
|
||||||
|
* throws |PEG.Grammar.GrammarError|. The checks are run in sequence in order
|
||||||
|
* of their definition.
|
||||||
*/
|
*/
|
||||||
compileParser: function(grammar, startRule) {
|
_checks: [
|
||||||
|
/* Checks that all referenced rules exist. */
|
||||||
|
function(ast, startRule) {
|
||||||
|
for (var rule in ast) {
|
||||||
|
ast[rule].checkReferencedRulesExist(ast);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Checks that the start rule is defined. */
|
||||||
|
function(ast, startRule) {
|
||||||
|
if (ast[startRule] === undefined) {
|
||||||
|
throw new PEG.Grammar.GrammarError(
|
||||||
|
"Missing \"" + startRule + "\" rule."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Checks that no left recursion is present. */
|
||||||
|
function(ast, startRule) {
|
||||||
|
for (var rule in ast) {
|
||||||
|
ast[rule].checkNoLeftRecursion(ast, []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generates a parser from a specified grammar AST and start rule. Throws
|
||||||
|
* |PEG.Grammar.GrammarError| if the AST contains a semantic error. Note that
|
||||||
|
* not all errors are detected during the generation and some may protrude to
|
||||||
|
* the generated parser and cause its malfunction.
|
||||||
|
*/
|
||||||
|
compileParser: function(ast, startRule) {
|
||||||
/*
|
/*
|
||||||
* This ensures that the same grammar and start rule always generate exactly
|
* This ensures that the same grammar and start rule always generate exactly
|
||||||
* the same parser.
|
* the same parser.
|
||||||
*/
|
*/
|
||||||
this._resetUniqueIdentifierCounters();
|
this._resetUniqueIdentifierCounters();
|
||||||
|
|
||||||
|
for (var i = 0; i < this._checks.length; i++) {
|
||||||
|
this._checks[i](ast, startRule);
|
||||||
|
}
|
||||||
|
|
||||||
var parseFunctionDefinitions = [];
|
var parseFunctionDefinitions = [];
|
||||||
for (var rule in grammar) {
|
for (var rule in ast) {
|
||||||
parseFunctionDefinitions.push(grammar[rule].compile());
|
parseFunctionDefinitions.push(ast[rule].compile());
|
||||||
}
|
}
|
||||||
|
|
||||||
var source = this.formatCode(
|
var source = this.formatCode(
|
||||||
|
|
Loading…
Reference in a new issue