1 # Copyright 2021 Northern.tech AS 2 3 # This file is part of CFEngine 3 - written and maintained by Northern.tech AS. 4 5 # This program is free software; you can redistribute it and/or modify it 6 # under the terms of the GNU General Public License as published by the 7 # Free Software Foundation; version 3. 8 9 # This program is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 14 # You should have received a copy of the GNU General Public License 15 # along with this program; if not, write to the Free Software 16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 17 18 # To the extent this program is licensed as part of the Enterprise 19 # versions of CFEngine, the applicable Commercial Open Source License 20 # (COSL) may apply to this file if you as a licensee so wish it. See 21 # included file COSL.txt. 22 23# Math Grammar 24 25# The result of this grammar is commited to the repo as math.pc 26# It's not generated as part of a build, but as a manual step 27# if you change this grammar, use 3rdparty/peg-0.1.15 to regenerate math.pc 28 29Expr <- SPACE Sum { yy->result = math_eval_pop(yy->stack, &(yy->stackp)); } 30 / . { strcpy(yy->failure, "expression could not be parsed"); } 31 32Sum <- Product ( PLUS Product { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l + r, yy->stack, &(yy->stackp)); } 33 / MINUS Product { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l - r, yy->stack, &(yy->stackp)); } 34 / CLOSE_ENOUGH Product { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(fabs(l - r) < 0.00000000000000001, yy->stack, &(yy->stackp)); } 35 / LESSEQ_THAN Product { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push((l < r || fabs(l - r) < 0.00000000000000001), yy->stack, &(yy->stackp)); } 36 / LESS_THAN Product { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l < r, yy->stack, &(yy->stackp)); } 37 / GREATEREQ_THAN Product { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push((l > r || fabs(l - r) < 0.00000000000000001), yy->stack, &(yy->stackp)); } 38 / GREATER_THAN Product { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l > r, yy->stack, &(yy->stackp)); } 39 )* 40 41Product <- Value ( POW Value { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(pow(l, r), yy->stack, &(yy->stackp)); } 42 / TIMES Value { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l * r, yy->stack, &(yy->stackp)); } 43 / DIVIDE Value { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l / r, yy->stack, &(yy->stackp)); } 44 / MOD Value { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push((long)l % (long)r, yy->stack, &(yy->stackp)); } 45 )* 46 47Value <- F_NUMBER SI_Unit { double scanned = 0; sscanf(yytext, "%lf", &scanned); math_eval_push(math_eval_pop(yy->stack, &(yy->stackp)) * scanned, yy->stack, &(yy->stackp)); /* Log(LOG_LEVEL_ERR, "YY: read FP %lf", scanned); */ } 48 / F_NUMBER { double scanned = 0; sscanf(yytext, "%lf", &scanned); math_eval_push(scanned, yy->stack, &(yy->stackp)); /*Log(LOG_LEVEL_ERR, "YY: read FP %lf", scanned);*/ } 49 / Constant 50 / Funcall 51 / OPEN Sum CLOSE 52 53Funcall <- Fname OPEN Value CLOSE { math_eval_push(EvaluateMathFunction(yy->fname, math_eval_pop(yy->stack, &(yy->stackp))), yy->stack, &(yy->stackp)); } 54 55Fname <- < ( "ceil" / "floor" / "log10" / "log2" / "log" / "sqrt" / "sin" / "cos" / "tan" / "asin" / "acos" / "atan" / "abs" / "step" ) > { strcpy(yy->fname, yytext); } 56 57Constant <- "e" { math_eval_push(2.7182818284590452354, yy->stack, &(yy->stackp)); } 58 / "log2e" { math_eval_push(1.4426950408889634074, yy->stack, &(yy->stackp)); } 59 / "log10e" { math_eval_push(0.43429448190325182765, yy->stack, &(yy->stackp)); } 60 / "ln2" { math_eval_push(0.69314718055994530942, yy->stack, &(yy->stackp)); } 61 / "ln10" { math_eval_push(2.30258509299404568402, yy->stack, &(yy->stackp)); } 62 / "pi" { math_eval_push(3.14159265358979323846, yy->stack, &(yy->stackp)); } 63 / "pi_2" { math_eval_push(1.57079632679489661923, yy->stack, &(yy->stackp)); } 64 / "pi_4" { math_eval_push(0.78539816339744830962, yy->stack, &(yy->stackp)); } 65 / "1_pi" { math_eval_push(0.31830988618379067154, yy->stack, &(yy->stackp)); } 66 / "2_pi" { math_eval_push(0.63661977236758134308, yy->stack, &(yy->stackp)); } 67 / "2_sqrtpi" { math_eval_push(1.12837916709551257390, yy->stack, &(yy->stackp)); } 68 / "sqrt2" { math_eval_push(1.41421356237309504880, yy->stack, &(yy->stackp)); } 69 / "sqrt1_2" { math_eval_push(0.70710678118654752440, yy->stack, &(yy->stackp)); } 70 71SI_Unit <- [kK] SPACE { math_eval_push(1000, yy->stack, &(yy->stackp)); } 72 / [mM] SPACE { math_eval_push(1000000, yy->stack, &(yy->stackp)); } 73 / [gG] SPACE { math_eval_push(1000000000, yy->stack, &(yy->stackp)); } 74 / [tT] SPACE { math_eval_push(1000000000000, yy->stack, &(yy->stackp)); } 75 / [pP] SPACE { math_eval_push(1000000000000000, yy->stack, &(yy->stackp)); } 76 77# Lexemes 78 79F_NUMBER <- < ( '-'? [0-9]+ '.'? [0-9]* / '-'? '.' [0-9]+ ) > SPACE 80CLOSE_ENOUGH <- '==' SPACE 81LESSEQ_THAN <- '<=' SPACE 82LESS_THAN <- '<' SPACE 83GREATEREQ_THAN <- '>=' SPACE 84GREATER_THAN <- '>' SPACE 85 86PLUS <- '+' SPACE 87MINUS <- '-' SPACE 88TIMES <- '*' SPACE 89DIVIDE <- '/' SPACE 90MOD <- '%' SPACE 91POW <- '^' SPACE / '**' SPACE 92OPEN <- '(' SPACE 93CLOSE <- ')' SPACE 94SPACE <- [ \t]* 95