parent
26969475f7
commit
460f0cc5bc
@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
|
||||
//
|
||||
// Check if the given element's expression is of type `semantic_*`
|
||||
//
|
||||
function isSemanticPredicate( element ) {
|
||||
|
||||
const type = element.expression.type;
|
||||
|
||||
if ( type === "semantic_and" ) return true;
|
||||
if ( type === "semantic_not" ) return true;
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Compiler pass to ensure the following are enforced:
|
||||
//
|
||||
// - plucking can not be done with an action block
|
||||
// - cannot pluck a semantic predicate
|
||||
//
|
||||
function reportIncorrectPlucking( ast, session ) {
|
||||
|
||||
session.buildVisitor( {
|
||||
|
||||
action( node ) {
|
||||
|
||||
this.visit( node.expression, true );
|
||||
|
||||
},
|
||||
|
||||
labeled( node, action ) {
|
||||
|
||||
if ( node.pick !== true ) return void 0;
|
||||
|
||||
if ( action === true )
|
||||
|
||||
session.error( `"@" cannot be used with an action block.`, node.location );
|
||||
|
||||
if ( isSemanticPredicate( node ) )
|
||||
|
||||
session.error( `"@" cannot be used on a semantic predicate.`, node.location );
|
||||
|
||||
this.visit( node.expression );
|
||||
|
||||
},
|
||||
|
||||
} )( ast );
|
||||
|
||||
}
|
||||
|
||||
module.exports = reportIncorrectPlucking;
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
|
||||
const { expect, use } = require( "chai" );
|
||||
const helpers = require( "./helpers" );
|
||||
const pass = require( "pegjs" ).compiler.passes.check.reportIncorrectPlucking;
|
||||
|
||||
use( helpers );
|
||||
|
||||
describe( "compiler pass |reportIncorrectPlucking|", function () {
|
||||
|
||||
function reports( error, edgecases ) {
|
||||
|
||||
it( error.slice( 0, -1 ), () => {
|
||||
|
||||
edgecases.forEach( grammar => expect( pass ).to.reportError( grammar, error ) );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
reports( `"@" cannot be used with an action block.`, [
|
||||
|
||||
`start1 = 'a' @'b' 'c' { /* empty action block */ }`,
|
||||
`start2 = 'a' @('b' @'c' { /* empty action block */ })`
|
||||
|
||||
] );
|
||||
|
||||
reports( `"@" cannot be used on a semantic predicate.`, [
|
||||
|
||||
`start1 = 'a' @&{ /* semantic_and */ } 'c'`,
|
||||
`start2 = 'a' @!{ /* semantic_not */ } 'c'`
|
||||
|
||||
] );
|
||||
|
||||
it( "allows valid plucking", function () {
|
||||
|
||||
expect( pass ).not.to.reportError( `
|
||||
|
||||
start1 = @'1' // return '1'
|
||||
start2 = @'1' / @'2' // return '1' or '2'
|
||||
start2 = '1' @'2' '3' // return '2'
|
||||
start3 = '1' @b:'2' '3' // return '2', label "b" can be used in semantic predicates
|
||||
start4 = a:'1' @b:'2' '3' // return '2', labels "a" and "b" can be used in semantic predicates
|
||||
start5 = @'1' @'2' '3' // return ['1', '2']
|
||||
start6 = @'1' @b:'2' '3' // return ['1', '2'], label "b" can be used in semantic predicates
|
||||
start7 = a:'1' @'2' &{} // return '2' if the semantic predicate doesnt fail
|
||||
|
||||
` );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
Loading…
Reference in New Issue