@ -5,60 +5,25 @@ var arrays = require("../../utils/arrays"),
/* Checks that no left recursion is present. */
function reportLeftRecursion ( ast ) {
function nop ( ) { }
function checkExpression ( node , appliedRules ) {
check ( node . expression , appliedRules ) ;
}
function checkSubnodes ( propertyName ) {
return function ( node , appliedRules ) {
arrays . each ( node [ propertyName ] , function ( n ) { check ( n , appliedRules ) ; } ) ;
} ;
}
var check = visitor . build ( {
grammar : checkSubnodes ( "rules" ) ,
rule :
function ( node , appliedRules ) {
check ( node . expression , appliedRules . concat ( node . name ) ) ;
} ,
named : checkExpression ,
choice : checkSubnodes ( "alternatives" ) ,
action : checkExpression ,
sequence :
function ( node , appliedRules ) {
if ( node . elements . length > 0 ) {
check ( node . elements [ 0 ] , appliedRules ) ;
}
} ,
labeled : checkExpression ,
text : checkExpression ,
simple _and : checkExpression ,
simple _not : checkExpression ,
semantic _and : nop ,
semantic _not : nop ,
optional : checkExpression ,
zero _or _more : checkExpression ,
one _or _more : checkExpression ,
rule _ref :
function ( node , appliedRules ) {
if ( arrays . contains ( appliedRules , node . name ) ) {
throw new GrammarError (
"Left recursion detected for rule \"" + node . name + "\"."
) ;
}
check ( asts . findRule ( ast , node . name ) , appliedRules ) ;
} ,
literal : nop ,
"class" : nop ,
any : nop
rule : function ( node , appliedRules ) {
check ( node . expression , appliedRules . concat ( node . name ) ) ;
} ,
sequence : function ( node , appliedRules ) {
if ( node . elements . length > 0 ) {
check ( node . elements [ 0 ] , appliedRules ) ;
}
} ,
rule _ref : function ( node , appliedRules ) {
if ( arrays . contains ( appliedRules , node . name ) ) {
throw new GrammarError (
"Left recursion detected for rule \"" + node . name + "\"."
) ;
}
check ( asts . findRule ( ast , node . name ) , appliedRules ) ;
}
} ) ;
check ( ast , [ ] ) ;