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-duplicate-labels.js

84 lines
1.8 KiB
JavaScript

"use strict";
const GrammarError = require( "../../grammar-error" );
const visitor = require( "../visitor" );
// Checks that each label is defined only once within each scope.
function reportDuplicateLabels( ast ) {
let check;
function cloneEnv( env ) {
const clone = {};
Object.keys( env ).forEach( name => {
clone[ name ] = env[ name ];
} );
return clone;
}
function checkExpressionWithClonedEnv( node, env ) {
check( node.expression, cloneEnv( env ) );
}
check = visitor.build( {
rule( node ) {
check( node.expression, {} );
},
choice( node, env ) {
node.alternatives.forEach( alternative => {
check( alternative, cloneEnv( env ) );
} );
},
action: checkExpressionWithClonedEnv,
labeled( node, env ) {
const label = node.label;
if ( Object.prototype.hasOwnProperty.call( env, label ) ) {
const start = env[ label ].start;
throw new GrammarError(
`Label "${ label }" is already defined at line ${ start.line }, column ${ start.column }.`,
node.location
);
}
check( node.expression, env );
env[ label ] = node.location;
},
text: checkExpressionWithClonedEnv,
simple_and: checkExpressionWithClonedEnv,
simple_not: checkExpressionWithClonedEnv,
optional: checkExpressionWithClonedEnv,
zero_or_more: checkExpressionWithClonedEnv,
one_or_more: checkExpressionWithClonedEnv,
group: checkExpressionWithClonedEnv
} );
check( ast );
}
module.exports = reportDuplicateLabels;