Externalisation des fonctions de retraitement de la grammaire

pull/529/head
Mael 2019-05-16 15:58:30 +02:00
parent dc08b0fd0f
commit 2e085dd71c
2 changed files with 76 additions and 70 deletions

View File

@ -1,3 +1,9 @@
@preprocessor esmodule
@{%
import {string, filteredVariable, variable, temporalVariable, operation, boolean, number, percentage } from './grammarFunctions'
%}
main ->
AS {% id %}
| Comparison {% id %}
@ -15,14 +21,7 @@ Parentheses -> "(" AS ")" {% ([,e]) => e %}
ComparisonOperator -> ">" | "<" | ">=" | "<=" | "=" | "!="
Comparison -> Comparable _ ComparisonOperator _ Comparable {% ([A, , operator, , B]) => ({
[operator]:
{
type: 'comparison',
explanation:
[A, B]
}
}) %}
Comparison -> Comparable _ ComparisonOperator _ Comparable {% operation('comparison')%}
Comparable -> ( AS | NonNumericTerminal) {% ([[e]]) => e %}
@ -34,11 +33,11 @@ NonNumericTerminal ->
NegatedVariable -> "≠" _ Variable {% ([,,{variable}]) => ({'≠': {explanation: variable} }) %}
FilteredVariable -> Variable _ Filter {% ([{variable},,filter],l,reject) => ['mensuel', 'annuel'].includes(filter) ? reject : ({filter: {filter, explanation: variable}}) %}
FilteredVariable -> Variable _ Filter {% filteredVariable %}
Filter -> "[" VariableFragment "]" {% ([,filter]) => filter %}
TemporalVariable -> Variable _ TemporalTransform {% ([{variable},,temporalTransform]) => ({'temporalTransform': {explanation: variable, temporalTransform} }) %}
TemporalVariable -> Variable _ TemporalTransform {% temporalVariable %}
TemporalTransform -> "[" Temporality "]" {% d =>d[1] %}
@ -47,15 +46,7 @@ Temporality -> "annuel" | "mensuel" {% id %}
# Addition and subtraction
AS -> AS _ ASOperator _ MD {% ([A, , operator, , B]) => ({
[operator]:
{
type: 'calculation',
explanation:
[A, B]
}
}) %}
AS -> AS _ ASOperator _ MD {% operation('calculation') %}
| MD {% id %}
@ -66,16 +57,7 @@ MDOperator -> "*" {% id %}
| "/" {% id %}
# Multiplication and division
MD -> MD _ MDOperator _ Parentheses {%
([A, , operator, , B]) => ({
[operator]:
{
type: 'calculation',
explanation:
[A, B]
}
}) %}
MD -> MD _ MDOperator _ Parentheses {% operation('calculation') %}
| Parentheses {% id %}
Term -> Variable {% id %}
@ -84,20 +66,9 @@ Term -> Variable {% id %}
| percentage {% id %}
Variable -> VariableFragment (_ Dot _ VariableFragment {% ([,,,fragment]) => fragment %}):*
{% ([firstFragment, nextFragments], l, reject) => {
let fragments = [firstFragment, ...nextFragments]
if (fragments.length === 1 && ['oui', 'non'].includes(fragments[0]))
return reject
return ({variable: {
fragments
}}) }%}
{% variable %}
String -> "'" [ .'a-zA-Z\-\u00C0-\u017F ]:+ "'" {% d => ({constant: {
type: 'string',
nodeValue: d[1].join(''),
rawNode: d[1].join('')
}}) %}
String -> "'" [ .'a-zA-Z\-\u00C0-\u017F ]:+ "'" {% string %}
VariableFragment -> VariableWord (_ VariableWord {% d=> ' ' + d[1] %}):* {% d => d[0] + d[1].join('') %}
@ -109,20 +80,11 @@ Dot -> [\.] {% d => null %}
_ -> [\s] {% d => null %}
number -> [0-9]:+ ([\.] [0-9]:+):? {% d => ({constant:{
number -> [0-9]:+ ([\.] [0-9]:+):? {% number %}
rawNode: d,
nodeValue: parseFloat(d[0].join("")+(d[1]?(d[1][0]+d[1][1].join("")):""))}}) %}
percentage -> [0-9]:+ ([\.] [0-9]:+):? [\%] {% percentage %}
percentage -> [0-9]:+ ([\.] [0-9]:+):? [\%] {% d => ({ 'constant':{
rawNode: d,
type: 'percentage', nodeValue: parseFloat(d[0].join("")+(d[1]?(d[1][0]+d[1][1].join("")):""))/100}}) %}
Boolean -> ("oui"
| "non" ) {% ([val])=> ({constant:{
rawNode: val,
type: 'boolean', nodeValue: {'oui': true, 'non': false}[val]}}) %}
Boolean -> (
"oui"
| "non" ) {% boolean %}

View File

@ -1,19 +1,63 @@
import React from 'react'
/* Those are postprocessor functions for the Nearley grammar.ne.
The advantage of putting them here is to get prettier's JS formatting, since Nealrey doesn't support it https://github.com/kach/nearley/issues/310 */
export let boolean = nodeValue => ({
category: 'boolean',
nodeValue: nodeValue,
// eslint-disable-next-line
jsx: () => <span className="boolean">{rawNode}</span>
export let operation = type => ([A, , operator, , B]) => ({
[operator]: {
type: type,
explanation: [A, B]
}
})
export let filteredVariable = ([{ variable }, , filter], l, reject) =>
['mensuel', 'annuel'].includes(filter)
? reject
: { filter: { filter, explanation: variable } }
export let temporalVariable = ([{ variable }, , temporalTransform]) => ({
temporalTransform: { explanation: variable, temporalTransform }
})
export let variable = ([firstFragment, nextFragments], l, reject) => {
let fragments = [firstFragment, ...nextFragments]
if (fragments.length === 1 && ['oui', 'non'].includes(fragments[0]))
return reject
return {
variable: {
fragments
}
}
}
export let number = d => ({
constant: {
rawNode: d,
nodeValue: parseFloat(
d[0].join('') + (d[1] ? d[1][0] + d[1][1].join('') : '')
)
}
})
export let percentage = d => ({
// We don't need to handle category == 'value' because YAML then returns it as
// numerical value, not a String: it goes to treatNumber
nodeValue:
parseFloat(d[0].join('') + (d[1] ? d[1][0] + d[1][1].join('') : '')) / 100,
category: 'percentage',
// eslint-disable-next-line
jsx: () => <span className="value">{rawNode.split('%')[0]} %</span>
//on ajoute l'espace nécessaire en français avant le pourcentage
constant: {
rawNode: d,
type: 'percentage',
nodeValue:
parseFloat(d[0].join('') + (d[1] ? d[1][0] + d[1][1].join('') : '')) / 100
}
})
export let boolean = ([val]) => ({
constant: {
rawNode: val,
type: 'boolean',
nodeValue: { oui: true, non: false }[val]
}
})
export let string = d => ({
constant: {
type: 'string',
nodeValue: d[1].join(''),
rawNode: d[1].join('')
}
})