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