Extract the |matchesEmpty| visitor from the |reportLeftRecursion| pass
Beside the recursion detector, the visitor will also be used by infinite loop detector. Note the newly created |asts.matchesEmpty| function re-creates the visitor each time it is called, which makes it slower than necessary. This could have been worked around in various ways but I chose to defer that optimization because real-world performance impact is small.
This commit is contained in:
parent
03a391e874
commit
95ce20ed92
2
Makefile
2
Makefile
|
@ -10,8 +10,8 @@ MODULES = utils/arrays \
|
|||
utils/classes \
|
||||
grammar-error \
|
||||
parser \
|
||||
compiler/asts \
|
||||
compiler/visitor \
|
||||
compiler/asts \
|
||||
compiler/opcodes \
|
||||
compiler/javascript \
|
||||
compiler/passes/generate-bytecode \
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var arrays = require("../utils/arrays");
|
||||
var arrays = require("../utils/arrays"),
|
||||
visitor = require("./visitor");
|
||||
|
||||
/* AST utilities. */
|
||||
var asts = {
|
||||
|
@ -8,6 +9,52 @@ var asts = {
|
|||
|
||||
indexOfRule: function(ast, name) {
|
||||
return arrays.indexOf(ast.rules, function(r) { return r.name === name; });
|
||||
},
|
||||
|
||||
matchesEmpty: function(ast, node) {
|
||||
function matchesTrue() { return true; }
|
||||
function matchesFalse() { return false; }
|
||||
|
||||
function matchesExpression(node) {
|
||||
return matches(node.expression);
|
||||
}
|
||||
|
||||
var matches = visitor.build({
|
||||
rule: matchesExpression,
|
||||
|
||||
choice: function(node) {
|
||||
return arrays.some(node.alternatives, matches);
|
||||
},
|
||||
|
||||
action: matchesExpression,
|
||||
|
||||
sequence: function(node) {
|
||||
return arrays.every(node.elements, matches);
|
||||
},
|
||||
|
||||
labeled: matchesExpression,
|
||||
text: matchesExpression,
|
||||
simple_and: matchesTrue,
|
||||
simple_not: matchesTrue,
|
||||
optional: matchesTrue,
|
||||
zero_or_more: matchesTrue,
|
||||
one_or_more: matchesExpression,
|
||||
semantic_and: matchesTrue,
|
||||
semantic_not: matchesTrue,
|
||||
|
||||
rule_ref: function(node) {
|
||||
return matches(asts.findRule(ast, node.name));
|
||||
},
|
||||
|
||||
literal: function(node) {
|
||||
return node.value === "";
|
||||
},
|
||||
|
||||
"class": matchesFalse,
|
||||
any: matchesFalse
|
||||
});
|
||||
|
||||
return matches(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -16,48 +16,6 @@ var arrays = require("../../utils/arrays"),
|
|||
* it can lead to left recursion.
|
||||
*/
|
||||
function reportLeftRecursion(ast) {
|
||||
function matchesEmptyTrue() { return true; }
|
||||
function matchesEmptyFalse() { return false; }
|
||||
|
||||
function matchesEmptyExpression(node) {
|
||||
return matchesEmpty(node.expression);
|
||||
}
|
||||
|
||||
var matchesEmpty = visitor.build({
|
||||
rule: matchesEmptyExpression,
|
||||
|
||||
choice: function(node) {
|
||||
return arrays.some(node.alternatives, matchesEmpty);
|
||||
},
|
||||
|
||||
action: matchesEmptyExpression,
|
||||
|
||||
sequence: function(node) {
|
||||
return arrays.every(node.elements, matchesEmpty);
|
||||
},
|
||||
|
||||
labeled: matchesEmptyExpression,
|
||||
text: matchesEmptyExpression,
|
||||
simple_and: matchesEmptyTrue,
|
||||
simple_not: matchesEmptyTrue,
|
||||
optional: matchesEmptyTrue,
|
||||
zero_or_more: matchesEmptyTrue,
|
||||
one_or_more: matchesEmptyExpression,
|
||||
semantic_and: matchesEmptyTrue,
|
||||
semantic_not: matchesEmptyTrue,
|
||||
|
||||
rule_ref: function(node) {
|
||||
return matchesEmpty(asts.findRule(ast, node.name));
|
||||
},
|
||||
|
||||
literal: function(node) {
|
||||
return node.value === "";
|
||||
},
|
||||
|
||||
"class": matchesEmptyFalse,
|
||||
any: matchesEmptyFalse
|
||||
});
|
||||
|
||||
var check = visitor.build({
|
||||
rule: function(node, visitedRules) {
|
||||
check(node.expression, visitedRules.concat(node.name));
|
||||
|
@ -69,7 +27,7 @@ function reportLeftRecursion(ast) {
|
|||
check(element, visitedRules);
|
||||
}
|
||||
|
||||
return matchesEmpty(element);
|
||||
return asts.matchesEmpty(ast, element);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in a new issue