2019-06-04 14:01:21 +00:00
|
|
|
# This grammar is inspired by the "fancier grammar" tab of the nearley playground : https://omrelli.ug/nearley-playground
|
|
|
|
|
2019-09-05 13:48:22 +00:00
|
|
|
# Look for the PEMDAS system : Parentheses, Exponents (omitted here), Multiplication, and you should guess the rest :)
|
2019-06-04 14:01:21 +00:00
|
|
|
|
2019-10-18 17:15:58 +00:00
|
|
|
# This preprocessor was disabled because it doesn't work with Jest
|
|
|
|
# @preprocessor esmodule
|
2019-05-16 13:58:30 +00:00
|
|
|
|
2019-09-05 13:48:22 +00:00
|
|
|
@{%
|
2019-10-18 17:15:58 +00:00
|
|
|
const {string, filteredVariable, variable, temporalVariable, binaryOperation, unaryOperation, boolean, number, numberWithUnit, percentage } = require('./grammarFunctions')
|
2019-09-10 16:24:05 +00:00
|
|
|
|
|
|
|
const moo = require("moo");
|
|
|
|
|
|
|
|
const letter = '[a-zA-Z\u00C0-\u017F]';
|
|
|
|
const letterOrNumber = '[a-zA-Z\u00C0-\u017F0-9\']';
|
|
|
|
const word = `${letter}(?:[\-']?${letterOrNumber}+)*`;
|
2019-11-04 16:44:03 +00:00
|
|
|
const wordOrNumber = `(?:${word}|${letterOrNumber}+)`
|
|
|
|
const words = `${word}(?:[\\s]?${wordOrNumber}+)*`
|
|
|
|
const numberRegExp = '-?(?:[1-9][0-9]+|[0-9])(?:\\.[0-9]+)?';
|
2019-09-10 16:24:05 +00:00
|
|
|
const percentageRegExp = numberRegExp + '\\%'
|
|
|
|
const lexer = moo.compile({
|
|
|
|
percentage: new RegExp(percentageRegExp),
|
|
|
|
'(': '(',
|
|
|
|
')': ')',
|
|
|
|
'[': '[',
|
|
|
|
']': ']',
|
2019-09-19 09:45:16 +00:00
|
|
|
comparison: ['>','<','>=','<=','=','!='],
|
|
|
|
additionSubstraction: /[\+-]/,
|
|
|
|
multiplicationDivision: ['*','/'],
|
2019-11-04 16:44:03 +00:00
|
|
|
words: new RegExp(words),
|
|
|
|
number: new RegExp(numberRegExp),
|
2019-09-10 16:24:05 +00:00
|
|
|
string: /'[ \t\.'a-zA-Z\-\u00C0-\u017F0-9 ]+'/,
|
2019-10-23 18:00:01 +00:00
|
|
|
'€': '€',
|
2019-09-10 16:24:05 +00:00
|
|
|
dot: ' . ',
|
2019-10-23 18:00:01 +00:00
|
|
|
letterOrNumber: new RegExp(letterOrNumber),
|
2019-09-19 09:45:16 +00:00
|
|
|
space: { match: /[\s]+/, lineBreaks: true }
|
2019-09-10 16:24:05 +00:00
|
|
|
});
|
2019-10-23 18:00:01 +00:00
|
|
|
|
|
|
|
const join = (args) => ({value: (args.map(x => x && x.value).join(""))})
|
|
|
|
const flattenJoin = ([a, b]) => Array.isArray(b) ? join([a, ...b]) : a
|
2019-05-16 13:58:30 +00:00
|
|
|
%}
|
|
|
|
|
2019-09-10 16:24:05 +00:00
|
|
|
@lexer lexer
|
|
|
|
|
2017-03-07 17:25:25 +00:00
|
|
|
main ->
|
2019-09-10 16:24:05 +00:00
|
|
|
AdditionSubstraction {% id %}
|
|
|
|
| Comparison {% id %}
|
|
|
|
| NonNumericTerminal {% id %}
|
2019-09-19 09:45:16 +00:00
|
|
|
| Negation {% id %}
|
2019-05-02 13:58:39 +00:00
|
|
|
|
|
|
|
NumericTerminal ->
|
2019-09-10 16:24:05 +00:00
|
|
|
Variable {% id %}
|
|
|
|
| TemporalVariable {% id %}
|
|
|
|
| FilteredVariable {% id %}
|
|
|
|
| number {% id %}
|
2019-05-02 13:58:39 +00:00
|
|
|
|
2019-09-19 09:45:16 +00:00
|
|
|
Negation ->
|
|
|
|
"-" %space Parentheses {% unaryOperation('calculation') %}
|
2019-09-10 16:24:05 +00:00
|
|
|
Parentheses ->
|
|
|
|
"(" AdditionSubstraction ")" {% ([,e]) => e %}
|
2019-09-19 09:45:16 +00:00
|
|
|
| "(" Negation ")" {% ([,e]) => e %}
|
2019-09-10 16:24:05 +00:00
|
|
|
| NumericTerminal {% id %}
|
2019-05-02 13:58:39 +00:00
|
|
|
|
2019-09-19 09:45:16 +00:00
|
|
|
Comparison -> Comparable %space %comparison %space Comparable {% binaryOperation('comparison')%}
|
2017-03-06 16:35:30 +00:00
|
|
|
|
2019-06-04 14:01:21 +00:00
|
|
|
Comparable -> ( AdditionSubstraction | NonNumericTerminal) {% ([[e]]) => e %}
|
2019-05-02 13:58:39 +00:00
|
|
|
|
2019-09-05 13:48:22 +00:00
|
|
|
NonNumericTerminal ->
|
2019-09-10 16:24:05 +00:00
|
|
|
boolean {% id %}
|
|
|
|
| string {% id %}
|
|
|
|
|
2019-11-04 16:44:03 +00:00
|
|
|
Variable -> %words (%dot %words {% ([,words]) => words %}):* {% variable %}
|
2017-03-06 16:35:30 +00:00
|
|
|
|
2019-10-23 18:00:01 +00:00
|
|
|
BaseUnit ->
|
2019-11-04 16:44:03 +00:00
|
|
|
%words {% id %}
|
2019-10-23 18:00:01 +00:00
|
|
|
| "€" {% id %}
|
2017-06-22 16:03:12 +00:00
|
|
|
|
2019-10-23 18:00:01 +00:00
|
|
|
Unit -> BaseUnit ("/" BaseUnit {% join %}):? {% join %}
|
2017-06-22 16:03:12 +00:00
|
|
|
|
2019-11-04 16:44:03 +00:00
|
|
|
Filter -> "[" %words "]" {% ([,filter]) => filter %}
|
2019-09-19 09:45:16 +00:00
|
|
|
FilteredVariable -> Variable %space Filter {% filteredVariable %}
|
2017-03-06 16:35:30 +00:00
|
|
|
|
2019-10-23 18:00:01 +00:00
|
|
|
TemporalTransform -> "[" ("mensuel" | "annuel" {% id %}) "]" {% ([,temporality]) => temporality %}
|
2019-09-19 09:45:16 +00:00
|
|
|
TemporalVariable -> Variable %space TemporalTransform {% temporalVariable %}
|
2017-03-06 16:35:30 +00:00
|
|
|
|
2019-09-10 16:24:05 +00:00
|
|
|
AdditionSubstraction ->
|
2019-09-19 09:45:16 +00:00
|
|
|
AdditionSubstraction %space %additionSubstraction %space MultiplicationDivision {% binaryOperation('calculation') %}
|
2019-09-10 16:24:05 +00:00
|
|
|
| MultiplicationDivision {% id %}
|
2017-03-06 16:35:30 +00:00
|
|
|
|
2019-09-10 16:24:05 +00:00
|
|
|
MultiplicationDivision ->
|
2019-09-19 09:45:16 +00:00
|
|
|
MultiplicationDivision %space %multiplicationDivision %space Parentheses {% binaryOperation('calculation') %}
|
2019-09-10 16:24:05 +00:00
|
|
|
| Parentheses {% id %}
|
2017-03-06 16:35:30 +00:00
|
|
|
|
2017-09-19 11:17:43 +00:00
|
|
|
|
2019-09-10 16:24:05 +00:00
|
|
|
boolean ->
|
|
|
|
"oui" {% boolean(true) %}
|
|
|
|
| "non" {% boolean(false) %}
|
2018-08-07 18:46:26 +00:00
|
|
|
|
2019-09-10 16:24:05 +00:00
|
|
|
number ->
|
|
|
|
%number {% number %}
|
2019-10-23 18:00:01 +00:00
|
|
|
| %number %space Unit {% numberWithUnit %}
|
2019-09-10 16:24:05 +00:00
|
|
|
| %percentage {% percentage %}
|
2019-09-19 09:45:16 +00:00
|
|
|
|
2019-09-10 16:24:05 +00:00
|
|
|
string -> %string {% string %}
|