2019-02-20 10:57:35 +00:00
// This should be the new way to implement mecanisms
// In a specific file
// TODO import them automatically
// TODO convert the legacy functions to new files
2019-07-22 10:36:50 +00:00
import barème from 'Engine/mecanisms/barème'
import barèmeContinu from 'Engine/mecanisms/barème-continu'
import barèmeLinéaire from 'Engine/mecanisms/barème-linéaire'
import variations from 'Engine/mecanisms/variations'
2019-07-23 12:33:35 +00:00
import operation from 'Engine/mecanisms/operation'
2019-04-03 15:40:51 +00:00
import { Parser } from 'nearley'
2019-07-22 10:36:50 +00:00
2019-04-03 15:40:51 +00:00
import {
add ,
divide ,
equals ,
gt ,
gte ,
keys ,
2019-05-15 08:52:20 +00:00
without ,
2019-04-03 15:40:51 +00:00
lt ,
lte ,
multiply ,
propOr ,
2019-06-11 10:03:45 +00:00
subtract ,
2019-06-13 16:01:49 +00:00
fromPairs ,
is ,
2019-06-13 16:17:22 +00:00
cond ,
T
2019-04-03 15:40:51 +00:00
} from 'ramda'
import React from 'react'
import Grammar from './grammar.ne'
import {
mecanismAllOf ,
mecanismComplement ,
mecanismError ,
mecanismInversion ,
mecanismMax ,
mecanismMin ,
mecanismNumericalSwitch ,
mecanismOneOf ,
mecanismProduct ,
mecanismReduction ,
mecanismSum ,
mecanismSynchronisation ,
2019-05-14 11:52:23 +00:00
mecanismOnePossibility
2019-04-03 15:40:51 +00:00
} from './mecanisms'
2019-07-11 16:25:08 +00:00
import { parseReferenceTransforms } from './parseReference'
2019-06-13 16:01:49 +00:00
2019-06-13 16:17:22 +00:00
export let parse = ( rules , rule , parsedRules ) => rawNode => {
2019-06-13 16:01:49 +00:00
let onNodeType = cond ( [
2019-06-13 16:17:22 +00:00
[ is ( String ) , parseString ( rules , rule , parsedRules ) ] ,
2019-06-13 16:01:49 +00:00
[ is ( Number ) , parseNumber ] ,
2019-06-13 16:17:22 +00:00
[ is ( Object ) , parseObject ( rules , rule , parsedRules ) ] ,
2019-06-13 16:01:49 +00:00
[ T , parseOther ]
] )
let defaultEvaluate = ( cache , situationGate , parsedRules , node ) => node
let parsedNode = onNodeType ( rawNode )
return parsedNode . evaluate
? parsedNode
: { ... parsedNode , evaluate : defaultEvaluate }
}
2019-02-20 10:57:35 +00:00
2019-03-04 17:55:51 +00:00
export let nearley = ( ) => new Parser ( Grammar . ParserRules , Grammar . ParserStart )
2018-06-29 09:13:05 +00:00
2019-06-13 16:17:22 +00:00
export let parseString = ( rules , rule , parsedRules ) => rawNode => {
2019-05-14 17:40:47 +00:00
/ * S t r i n g s c o r r e s p o n d t o i n f i x e x p r e s s i o n s .
* Indeed , a subset of expressions like simple arithmetic operations ` 3 + (quantity * 2) ` or like ` salary [month] ` are more explicit that their prefixed counterparts .
* This function makes them prefixed operations . * /
2018-06-29 09:13:05 +00:00
2019-06-04 14:37:20 +00:00
let [ parseResult ] = nearley ( ) . feed ( rawNode ) . results
2018-06-29 09:13:05 +00:00
2019-06-13 16:17:22 +00:00
return parseObject ( rules , rule , parsedRules ) ( parseResult )
2018-06-29 09:13:05 +00:00
}
2019-06-13 16:01:49 +00:00
export let parseNumber = rawNode => ( {
2018-07-27 16:50:11 +00:00
text : '' + rawNode ,
category : 'number' ,
nodeValue : rawNode ,
type : 'numeric' ,
jsx : < span className = "number" > { rawNode } < / s p a n >
} )
2019-06-13 16:01:49 +00:00
export let parseOther = rawNode => {
2018-06-29 09:13:05 +00:00
throw new Error (
'Cette donnée : ' + rawNode + ' doit être un Number, String ou Object'
)
}
2019-05-02 14:24:22 +00:00
2019-06-13 16:17:22 +00:00
export let parseObject = ( rules , rule , parsedRules ) => rawNode => {
2019-05-15 08:52:20 +00:00
/ * T O D O i n s t e a d o f d e s c r i b i n g m e c a n i s m s i n k n o w n M e c a n i s m s . y a m l , e x t e r n a l i z e t h e m e c a n i s m s t h e m s e l v e s i n a n i n d i v i d u a l f i l e a n d d e s c r i b e i t
2018-06-29 09:13:05 +00:00
let mecanisms = intersection ( keys ( rawNode ) , keys ( knownMecanisms ) )
if ( mecanisms . length != 1 ) {
2019-05-15 08:52:20 +00:00
}
* /
let attributes = keys ( rawNode ) ,
descriptiveAttributes = [ 'description' , 'note' , 'référence' ] ,
relevantAttributes = without ( descriptiveAttributes , attributes )
if ( relevantAttributes . length !== 1 )
throw new Error ( ` OUPS : On ne devrait reconnaître que un et un seul mécanisme dans cet objet (au-delà des attributs descriptifs tels que "description", "commentaire", etc.)
2018-07-09 12:13:38 +00:00
Objet YAML : $ { JSON . stringify ( rawNode ) }
Cette liste doit avoir un et un seul élément .
2019-06-13 16:01:49 +00:00
Si vous venez tout juste d 'ajouter un nouveau mécanisme, vérifier qu' il est bien intégré dans le dispatch de parse . js
2018-07-09 12:13:38 +00:00
` )
2019-05-15 08:52:20 +00:00
let k = relevantAttributes [ 0 ] ,
2018-06-29 09:13:05 +00:00
v = rawNode [ k ]
2019-05-15 08:52:20 +00:00
let knownOperations = {
'*' : [ multiply , '∗ ' ] ,
'/' : [ divide , '∕ ' ] ,
'+' : [ add ] ,
'-' : [ subtract , '− ' ] ,
'<' : [ lt ] ,
'<=' : [ lte , '≤' ] ,
'>' : [ gt ] ,
'>=' : [ gte , '≥' ] ,
'=' : [ equals ] ,
'!=' : [ ( a , b ) => ! equals ( a , b ) , '≠' ]
} ,
2019-06-11 10:03:45 +00:00
operationDispatch = fromPairs (
Object . entries ( knownOperations ) . map ( ( [ k , [ f , symbol ] ] ) => [
k ,
2019-07-23 12:33:35 +00:00
operation ( k , f , symbol )
2019-06-11 10:03:45 +00:00
] )
2019-05-15 08:52:20 +00:00
)
2018-06-29 09:13:05 +00:00
let dispatch = {
'une de ces conditions' : mecanismOneOf ,
'toutes ces conditions' : mecanismAllOf ,
'aiguillage numérique' : mecanismNumericalSwitch ,
somme : mecanismSum ,
multiplication : mecanismProduct ,
2019-02-20 10:57:35 +00:00
barème ,
2019-07-11 16:25:08 +00:00
'barème linéaire' : barèmeLinéaire ,
'barème continu' : barèmeContinu ,
2018-06-29 09:13:05 +00:00
'le maximum de' : mecanismMax ,
'le minimum de' : mecanismMin ,
complément : mecanismComplement ,
2019-05-15 14:31:33 +00:00
'une possibilité' : mecanismOnePossibility ( rule . dottedName ) ,
2019-01-30 17:53:57 +00:00
'inversion numérique' : mecanismInversion ( rule . dottedName ) ,
2018-08-07 16:20:08 +00:00
allègement : mecanismReduction ,
2019-07-22 10:36:50 +00:00
variations ,
2019-05-15 08:52:20 +00:00
synchronisation : mecanismSynchronisation ,
... operationDispatch ,
filter : ( ) =>
2019-06-13 16:17:22 +00:00
parseReferenceTransforms ( rules , rule , parsedRules ) ( {
2019-05-15 14:31:33 +00:00
filter : v . filter ,
2019-05-15 08:52:20 +00:00
variable : v . explanation
} ) ,
2019-06-13 16:17:22 +00:00
variable : ( ) =>
parseReferenceTransforms ( rules , rule , parsedRules ) ( { variable : v } ) ,
2019-05-15 08:52:20 +00:00
temporalTransform : ( ) =>
2019-06-13 16:17:22 +00:00
parseReferenceTransforms ( rules , rule , parsedRules ) ( {
2019-05-15 08:52:20 +00:00
variable : v . explanation ,
temporalTransform : v . temporalTransform
} ) ,
constant : ( ) => ( {
type : v . type ,
nodeValue : v . nodeValue ,
2019-07-11 15:07:34 +00:00
unit : v . unit ,
2019-05-15 08:52:20 +00:00
// eslint-disable-next-line
jsx : ( ) => < span className = { v . type } > { v . rawNode } < / s p a n >
} )
2018-06-29 09:13:05 +00:00
} ,
action = propOr ( mecanismError , k , dispatch )
2019-06-13 16:17:22 +00:00
return action ( parse ( rules , rule , parsedRules ) , k , v )
2018-06-29 09:13:05 +00:00
}