44#pragma GCC diagnostic push 
   45#pragma GCC diagnostic ignored "-Wunused-variable" 
   46#pragma GCC diagnostic ignored "-Wsign-compare" 
   49#include <libeval_compiler/grammar.c> 
   50#include <libeval_compiler/grammar.h> 
   53#pragma GCC diagnostic pop 
   57#define libeval_dbg(level, fmt, ...) \ 
   58    wxLogTrace( "libeval_compiler", fmt, __VA_ARGS__ ); 
 
   70    t2->
leaf[0]      = 
nullptr;
 
   71    t2->
leaf[1]      = 
nullptr;
 
 
  112    for( 
int i = 0; simpleOps[i].op >= 0; i++ )
 
  114        if( simpleOps[i].op == op )
 
  115            return simpleOps[i].mnemonic;
 
 
  162        str = wxString::Format( 
"PUSH VAR [%p]", 
m_ref.get() );
 
  167            str = wxString::Format( 
"PUSH nullptr" );
 
  169            str = wxString::Format( 
"PUSH NUM [%.10f]", 
m_value->AsDouble() );
 
  171            str = wxString::Format( 
"PUSH STR [%ls]", 
m_value->AsString() );
 
  175        str = wxString::Format( 
"MCALL" );
 
  179        str = wxString::Format( 
"FCALL" );
 
 
  235    while( p < 
m_str.length() && cond( 
m_str[p] ) )
 
  237        rv.append( 1, 
m_str[p] );
 
 
  246                            const std::function<
bool( wxUniChar )>& stopCond )
 const 
  250    if( remaining < (
int) match.length() )
 
  253    if( 
m_str.substr( 
m_pos, match.length() ) == match )
 
  254        return ( remaining == (
int) match.length() || stopCond( 
m_str[
m_pos + match.length()] ) );
 
 
  267    m_parser = LIBEVAL::ParseAlloc( malloc );
 
 
  275    LIBEVAL::ParseFree( 
m_parser, free );
 
 
  342    libeval_dbg(0, 
"str: '%s' empty: %d\n", aString.c_str(), !!aString.empty() );
 
  344    if( aString.empty() )
 
  371    } 
while( tok.
token );
 
 
  414    aToken.
token = G_STRING;
 
 
  426    for( 
const wxString& unitName : 
m_unitResolver->GetSupportedUnits() )
 
  431                                        return !isalnum( c );
 
  434            libeval_dbg(10, 
"Match unit '%s'\n", unitName.c_str() );
 
 
  456    retval.
token = G_ENDS;
 
  464    auto isDecimalSeparator =
 
  465            [&]( wxUniChar ch ) -> 
bool 
  474                bool      haveSeparator = 
false;
 
  479                    if( isDecimalSeparator( ch ) && haveSeparator )
 
  482                    current.append( 1, ch );
 
  484                    if( isDecimalSeparator( ch ) )
 
  485                        haveSeparator = 
true;
 
  489                } 
while( isdigit( ch ) || isDecimalSeparator( ch ) );
 
  492                for( 
int i = current.length(); i; i-- )
 
  494                    if( isDecimalSeparator( current[i - 1] ) )
 
  518    else if( isdigit( ch ) )
 
  522        retval.
token = G_VALUE;
 
  523        retval.
value.
str = 
new wxString( current );
 
  533        retval.
token            = G_UNIT;
 
  536    else if( ch == 
'\'' ) 
 
  542    else if( isalpha( ch ) || ch == 
'_' )
 
  544        current = 
m_tokenizer.GetChars( []( 
int c ) -> 
bool { 
return isalnum( c ) || c == 
'_'; } );
 
  545        retval.
token = G_IDENTIFIER;
 
  546        retval.
value.
str = 
new wxString( current );
 
  549    else if( 
m_tokenizer.MatchAhead( 
"==", []( 
int c ) -> 
bool { return c != 
'='; } ) )
 
  551        retval.
token = G_EQUAL;
 
  554    else if( 
m_tokenizer.MatchAhead( 
"!=", []( 
int c ) -> 
bool { return c != 
'='; } ) )
 
  556        retval.
token = G_NOT_EQUAL;
 
  559    else if( 
m_tokenizer.MatchAhead( 
"<=", []( 
int c ) -> 
bool { return c != 
'='; } ) )
 
  561        retval.
token = G_LESS_EQUAL_THAN;
 
  564    else if( 
m_tokenizer.MatchAhead( 
">=", []( 
int c ) -> 
bool { return c != 
'='; } ) )
 
  566        retval.
token = G_GREATER_EQUAL_THAN;
 
  569    else if( 
m_tokenizer.MatchAhead( 
"&&", []( 
int c ) -> 
bool { return c != 
'&'; } ) )
 
  571        retval.
token = G_BOOL_AND;
 
  574    else if( 
m_tokenizer.MatchAhead( 
"||", []( 
int c ) -> 
bool { return c != 
'|'; } ) )
 
  576        retval.
token = G_BOOL_OR;
 
  584        case '+': retval.
token = G_PLUS;         
break;
 
  585        case '!': retval.
token = G_BOOL_NOT;     
break;
 
  586        case '-': retval.
token = G_MINUS;        
break;
 
  587        case '*': retval.
token = G_MULT;         
break;
 
  588        case '/': retval.
token = G_DIVIDE;       
break;
 
  589        case '<': retval.
token = G_LESS_THAN;    
break;
 
  590        case '>': retval.
token = G_GREATER_THAN; 
break;
 
  591        case '(': retval.
token = G_PARENL;       
break;
 
  592        case ')': retval.
token = G_PARENR;       
break;
 
  593        case ';': retval.
token = G_SEMCOL;       
break;
 
  594        case '.': retval.
token = G_STRUCT_REF;   
break;
 
  595        case ',': retval.
token = G_COMMA;        
break;
 
  598            if( 
m_tokenizer.MatchAhead( 
"${", []( 
int c ) -> 
bool { return c != 
'{'; } ) )
 
 
  626    str.Printf( 
"\n[%p L0:%-20p L1:%-20p] ", tok, tok->
leaf[0], tok->
leaf[1] );
 
  629    for( 
int i = 0; i < 2 * depth; i++ )
 
  685        str.Printf( 
"UNIT: %d ", tok->
value.
idx );
 
 
  737    std::unique_ptr<VALUE> val = std::make_unique<VALUE>( aValue );
 
  738    val->SetUnits( aUnits );
 
  739    uop = 
new UOP( aOp, std::move( val ) );
 
 
  747    std::unique_ptr<VALUE> val = std::make_unique<VALUE>( aValue, aStringIsWildcard );
 
  748    uop = 
new UOP( aOp, std::move( val ) );
 
 
  756    uop = 
new UOP( aOp, std::move( aRef ) );
 
 
  764    uop = 
new UOP( aOp, std::move( aFunc ), std::move( aRef ) );
 
 
  790    std::vector<TREE_NODE*> args;
 
  797        args.push_back( root );
 
  805                args.push_back(n->
leaf[1]);
 
  814    std::reverse( args.begin(), args.end() );
 
  816    for( 
size_t i = 0; i < args.size(); i++ )
 
 
  825    std::vector<TREE_NODE*> stack;
 
  827    int                     numericValueCount = 0;
 
  828    wxString                missingUnitsMsg;
 
  829    int                     missingUnitsSrcPos = 0;
 
  833        std::unique_ptr<VALUE> val = std::make_unique<VALUE>( 1.0 );
 
  841    stack.push_back( 
m_tree );
 
  848    while( !stack.empty() )
 
  852        libeval_dbg( 4, 
"process node %p [op %d] [stack %lu]\n", node, node->
op, (
unsigned long)stack.size() );
 
  892            switch( node->
leaf[1]->
op )
 
  901                    std::unique_ptr<VAR_REF> vref = aCode->
CreateVarRef( itemName, propName );
 
  905                        msg.Printf( 
_( 
"Unrecognized item '%s'" ), itemName );
 
  910                        msg.Printf( 
_( 
"Unrecognized property '%s'" ), propName );
 
  929                    std::unique_ptr<VAR_REF> vref = aCode->
CreateVarRef( itemName, 
"" );
 
  933                        msg.Printf( 
_( 
"Unrecognized item '%s'" ), itemName );
 
  941                    libeval_dbg( 10, 
"emit func call: %s\n", functionName );
 
  945                        msg.Printf( 
_( 
"Unrecognized function '%s'" ), functionName );
 
  957                            aPreflightContext->
Push( param );
 
  961                                [&]( 
const wxString& aMessage, 
int aOffset )
 
  969                            func( aPreflightContext, vref.get() );
 
  970                            aPreflightContext->
Pop();           
 
  986                    stack.push_back( node->
leaf[1] );
 
  989                        stack.push_back( pnode );
 
 1002                    std::unique_ptr<VAR_REF> vref = aCode->
CreateVarRef( itemName, propName );
 
 1006                        msg.Printf( 
_( 
"Unrecognized item '%s'" ), itemName );
 
 1010                    msg.Printf( 
_( 
"Unrecognized property '%s'" ), propName );
 
 1038                    msg.Printf( 
_( 
"Unexpected units for '%s'" ), 
formatNode( node ) );
 
 1051                    missingUnitsMsg.Printf( 
_( 
"Missing units for '%s'| (%s)" ),
 
 1054                    missingUnitsSrcPos = node->
srcPos;
 
 1062            numericValueCount++;
 
 1069            bool isWildcard = str.Contains(
"?") || str.Contains(
"*");
 
 1081                msg.Printf( 
_( 
"Unrecognized item '%s'" ), 
formatNode( node ) );
 
 1101                stack.push_back( node->
leaf[0] );
 
 1106                stack.push_back( node->
leaf[1] );
 
 1118            node->
uop = 
nullptr;
 
 1132    if( !missingUnitsMsg.IsEmpty() && numericValueCount == 1 )
 
 
 1147        VALUE* value = 
nullptr;
 
 1172#define AS_DOUBLE( arg ) ( arg ? arg->AsDouble() : 0.0 ) 
 1184                ctx->
ReportError( wxString::Format( 
_( 
"Type mismatch between '%s' and %lf" ),
 
 1190                ctx->
ReportError( wxString::Format( 
_( 
"Type mismatch between %lf and '%s'" ),
 
 1200        auto getOpResultUnits =
 
 1207                        return aVal2->GetUnits();
 
 1212                    return aVal2->GetUnits();
 
 1221            resultUnits = getOpResultUnits( arg1, arg2 );
 
 1226            resultUnits = getOpResultUnits( arg1, arg2 );
 
 1231            resultUnits = getOpResultUnits( arg1, arg2 );
 
 1236            resultUnits = getOpResultUnits( arg1, arg2 );
 
 1255            if( !arg1 || !arg2 )
 
 1256                result = arg1 == arg2 ? 1 : 0;
 
 1264            if( !arg1 || !arg2 )
 
 1265                result = arg1 != arg2 ? 1 : 0;
 
 1294        double          ARG1VALUE = arg1 ? arg1->
AsDouble() : 0.0;
 
 1301            result = ARG1VALUE != 0.0 ? 0 : 1;
 
 1304            result = ARG1VALUE != 0.0 ? 1 : 0;
 
 
 1330    if( ctx->
SP() == 1 )
 
 1340        wxASSERT( ctx->
SP() == 1 );
 
 
 
std::unique_ptr< UNIT_RESOLVER > m_unitResolver
 
void newString(const wxString &aString)
 
void freeTree(LIBEVAL::TREE_NODE *tree)
 
bool lexString(T_TOKEN &aToken)
 
void GcItem(TREE_NODE *aItem)
 
bool generateUCode(UCODE *aCode, CONTEXT *aPreflightContext)
 
char m_localeDecimalSeparator
 
std::function< void(const wxString &aMessage, int aOffset)> m_errorCallback
 
bool lexDefault(T_TOKEN &aToken)
 
std::vector< TREE_NODE * > m_gcItems
 
void reportError(COMPILATION_STAGE stage, const wxString &aErrorMsg, int aPos=-1)
 
void setRoot(LIBEVAL::TREE_NODE *root)
 
std::vector< wxString * > m_gcStrings
 
bool Compile(const wxString &aString, UCODE *aCode, CONTEXT *aPreflightContext)
 
ERROR_STATUS m_errorStatus
 
void parseError(const char *s)
 
VALUE * StoreValue(VALUE *aValue)
 
void ReportError(const wxString &aErrorMsg)
 
std::function< void(const wxString &aMessage, int aOffset)> m_errorCallback
 
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
 
wxString GetChars(const std::function< bool(wxUniChar)> &cond) const
 
bool MatchAhead(const wxString &match, const std::function< bool(wxUniChar)> &stopCond) const
 
void SetUop(int aOp, double aValue, EDA_UNITS aUnits)
 
virtual std::unique_ptr< VAR_REF > CreateVarRef(const wxString &var, const wxString &field)
 
std::vector< UOP * > m_ucode
 
VALUE * Run(CONTEXT *ctx)
 
virtual FUNC_CALL_REF CreateFuncCall(const wxString &name)
 
std::unique_ptr< VAR_REF > m_ref
 
std::unique_ptr< VALUE > m_value
 
virtual const wxString & AsString() const
 
void SetUnits(const EDA_UNITS aUnits)
 
virtual bool NotEqualTo(CONTEXT *aCtx, const VALUE *b) const
 
virtual double AsDouble() const
 
EDA_UNITS GetUnits() const
 
VAR_TYPE_T GetType() const
 
virtual bool EqualTo(CONTEXT *aCtx, const VALUE *b) const
 
#define libeval_dbg(level, fmt,...)
 
#define TR_OP_GREATER_EQUAL
 
#define TR_UOP_PUSH_VALUE
 
#define TR_OP_METHOD_CALL
 
#define TR_OP_BINARY_MASK
 
KICOMMON_API double DoubleValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Convert aTextValue to a double.
 
TREE_NODE * newNode(LIBEVAL::COMPILER *compiler, int op, const T_TOKEN_VALUE &value)
 
static std::vector< TREE_NODE * > squashParamList(TREE_NODE *root)
 
constexpr T_TOKEN defaultToken
 
void dumpNode(wxString &buf, TREE_NODE *tok, int depth=0)
 
constexpr T_TOKEN_VALUE defaultTokenValue
 
std::function< void(CONTEXT *, void *)> FUNC_CALL_REF
 
static const wxString formatOpName(int op)
 
const wxString formatNode(TREE_NODE *node)
 
static void prepareTree(LIBEVAL::TREE_NODE *node)
 
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
 
@ VALUE
Field Value of part, i.e. "3.3K".
 
wxString result
Test unit parsing edge cases and error handling.
 
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.