e6d018a88d
This is related to my last commit. I've updated all the JavaScript files to satisfy 'eslint-config-futagozaryuu', my eslint configuration. I'm sure I've probally missed something, but I've run all NPM scripts and Gulp tasks, fixed any bugs that cropped up, and updated some stuff (mainly related to generated messages), so as far as I can, tell this conversion is over (I know I've probally jixed it just by saying this ;P).
66 lines
1.5 KiB
JavaScript
66 lines
1.5 KiB
JavaScript
"use strict";
|
|
|
|
const GrammarError = require( "../../grammar-error" );
|
|
const asts = require( "../asts" );
|
|
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 ! asts.alwaysConsumesOnSuccess( ast, 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( asts.findRule( ast, node.name ) );
|
|
|
|
}
|
|
} );
|
|
|
|
check( ast );
|
|
|
|
}
|
|
|
|
module.exports = reportInfiniteRecursion;
|