You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pegjs/lib/compiler/passes/report-infinite-recursion.js

65 lines
1.4 KiB
JavaScript

"use strict";
const GrammarError = require( "../../grammar-error" );
const visitor = require( "../visitor" );
// Reports left recursion in the grammar, which prevents infinite recursion in
// the generated parser.
//
// Both direct and indirect recursion is detected. The pass also correctly
// reports cases like this:
//
// start = "a"? start
//
// In general, if a rule reference can be reached without consuming any input,
// it can lead to left recursion.
function reportInfiniteRecursion( ast ) {
const visitedRules = [];
const check = visitor.build( {
rule( node ) {
visitedRules.push( node.name );
check( node.expression );
visitedRules.pop( node.name );
},
sequence( node ) {
node.elements.every( element => {
check( element );
return ! ast.alwaysConsumesOnSuccess( element );
} );
},
rule_ref( node ) {
if ( visitedRules.indexOf( node.name ) !== -1 ) {
visitedRules.push( node.name );
const rulePath = visitedRules.join( " -> " );
throw new GrammarError(
`Possible infinite loop when parsing (left recursion: ${ rulePath }).`,
node.location
);
}
check( ast.findRule( node.name ) );
}
} );
check( ast );
}
module.exports = reportInfiniteRecursion;