KiCad PCB EDA Suite
PCB_EXPR_COMPILER Class Reference

#include <pcb_expr_evaluator.h>

Inheritance diagram for PCB_EXPR_COMPILER:
LIBEVAL::COMPILER

Public Member Functions

 PCB_EXPR_COMPILER ()
 
void Clear ()
 
void parseError (const char *s)
 
void parseOk ()
 
int GetSourcePos () const
 
void setRoot (LIBEVAL::TREE_NODE *root)
 
void freeTree (LIBEVAL::TREE_NODE *tree)
 
bool Compile (const wxString &aString, UCODE *aCode, CONTEXT *aPreflightContext)
 
void SetErrorCallback (std::function< void(const wxString &aMessage, int aOffset)> aCallback)
 
bool IsErrorPending () const
 
const ERROR_STATUS & GetError () const
 
void GcItem (TREE_NODE *aItem)
 
void GcItem (wxString *aItem)
 

Protected Types

enum  LEXER_STATE { LS_DEFAULT = 0 , LS_STRING = 1 }
 

Protected Member Functions

bool generateUCode (UCODE *aCode, CONTEXT *aPreflightContext)
 
void reportError (COMPILATION_STAGE stage, const wxString &aErrorMsg, int aPos=-1)
 
void newString (const wxString &aString)
 
T_TOKEN getToken ()
 
bool lexDefault (T_TOKEN &aToken)
 
bool lexString (T_TOKEN &aToken)
 
int resolveUnits ()
 

Protected Attributes

LEXER_STATE m_lexerState
 
void * m_parser
 
TOKENIZER m_tokenizer
 
char m_localeDecimalSeparator
 
std::unique_ptr< UNIT_RESOLVER > m_unitResolver
 
int m_sourcePos
 
bool m_parseFinished
 
ERROR_STATUS m_errorStatus
 
std::function< void(const wxString &aMessage, int aOffset)> m_errorCallback
 
TREE_NODE * m_tree
 
std::vector< TREE_NODE * > m_gcItems
 
std::vector< wxString * > m_gcStrings
 

Detailed Description

Definition at line 199 of file pcb_expr_evaluator.h.

Member Enumeration Documentation

◆ LEXER_STATE

enum LIBEVAL::COMPILER::LEXER_STATE
protectedinherited
Enumerator
LS_DEFAULT 
LS_STRING 

Definition at line 517 of file libeval_compiler.h.

518 {
519 LS_DEFAULT = 0,
520 LS_STRING = 1,
521 };

Constructor & Destructor Documentation

◆ PCB_EXPR_COMPILER()

PCB_EXPR_COMPILER::PCB_EXPR_COMPILER ( )

Definition at line 1217 of file pcb_expr_evaluator.cpp.

1218{
1219 m_unitResolver = std::make_unique<PCB_UNIT_RESOLVER>();
1220}
std::unique_ptr< UNIT_RESOLVER > m_unitResolver

References LIBEVAL::COMPILER::m_unitResolver.

Member Function Documentation

◆ Clear()

void LIBEVAL::COMPILER::Clear ( )
inherited

Definition at line 261 of file libeval_compiler.cpp.

262{
263 //free( current.token );
265
266 if( m_tree )
267 {
268 freeTree( m_tree );
269 m_tree = nullptr;
270 }
271
272 m_tree = nullptr;
273
274 for( auto tok : m_gcItems )
275 delete tok;
276
277 for( auto tok: m_gcStrings )
278 delete tok;
279
280 m_gcItems.clear();
281 m_gcStrings.clear();
282}
void freeTree(LIBEVAL::TREE_NODE *tree)
std::vector< TREE_NODE * > m_gcItems
std::vector< wxString * > m_gcStrings

References LIBEVAL::TOKENIZER::Clear(), LIBEVAL::COMPILER::freeTree(), LIBEVAL::COMPILER::m_gcItems, LIBEVAL::COMPILER::m_gcStrings, LIBEVAL::COMPILER::m_tokenizer, and LIBEVAL::COMPILER::m_tree.

Referenced by LIBEVAL::COMPILER::newString(), and LIBEVAL::COMPILER::~COMPILER().

◆ Compile()

bool LIBEVAL::COMPILER::Compile ( const wxString &  aString,
UCODE aCode,
CONTEXT aPreflightContext 
)
inherited

Definition at line 297 of file libeval_compiler.cpp.

298{
299 // Feed parser token after token until end of input.
300
301 newString( aString );
302
303 if( m_tree )
304 {
305 freeTree( m_tree );
306 m_tree = nullptr;
307 }
308
309 m_tree = nullptr;
310 m_parseFinished = false;
311 T_TOKEN tok( defaultToken );
312
313 libeval_dbg(0, "str: '%s' empty: %d\n", aString.c_str(), !!aString.empty() );
314
315 if( aString.empty() )
316 {
317 m_parseFinished = true;
318 return generateUCode( aCode, aPreflightContext );
319 }
320
321 do
322 {
324
325 tok = getToken();
326
327 if( tok.value.str )
328 GcItem( tok.value.str );
329
330 libeval_dbg(10, "parse: tok %d valstr %p\n", tok.token, tok.value.str );
331 Parse( m_parser, tok.token, tok, this );
332
334 return false;
335
336 if( m_parseFinished || tok.token == G_ENDS )
337 {
338 // Reset parser by passing zero as token ID, value is ignored.
339 Parse( m_parser, 0, tok, this );
340 break;
341 }
342 } while( tok.token );
343
344 return generateUCode( aCode, aPreflightContext );
345}
void newString(const wxString &aString)
void GcItem(TREE_NODE *aItem)
bool generateUCode(UCODE *aCode, CONTEXT *aPreflightContext)
ERROR_STATUS m_errorStatus
size_t GetPos() const
#define libeval_dbg(level, fmt,...)
constexpr T_TOKEN defaultToken
PARSE_RESULT Parse(const wxString &aString, NOTATION aNotation=NOTATION::SI, SIM_VALUE::TYPE aValueType=SIM_VALUE::TYPE_FLOAT)
Definition: sim_value.cpp:189

References LIBEVAL::defaultToken, LIBEVAL::COMPILER::freeTree(), LIBEVAL::COMPILER::GcItem(), LIBEVAL::COMPILER::generateUCode(), LIBEVAL::TOKENIZER::GetPos(), LIBEVAL::COMPILER::getToken(), libeval_dbg, LIBEVAL::COMPILER::m_errorStatus, LIBEVAL::COMPILER::m_parseFinished, LIBEVAL::COMPILER::m_parser, LIBEVAL::COMPILER::m_sourcePos, LIBEVAL::COMPILER::m_tokenizer, LIBEVAL::COMPILER::m_tree, LIBEVAL::COMPILER::newString(), SIM_VALUE_PARSER::Parse(), LIBEVAL::ERROR_STATUS::pendingError, LIBEVAL::T_TOKEN_VALUE::str, LIBEVAL::T_TOKEN::token, and LIBEVAL::T_TOKEN::value.

Referenced by DRC_RULE_CONDITION::Compile(), PCB_EXPR_EVALUATOR::Evaluate(), and testEvalExpr().

◆ freeTree()

void LIBEVAL::COMPILER::freeTree ( LIBEVAL::TREE_NODE tree)
inherited

Definition at line 687 of file libeval_compiler.cpp.

688{
689 if ( tree->leaf[0] )
690 freeTree( tree->leaf[0] );
691
692 if ( tree->leaf[1] )
693 freeTree( tree->leaf[1] );
694
695 delete tree->uop;
696}
TREE_NODE * leaf[2]

References LIBEVAL::COMPILER::freeTree(), LIBEVAL::TREE_NODE::leaf, and LIBEVAL::TREE_NODE::uop.

Referenced by LIBEVAL::COMPILER::Clear(), LIBEVAL::COMPILER::Compile(), LIBEVAL::COMPILER::freeTree(), and LIBEVAL::COMPILER::~COMPILER().

◆ GcItem() [1/2]

void LIBEVAL::COMPILER::GcItem ( TREE_NODE aItem)
inlineinherited

Definition at line 513 of file libeval_compiler.h.

513{ m_gcItems.push_back( aItem ); }

References LIBEVAL::COMPILER::m_gcItems.

Referenced by LIBEVAL::COMPILER::Compile(), and LIBEVAL::newNode().

◆ GcItem() [2/2]

void LIBEVAL::COMPILER::GcItem ( wxString *  aItem)
inlineinherited

Definition at line 514 of file libeval_compiler.h.

514{ m_gcStrings.push_back( aItem ); }

References LIBEVAL::COMPILER::m_gcStrings.

◆ generateUCode()

bool LIBEVAL::COMPILER::generateUCode ( UCODE aCode,
CONTEXT aPreflightContext 
)
protectedinherited

Definition at line 791 of file libeval_compiler.cpp.

792{
793 std::vector<TREE_NODE*> stack;
794 wxString msg;
795
796 if( !m_tree )
797 {
798 std::unique_ptr<VALUE> val = std::make_unique<VALUE>( 1.0 );
799 // Empty expression returns true
800 aCode->AddOp( new UOP( TR_UOP_PUSH_VALUE, std::move(val) ) );
801 return true;
802 }
803
805
806 stack.push_back( m_tree );
807
808 wxString dump;
809
810 dumpNode( dump, m_tree, 0 );
811 libeval_dbg( 3, "Tree dump:\n%s\n\n", (const char*) dump.c_str() );
812
813 while( !stack.empty() )
814 {
815 TREE_NODE* node = stack.back();
816
817 libeval_dbg( 4, "process node %p [op %d] [stack %lu]\n",
818 node, node->op, (unsigned long)stack.size() );
819
820 // process terminal nodes first
821 switch( node->op )
822 {
823 case TR_OP_FUNC_CALL:
824 // Function call's uop was generated inside TR_STRUCT_REF
825 if( !node->uop )
826 {
827 reportError( CST_CODEGEN, _( "Unknown parent of function parameters" ),
828 node->srcPos );
829 }
830
831 node->isTerminal = true;
832 break;
833
834 case TR_STRUCT_REF:
835 {
836 // leaf[0]: object
837 // leaf[1]: field (TR_IDENTIFIER) or TR_OP_FUNC_CALL
838
839 if( node->leaf[0]->op != TR_IDENTIFIER )
840 {
841 int pos = node->leaf[0]->srcPos;
842
843 if( node->leaf[0]->value.str )
844 pos -= static_cast<int>( node->leaf[0]->value.str->length() );
845
846 reportError( CST_CODEGEN, _( "Unknown parent of property" ), pos );
847
848 node->leaf[0]->isVisited = true;
849 node->leaf[1]->isVisited = true;
850
851 node->SetUop( TR_UOP_PUSH_VALUE, 0.0 );
852 node->isTerminal = true;
853 break;
854 }
855
856 switch( node->leaf[1]->op )
857 {
858 case TR_IDENTIFIER:
859 {
860 // leaf[0]: object
861 // leaf[1]: field
862
863 wxString itemName = *node->leaf[0]->value.str;
864 wxString propName = *node->leaf[1]->value.str;
865 std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( itemName, propName );
866
867 if( !vref )
868 {
869 msg.Printf( _( "Unrecognized item '%s'" ), itemName );
871 node->leaf[0]->srcPos - (int) itemName.length() );
872 }
873 else if( vref->GetType() == VT_PARSE_ERROR )
874 {
875 msg.Printf( _( "Unrecognized property '%s'" ), propName );
877 node->leaf[1]->srcPos - (int) propName.length() );
878 }
879
880 node->leaf[0]->isVisited = true;
881 node->leaf[1]->isVisited = true;
882
883 node->SetUop( TR_UOP_PUSH_VAR, std::move( vref ) );
884 node->isTerminal = true;
885 break;
886 }
887 case TR_OP_FUNC_CALL:
888 {
889 // leaf[0]: object
890 // leaf[1]: TR_OP_FUNC_CALL
891 // leaf[0]: function name
892 // leaf[1]: parameter
893
894 wxString itemName = *node->leaf[0]->value.str;
895 std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( itemName, "" );
896
897 if( !vref )
898 {
899 msg.Printf( _( "Unrecognized item '%s'" ), itemName );
901 node->leaf[0]->srcPos - (int) itemName.length() );
902 }
903
904 wxString functionName = *node->leaf[1]->leaf[0]->value.str;
905 auto func = aCode->CreateFuncCall( functionName );
906 std::vector<TREE_NODE*> params = squashParamList( node->leaf[1]->leaf[1] );
907
908 libeval_dbg( 10, "emit func call: %s\n", functionName );
909
910 if( !func )
911 {
912 msg.Printf( _( "Unrecognized function '%s'" ), functionName );
913 reportError( CST_CODEGEN, msg, node->leaf[0]->srcPos + 1 );
914 }
915
916 if( func )
917 {
918 // Preflight the function call
919
920 for( TREE_NODE* pnode : params )
921 {
922 VALUE* param = aPreflightContext->AllocValue();
923 param->Set( *pnode->value.str );
924 aPreflightContext->Push( param );
925 }
926
927 aPreflightContext->SetErrorCallback(
928 [&]( const wxString& aMessage, int aOffset )
929 {
930 size_t loc = node->leaf[1]->leaf[1]->srcPos;
931 reportError( CST_CODEGEN, aMessage, (int) loc - 1 );
932 } );
933
934 try
935 {
936 func( aPreflightContext, vref.get() );
937 aPreflightContext->Pop(); // return value
938 }
939 catch( ... )
940 {
941 }
942 }
943
944 node->leaf[0]->isVisited = true;
945 node->leaf[1]->isVisited = true;
946 node->leaf[1]->leaf[0]->isVisited = true;
947 node->leaf[1]->leaf[1]->isVisited = true;
948
949 // Our non-terminal-node stacking algorithm can't handle doubly-nested
950 // structures so we need to pop a level by replacing the TR_STRUCT_REF with
951 // a TR_OP_FUNC_CALL and its function parameter
952 stack.pop_back();
953 stack.push_back( node->leaf[1] );
954
955 for( TREE_NODE* pnode : params )
956 stack.push_back( pnode );
957
958 node->leaf[1]->SetUop( TR_OP_METHOD_CALL, func, std::move( vref ) );
959 node->isTerminal = false;
960 break;
961 }
962
963 default:
964 // leaf[0]: object
965 // leaf[1]: malformed syntax
966
967 wxString itemName = *node->leaf[0]->value.str;
968 wxString propName = *node->leaf[1]->value.str;
969 std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( itemName, propName );
970
971 if( !vref )
972 {
973 msg.Printf( _( "Unrecognized item '%s'" ), itemName );
975 node->leaf[0]->srcPos - (int) itemName.length() );
976 }
977
978 msg.Printf( _( "Unrecognized property '%s'" ), propName );
979 reportError( CST_CODEGEN, msg, node->leaf[0]->srcPos + 1 );
980
981 node->leaf[0]->isVisited = true;
982 node->leaf[1]->isVisited = true;
983
984 node->SetUop( TR_UOP_PUSH_VALUE, 0.0 );
985 node->isTerminal = true;
986 break;
987 }
988
989 break;
990 }
991
992 case TR_NUMBER:
993 {
994 TREE_NODE* son = node->leaf[0];
995 double value;
996
997 if( !node->value.str )
998 {
999 value = 0.0;
1000 }
1001 else if( son && son->op == TR_UNIT )
1002 {
1003 int units = son->value.idx;
1004 value = m_unitResolver->Convert( *node->value.str, units );
1005 son->isVisited = true;
1006 }
1007 else
1008 {
1009 msg.Printf( _( "Missing units for '%s'| (%s)" ),
1010 *node->value.str,
1011 m_unitResolver->GetSupportedUnitsMessage() );
1012 reportError( CST_CODEGEN, msg, node->srcPos );
1013
1014 value = DoubleValueFromString( EDA_UNITS::UNSCALED, *node->value.str );
1015 }
1016
1017 node->SetUop( TR_UOP_PUSH_VALUE, value );
1018 node->isTerminal = true;
1019 break;
1020 }
1021
1022 case TR_STRING:
1023 {
1024 wxString str = *node->value.str;
1025 bool isWildcard = str.Contains("?") || str.Contains("*");
1026 node->SetUop( TR_UOP_PUSH_VALUE, str, isWildcard );
1027 node->isTerminal = true;
1028 break;
1029 }
1030
1031 case TR_IDENTIFIER:
1032 {
1033 std::unique_ptr<VAR_REF> vref = aCode->CreateVarRef( *node->value.str, "" );
1034
1035 if( !vref )
1036 {
1037 msg.Printf( _( "Unrecognized item '%s'" ), *node->value.str );
1038 reportError( CST_CODEGEN, msg, node->srcPos - (int) node->value.str->length() );
1039 }
1040
1041 node->SetUop( TR_UOP_PUSH_VALUE, std::move( vref ) );
1042 node->isTerminal = true;
1043 break;
1044 }
1045
1046 default:
1047 node->SetUop( node->op );
1048 node->isTerminal = ( !node->leaf[0] || node->leaf[0]->isVisited )
1049 && ( !node->leaf[1] || node->leaf[1]->isVisited );
1050 break;
1051 }
1052
1053 if( !node->isTerminal )
1054 {
1055 if( node->leaf[0] && !node->leaf[0]->isVisited )
1056 {
1057 stack.push_back( node->leaf[0] );
1058 node->leaf[0]->isVisited = true;
1059 continue;
1060 }
1061 else if( node->leaf[1] && !node->leaf[1]->isVisited )
1062 {
1063 stack.push_back( node->leaf[1] );
1064 node->leaf[1]->isVisited = true;
1065 }
1066
1067 continue;
1068 }
1069
1070 node->isVisited = true;
1071
1072 if( node->uop )
1073 {
1074 aCode->AddOp( node->uop );
1075 node->uop = nullptr;
1076 }
1077
1078 stack.pop_back();
1079 }
1080
1081 libeval_dbg(2,"dump: \n%s\n", aCode->Dump().c_str() );
1082
1083 return true;
1084}
double DoubleValueFromString(EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType)
Function DoubleValueFromString converts aTextValue to a double.
Definition: base_units.cpp:276
void reportError(COMPILATION_STAGE stage, const wxString &aErrorMsg, int aPos=-1)
#define _(s)
#define TR_UOP_PUSH_VAR
#define TR_UOP_PUSH_VALUE
#define TR_OP_FUNC_CALL
#define TR_OP_METHOD_CALL
static std::vector< TREE_NODE * > squashParamList(TREE_NODE *root)
void dumpNode(wxString &buf, TREE_NODE *tok, int depth=0)
static void prepareTree(LIBEVAL::TREE_NODE *node)
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.

References _, LIBEVAL::UCODE::AddOp(), LIBEVAL::CONTEXT::AllocValue(), LIBEVAL::UCODE::CreateFuncCall(), LIBEVAL::UCODE::CreateVarRef(), LIBEVAL::CST_CODEGEN, DoubleValueFromString(), LIBEVAL::UCODE::Dump(), dump(), LIBEVAL::dumpNode(), LIBEVAL::T_TOKEN_VALUE::idx, LIBEVAL::TREE_NODE::isTerminal, LIBEVAL::TREE_NODE::isVisited, LIBEVAL::TREE_NODE::leaf, libeval_dbg, LIBEVAL::COMPILER::m_tree, LIBEVAL::COMPILER::m_unitResolver, LIBEVAL::TREE_NODE::op, LIBEVAL::CONTEXT::Pop(), LIBEVAL::prepareTree(), LIBEVAL::CONTEXT::Push(), LIBEVAL::COMPILER::reportError(), LIBEVAL::VALUE::Set(), LIBEVAL::CONTEXT::SetErrorCallback(), LIBEVAL::TREE_NODE::SetUop(), LIBEVAL::squashParamList(), LIBEVAL::TREE_NODE::srcPos, LIBEVAL::T_TOKEN_VALUE::str, LIBEVAL::TR_IDENTIFIER, LIBEVAL::TR_NUMBER, TR_OP_FUNC_CALL, TR_OP_METHOD_CALL, LIBEVAL::TR_STRING, LIBEVAL::TR_STRUCT_REF, LIBEVAL::TR_UNIT, TR_UOP_PUSH_VALUE, TR_UOP_PUSH_VAR, UNSCALED, LIBEVAL::TREE_NODE::uop, LIBEVAL::TREE_NODE::value, and LIBEVAL::VT_PARSE_ERROR.

Referenced by LIBEVAL::COMPILER::Compile().

◆ GetError()

const ERROR_STATUS & LIBEVAL::COMPILER::GetError ( ) const
inlineinherited

Definition at line 511 of file libeval_compiler.h.

511{ return m_errorStatus; }

References LIBEVAL::COMPILER::m_errorStatus.

Referenced by testEvalExpr().

◆ GetSourcePos()

int LIBEVAL::COMPILER::GetSourcePos ( ) const
inlineinherited

Definition at line 498 of file libeval_compiler.h.

498{ return m_sourcePos; }

References LIBEVAL::COMPILER::m_sourcePos.

Referenced by LIBEVAL::newNode().

◆ getToken()

T_TOKEN LIBEVAL::COMPILER::getToken ( )
protectedinherited

Definition at line 357 of file libeval_compiler.cpp.

358{
359 T_TOKEN rv;
360 rv.value.str = nullptr;
361
362 bool done = false;
363
364 do
365 {
366 switch( m_lexerState )
367 {
368 case LS_DEFAULT:
369 done = lexDefault( rv );
370 break;
371 case LS_STRING:
372 done = lexString( rv );
373 break;
374 }
375 } while( !done );
376
377 return rv;
378}
bool lexString(T_TOKEN &aToken)
LEXER_STATE m_lexerState
bool lexDefault(T_TOKEN &aToken)

References LIBEVAL::COMPILER::lexDefault(), LIBEVAL::COMPILER::lexString(), LIBEVAL::COMPILER::LS_DEFAULT, LIBEVAL::COMPILER::LS_STRING, LIBEVAL::COMPILER::m_lexerState, LIBEVAL::T_TOKEN_VALUE::str, and LIBEVAL::T_TOKEN::value.

Referenced by LIBEVAL::COMPILER::Compile().

◆ IsErrorPending()

bool LIBEVAL::COMPILER::IsErrorPending ( ) const
inlineinherited

◆ lexDefault()

bool LIBEVAL::COMPILER::lexDefault ( T_TOKEN aToken)
protectedinherited

Definition at line 414 of file libeval_compiler.cpp.

415{
416 T_TOKEN retval;
417 wxString current;
418 int convertFrom;
419 wxString msg;
420
421 retval.value.str = nullptr;
422 retval.value.num = 0.0;
423 retval.value.idx = -1;
424 retval.token = G_ENDS;
425
426 if( m_tokenizer.Done() )
427 {
428 aToken = retval;
429 return true;
430 }
431
432 auto isDecimalSeparator =
433 [&]( wxUniChar ch ) -> bool
434 {
435 return ( ch == m_localeDecimalSeparator || ch == '.' || ch == ',' );
436 };
437
438 // Lambda: get value as string, store into clToken.token and update current index.
439 auto extractNumber =
440 [&]()
441 {
442 bool haveSeparator = false;
443 wxUniChar ch = m_tokenizer.GetChar();
444
445 do
446 {
447 if( isDecimalSeparator( ch ) && haveSeparator )
448 break;
449
450 current.append( 1, ch );
451
452 if( isDecimalSeparator( ch ) )
453 haveSeparator = true;
454
456 ch = m_tokenizer.GetChar();
457 } while( isdigit( ch ) || isDecimalSeparator( ch ) );
458
459 // Ensure that the systems decimal separator is used
460 for( int i = current.length(); i; i-- )
461 {
462 if( isDecimalSeparator( current[i - 1] ) )
463 current[i - 1] = m_localeDecimalSeparator;
464 }
465 };
466
467
468 int ch;
469
470 // Start processing of first/next token: Remove whitespace
471 for( ;; )
472 {
473 ch = m_tokenizer.GetChar();
474
475 if( ch == ' ' )
477 else
478 break;
479 }
480
481 libeval_dbg(10, "LEX ch '%c' pos %lu\n", ch, (unsigned long)m_tokenizer.GetPos() );
482
483 if( ch == 0 )
484 {
485 /* End of input */
486 }
487 else if( isdigit( ch ) )
488 {
489 // VALUE
490 extractNumber();
491 retval.token = G_VALUE;
492 retval.value.str = new wxString( current );
493 }
494 else if( ( convertFrom = resolveUnits() ) >= 0 )
495 {
496 // UNIT
497 // Units are appended to a VALUE.
498 // Determine factor to default unit if unit for value is given.
499 // Example: Default is mm, unit is inch: factor is 25.4
500 // The factor is assigned to the terminal UNIT. The actual
501 // conversion is done within a parser action.
502 retval.token = G_UNIT;
503 retval.value.idx = convertFrom;
504 }
505 else if( ch == '\'' ) // string literal
506 {
509 return false;
510 }
511 else if( isalpha( ch ) || ch == '_' )
512 {
513 current = m_tokenizer.GetChars( []( int c ) -> bool { return isalnum( c ) || c == '_'; } );
514 retval.token = G_IDENTIFIER;
515 retval.value.str = new wxString( current );
516 m_tokenizer.NextChar( current.length() );
517 }
518 else if( m_tokenizer.MatchAhead( "==", []( int c ) -> bool { return c != '='; } ) )
519 {
520 retval.token = G_EQUAL;
522 }
523 else if( m_tokenizer.MatchAhead( "!=", []( int c ) -> bool { return c != '='; } ) )
524 {
525 retval.token = G_NOT_EQUAL;
527 }
528 else if( m_tokenizer.MatchAhead( "<=", []( int c ) -> bool { return c != '='; } ) )
529 {
530 retval.token = G_LESS_EQUAL_THAN;
532 }
533 else if( m_tokenizer.MatchAhead( ">=", []( int c ) -> bool { return c != '='; } ) )
534 {
535 retval.token = G_GREATER_EQUAL_THAN;
537 }
538 else if( m_tokenizer.MatchAhead( "&&", []( int c ) -> bool { return c != '&'; } ) )
539 {
540 retval.token = G_BOOL_AND;
542 }
543 else if( m_tokenizer.MatchAhead( "||", []( int c ) -> bool { return c != '|'; } ) )
544 {
545 retval.token = G_BOOL_OR;
547 }
548 else
549 {
550 // Single char tokens
551 switch( ch )
552 {
553 case '+': retval.token = G_PLUS; break;
554 case '!': retval.token = G_BOOL_NOT; break;
555 case '-': retval.token = G_MINUS; break;
556 case '*': retval.token = G_MULT; break;
557 case '/': retval.token = G_DIVIDE; break;
558 case '<': retval.token = G_LESS_THAN; break;
559 case '>': retval.token = G_GREATER_THAN; break;
560 case '(': retval.token = G_PARENL; break;
561 case ')': retval.token = G_PARENR; break;
562 case ';': retval.token = G_SEMCOL; break;
563 case '.': retval.token = G_STRUCT_REF; break;
564 case ',': retval.token = G_COMMA; break;
565
566 default:
567 reportError( CST_PARSE, wxString::Format( _( "Unrecognized character '%c'" ),
568 (char) ch ) );
569 break;
570 }
571
573 }
574
575 aToken = retval;
576 return true;
577}
void NextChar(int aAdvance=1)
wxString GetChars(const std::function< bool(wxUniChar)> &cond) const
bool MatchAhead(const wxString &match, const std::function< bool(wxUniChar)> &stopCond) const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200

References _, LIBEVAL::CST_PARSE, LIBEVAL::TOKENIZER::Done(), Format(), LIBEVAL::TOKENIZER::GetChar(), LIBEVAL::TOKENIZER::GetChars(), LIBEVAL::TOKENIZER::GetPos(), LIBEVAL::T_TOKEN_VALUE::idx, libeval_dbg, LIBEVAL::COMPILER::LS_STRING, LIBEVAL::COMPILER::m_lexerState, LIBEVAL::COMPILER::m_localeDecimalSeparator, LIBEVAL::COMPILER::m_tokenizer, LIBEVAL::TOKENIZER::MatchAhead(), LIBEVAL::TOKENIZER::NextChar(), LIBEVAL::T_TOKEN_VALUE::num, LIBEVAL::COMPILER::reportError(), LIBEVAL::COMPILER::resolveUnits(), LIBEVAL::T_TOKEN_VALUE::str, LIBEVAL::T_TOKEN::token, and LIBEVAL::T_TOKEN::value.

Referenced by LIBEVAL::COMPILER::getToken().

◆ lexString()

bool LIBEVAL::COMPILER::lexString ( T_TOKEN aToken)
protectedinherited

Definition at line 381 of file libeval_compiler.cpp.

382{
383 wxString str = m_tokenizer.GetChars( []( int c ) -> bool { return c != '\''; } );
384
385 aToken.token = G_STRING;
386 aToken.value.str = new wxString( str );
387
388 m_tokenizer.NextChar( str.length() + 1 );
390 return true;
391}

References LIBEVAL::TOKENIZER::GetChars(), LIBEVAL::COMPILER::LS_DEFAULT, LIBEVAL::COMPILER::m_lexerState, LIBEVAL::COMPILER::m_tokenizer, LIBEVAL::TOKENIZER::NextChar(), LIBEVAL::T_TOKEN_VALUE::str, LIBEVAL::T_TOKEN::token, and LIBEVAL::T_TOKEN::value.

Referenced by LIBEVAL::COMPILER::getToken().

◆ newString()

void LIBEVAL::COMPILER::newString ( const wxString &  aString)
protectedinherited

◆ parseError()

void LIBEVAL::COMPILER::parseError ( const char *  s)
inherited

Definition at line 285 of file libeval_compiler.cpp.

286{
288}

References LIBEVAL::CST_PARSE, and LIBEVAL::COMPILER::reportError().

◆ parseOk()

void LIBEVAL::COMPILER::parseOk ( )
inherited

Definition at line 291 of file libeval_compiler.cpp.

292{
293 m_parseFinished = true;
294}

References LIBEVAL::COMPILER::m_parseFinished.

◆ reportError()

void LIBEVAL::COMPILER::reportError ( COMPILATION_STAGE  stage,
const wxString &  aErrorMsg,
int  aPos = -1 
)
protectedinherited

◆ resolveUnits()

int LIBEVAL::COMPILER::resolveUnits ( )
protectedinherited

Definition at line 394 of file libeval_compiler.cpp.

395{
396 int unitId = 0;
397
398 for( const wxString& unitName : m_unitResolver->GetSupportedUnits() )
399 {
400 if( m_tokenizer.MatchAhead( unitName, []( int c ) -> bool { return !isalnum( c ); } ) )
401 {
402 libeval_dbg(10, "Match unit '%s'\n", unitName.c_str() );
403 m_tokenizer.NextChar( unitName.length() );
404 return unitId;
405 }
406
407 unitId++;
408 }
409
410 return -1;
411}

References libeval_dbg, LIBEVAL::COMPILER::m_tokenizer, LIBEVAL::COMPILER::m_unitResolver, LIBEVAL::TOKENIZER::MatchAhead(), and LIBEVAL::TOKENIZER::NextChar().

Referenced by LIBEVAL::COMPILER::lexDefault().

◆ SetErrorCallback()

void LIBEVAL::COMPILER::SetErrorCallback ( std::function< void(const wxString &aMessage, int aOffset)>  aCallback)
inlineinherited

Definition at line 505 of file libeval_compiler.h.

506 {
507 m_errorCallback = std::move( aCallback );
508 }

References LIBEVAL::COMPILER::m_errorCallback.

Referenced by DRC_RULE_CONDITION::Compile(), and PCB_EXPR_EVALUATOR::SetErrorCallback().

◆ setRoot()

void LIBEVAL::COMPILER::setRoot ( LIBEVAL::TREE_NODE root)
inherited

Definition at line 681 of file libeval_compiler.cpp.

682{
683 m_tree = root;
684}

References LIBEVAL::COMPILER::m_tree.

Member Data Documentation

◆ m_errorCallback

std::function<void( const wxString& aMessage, int aOffset )> LIBEVAL::COMPILER::m_errorCallback
protectedinherited

◆ m_errorStatus

ERROR_STATUS LIBEVAL::COMPILER::m_errorStatus
protectedinherited

◆ m_gcItems

std::vector<TREE_NODE*> LIBEVAL::COMPILER::m_gcItems
protectedinherited

Definition at line 555 of file libeval_compiler.h.

Referenced by LIBEVAL::COMPILER::Clear(), and LIBEVAL::COMPILER::GcItem().

◆ m_gcStrings

std::vector<wxString*> LIBEVAL::COMPILER::m_gcStrings
protectedinherited

Definition at line 556 of file libeval_compiler.h.

Referenced by LIBEVAL::COMPILER::Clear(), and LIBEVAL::COMPILER::GcItem().

◆ m_lexerState

LEXER_STATE LIBEVAL::COMPILER::m_lexerState
protectedinherited

◆ m_localeDecimalSeparator

char LIBEVAL::COMPILER::m_localeDecimalSeparator
protectedinherited

◆ m_parseFinished

bool LIBEVAL::COMPILER::m_parseFinished
protectedinherited

◆ m_parser

void* LIBEVAL::COMPILER::m_parser
protectedinherited

◆ m_sourcePos

int LIBEVAL::COMPILER::m_sourcePos
protectedinherited

◆ m_tokenizer

◆ m_tree

◆ m_unitResolver

std::unique_ptr<UNIT_RESOLVER> LIBEVAL::COMPILER::m_unitResolver
protectedinherited

The documentation for this class was generated from the following files: