import { Option } from 'ts-std' ; import ParseError from './parse-error' ; export interface ConfigurationPredicate { eval ( cfg ) : boolean ; } class ConfigurationOption implements ConfigurationPredicate { static parse ( input , lineno ) { if ( input === '' || /\(|\)|,/ . test ( input ) ) { throw new ParseError ( 'expecting a single cfg predicate' , lineno ) ; } return new this ( input ) ; } private constructor ( private option ) { } eval ( cfg ) { return cfg . includes ( this . option ) ; } } class ConfigurationAll implements ConfigurationPredicate { static parse ( input , lineno ) { let match = /^all\((.+)\)$/ . exec ( input ) ; if ( match ) { return new this ( parsePredicates ( match [ 1 ] , lineno ) ) ; } else { return null ; } } private constructor ( private predicates ) { } eval ( cfg ) { return this . predicates . every ( p => p . eval ( cfg ) ) ; } } class ConfigurationAny implements ConfigurationPredicate { static parse ( input , lineno ) { let match = /^any\((.+)\)$/ . exec ( input ) ; if ( match ) { return new this ( parsePredicates ( match [ 1 ] , lineno ) ) ; } else { return null ; } } private constructor ( private predicates ) { } eval ( cfg ) { return this . predicates . some ( p => p . eval ( cfg ) ) ; } } class ConfigurationNot implements ConfigurationPredicate { static parse ( input , lineno ) { let match = /^not\((.+)\)$/ . exec ( input ) ; if ( match ) { return new this ( parse ( match [ 1 ] , lineno ) ) ; } else { return null ; } } private constructor ( private predicate ) { } eval ( cfg ) { return ! this . predicate . eval ( cfg ) ; } } export default function parse ( input , lineno ) { return ConfigurationAll . parse ( input , lineno ) || ConfigurationAny . parse ( input , lineno ) || ConfigurationNot . parse ( input , lineno ) || ConfigurationOption . parse ( input , lineno ) ; } function parsePredicates ( input , lineno ) { let items = input . split ( ',' ) . map ( item => item . trim ( ) ) ; if ( items . length > 0 && items [ items . length - 1 ] === '' ) { items . pop ( ) ; } if ( items . length === 0 ) { throw new ParseError ( 'expecting at least one cfg predicate' , lineno ) ; } return items . map ( item => parse ( item , lineno ) ) ; }