committed by
Maciej Suminski
8 changed files with 1678 additions and 1 deletions
-
2common/CMakeLists.txt
-
7common/base_units.cpp
-
1011common/libeval/grammar.c
-
68common/libeval/grammar.lemon
-
52common/libeval/main.cpp
-
334common/libeval/numeric_evaluator.cpp
-
12include/libeval/grammar.h
-
193include/libeval/numeric_evaluator.h
1011
common/libeval/grammar.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,68 @@ |
|||
/* |
|||
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 { NumericEvaluator* pEval } |
|||
|
|||
%nonassoc VAR ASSIGN UNIT SEMCOL. |
|||
%left PLUS MINUS. |
|||
%left DIVIDE MULT. |
|||
|
|||
%include { |
|||
#include <assert.h> |
|||
#include <math.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) ::= VALUE(B) UNIT(C). { A.dValue = B.dValue * C.dValue; A.valid=true; } |
|||
expr(A) ::= MINUS 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; } |
|||
|
@ -0,0 +1,52 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
|
|||
#include <stdio.h>
|
|||
#include <assert.h>
|
|||
|
|||
#include "numeric_evaluator.h"
|
|||
|
|||
int main() |
|||
{ |
|||
NumericEvaluator eval; |
|||
|
|||
eval.process("2.54mm+50mil"); |
|||
if (eval.isValid()) printf("%s\n", eval.result()); |
|||
|
|||
eval.process("x=1; y=5;"); |
|||
if (eval.isValid()) printf("%s\n", eval.result()); |
|||
eval.process("x+y"); |
|||
if (eval.isValid()) printf("%s\n", eval.result()); |
|||
|
|||
eval.setVar("posx", -3.14152); |
|||
bool retval = eval.process("posx"); |
|||
assert(retval == eval.isValid()); |
|||
if (eval.isValid()) printf("%s\n", eval.result()); |
|||
|
|||
eval.process("x=1; y=2"); |
|||
eval.setVar("z", 3); |
|||
eval.process("x+y+z"); |
|||
printf("x+y+z=%s\n", eval.result()); |
|||
|
|||
eval.process("1\""); |
|||
printf("1\" = %s\n", eval.result()); |
|||
eval.process("12.7 - 0.1\" - 50mil"); |
|||
printf("12.7 - 0.1\" - 50mil = %s\n", eval.result()); |
|||
} |
|||
|
@ -0,0 +1,334 @@ |
|||
/*
|
|||
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/>.
|
|||
*/ |
|||
|
|||
#define TESTMODE 0
|
|||
|
|||
#include <libeval/numeric_evaluator.h>
|
|||
|
|||
#if !TESTMODE
|
|||
#include <common.h>
|
|||
#else
|
|||
#include <unistd.h>
|
|||
#endif
|
|||
|
|||
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
#include <ctype.h>
|
|||
|
|||
|
|||
/* The (generated) lemon parser is written in C.
|
|||
* In order to keep its symbol from the global namespace include the parser code with |
|||
* a C++ namespace. |
|||
*/ |
|||
namespace numEval |
|||
{ |
|||
|
|||
#ifdef __GNUC__
|
|||
#pragma GCC diagnostic push
|
|||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
|||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
|||
#endif
|
|||
|
|||
#include "grammar.c"
|
|||
#ifdef __GNUC__
|
|||
#pragma GCC diagnostic pop
|
|||
#endif
|
|||
|
|||
} /* namespace numEval */ |
|||
|
|||
NumericEvaluator :: NumericEvaluator() : pClParser(0) |
|||
{ |
|||
cClDecSep = '.'; |
|||
|
|||
bClTextInputStorage = true; |
|||
|
|||
init(); |
|||
} |
|||
|
|||
NumericEvaluator :: ~NumericEvaluator() |
|||
{ |
|||
numEval::ParseFree(pClParser, free); |
|||
|
|||
// Allow explicit call to destructor
|
|||
pClParser = nullptr; |
|||
|
|||
clear(); |
|||
} |
|||
|
|||
void |
|||
NumericEvaluator :: init() |
|||
{ |
|||
if (pClParser == nullptr) |
|||
pClParser = numEval::ParseAlloc(malloc); |
|||
|
|||
//numEval::ParseTrace(stdout, "lib");
|
|||
|
|||
#if TESTMODE
|
|||
eClUnitDefault = Unit::Metric; |
|||
#else
|
|||
switch (g_UserUnit) |
|||
{ |
|||
case INCHES : eClUnitDefault = Unit::Inch; break; |
|||
case MILLIMETRES : eClUnitDefault = Unit::Metric; break; |
|||
default: eClUnitDefault = Unit::Metric; break; |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
void |
|||
NumericEvaluator :: clear() |
|||
{ |
|||
free(clToken.token); |
|||
clToken.token = nullptr; |
|||
clToken.input = nullptr; |
|||
bClError = true; |
|||
} |
|||
|
|||
void |
|||
NumericEvaluator :: parse(int token, numEval::TokenType value) |
|||
{ |
|||
numEval::Parse(pClParser, token, value, this); |
|||
} |
|||
|
|||
void |
|||
NumericEvaluator :: parseError(const char* s) |
|||
{ |
|||
bClError = true; |
|||
} |
|||
|
|||
void |
|||
NumericEvaluator :: parseOk() |
|||
{ |
|||
bClError = false; |
|||
bClParseFinished = true; |
|||
} |
|||
|
|||
void |
|||
NumericEvaluator :: parseSetResult(double val) |
|||
{ |
|||
snprintf(clToken.token, clToken.OutLen, "%g", val); |
|||
} |
|||
|
|||
const char* |
|||
NumericEvaluator :: textInput(const void* pObj) const |
|||
{ |
|||
auto it = clObjMap.find(pObj); |
|||
if (it != clObjMap.end()) return it->second.c_str(); |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
bool |
|||
NumericEvaluator :: process(const char* s) |
|||
{ |
|||
/* Process new string.
|
|||
* Feed parser token after token until end of input. |
|||
*/ |
|||
|
|||
newString(s); |
|||
|
|||
if (pClParser == nullptr) init(); |
|||
bClParseFinished = false; |
|||
|
|||
Token tok; |
|||
numEval::TokenType parseTok; |
|||
do { |
|||
tok = getToken(); |
|||
parse(tok.token, tok.value); |
|||
if (bClParseFinished || tok.token == ENDS) { |
|||
numEval::Parse(pClParser, 0, parseTok, this); |
|||
break; |
|||
} |
|||
//usleep(200000);
|
|||
} while (tok.token); |
|||
|
|||
return !bClError; |
|||
} |
|||
|
|||
bool |
|||
NumericEvaluator :: process(const char* s, const void* pObj) |
|||
{ |
|||
if (bClTextInputStorage) // Store input string for (text entry) pObj.
|
|||
clObjMap[pObj] = s; |
|||
return process(s); |
|||
} |
|||
|
|||
void |
|||
NumericEvaluator :: newString(const char* s) |
|||
{ |
|||
clear(); |
|||
auto len = strlen(s); |
|||
clToken.token = reinterpret_cast<decltype(clToken.token)>(malloc(TokenStat::OutLen+1)); |
|||
clToken.inputLen = len; |
|||
clToken.pos = 0; |
|||
clToken.input = s; |
|||
bClParseFinished = false; |
|||
} |
|||
|
|||
NumericEvaluator::Token |
|||
NumericEvaluator :: getToken() |
|||
{ |
|||
Token retval; |
|||
size_t idx; |
|||
|
|||
retval.token = ENDS; |
|||
retval.value.dValue = 0; |
|||
|
|||
if (clToken.token == nullptr) return retval; |
|||
if (clToken.input == nullptr) return retval; |
|||
if (clToken.pos >= clToken.inputLen) return retval; |
|||
|
|||
// Lambda: get value as string, store into clToken.token and update current index.
|
|||
auto extractNumber = [&idx, this]() { |
|||
short sepCount = 0; |
|||
idx = 0; |
|||
auto ch = clToken.input[clToken.pos]; |
|||
do { |
|||
if (ch == cClDecSep && sepCount) break; |
|||
clToken.token[idx++] = ch; |
|||
if (ch == cClDecSep) sepCount++; |
|||
ch = clToken.input[++clToken.pos]; |
|||
} while (isdigit(ch) || ch == cClDecSep); |
|||
clToken.token[idx] = 0; |
|||
}; |
|||
|
|||
// Lamda: Get unit for current token. Returns Unit::Invalid if token is not a unit.
|
|||
auto checkUnit = [this]() -> Unit { |
|||
// '"' or "mm" or "mil"
|
|||
char ch = clToken.input[clToken.pos]; |
|||
if (ch == '"' || ch == 'm') { |
|||
Unit convertFrom = Unit::Invalid; |
|||
if (ch == '"') { |
|||
convertFrom = Unit::Inch; |
|||
clToken.pos++; |
|||
} |
|||
else { |
|||
// Do not use strcasecmp() as it is not available on all platforms
|
|||
const char* cptr = &clToken.input[clToken.pos]; |
|||
const auto sizeLeft = clToken.inputLen - clToken.pos; |
|||
if (sizeLeft >= 2) { |
|||
if (tolower(cptr[1]) == 'm' && !isalnum(cptr[2])) { |
|||
convertFrom = Unit::Metric; |
|||
clToken.pos += 2; |
|||
} |
|||
else if (sizeLeft >= 3) { |
|||
if (tolower(cptr[1]) == 'i' && tolower(cptr[2]) == 'l' && !isalnum(cptr[3])) { |
|||
convertFrom = Unit::Mil; |
|||
clToken.pos += 3; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return convertFrom; |
|||
} |
|||
return Unit::Invalid; |
|||
}; |
|||
|
|||
// Start processing of first/next token: Remove whitespace
|
|||
char ch; |
|||
for (;;) { |
|||
ch = clToken.input[clToken.pos]; |
|||
if (ch == ' ') { |
|||
clToken.pos++; |
|||
} |
|||
else break; |
|||
} |
|||
|
|||
Unit convertFrom; |
|||
|
|||
if (ch == 0) { |
|||
/* End of input */ |
|||
} |
|||
else if (isdigit(ch) || ch == cClDecSep) { // VALUE
|
|||
extractNumber(); |
|||
retval.token = VALUE; |
|||
retval.value.dValue = atof(clToken.token); |
|||
} |
|||
else if ((convertFrom = checkUnit()) != Unit::Invalid) { // UNIT
|
|||
/* Units are appended to a VALUE.
|
|||
* Determine factor to default unit if unit for value is given. |
|||
* Example: Default is mm, unit is inch: factor is 25.4 |
|||
* The factor is assigned to the terminal UNIT. The actual |
|||
* conversion is done within a parser action. |
|||
*/ |
|||
retval.token = UNIT; |
|||
if (eClUnitDefault == Unit::Metric) |
|||
{ |
|||
switch (convertFrom) |
|||
{ |
|||
case Unit::Inch : retval.value.dValue = 25.4; break; |
|||
case Unit::Mil : retval.value.dValue = 25.4/1000.0; break; |
|||
case Unit::Metric : retval.value.dValue = 1.0; break; |
|||
case Unit::Invalid : break; |
|||
} |
|||
} |
|||
else if (eClUnitDefault == Unit::Inch) |
|||
{ |
|||
switch (convertFrom) |
|||
{ |
|||
case Unit::Inch : retval.value.dValue = 1.0; break; |
|||
case Unit::Mil : retval.value.dValue = 1.0/1000.0; break; |
|||
case Unit::Metric : retval.value.dValue = 1.0/25.4; break; |
|||
case Unit::Invalid : break; |
|||
} |
|||
} |
|||
} |
|||
else if (isalpha(ch)) { // VAR
|
|||
const char* cptr = &clToken.input[clToken.pos]; |
|||
cptr++; |
|||
while (isalnum(*cptr)) cptr++; |
|||
retval.token = VAR; |
|||
size_t bytesToCopy = cptr - &clToken.input[clToken.pos]; |
|||
if (bytesToCopy >= sizeof(retval.value.text)) bytesToCopy = sizeof(retval.value.text)-1; |
|||
strncpy(retval.value.text, &clToken.input[clToken.pos], bytesToCopy); |
|||
retval.value.text[bytesToCopy] = 0; |
|||
clToken.pos += cptr - &clToken.input[clToken.pos]; |
|||
} |
|||
else { // Single char tokens
|
|||
switch (ch) { |
|||
case '+' : retval.token = PLUS; break; |
|||
case '-' : retval.token = MINUS; break; |
|||
case '*' : retval.token = MULT; break; |
|||
case '/' : retval.token = DIVIDE; break; |
|||
case '(' : retval.token = PARENL; break; |
|||
case ')' : retval.token = PARENR; break; |
|||
case '=' : retval.token = ASSIGN; break; |
|||
case ';' : retval.token = SEMCOL; break; |
|||
} |
|||
clToken.pos++; |
|||
} |
|||
|
|||
return retval; |
|||
} |
|||
|
|||
void |
|||
NumericEvaluator :: setVar(const std::string& s, double value) |
|||
{ |
|||
clVarMap[s] = value; |
|||
} |
|||
|
|||
double |
|||
NumericEvaluator :: getVar(const std::string& s) |
|||
{ |
|||
auto result = clVarMap.find(s); |
|||
if (result != clVarMap.end()) return result->second; |
|||
return 0.0; |
|||
} |
@ -0,0 +1,12 @@ |
|||
#define VAR 1 |
|||
#define ASSIGN 2 |
|||
#define UNIT 3 |
|||
#define SEMCOL 4 |
|||
#define PLUS 5 |
|||
#define MINUS 6 |
|||
#define DIVIDE 7 |
|||
#define MULT 8 |
|||
#define ENDS 9 |
|||
#define VALUE 10 |
|||
#define PARENL 11 |
|||
#define PARENR 12 |
@ -0,0 +1,193 @@ |
|||
/* |
|||
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/>. |
|||
*/ |
|||
|
|||
/* |
|||
An evaluator object is used to replace an input string that represents |
|||
a mathematical expression by its result. |
|||
|
|||
Example: Consider the input "3+4". The result of this expression is "7". |
|||
The NumericEvaluator can be used like this: |
|||
|
|||
NumericEvaluator eval; |
|||
eval.process("3+4"); |
|||
printf("3+4", eval.result()); |
|||
|
|||
The same example with error checking. Please note that even a valid input string may result |
|||
in an empty output string or "NaN". |
|||
|
|||
NumericEvaluator eval; |
|||
bool ret = eval.process("3+4"); |
|||
assert(ret == eval.isValid()); // isValid() reflects return value of process(). |
|||
if (eval.isValid()) printf("3+4=%s\n", eval.result()); |
|||
|
|||
Using variables |
|||
Expressions can refer to variables if they were defined by previous expressions. |
|||
A variable can be defined by an expression or by the setVar() method. |
|||
Expressions that define/set variables do not have a result. |
|||
|
|||
eval.process("x=1; y=2"); // Result is NaN |
|||
eval.setVar("z", 3); |
|||
eval.process("x+y+z"); |
|||
printf("x+y+z=%s\n", eval.result()); |
|||
|
|||
Input string storage |
|||
An evaluator object can store and retrieve the original input string using a pointer |
|||
as key. This can be used to restore the input string of a text entry field. |
|||
|
|||
eval.process("25.4-0.7", &eval); |
|||
printf("%s = %s\n", eval.textInput(&eval), eval.result()); |
|||
|
|||
Unit conversion |
|||
The evaluator uses a default unit and constants can be specified with a unit. |
|||
As long as no units are used the default unit is not relevant. The default |
|||
unit is taken from the global (Kicad) variable g_UserUnit. |
|||
Supported units are millimeters (mm), Mil (mil) and inch (") |
|||
|
|||
eval.process("1\""); |
|||
printf("1\" = %s\n", eval.result()); |
|||
eval.process("12.7 - 0.1\" - 50mil"); |
|||
printf("12.7 - 0.1\" - 50mil = %s\n", eval.result()); |
|||
*/ |
|||
|
|||
#ifndef NUMERIC_EVALUATOR_H_ |
|||
#define NUMERIC_EVALUATOR_H_ |
|||
|
|||
#include "grammar.h" |
|||
#include <stddef.h> |
|||
#include <string> |
|||
#include <string> |
|||
#include <map> |
|||
|
|||
// This namespace is used for the lemon parser |
|||
namespace numEval |
|||
{ |
|||
|
|||
struct TokenType |
|||
{ |
|||
union { |
|||
double dValue; |
|||
int iValue; |
|||
}; |
|||
bool valid; |
|||
char text[32]; |
|||
}; |
|||
|
|||
} // namespace numEval |
|||
|
|||
class NumericEvaluator { |
|||
enum class Unit { Invalid, Metric, Inch, Mil }; |
|||
|
|||
public: |
|||
NumericEvaluator(); |
|||
~NumericEvaluator(); |
|||
|
|||
/* Initialization and destruction. init() is invoked be the constructor and should not be needed |
|||
* by the user. |
|||
* clear() should be invoked by the user if a new input string is to be processed. It will reset |
|||
* the parser. User defined variables are retained. |
|||
*/ |
|||
void init(); |
|||
void clear(); |
|||
|
|||
/* Set the decimal separator for the input string. Defaults to '.' */ |
|||
void setDecimalSeparator(char sep); |
|||
|
|||
/* Enable or disable support for input string storage. |
|||
* If enabled the input string is saved if process(const char*, const void*) is used. |
|||
*/ |
|||
void enableTextInputStorage(bool w) { bClTextInputStorage = w; } |
|||
|
|||
/* Used by the lemon parser */ |
|||
void parse(int token, numEval::TokenType value); |
|||
void parseError(const char* s); |
|||
void parseOk(); |
|||
void parseSetResult(double); |
|||
|
|||
/* Check if previous invokation of process() was successful */ |
|||
inline bool isValid() const { return !bClError; } |
|||
|
|||
/* Result of string processing. Undefined if !isValid() */ |
|||
inline const char* result() const { return clToken.token; } |
|||
|
|||
/* Evaluate input string. |
|||
* Result can be retrieved by result(). |
|||
* Returns true if input string could be evaluated, otherwise false. |
|||
*/ |
|||
bool process(const char* s); |
|||
|
|||
/* Like process(const char*) but also stores input string in a std:map with key pObj. */ |
|||
bool process(const char* s, const void* pObj); |
|||
|
|||
/* Retrieve old input string with key pObj. */ |
|||
const char* textInput(const void* pObj) const; |
|||
|
|||
/* Add/set variable with value */ |
|||
void setVar(const std::string&, double value); |
|||
|
|||
/* Get value of variable. Returns 0.0 if not defined. */ |
|||
double getVar(const std::string&); |
|||
|
|||
/* Remove single variable */ |
|||
void removeVar(const std::string& s) { clVarMap.erase(s); } |
|||
|
|||
/* Remove all variables */ |
|||
void clearVar() { clVarMap.clear(); } |
|||
|
|||
protected: |
|||
/* Token type used by the tokenizer */ |
|||
struct Token { |
|||
int token; |
|||
numEval::TokenType value; |
|||
}; |
|||
|
|||
/* Begin processing of a new input string */ |
|||
void newString(const char* s); |
|||
|
|||
/* Tokenizer: Next token/value taken from input string. */ |
|||
Token getToken(); |
|||
|
|||
private: |
|||
void* pClParser; // the current lemon parser state machine |
|||
|
|||
/* Token state for input string. */ |
|||
struct TokenStat { |
|||
enum { OutLen=32 }; |
|||
TokenStat() : input(0), token(0), inputLen(0) { /* empty */ } |
|||
const char* input; // current input string ("var=4") |
|||
char* token; // output token ("var", type:VAR; "4", type:VALUE) |
|||
size_t inputLen; // strlen(input) |
|||
size_t pos; // current index |
|||
} clToken; |
|||
|
|||
char cClDecSep; // decimal separator ('.') |
|||
|
|||
/* Parse progress. Set by parser actions. */ |
|||
bool bClError; |
|||
bool bClParseFinished; |
|||
|
|||
bool bClTextInputStorage; // Enable input string storage used by process(const char*, const void*) |
|||
|
|||
Unit eClUnitDefault; // Default unit for values |
|||
|
|||
std::map<const void*, std::string> clObjMap; // Map pointer to text entry -> (original) input string |
|||
std::map<std::string, double> clVarMap; |
|||
}; |
|||
|
|||
|
|||
#endif /* NUMERIC_EVALUATOR_H_ */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue