Kicad-ize the numeric evaluator.
Naming conventions, code formatting, and wxStrings. (cherry picked from commit 4a0d7a8)
This commit is contained in:
parent
0f78f97232
commit
f0f9e4a1cb
|
@ -397,10 +397,10 @@ int ValueFromTextCtrl( const wxTextCtrl& aTextCtr )
|
||||||
{
|
{
|
||||||
int value;
|
int value;
|
||||||
wxString msg = aTextCtr.GetValue();
|
wxString msg = aTextCtr.GetValue();
|
||||||
NumericEvaluator eval;
|
NUMERIC_EVALUATOR eval( g_UserUnit );
|
||||||
|
|
||||||
if( eval.process( msg.mb_str() ) )
|
if( eval.Process( msg ) )
|
||||||
msg = wxString::FromUTF8( eval.result() );
|
msg = eval.Result();
|
||||||
|
|
||||||
value = ValueFromString( g_UserUnit, msg );
|
value = ValueFromString( g_UserUnit, msg );
|
||||||
|
|
||||||
|
|
|
@ -98,9 +98,9 @@ typedef union {
|
||||||
#ifndef YYSTACKDEPTH
|
#ifndef YYSTACKDEPTH
|
||||||
#define YYSTACKDEPTH 100
|
#define YYSTACKDEPTH 100
|
||||||
#endif
|
#endif
|
||||||
#define ParseARG_SDECL NumericEvaluator* pEval ;
|
#define ParseARG_SDECL NUMERIC_EVALUATOR* pEval ;
|
||||||
#define ParseARG_PDECL , NumericEvaluator* pEval
|
#define ParseARG_PDECL , NUMERIC_EVALUATOR* pEval
|
||||||
#define ParseARG_FETCH NumericEvaluator* pEval = yypParser->pEval
|
#define ParseARG_FETCH NUMERIC_EVALUATOR* pEval = yypParser->pEval
|
||||||
#define ParseARG_STORE yypParser->pEval = pEval
|
#define ParseARG_STORE yypParser->pEval = pEval
|
||||||
#define YYNSTATE 16
|
#define YYNSTATE 16
|
||||||
#define YYNRULE 16
|
#define YYNRULE 16
|
||||||
|
@ -757,12 +757,12 @@ static void yy_reduce(
|
||||||
break;
|
break;
|
||||||
case 9: /* expr ::= VAR */
|
case 9: /* expr ::= VAR */
|
||||||
#line 55 "grammar.lemon"
|
#line 55 "grammar.lemon"
|
||||||
{ yygotominor.yy0.dValue = pEval->getVar(yymsp[0].minor.yy0.text); yygotominor.yy0.valid=true; }
|
{ yygotominor.yy0.dValue = pEval->GetVar(yymsp[0].minor.yy0.text); yygotominor.yy0.valid=true; }
|
||||||
#line 762 "grammar.c"
|
#line 762 "grammar.c"
|
||||||
break;
|
break;
|
||||||
case 10: /* expr ::= VAR ASSIGN expr */
|
case 10: /* expr ::= VAR ASSIGN expr */
|
||||||
#line 56 "grammar.lemon"
|
#line 56 "grammar.lemon"
|
||||||
{ pEval->setVar(yymsp[-2].minor.yy0.text, yymsp[0].minor.yy0.dValue); yygotominor.yy0.dValue = yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=false; }
|
{ pEval->SetVar(yymsp[-2].minor.yy0.text, yymsp[0].minor.yy0.dValue); yygotominor.yy0.dValue = yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=false; }
|
||||||
#line 767 "grammar.c"
|
#line 767 "grammar.c"
|
||||||
break;
|
break;
|
||||||
case 11: /* expr ::= expr PLUS expr */
|
case 11: /* expr ::= expr PLUS expr */
|
||||||
|
|
|
@ -52,8 +52,8 @@ stmt ::= expr SEMCOL. { pEval->parseSetResult(NAN); }
|
||||||
expr(A) ::= VALUE(B). { A.dValue = B.dValue; A.valid=true; }
|
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) ::= 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) ::= 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). { 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) ::= 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) 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) 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) MULT expr(C). { A.dValue = B.dValue * C.dValue; A.valid=C.valid; }
|
||||||
|
|
|
@ -17,24 +17,9 @@
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define TESTMODE 0
|
|
||||||
|
|
||||||
#include <libeval/numeric_evaluator.h>
|
#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>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* The (generated) lemon parser is written in C.
|
/* The (generated) lemon parser is written in C.
|
||||||
* In order to keep its symbol from the global namespace include the parser code with
|
* In order to keep its symbol from the global namespace include the parser code with
|
||||||
* a C++ namespace.
|
* a C++ namespace.
|
||||||
|
@ -49,335 +34,330 @@ namespace numEval
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "grammar.c"
|
#include "grammar.c"
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} /* namespace numEval */
|
} /* namespace numEval */
|
||||||
|
|
||||||
// JEY TODO: remove this version;
|
NUMERIC_EVALUATOR::NUMERIC_EVALUATOR( EDA_UNITS_T aUnits, bool aUseMils )
|
||||||
NumericEvaluator :: NumericEvaluator() :
|
|
||||||
pClParser( 0 )
|
|
||||||
{
|
{
|
||||||
struct lconv* lc = localeconv();
|
struct lconv* lc = localeconv();
|
||||||
cClDecSep = *lc->decimal_point;
|
m_localeDecimalSeparator = *lc->decimal_point;
|
||||||
|
|
||||||
bClTextInputStorage = true;
|
m_parseError = false;
|
||||||
|
m_parseFinished = false;
|
||||||
|
|
||||||
bClError = false;
|
m_parser = numEval::ParseAlloc( malloc );
|
||||||
bClParseFinished = false;
|
|
||||||
|
|
||||||
if( pClParser == nullptr )
|
switch( aUnits )
|
||||||
pClParser = numEval::ParseAlloc(malloc);
|
{
|
||||||
|
case INCHES:
|
||||||
switch( g_UserUnit )
|
if( aUseMils )
|
||||||
{
|
m_defaultUnits = Unit::Mil;
|
||||||
case INCHES:
|
else
|
||||||
eClUnitDefault = Unit::Inch;
|
m_defaultUnits = Unit::Inch;
|
||||||
break;
|
break;
|
||||||
case MILLIMETRES:
|
case MILLIMETRES:m_defaultUnits = Unit::Metric;
|
||||||
eClUnitDefault = Unit::Metric;
|
break;
|
||||||
break;
|
default:m_defaultUnits = Unit::Metric;
|
||||||
default:
|
break;
|
||||||
eClUnitDefault = Unit::Metric;
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NumericEvaluator::NumericEvaluator( EDA_UNITS_T aUnits, bool aUseMils ) :
|
|
||||||
pClParser( 0 )
|
NUMERIC_EVALUATOR::~NUMERIC_EVALUATOR()
|
||||||
{
|
{
|
||||||
struct lconv* lc = localeconv();
|
numEval::ParseFree( m_parser, free );
|
||||||
cClDecSep = *lc->decimal_point;
|
|
||||||
|
|
||||||
bClTextInputStorage = true;
|
// Allow explicit call to destructor
|
||||||
pClParser = numEval::ParseAlloc(malloc);
|
m_parser = nullptr;
|
||||||
|
|
||||||
switch( aUnits )
|
Clear();
|
||||||
{
|
|
||||||
case INCHES:
|
|
||||||
if( aUseMils )
|
|
||||||
eClUnitDefault = Unit::Mil;
|
|
||||||
else
|
|
||||||
eClUnitDefault = Unit::Inch;
|
|
||||||
break;
|
|
||||||
case MILLIMETRES:
|
|
||||||
eClUnitDefault = Unit::Metric;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
eClUnitDefault = Unit::Metric;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NumericEvaluator :: ~NumericEvaluator()
|
|
||||||
|
void NUMERIC_EVALUATOR::Clear()
|
||||||
{
|
{
|
||||||
numEval::ParseFree(pClParser, free);
|
free( m_token.token );
|
||||||
|
m_token.token = nullptr;
|
||||||
// Allow explicit call to destructor
|
m_token.input = nullptr;
|
||||||
pClParser = nullptr;
|
m_parseError = true;
|
||||||
|
m_originalText = wxEmptyString;
|
||||||
clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
NumericEvaluator :: clear(const void* pObj)
|
|
||||||
{
|
|
||||||
free(clToken.token);
|
|
||||||
clToken.token = nullptr;
|
|
||||||
clToken.input = nullptr;
|
|
||||||
bClError = true;
|
|
||||||
|
|
||||||
if (bClTextInputStorage)
|
void NUMERIC_EVALUATOR::parseError( const char* s )
|
||||||
clObjMap.clear();
|
{
|
||||||
|
m_parseError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
NumericEvaluator :: parse(int token, numEval::TokenType value)
|
void NUMERIC_EVALUATOR::parseOk()
|
||||||
{
|
{
|
||||||
numEval::Parse(pClParser, token, value, this);
|
m_parseFinished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
NumericEvaluator :: parseError(const char* s)
|
void NUMERIC_EVALUATOR::parseSetResult( double val )
|
||||||
{
|
{
|
||||||
bClError = true;
|
snprintf( m_token.token, m_token.OutLen, "%.10g", val );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
NumericEvaluator :: parseOk()
|
wxString NUMERIC_EVALUATOR::OriginalText() const
|
||||||
{
|
{
|
||||||
bClParseFinished = true;
|
return m_originalText;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
NumericEvaluator :: parseSetResult(double val)
|
bool NUMERIC_EVALUATOR::Process( const wxString& aString )
|
||||||
{
|
{
|
||||||
snprintf(clToken.token, clToken.OutLen, "%.10g", val);
|
m_originalText = aString;
|
||||||
|
|
||||||
|
// Feed parser token after token until end of input.
|
||||||
|
|
||||||
|
newString( aString );
|
||||||
|
m_parseError = false;
|
||||||
|
m_parseFinished = false;
|
||||||
|
Token tok;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tok = getToken();
|
||||||
|
numEval::Parse( m_parser, tok.token, tok.value, this );
|
||||||
|
|
||||||
|
if( m_parseFinished || tok.token == ENDS )
|
||||||
|
{
|
||||||
|
// Reset parser by passing zero as token ID, value is ignored.
|
||||||
|
numEval::Parse( m_parser, 0, tok.value, this );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while( tok.token );
|
||||||
|
|
||||||
|
return !m_parseError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
|
||||||
NumericEvaluator :: textInput(const void* pObj) const
|
|
||||||
{
|
|
||||||
auto it = clObjMap.find(pObj);
|
|
||||||
if (it != clObjMap.end()) return it->second.c_str();
|
|
||||||
|
|
||||||
return nullptr;
|
void NUMERIC_EVALUATOR::newString( const wxString& aString )
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
auto len = aString.length();
|
||||||
|
m_token.token = reinterpret_cast<decltype( m_token.token )>( malloc( TokenStat::OutLen + 1 ));
|
||||||
|
strcpy( m_token.token, "0" );
|
||||||
|
m_token.inputLen = len;
|
||||||
|
m_token.pos = 0;
|
||||||
|
m_token.input = aString.mb_str();
|
||||||
|
m_parseFinished = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
NumericEvaluator :: process(const char* s)
|
NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
|
||||||
{
|
{
|
||||||
/* Process new string.
|
Token retval;
|
||||||
* Feed parser token after token until end of input.
|
size_t idx;
|
||||||
*/
|
|
||||||
|
|
||||||
newString(s);
|
retval.token = ENDS;
|
||||||
|
retval.value.dValue = 0;
|
||||||
|
|
||||||
if (pClParser == nullptr)
|
if( m_token.token == nullptr )
|
||||||
pClParser = numEval::ParseAlloc(malloc);
|
return retval;
|
||||||
|
|
||||||
bClError = false;
|
if( m_token.input == nullptr )
|
||||||
bClParseFinished = false;
|
return retval;
|
||||||
|
|
||||||
Token tok;
|
if( m_token.pos >= m_token.inputLen )
|
||||||
do {
|
return retval;
|
||||||
tok = getToken();
|
|
||||||
parse(tok.token, tok.value);
|
|
||||||
if (bClParseFinished || tok.token == ENDS) {
|
|
||||||
// Reset parser by passing zero as token ID, value is ignored.
|
|
||||||
numEval::Parse(pClParser, 0, tok.value, this);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//usleep(200000);
|
|
||||||
} while (tok.token);
|
|
||||||
|
|
||||||
return !bClError;
|
auto isDecimalSeparator = [ & ]( char ch ) -> bool {
|
||||||
|
return ( ch == m_localeDecimalSeparator || ch == '.' || ch == ',' );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lambda: get value as string, store into clToken.token and update current index.
|
||||||
|
auto extractNumber = [ & ]() {
|
||||||
|
bool haveSeparator = false;
|
||||||
|
idx = 0;
|
||||||
|
auto ch = m_token.input[ m_token.pos ];
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if( isDecimalSeparator( ch ) && haveSeparator )
|
||||||
|
break;
|
||||||
|
|
||||||
|
m_token.token[ idx++ ] = ch;
|
||||||
|
|
||||||
|
if( isDecimalSeparator( ch ))
|
||||||
|
haveSeparator = true;
|
||||||
|
|
||||||
|
ch = m_token.input[ ++m_token.pos ];
|
||||||
|
} while( isdigit( ch ) || isDecimalSeparator( ch ));
|
||||||
|
|
||||||
|
m_token.token[ idx ] = 0;
|
||||||
|
|
||||||
|
// Ensure that the systems decimal separator is used
|
||||||
|
for( int i = strlen( m_token.token ); i; i-- )
|
||||||
|
if( isDecimalSeparator( m_token.token[ i - 1 ] ))
|
||||||
|
m_token.token[ i - 1 ] = m_localeDecimalSeparator;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lamda: Get unit for current token.
|
||||||
|
// Valid units are ", in, mm, mil and thou. Returns Unit::Invalid otherwise.
|
||||||
|
auto checkUnit = [ this ]() -> Unit {
|
||||||
|
char ch = m_token.input[ m_token.pos ];
|
||||||
|
|
||||||
|
if( ch == '"' )
|
||||||
|
{
|
||||||
|
m_token.pos++;
|
||||||
|
return Unit::Inch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not use strcasecmp() as it is not available on all platforms
|
||||||
|
const char* cptr = &m_token.input[ m_token.pos ];
|
||||||
|
const auto sizeLeft = m_token.inputLen - m_token.pos;
|
||||||
|
|
||||||
|
if( sizeLeft >= 2 && ch == 'm' && cptr[ 1 ] == 'm' && !isalnum( cptr[ 2 ] ))
|
||||||
|
{
|
||||||
|
m_token.pos += 2;
|
||||||
|
return Unit::Metric;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sizeLeft >= 2 && ch == 'i' && cptr[ 1 ] == 'n' && !isalnum( cptr[ 2 ] ))
|
||||||
|
{
|
||||||
|
m_token.pos += 2;
|
||||||
|
return Unit::Inch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sizeLeft >= 3 && ch == 'm' && cptr[ 1 ] == 'i' && cptr[ 2 ] == 'l' && !isalnum( cptr[ 3 ] ))
|
||||||
|
{
|
||||||
|
m_token.pos += 3;
|
||||||
|
return Unit::Mil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sizeLeft >= 4 && ch == 't' && cptr[ 1 ] == 'h' && cptr[ 2 ] == 'o' && cptr[ 2 ] == 'u' && !isalnum( cptr[ 3 ] ))
|
||||||
|
{
|
||||||
|
m_token.pos += 4;
|
||||||
|
return Unit::Mil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Unit::Invalid;
|
||||||
|
};
|
||||||
|
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
// Start processing of first/next token: Remove whitespace
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
ch = m_token.input[ m_token.pos ];
|
||||||
|
|
||||||
|
if( ch == ' ' )
|
||||||
|
m_token.pos++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit convertFrom;
|
||||||
|
|
||||||
|
if( ch == 0 )
|
||||||
|
{
|
||||||
|
/* End of input */
|
||||||
|
}
|
||||||
|
else if( isdigit( ch ) || isDecimalSeparator( ch ))
|
||||||
|
{
|
||||||
|
// VALUE
|
||||||
|
extractNumber();
|
||||||
|
retval.token = VALUE;
|
||||||
|
retval.value.dValue = atof( m_token.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( m_defaultUnits == 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( m_defaultUnits == 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( m_defaultUnits == Unit::Mil )
|
||||||
|
{
|
||||||
|
switch( convertFrom )
|
||||||
|
{
|
||||||
|
case Unit::Inch :retval.value.dValue = 1.0 * 1000.0; break;
|
||||||
|
case Unit::Mil :retval.value.dValue = 1.0; break;
|
||||||
|
case Unit::Metric :retval.value.dValue = 1000.0 / 25.4; break;
|
||||||
|
case Unit::Invalid :break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( isalpha( ch ))
|
||||||
|
{
|
||||||
|
// VAR
|
||||||
|
const char* cptr = &m_token.input[ m_token.pos ];
|
||||||
|
cptr++;
|
||||||
|
|
||||||
|
while( isalnum( *cptr ))
|
||||||
|
cptr++;
|
||||||
|
|
||||||
|
retval.token = VAR;
|
||||||
|
size_t bytesToCopy = cptr - &m_token.input[ m_token.pos ];
|
||||||
|
|
||||||
|
if( bytesToCopy >= sizeof( retval.value.text ))
|
||||||
|
bytesToCopy = sizeof( retval.value.text ) - 1;
|
||||||
|
|
||||||
|
strncpy( retval.value.text, &m_token.input[ m_token.pos ], bytesToCopy );
|
||||||
|
retval.value.text[ bytesToCopy ] = 0;
|
||||||
|
m_token.pos += cptr - &m_token.input[ m_token.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;
|
||||||
|
default :m_parseError = true; break; /* invalid character */
|
||||||
|
}
|
||||||
|
m_token.pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void NUMERIC_EVALUATOR::SetVar( const wxString& aString, double aValue )
|
||||||
NumericEvaluator :: process(const char* s, const void* pObj)
|
|
||||||
{
|
{
|
||||||
if (bClTextInputStorage) // Store input string for (text entry) pObj.
|
m_varMap[ aString ] = aValue;
|
||||||
clObjMap[pObj] = s;
|
|
||||||
return process(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
double NUMERIC_EVALUATOR::GetVar( const wxString& aString )
|
||||||
NumericEvaluator :: newString(const char* s)
|
|
||||||
{
|
{
|
||||||
clear();
|
if( m_varMap[ aString ] )
|
||||||
auto len = strlen(s);
|
return m_varMap[ aString ];
|
||||||
clToken.token = reinterpret_cast<decltype(clToken.token)>(malloc(TokenStat::OutLen+1));
|
else
|
||||||
strcpy(clToken.token, "0");
|
return 0.0;
|
||||||
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;
|
|
||||||
|
|
||||||
auto isDecSep = [&](char ch) -> bool {
|
|
||||||
if (ch == cClDecSep) return true;
|
|
||||||
if (cClDecSep == ',' && ch == '.') return true;
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lambda: get value as string, store into clToken.token and update current index.
|
|
||||||
auto extractNumber = [&]() {
|
|
||||||
short sepCount = 0;
|
|
||||||
idx = 0;
|
|
||||||
auto ch = clToken.input[clToken.pos];
|
|
||||||
do {
|
|
||||||
if (ch == isDecSep(ch) && sepCount) break;
|
|
||||||
clToken.token[idx++] = ch;
|
|
||||||
if (isDecSep(ch)) sepCount++;
|
|
||||||
ch = clToken.input[++clToken.pos];
|
|
||||||
} while (isdigit(ch) || isDecSep(ch));
|
|
||||||
clToken.token[idx] = 0;
|
|
||||||
|
|
||||||
// Ensure that the systems decimal separator is used
|
|
||||||
for (int i = strlen(clToken.token); i; i--) if (isDecSep(clToken.token[i-1])) clToken.token[i-1] = cClDecSep;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lamda: Get unit for current token.
|
|
||||||
// Valid units are ", in, mm, mil and thou. Returns Unit::Invalid otherwise.
|
|
||||||
auto checkUnit = [this]() -> Unit {
|
|
||||||
char ch = clToken.input[clToken.pos];
|
|
||||||
if (ch == '"') {
|
|
||||||
clToken.pos++;
|
|
||||||
return Unit::Inch;
|
|
||||||
}
|
|
||||||
// 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 && ch == 'm' && tolower(cptr[1]) == 'm' && !isalnum(cptr[2])) {
|
|
||||||
clToken.pos += 2;
|
|
||||||
return Unit::Metric;
|
|
||||||
}
|
|
||||||
if (sizeLeft >= 2 && ch == 'i' && tolower(cptr[1]) == 'n' && !isalnum(cptr[2])) {
|
|
||||||
clToken.pos += 2;
|
|
||||||
return Unit::Inch;
|
|
||||||
}
|
|
||||||
if (sizeLeft >= 3 && ch == 'm' && tolower(cptr[1]) == 'i' && tolower(cptr[2]) == 'l' && !isalnum(cptr[3])) {
|
|
||||||
clToken.pos += 3;
|
|
||||||
return Unit::Mil;
|
|
||||||
}
|
|
||||||
if (sizeLeft >= 4 && ch == 't' && tolower(cptr[1]) == 'h' && tolower(cptr[2]) == 'o' && tolower(cptr[2]) == 'u' && !isalnum(cptr[3])) {
|
|
||||||
clToken.pos += 4;
|
|
||||||
return Unit::Mil;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) || isDecSep(ch)) { // 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 (eClUnitDefault == Unit::Mil)
|
|
||||||
{
|
|
||||||
switch (convertFrom)
|
|
||||||
{
|
|
||||||
case Unit::Inch : retval.value.dValue = 1.0*1000.0; break;
|
|
||||||
case Unit::Mil : retval.value.dValue = 1.0; break;
|
|
||||||
case Unit::Metric : retval.value.dValue = 1000.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;
|
|
||||||
default: bClError = true; break; /* invalid character */
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
TEXT_CTRL_EVAL::TEXT_CTRL_EVAL( wxWindow* aParent, wxWindowID aId, const
|
TEXT_CTRL_EVAL::TEXT_CTRL_EVAL( wxWindow* aParent, wxWindowID aId, const
|
||||||
wxString& aValue, const wxPoint& aPos, const wxSize& aSize, long aStyle,
|
wxString& aValue, const wxPoint& aPos, const wxSize& aSize, long aStyle,
|
||||||
const wxValidator& aValidator, const wxString& aName )
|
const wxValidator& aValidator, const wxString& aName )
|
||||||
: wxTextCtrl( aParent, aId, aValue, aPos, aSize, aStyle | wxTE_PROCESS_ENTER, aValidator, aName )
|
: wxTextCtrl( aParent, aId, aValue, aPos, aSize, aStyle | wxTE_PROCESS_ENTER, aValidator, aName ),
|
||||||
|
m_eval( g_UserUnit )
|
||||||
{
|
{
|
||||||
Connect( wxEVT_SET_FOCUS,
|
Connect( wxEVT_SET_FOCUS,
|
||||||
wxFocusEventHandler( TEXT_CTRL_EVAL::onTextFocusGet ), NULL, this );
|
wxFocusEventHandler( TEXT_CTRL_EVAL::onTextFocusGet ), NULL, this );
|
||||||
|
@ -38,19 +39,19 @@ TEXT_CTRL_EVAL::TEXT_CTRL_EVAL( wxWindow* aParent, wxWindowID aId, const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TEXT_CTRL_EVAL::SetValue( const wxString& aValue )
|
void TEXT_CTRL_EVAL::SetValue( const wxString& aValue )
|
||||||
{
|
{
|
||||||
wxTextCtrl::SetValue( aValue );
|
wxTextCtrl::SetValue( aValue );
|
||||||
m_eval.clear( this );
|
m_eval.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TEXT_CTRL_EVAL::onTextFocusGet( wxFocusEvent& aEvent )
|
void TEXT_CTRL_EVAL::onTextFocusGet( wxFocusEvent& aEvent )
|
||||||
{
|
{
|
||||||
auto oldStr = m_eval.textInput( this );
|
wxString oldStr = m_eval.OriginalText();
|
||||||
|
|
||||||
if( oldStr )
|
if( oldStr.length() )
|
||||||
wxTextCtrl::SetValue( wxString::FromUTF8( oldStr ) );
|
SetValue( oldStr );
|
||||||
|
|
||||||
aEvent.Skip();
|
aEvent.Skip();
|
||||||
}
|
}
|
||||||
|
@ -76,8 +77,8 @@ void TEXT_CTRL_EVAL::onTextEnter( wxCommandEvent& aEvent )
|
||||||
void TEXT_CTRL_EVAL::evaluate()
|
void TEXT_CTRL_EVAL::evaluate()
|
||||||
{
|
{
|
||||||
if( GetValue().IsEmpty() )
|
if( GetValue().IsEmpty() )
|
||||||
wxTextCtrl::SetValue( "0" );
|
wxTextCtrl::SetValue( "0" );
|
||||||
|
|
||||||
if( m_eval.process( GetValue().mb_str(), this ) )
|
if( m_eval.Process( GetValue() ) )
|
||||||
wxTextCtrl::SetValue( wxString::FromUTF8( m_eval.result() ) );
|
SetValue( m_eval.Result() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,10 +65,10 @@ void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
|
||||||
{
|
{
|
||||||
if( m_allowEval )
|
if( m_allowEval )
|
||||||
{
|
{
|
||||||
auto oldStr = m_eval.textInput( this );
|
wxString oldStr = m_eval.OriginalText();
|
||||||
|
|
||||||
if( oldStr )
|
if( oldStr.length() )
|
||||||
m_textEntry->SetValue( wxString::FromUTF8( oldStr ) );
|
m_textEntry->SetValue( oldStr );
|
||||||
}
|
}
|
||||||
|
|
||||||
aEvent.Skip();
|
aEvent.Skip();
|
||||||
|
@ -104,10 +104,10 @@ void UNIT_BINDER::onTextEnter( wxCommandEvent& aEvent )
|
||||||
void UNIT_BINDER::evaluate()
|
void UNIT_BINDER::evaluate()
|
||||||
{
|
{
|
||||||
if( m_textEntry->GetValue().IsEmpty() )
|
if( m_textEntry->GetValue().IsEmpty() )
|
||||||
m_textEntry->SetValue( "0" );
|
m_textEntry->ChangeValue( "0" );
|
||||||
|
|
||||||
if( m_eval.process( m_textEntry->GetValue().mb_str(), this ) )
|
if( m_eval.Process( m_textEntry->GetValue() ) )
|
||||||
m_textEntry->SetValue( wxString::FromUTF8( m_eval.result() ) );
|
m_textEntry->ChangeValue( m_eval.Result() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ bool UNIT_BINDER::Validate( bool setFocusOnError )
|
||||||
{
|
{
|
||||||
wxString msg = wxString::Format( _( "%s must be larger than %s." ),
|
wxString msg = wxString::Format( _( "%s must be larger than %s." ),
|
||||||
valueDescriptionFromLabel( m_label ),
|
valueDescriptionFromLabel( m_label ),
|
||||||
StringFromValue( EDA_UNITS_T::MILLIMETRES, m_min, true ) );
|
StringFromValue( m_units, m_min, true ) );
|
||||||
DisplayError( textInput->GetParent(), msg );
|
DisplayError( textInput->GetParent(), msg );
|
||||||
|
|
||||||
if( setFocusOnError )
|
if( setFocusOnError )
|
||||||
|
@ -154,7 +154,7 @@ bool UNIT_BINDER::Validate( bool setFocusOnError )
|
||||||
{
|
{
|
||||||
wxString msg = wxString::Format( _( "%s must be smaller than %s." ),
|
wxString msg = wxString::Format( _( "%s must be smaller than %s." ),
|
||||||
valueDescriptionFromLabel( m_label ),
|
valueDescriptionFromLabel( m_label ),
|
||||||
StringFromValue( EDA_UNITS_T::MILLIMETRES, m_max, true ) );
|
StringFromValue( m_units, m_max, true ) );
|
||||||
DisplayError( textInput->GetParent(), msg );
|
DisplayError( textInput->GetParent(), msg );
|
||||||
|
|
||||||
if( setFocusOnError )
|
if( setFocusOnError )
|
||||||
|
@ -182,7 +182,7 @@ void UNIT_BINDER::SetValue( wxString aValue )
|
||||||
m_textEntry->SetValue( aValue );
|
m_textEntry->SetValue( aValue );
|
||||||
|
|
||||||
if( m_allowEval )
|
if( m_allowEval )
|
||||||
m_eval.clear();
|
m_eval.Clear();
|
||||||
|
|
||||||
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_useMils ) );
|
m_unitLabel->SetLabel( GetAbbreviatedUnitsLabel( m_units, m_useMils ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,39 +80,32 @@ Supported units are millimeters (mm), Mil (mil) and inch (")
|
||||||
namespace numEval
|
namespace numEval
|
||||||
{
|
{
|
||||||
|
|
||||||
struct TokenType
|
struct TokenType
|
||||||
{
|
{
|
||||||
union {
|
union
|
||||||
double dValue;
|
{
|
||||||
int iValue;
|
double dValue;
|
||||||
};
|
int iValue;
|
||||||
|
};
|
||||||
|
|
||||||
bool valid;
|
bool valid;
|
||||||
char text[32];
|
char text[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace numEval
|
} // namespace numEval
|
||||||
|
|
||||||
class NumericEvaluator {
|
class NUMERIC_EVALUATOR
|
||||||
enum class Unit { Invalid, Metric, Inch, Mil };
|
{
|
||||||
|
enum class Unit { Invalid, Metric, Inch, Mil };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NumericEvaluator();
|
NUMERIC_EVALUATOR( EDA_UNITS_T aUnits, bool aUseMils = false );
|
||||||
NumericEvaluator( EDA_UNITS_T aUnits, bool aUseMils );
|
~NUMERIC_EVALUATOR();
|
||||||
~NumericEvaluator();
|
|
||||||
|
|
||||||
/* clear() should be invoked by the client if a new input string is to be processed. It
|
/* clear() should be invoked by the client if a new input string is to be processed. It
|
||||||
* will reset the parser. User defined variables are retained.
|
* will reset the parser. User defined variables are retained.
|
||||||
*/
|
*/
|
||||||
void clear(const void* pObj = nullptr);
|
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 */
|
/* Used by the lemon parser */
|
||||||
void parseError(const char* s);
|
void parseError(const char* s);
|
||||||
|
@ -120,83 +113,76 @@ public:
|
||||||
void parseSetResult(double);
|
void parseSetResult(double);
|
||||||
|
|
||||||
/* Check if previous invokation of process() was successful */
|
/* Check if previous invokation of process() was successful */
|
||||||
inline bool isValid() const { return !bClError; }
|
inline bool IsValid() const { return !m_parseError; }
|
||||||
|
|
||||||
/* Result of string processing. Undefined if !isValid() */
|
/* Result of string processing. Undefined if !isValid() */
|
||||||
inline const char* result() const { return clToken.token; }
|
inline wxString Result() const { return wxString::FromUTF8( m_token.token ); }
|
||||||
|
|
||||||
/* Numeric result of string processing, in default units. */
|
|
||||||
inline const double value() const { return resultValue; }
|
|
||||||
|
|
||||||
/* Evaluate input string.
|
/* Evaluate input string.
|
||||||
* Result can be retrieved by result().
|
* Result can be retrieved by result().
|
||||||
* Returns true if input string could be evaluated, otherwise false.
|
* Returns true if input string could be evaluated, otherwise false.
|
||||||
*/
|
*/
|
||||||
bool process(const char* s);
|
bool Process( const wxString& aString );
|
||||||
|
|
||||||
/* Like process(const char*) but also stores input string in a std:map with key pObj. */
|
/* Retrieve the original text before evaluation. */
|
||||||
bool process(const char* s, const void* pObj);
|
wxString OriginalText() const;
|
||||||
|
|
||||||
/* Retrieve old input string with key pObj. */
|
|
||||||
const char* textInput(const void* pObj) const;
|
|
||||||
|
|
||||||
/* Add/set variable with value */
|
/* Add/set variable with value */
|
||||||
void setVar(const std::string&, double value);
|
void SetVar( const wxString& aString, double aValue );
|
||||||
|
|
||||||
/* Get value of variable. Returns 0.0 if not defined. */
|
/* Get value of variable. Returns 0.0 if not defined. */
|
||||||
double getVar(const std::string&);
|
double GetVar( const wxString& aString );
|
||||||
|
|
||||||
/* Remove single variable */
|
/* Remove single variable */
|
||||||
void removeVar(const std::string& s) { clVarMap.erase(s); }
|
void RemoveVar( const wxString& aString ) { m_varMap.erase( aString ); }
|
||||||
|
|
||||||
/* Remove all variables */
|
/* Remove all variables */
|
||||||
void clearVar() { clVarMap.clear(); }
|
void ClearVar() { m_varMap.clear(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Token type used by the tokenizer */
|
/* Token type used by the tokenizer */
|
||||||
struct Token {
|
struct Token
|
||||||
|
{
|
||||||
int token;
|
int token;
|
||||||
numEval::TokenType value;
|
numEval::TokenType value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Begin processing of a new input string */
|
/* Begin processing of a new input string */
|
||||||
void newString(const char* s);
|
void newString( const wxString& aString );
|
||||||
|
|
||||||
/* Tokenizer: Next token/value taken from input string. */
|
/* Tokenizer: Next token/value taken from input string. */
|
||||||
Token getToken();
|
Token getToken();
|
||||||
|
|
||||||
/* Used by processing loop */
|
/* Used by processing loop */
|
||||||
void parse(int token, numEval::TokenType value);
|
void parse( int token, numEval::TokenType value );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void* pClParser; // the current lemon parser state machine
|
void* m_parser; // the current lemon parser state machine
|
||||||
|
|
||||||
/* Token state for input string. */
|
/* Token state for input string. */
|
||||||
struct TokenStat {
|
struct TokenStat
|
||||||
enum { OutLen=32 };
|
{
|
||||||
TokenStat() : input(0), token(0), inputLen(0), pos(0) { /* empty */ }
|
enum { OutLen = 32 };
|
||||||
const char* input; // current input string ("var=4")
|
TokenStat() : input( 0 ), token( 0 ), inputLen( 0 ), pos( 0 ) { /* empty */ }
|
||||||
char* token; // output token ("var", type:VAR; "4", type:VALUE)
|
const char* input; // current input string ("var=4")
|
||||||
size_t inputLen; // strlen(input)
|
char* token; // output token ("var", type:VAR; "4", type:VALUE)
|
||||||
size_t pos; // current index
|
size_t inputLen; // strlen(input)
|
||||||
} clToken;
|
size_t pos; // current index
|
||||||
|
}
|
||||||
|
m_token;
|
||||||
|
|
||||||
char cClDecSep; // decimal separator ('.')
|
char m_localeDecimalSeparator;
|
||||||
|
|
||||||
/* Parse progress. Set by parser actions. */
|
/* Parse progress. Set by parser actions. */
|
||||||
bool bClError;
|
bool m_parseError;
|
||||||
bool bClParseFinished;
|
bool m_parseFinished;
|
||||||
|
|
||||||
/* The result (in eClUnitDefault units) */
|
Unit m_defaultUnits; // Default unit for values
|
||||||
int resultValue;
|
|
||||||
|
|
||||||
bool bClTextInputStorage; // Enable input string storage used by process(const char*, const void*)
|
wxString m_originalText;
|
||||||
|
|
||||||
Unit eClUnitDefault; // Default unit for values
|
std::map<wxString, double> m_varMap;
|
||||||
|
|
||||||
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_ */
|
#endif /* NUMERIC_EVALUATOR_H_ */
|
|
@ -57,7 +57,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
///> Numeric expression evaluator
|
///> Numeric expression evaluator
|
||||||
NumericEvaluator m_eval;
|
NUMERIC_EVALUATOR m_eval;
|
||||||
|
|
||||||
void onTextFocusGet( wxFocusEvent& aEvent );
|
void onTextFocusGet( wxFocusEvent& aEvent );
|
||||||
void onTextFocusLost( wxFocusEvent& aEvent );
|
void onTextFocusLost( wxFocusEvent& aEvent );
|
||||||
|
|
|
@ -121,7 +121,7 @@ protected:
|
||||||
int m_max;
|
int m_max;
|
||||||
|
|
||||||
///> Evaluator
|
///> Evaluator
|
||||||
NumericEvaluator m_eval;
|
NUMERIC_EVALUATOR m_eval;
|
||||||
bool m_allowEval;
|
bool m_allowEval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1022,7 +1022,6 @@ const BOX2I MODULE::ViewBBox() const
|
||||||
area.Inflate( biggest_clearance );
|
area.Inflate( biggest_clearance );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue