70 lines
2.5 KiB
Plaintext
70 lines
2.5 KiB
Plaintext
/*
|
|
This file is part of libeval, a simple math expression evaluator
|
|
|
|
Copyright (C) 2017 Michael Geselbracht, mgeselbracht3@gmail.com
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
%token_type { numEval::TokenType }
|
|
%extra_argument { NUMERIC_EVALUATOR* pEval }
|
|
|
|
%nonassoc VAR ASSIGN SEMCOL.
|
|
%left PLUS MINUS.
|
|
%right UNIT.
|
|
%left DIVIDE MULT.
|
|
|
|
%include {
|
|
#include <assert.h>
|
|
#include <libeval/numeric_evaluator.h>
|
|
}
|
|
|
|
%syntax_error {
|
|
pEval->parseError("Syntax error");
|
|
}
|
|
|
|
%parse_accept {
|
|
pEval->parseOk();
|
|
}
|
|
|
|
main ::= in.
|
|
|
|
/* Allow multiple statements in input string: x=1; y=2 */
|
|
in ::= stmt.
|
|
in ::= in stmt.
|
|
|
|
/* A statement can be empty, an expr or an expr followed by ';' */
|
|
stmt ::= ENDS.
|
|
stmt ::= expr(A) ENDS. { pEval->parseSetResult(A.valid ? A.dValue : NAN); }
|
|
stmt ::= expr SEMCOL. { pEval->parseSetResult(NAN); }
|
|
|
|
expr(A) ::= VALUE(B). { A.dValue = B.dValue; A.valid=true; }
|
|
expr(A) ::= expr(B) UNIT(C). { A.dValue = B.dValue * C.dValue; A.valid=B.valid; }
|
|
expr(A) ::= MINUS expr(B). { A.dValue = -B.dValue; A.valid=B.valid; }
|
|
expr(A) ::= PLUS expr(B). { A.dValue = B.dValue; A.valid=B.valid; }
|
|
expr(A) ::= VAR(B). { A.dValue = pEval->GetVar(B.text); A.valid=true; }
|
|
expr(A) ::= VAR(B) ASSIGN expr(C). { pEval->SetVar(B.text, C.dValue); A.dValue = C.dValue; A.valid=false; }
|
|
expr(A) ::= expr(B) PLUS expr(C). { A.dValue = B.dValue + C.dValue; A.valid=C.valid; }
|
|
expr(A) ::= expr(B) MINUS expr(C). { A.dValue = B.dValue - C.dValue; A.valid=C.valid; }
|
|
expr(A) ::= expr(B) MULT expr(C). { A.dValue = B.dValue * C.dValue; A.valid=C.valid; }
|
|
expr(A) ::= expr(B) DIVIDE expr(C). {
|
|
if (C.dValue != 0.0) {
|
|
A.dValue = B.dValue / C.dValue;
|
|
}
|
|
else pEval->parseError("Div by zero");
|
|
A.valid=C.valid;
|
|
}
|
|
expr(A) ::= PARENL expr(B) PARENR. { A.dValue = B.dValue; A.valid=B.valid; }
|
|
|