From 3b978d061ad72c1c5b8fabc2d7121e8159a544d0 Mon Sep 17 00:00:00 2001 From: Mael Date: Tue, 14 May 2019 19:40:47 +0200 Subject: [PATCH] =?UTF-8?q?R=C3=A9=C3=A9criture=20de=20la=20grammaire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Elle renvoit un objet qui est une vision prefixe du contenu parsé --- source/engine/grammar.ne | 70 +++++++++++------------ source/engine/treat.js | 116 ++------------------------------------- 2 files changed, 37 insertions(+), 149 deletions(-) diff --git a/source/engine/grammar.ne b/source/engine/grammar.ne index 1598a251f..115ff8137 100644 --- a/source/engine/grammar.ne +++ b/source/engine/grammar.ne @@ -1,9 +1,3 @@ -@preprocessor esmodule - -@{% -import maSuperFonction from './maSuperFonction' -import treatVariableTransforms from './treatVariable' -%} # To understand or edit this file, use the awesome nearley playground (but save your work, it can crash sometimes) : https://omrelli.ug/nearley-playground/ @@ -21,13 +15,17 @@ NumericTerminal -> | number {% id %} # Parentheses -P -> "(" _ AS _ ")" {% function(d) {return {category:'parentheses', explanation: d[2]}} %} +P -> "(" _ AS _ ")" {% ([,,e]) => e %} | NumericTerminal {% id %} +ComparisonOperator -> ">" | "<" | ">=" | "<=" | "=" | "!=" -Comparison -> Comparable _ ComparisonOperator _ Comparable {% yo => maSuperFonction(yo) %} +Comparison -> Comparable _ ComparisonOperator _ Comparable {% ([A, , operator, , B]) => ({ + [operator]: + [A, B] +}) %} -Comparable -> ( AS | NonNumericTerminal) {% d => d[0][0] %} +Comparable -> ( AS | NonNumericTerminal) {% ([[e]]) => e %} NonNumericTerminal -> Boolean {% id %} @@ -35,28 +33,24 @@ NonNumericTerminal -> | NegatedVariable {% id %} -ComparisonOperator -> ">" | "<" | ">=" | "<=" | "=" | "!=" +NegatedVariable -> "≠" _ Variable {% ([,,variable]) => ({'≠': variable }) %} -NegatedVariable -> "≠" _ Variable {% d => ({category: 'negatedVariable', variable: d[2] }) %} +FilteredVariable -> Variable _ Filter {% ([variable,,filtre]) => ({filtre: {filtre, variable}}) %} -FilteredVariable -> Variable _ Filter {% d => ({category: 'variable', filter: d[2], variable: d[0] }) %} +Filter -> "(" VariableFragment ")" {% ([,filtre]) =>filtre %} -Filter -> "(" VariableFragment ")" {% d =>d[1] %} +TemporalVariable -> Variable _ TemporalTransform {% ([variable,,chemin]) => ({'conversion temporelle': {variable, chemin}}) %} -TemporalVariable -> Variable _ TemporalTransform {% d => ({...d[0], temporalTransform: d[2] }) %} +TemporalTransform -> "[" Temporality "]" {% d =>d[1] %} -TemporalTransform -> "[" Temporalities "]" {% d =>d[1] %} - -Temporalities -> "annuel" | "mensuel" {% id %} +Temporality -> "annuel" | "mensuel" {% id %} #----- # Addition and subtraction -AS -> AS _ ASOperator _ MD {% d => ({ - category: 'calcExpression', - operator: d[2], - explanation: [d[0], d[4]], - type: 'numeric' +AS -> AS _ ASOperator _ MD {% ([A, , operator, , B]) => ({ + [operator]: + [A, B] }) %} | MD {% id %} @@ -69,11 +63,10 @@ MDOperator -> "*" {% id %} | "/" {% id %} # Multiplication and division -MD -> MD _ MDOperator _ P {% d => ({ - category: 'calcExpression', - operator: d[2], - explanation: [d[0], d[4]], - type: 'numeric' +MD -> MD _ MDOperator _ P {% +([A, , operator, , B]) => ({ + [operator]: + [A, B] }) %} | P {% id %} @@ -83,16 +76,18 @@ Term -> Variable {% id %} | number {% id %} | percentage {% id %} -Variable -> VariableFragment (_ Dot _ VariableFragment {% [,,,fragment] => fragment %}):* -{% ([firstFragment, nextFragments]) => treatVariableTransforms({ +Variable -> VariableFragment (_ Dot _ VariableFragment {% ([,,,fragment]) => fragment %}):* +{% ([firstFragment, nextFragments]) => +({variable: { + category: 'variable', fragments: [firstFragment, ...nextFragments], -}) %} +}}) %} -String -> "'" [ .'a-zA-Z\-\u00C0-\u017F ]:+ "'" {% d => ({ - category: 'value', +String -> "'" [ .'a-zA-Z\-\u00C0-\u017F ]:+ "'" {% d => ({constante: { + type: 'string', nodeValue: d[1].join('') -}) %} +}}) %} VariableFragment -> VariableWord (_ VariableWord {% d=> ' ' + d[1] %}):* {% d => d[0] + d[1].join('') %} @@ -104,10 +99,11 @@ Dot -> [\.] {% d => null %} _ -> [\s] {% d => null %} -number -> [0-9]:+ ([\.] [0-9]:+):? {% d => ({category: 'value', nodeValue: parseFloat(d[0].join("")+(d[1]?(d[1][0]+d[1][1].join("")):""))}) %} +number -> [0-9]:+ ([\.] [0-9]:+):? {% d => ({constante:{ nodeValue: parseFloat(d[0].join("")+(d[1]?(d[1][0]+d[1][1].join("")):""))}}) %} -percentage -> [0-9]:+ ([\.] [0-9]:+):? [\%] {% d => percentage(d)%} +percentage -> [0-9]:+ ([\.] [0-9]:+):? [\%] {% d => ({ 'percentage':{ nodeValue: parseFloat(d[0].join("")+(d[1]?(d[1][0]+d[1][1].join("")):""))/100}}) %} -Boolean -> "oui" {% d=> ({category: 'boolean', nodeValue: true}) %} - | "non" {% d=> ({category: 'boolean', nodeValue: false}) %} + +Boolean -> ("oui" + | "non" ) {% ([val])=> ({constante:{type: 'boolean', nodeValue: {'oui': true, 'non': false}[val]}}) %} diff --git a/source/engine/treat.js b/source/engine/treat.js index 8903aef81..eef12d4f0 100644 --- a/source/engine/treat.js +++ b/source/engine/treat.js @@ -58,11 +58,9 @@ import { export let nearley = () => new Parser(Grammar.ParserRules, Grammar.ParserStart) export let treatString = (rules, rule) => rawNode => { - /* On a affaire à un string, donc à une expression infixe. - Elle sera traité avec le parser obtenu grâce à NearleyJs et notre grammaire `grammar.ne`. - On obtient un objet de type Variable (avec potentiellement un 'modifier', par exemple temporel), CalcExpression ou Comparison. - Cet objet est alors rebalancé à 'treat'. - */ + /* Strings correspond to infix expressions. + * 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. */ let [parseResult, ...additionnalResults] = nearley().feed(rawNode).results @@ -79,113 +77,7 @@ export let treatString = (rules, rule) => rawNode => { ) } - if (parseResult.category == 'variable') - return treatVariableTransforms(rules, rule)(parseResult) - if (parseResult.category == 'negatedVariable') - return treatNegatedVariable( - treatVariable(rules, rule)(parseResult.variable) - ) - - if ( - parseResult.category == 'calcExpression' || - parseResult.category == 'comparison' - ) { - let evaluate = (cache, situation, parsedRules, node) => { - let operatorFunction = { - '*': multiply, - '/': divide, - '+': add, - '-': subtract, - '<': lt, - '<=': lte, - '>': gt, - '>=': gte, - '=': equals, - '!=': (a, b) => !equals(a, b) - }[node.operator], - explanation = map( - curry(evaluateNode)(cache, situation, parsedRules), - node.explanation - ), - value1 = explanation[0].nodeValue, - value2 = explanation[1].nodeValue, - nodeValue = - value1 == null || value2 == null - ? null - : operatorFunction(value1, value2), - missingVariables = mergeMissing( - explanation[0].missingVariables, - explanation[1].missingVariables - ) - - return rewriteNode(node, nodeValue, explanation, missingVariables) - } - - let explanation = parseResult.explanation.map( - cond([ - [ - propEq('category', 'variable'), - treatVariableTransforms(rules, rule) - ], - [ - propEq('category', 'value'), - node => ({ - nodeValue: node.nodeValue, - // eslint-disable-next-line - jsx: nodeValue => {nodeValue} - }) - ], - [ - propEq('category', 'percentage'), - node => ({ - nodeValue: node.nodeValue, - // eslint-disable-next-line - jsx: nodeValue => ( - {nodeValue * 100}% - ) - //the best would be to display the original text before parsing, but nearley does'nt let us access it - }) - ] - ]) - ), - operator = parseResult.operator - let operatorToUnicode = operator => - ({ - '>=': '≥', - '<=': '≤', - '!=': '≠', - '*': '∗', - '/': '∕', - '-': '−' - }[operator] || operator) - let jsx = (nodeValue, explanation) => ( - - - {makeJsx(explanation[0])} - - {operatorToUnicode(parseResult.operator)} - - {makeJsx(explanation[1])} - - } - /> - ) - - return { - evaluate, - jsx, - - operator, - text: rawNode, - category: parseResult.category, - type: parseResult.category == 'calcExpression' ? 'numeric' : 'boolean', - explanation - } - } + return treatObject(rules, rule)(parseResult) } export let treatNumber = rawNode => ({