2020-03-26 15:03:19 +00:00
import parseRule from 'Engine/parseRule'
import { safeLoad } from 'js-yaml'
import { parseReference } from './parseReference'
2020-03-30 17:14:03 +00:00
import { ParsedRules , Rules } from './types'
2020-03-26 15:03:19 +00:00
/ *
Dans ce fichier , les r è gles YAML sont pars é es .
Elles expriment un langage orient é expression , les expressions é tant
- pr é fixes quand elles sont des 'mécanismes' ( des mot - clefs repr é sentant des calculs courants dans la loi )
- infixes pour les feuilles : des tests d 'égalité, d' inclusion , des comparaisons sur des variables ou tout simplement la variable elle - m ê me , ou une op é ration effectu é e sur la variable
* /
2020-03-30 17:14:03 +00:00
export default function parseRules < Names extends string > (
rawRules : Rules < Names > | string
) : ParsedRules < Names > {
const rules =
typeof rawRules === 'string'
? ( safeLoad ( rawRules . replace ( /\t/g , ' ' ) ) as Rules < Names > )
: rawRules
2020-03-26 15:03:19 +00:00
/ * F i r s t w e p a r s e e a c h r u l e o n e b y o n e . W h e n a m e c h a n i s m i s e n c o u n t e r e d , i t i s
recursively parsed . When a reference to a variable is encountered , a
'variable' node is created , we don ' t parse variables recursively . * /
let parsedRules = { }
/ * A r u l e ` A ` c a n d i s a b l e a r u l e ` B ` u s i n g t h e r u l e ` r e n d n o n a p p l i c a b l e : B `
in the definition of ` A ` . We need to map these exonerations to be able to
retreive them from ` B ` * /
let nonApplicableMapping : Record < string , any > = { }
let replacedByMapping : Record < string , any > = { }
2020-03-30 17:14:03 +00:00
; ( Object . keys ( rules ) as Names [ ] ) . map ( dottedName = > {
const parsedRule = parseRule ( rules , dottedName , parsedRules )
2020-03-26 15:03:19 +00:00
2020-03-30 17:14:03 +00:00
if ( parsedRule [ 'rend non applicable' ] ) {
nonApplicableMapping [ parsedRule . dottedName ] =
parsedRule [ 'rend non applicable' ]
2020-03-26 15:03:19 +00:00
}
2020-03-30 17:14:03 +00:00
const replaceDescriptors = parsedRule [ 'remplace' ]
2020-03-26 15:03:19 +00:00
if ( replaceDescriptors ) {
replaceDescriptors . forEach (
descriptor = >
( replacedByMapping [ descriptor . referenceName ] = [
. . . ( replacedByMapping [ descriptor . referenceName ] ? ? [ ] ) ,
2020-03-30 17:14:03 +00:00
{ . . . descriptor , referenceName : parsedRule.dottedName }
2020-03-26 15:03:19 +00:00
] )
)
}
} )
Object . entries ( nonApplicableMapping ) . forEach ( ( [ a , b ] ) = > {
b . forEach ( ruleName = > {
parsedRules [ ruleName ] . isDisabledBy . push (
parseReference ( rules , parsedRules [ ruleName ] , parsedRules ) ( a )
)
} )
} )
Object . entries ( replacedByMapping ) . forEach ( ( [ a , b ] ) = > {
parsedRules [ a ] . replacedBy = b . map ( ( { referenceName , . . . other } ) = > ( {
referenceNode : parseReference (
rules ,
parsedRules [ referenceName ] ,
parsedRules
) ( referenceName ) ,
. . . other
} ) )
} )
/ * T h e n w e n e e d t o i n f e r u n i t s . S i n c e o n l y r e f e r e n c e s t o v a r i a b l e s h a v e b e e n c r e a t e d , w e n e e d t o w a i t f o r t h e l a t t e r m a p t o c o m p l e t e b e f o r e s t a r t i n g t h i s j o b . C o n s i d e r t h i s e x a m p l e :
A = B * C
B = D / E
C unit é km
D unit é €
E unit é km
*
* When parsing A 's formula, we don' t know the unit of B , since only the final nodes have units ( it would be too cumbersome to specify a unit to each variable ) , and B hasn ' t been parsed yet .
*
* * /
2020-03-30 17:14:03 +00:00
return parsedRules as ParsedRules < Names >
2020-03-26 15:03:19 +00:00
}