KiCad PCB EDA Suite
Loading...
Searching...
No Matches
libeval_compiler.h
Go to the documentation of this file.
1/*
2 This file is part of libeval, a simple math expression evaluator
3
4 Copyright (C) 2007 Michael Geselbracht, [email protected]
5 Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
19*/
20
21#pragma once
22
23#include <cstddef>
24#include <functional>
25#include <map>
26#include <string>
27#include <stack>
28
29#include <kicommon.h>
30#include <base_units.h>
31#include <wx/intl.h>
32
33#if defined(WIN32)
34// This gets leaked by python headers on MSVC only and will cause chaos
35#undef COMPILER
36#endif
37
38#define TR_OP_BINARY_MASK 0x200
39#define TR_OP_UNARY_MASK 0x100
40
41#define TR_OP_MUL 0x201
42#define TR_OP_DIV 0x202
43#define TR_OP_ADD 0x203
44#define TR_OP_SUB 0x204
45#define TR_OP_LESS 0x205
46#define TR_OP_GREATER 0x206
47#define TR_OP_LESS_EQUAL 0x207
48#define TR_OP_GREATER_EQUAL 0x208
49#define TR_OP_EQUAL 0x209
50#define TR_OP_NOT_EQUAL 0x20a
51#define TR_OP_BOOL_AND 0x20b
52#define TR_OP_BOOL_OR 0x20c
53#define TR_OP_BOOL_NOT 0x100
54#define TR_OP_FUNC_CALL 24
55#define TR_OP_METHOD_CALL 25
56#define TR_UOP_PUSH_VAR 1
57#define TR_UOP_PUSH_VALUE 2
58
59// This namespace is used for the lemon parser
60namespace LIBEVAL
61{
62
63class COMPILER;
64
66{
70};
71
73{
74 bool pendingError = false;
75
77 wxString message;
78 int srcPos;
79};
80
81
83{
90};
91
93{
102 TR_NULL = 8
104
105class UOP;
106class UCODE;
107class CONTEXT;
108class VAR_REF;
109
110typedef std::function<void( CONTEXT*, void* )> FUNC_CALL_REF;
111
113{
114 wxString* str;
115 double num;
116 int idx;
117};
118
119// Lemon can't handle c'tors and d'tors, so we provide a poor-man's version.
120constexpr T_TOKEN_VALUE defaultTokenValue = { nullptr, 0.0, 0 };
121
122
124{
125 int token;
127};
128
129// Lemon can't handle c'tors and d'tors, so we provide a poor-man's version.
131
132
134{
135public:
137
138 int op;
139 TREE_NODE* leaf[2];
141 bool valid;
145
146 void SetUop( int aOp, double aValue, EDA_UNITS aUnits );
147 void SetUop( int aOp, const wxString& aValue, bool aStringIsWildcard );
148 void SetUop( int aOp, std::unique_ptr<VAR_REF> aRef = nullptr );
149 void SetUop( int aOp, FUNC_CALL_REF aFunc, std::unique_ptr<VAR_REF> aRef = nullptr );
150};
151
152
153TREE_NODE* newNode( LIBEVAL::COMPILER* compiler, int op,
154 const T_TOKEN_VALUE& value = defaultTokenValue );
155
157{
158public:
160 {
161 }
162
164 {
165 }
166
167 virtual const std::vector<wxString>& GetSupportedUnits() const
168 {
169 static const std::vector<wxString> nullUnits;
170
171 return nullUnits;
172 }
173
174
175 virtual const std::vector<EDA_UNITS>& GetSupportedUnitsTypes() const
176 {
177 static const std::vector<EDA_UNITS> nullUnits;
178
179 return nullUnits;
180 }
181
182 virtual wxString GetSupportedUnitsMessage() const
183 {
184 return wxEmptyString;
185 }
186
187 virtual double Convert( const wxString& aString, int unitType ) const
188 {
189 return 0.0;
190 }
191};
192
193
195{
196public:
198 m_type( VT_UNDEFINED ),
199 m_valueDbl( 0 ),
200 m_stringIsWildcard( false ),
201 m_isDeferredDbl( false ),
202 m_isDeferredStr( false ),
203 m_units( EDA_UNITS::UNSCALED )
204 {}
205
206 VALUE( const wxString& aStr, bool aIsWildcard = false ) :
207 m_type( VT_STRING ),
208 m_valueDbl( 0 ),
209 m_valueStr( aStr ),
210 m_stringIsWildcard( aIsWildcard ),
211 m_isDeferredDbl( false ),
212 m_isDeferredStr( false ),
213 m_units( EDA_UNITS::UNSCALED )
214 {}
215
216 VALUE( const double aVal ) :
217 m_type( VT_NUMERIC ),
218 m_valueDbl( aVal ),
219 m_stringIsWildcard( false ),
220 m_isDeferredDbl( false ),
221 m_isDeferredStr( false ),
222 m_units( EDA_UNITS::UNSCALED )
223 {}
224
226 {
227 VALUE* v = new VALUE();
228 v->m_type = VT_NULL;
229 return v;
230 }
231
232 virtual ~VALUE() = default;
233
234 virtual double AsDouble() const
235 {
236 if( m_isDeferredDbl )
237 {
238 m_valueDbl = m_lambdaDbl();
239 m_isDeferredDbl = false;
240 }
241
242 return m_valueDbl;
243 }
244
245 virtual const wxString& AsString() const
246 {
247 if( m_isDeferredStr )
248 {
249 m_valueStr = m_lambdaStr();
250 m_isDeferredStr = false;
251 }
252
253 return m_valueStr;
254 }
255
256 virtual bool EqualTo( CONTEXT* aCtx, const VALUE* b ) const;
257
258 // NB: this is not an inverse of EqualTo as they both return false for undefined values.
259 virtual bool NotEqualTo( CONTEXT* aCtx, const VALUE* b ) const;
260
261 VAR_TYPE_T GetType() const { return m_type; };
262
263 void Set( double aValue )
264 {
265 m_type = VT_NUMERIC;
266 m_valueDbl = aValue;
267 }
268
269 void SetDeferredEval( std::function<double()> aLambda )
270 {
271 m_type = VT_NUMERIC;
272 m_lambdaDbl = std::move( aLambda );
273 m_isDeferredDbl = true;
274 }
275
276 void SetDeferredEval( std::function<wxString()> aLambda )
277 {
278 m_type = VT_STRING;
279 m_lambdaStr = std::move( aLambda );
280 m_isDeferredStr = true;
281 }
282
283 void Set( const wxString& aValue )
284 {
285 m_type = VT_STRING;
286 m_valueStr = aValue;
287 }
288
289 void Set( const VALUE &val )
290 {
291 m_type = val.m_type;
292 m_valueDbl = val.m_valueDbl;
293
294 if( m_type == VT_STRING )
295 m_valueStr = val.m_valueStr;
296 }
297
298 void SetUnits( const EDA_UNITS aUnits ) { m_units = aUnits; }
299
300 EDA_UNITS GetUnits() const { return m_units; }
301
302 bool StringIsWildcard() const { return m_stringIsWildcard; }
303
304private:
306 mutable double m_valueDbl; // mutable to support deferred evaluation
307 mutable wxString m_valueStr; // mutable to support deferred evaluation
309
310 mutable bool m_isDeferredDbl;
311 std::function<double()> m_lambdaDbl;
312
313 mutable bool m_isDeferredStr;
314 std::function<wxString()> m_lambdaStr;
315
317};
318
320{
321public:
323 {}
324
325 virtual ~VAR_REF() = default;
326
327 virtual VAR_TYPE_T GetType() const = 0;
328 virtual VALUE* GetValue( CONTEXT* aCtx ) = 0;
329};
330
331
333{
334public:
336 m_stack(),
337 m_stackPtr( 0 )
338 {
339 m_ownedValues.reserve( 20 );
340 }
341
342 virtual ~CONTEXT()
343 {
344 for( VALUE* v : m_ownedValues )
345 delete v;
346 }
347
348 // We own at least one list of raw pointers. Don't let the compiler fill in copy c'tors that
349 // will only land us in trouble.
350 CONTEXT( const CONTEXT& ) = delete;
351 CONTEXT& operator=( const CONTEXT& ) = delete;
352
354 {
355 m_ownedValues.emplace_back( new VALUE );
356 return m_ownedValues.back();
357 }
358
360 {
361 m_ownedValues.emplace_back( aValue );
362 return m_ownedValues.back();
363 }
364
365 void Push( VALUE* v )
366 {
367 m_stack[ m_stackPtr++ ] = v;
368 }
369
371 {
372 if( m_stackPtr == 0 )
373 {
374 ReportError( _( "Malformed expression" ) );
375 return AllocValue();
376 }
377
378 return m_stack[ --m_stackPtr ];
379 }
380
381 int SP() const
382 {
383 return m_stackPtr;
384 };
385
386 void SetErrorCallback( std::function<void( const wxString& aMessage, int aOffset )> aCallback )
387 {
388 m_errorCallback = std::move( aCallback );
389 }
390
391 bool HasErrorCallback() { return m_errorCallback != nullptr; }
392
393 void ReportError( const wxString& aErrorMsg );
394
395private:
396 std::vector<VALUE*> m_ownedValues;
397 VALUE* m_stack[100]; // std::stack not performant enough
399
400 std::function<void( const wxString& aMessage, int aOffset )> m_errorCallback;
401};
402
403
405{
406public:
408 {}
409
410 virtual ~UCODE();
411
412 // We own at least one list of raw pointers. Don't let the compiler fill in copy c'tors that
413 // will only land us in trouble.
414 UCODE( const UCODE& ) = delete;
415 UCODE& operator=( const UCODE& ) = delete;
416
417 void AddOp( UOP* uop )
418 {
419 m_ucode.push_back(uop);
420 }
421
422 VALUE* Run( CONTEXT* ctx );
423 wxString Dump() const;
424
425 virtual std::unique_ptr<VAR_REF> CreateVarRef( const wxString& var, const wxString& field )
426 {
427 return nullptr;
428 }
429
430 virtual FUNC_CALL_REF CreateFuncCall( const wxString& name )
431 {
432 return nullptr;
433 }
434
435protected:
436 std::vector<UOP*> m_ucode;
437};
438
439
441{
442public:
443 UOP( int op, std::unique_ptr<VALUE> value ) :
444 m_op( op ),
445 m_ref(nullptr),
446 m_value( std::move( value ) )
447 {}
448
449 UOP( int op, std::unique_ptr<VAR_REF> vref ) :
450 m_op( op ),
451 m_ref( std::move( vref ) ),
452 m_value(nullptr)
453 {}
454
455 UOP( int op, FUNC_CALL_REF func, std::unique_ptr<VAR_REF> vref = nullptr ) :
456 m_op( op ),
457 m_func( std::move( func ) ),
458 m_ref( std::move( vref ) ),
459 m_value(nullptr)
460 {}
461
462 virtual ~UOP() = default;
463
464 void Exec( CONTEXT* ctx );
465
466 wxString Format() const;
467
468private:
469 int m_op;
470
472 std::unique_ptr<VAR_REF> m_ref;
473 std::unique_ptr<VALUE> m_value;
474};
475
477{
478public:
479 void Restart( const wxString& aStr )
480 {
481 m_str = aStr;
482 m_pos = 0;
483 }
484
485 void Clear()
486 {
487 m_str = "";
488 m_pos = 0;
489 }
490
491 int GetChar() const
492 {
493 if( m_pos >= m_str.length() )
494 return 0;
495
496 return m_str[m_pos];
497 }
498
499 bool Done() const
500 {
501 return m_pos >= m_str.length();
502 }
503
504 void NextChar( int aAdvance = 1 )
505 {
506 m_pos += aAdvance;
507 }
508
509 size_t GetPos() const
510 {
511 return m_pos;
512 }
513
514 wxString GetString();
515
516 wxString GetChars( const std::function<bool( wxUniChar )>& cond ) const;
517
518 bool MatchAhead( const wxString& match,
519 const std::function<bool( wxUniChar )>& stopCond ) const;
520
521private:
522 wxString m_str;
523 size_t m_pos = 0;
524};
525
526
528{
529public:
530 COMPILER();
531 virtual ~COMPILER();
532
533 // We own at least one list of raw pointers. Don't let the compiler fill in copy c'tors that
534 // will only land us in trouble.
535 COMPILER( const COMPILER& ) = delete;
536 COMPILER& operator=( const COMPILER& ) = delete;
537
538 /*
539 * clear() should be invoked by the client if a new input string is to be processed. It
540 * will reset the parser. User defined variables are retained.
541 */
542 void Clear();
543
544 /* Used by the lemon parser */
545 void parseError( const char* s );
546 void parseOk();
547
548 int GetSourcePos() const { return m_sourcePos; }
549
550 void setRoot( LIBEVAL::TREE_NODE *root );
551 void freeTree( LIBEVAL::TREE_NODE *tree );
552
553 bool Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflightContext );
554
555 void SetErrorCallback( std::function<void( const wxString& aMessage, int aOffset )> aCallback )
556 {
557 m_errorCallback = std::move( aCallback );
558 }
559
560 bool IsErrorPending() const { return m_errorStatus.pendingError; }
561 const ERROR_STATUS& GetError() const { return m_errorStatus; }
562
563 void GcItem( TREE_NODE* aItem ) { m_gcItems.push_back( aItem ); }
564 void GcItem( wxString* aItem ) { m_gcStrings.push_back( aItem ); }
565
566protected:
568 {
569 LS_DEFAULT = 0,
570 LS_STRING = 1,
571 };
572
574
575 bool generateUCode( UCODE* aCode, CONTEXT* aPreflightContext );
576
577 void reportError( COMPILATION_STAGE stage, const wxString& aErrorMsg, int aPos = -1 );
578
579 /* Begin processing of a new input string */
580 void newString( const wxString& aString );
581
582 /* Tokenizer: Next token/value taken from input string. */
583 T_TOKEN getToken();
584 bool lexDefault( T_TOKEN& aToken );
585 bool lexString( T_TOKEN& aToken );
586
587 int resolveUnits();
588
589protected:
590 /* Token state for input string. */
591 void* m_parser; // the current lemon parser state machine
594
595 std::unique_ptr<UNIT_RESOLVER> m_unitResolver;
596
600
601 std::function<void( const wxString& aMessage, int aOffset )> m_errorCallback;
602
604
605 std::vector<TREE_NODE*> m_gcItems;
606 std::vector<wxString*> m_gcStrings;
607};
608
609
610} // namespace LIBEVAL
611
const char * name
Definition: DXF_plotter.cpp:62
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
bool IsErrorPending() const
std::unique_ptr< UNIT_RESOLVER > m_unitResolver
void GcItem(wxString *aItem)
void GcItem(TREE_NODE *aItem)
LEXER_STATE m_lexerState
COMPILER(const COMPILER &)=delete
std::function< void(const wxString &aMessage, int aOffset)> m_errorCallback
int GetSourcePos() const
std::vector< TREE_NODE * > m_gcItems
const ERROR_STATUS & GetError() const
COMPILER & operator=(const COMPILER &)=delete
std::vector< wxString * > m_gcStrings
ERROR_STATUS m_errorStatus
std::vector< VALUE * > m_ownedValues
VALUE * StoreValue(VALUE *aValue)
std::function< void(const wxString &aMessage, int aOffset)> m_errorCallback
CONTEXT(const CONTEXT &)=delete
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
CONTEXT & operator=(const CONTEXT &)=delete
void Push(VALUE *v)
void NextChar(int aAdvance=1)
void Restart(const wxString &aStr)
size_t GetPos() const
virtual std::unique_ptr< VAR_REF > CreateVarRef(const wxString &var, const wxString &field)
void AddOp(UOP *uop)
UCODE(const UCODE &)=delete
std::vector< UOP * > m_ucode
virtual FUNC_CALL_REF CreateFuncCall(const wxString &name)
UCODE & operator=(const UCODE &)=delete
virtual wxString GetSupportedUnitsMessage() const
virtual const std::vector< EDA_UNITS > & GetSupportedUnitsTypes() const
virtual double Convert(const wxString &aString, int unitType) const
virtual const std::vector< wxString > & GetSupportedUnits() const
virtual ~UOP()=default
UOP(int op, FUNC_CALL_REF func, std::unique_ptr< VAR_REF > vref=nullptr)
std::unique_ptr< VAR_REF > m_ref
FUNC_CALL_REF m_func
UOP(int op, std::unique_ptr< VALUE > value)
std::unique_ptr< VALUE > m_value
UOP(int op, std::unique_ptr< VAR_REF > vref)
void Set(double aValue)
virtual const wxString & AsString() const
void SetUnits(const EDA_UNITS aUnits)
void SetDeferredEval(std::function< wxString()> aLambda)
bool StringIsWildcard() const
virtual ~VALUE()=default
void Set(const wxString &aValue)
static VALUE * MakeNullValue()
std::function< double()> m_lambdaDbl
virtual double AsDouble() const
EDA_UNITS GetUnits() const
VAR_TYPE_T GetType() const
void Set(const VALUE &val)
VALUE(const double aVal)
void SetDeferredEval(std::function< double()> aLambda)
std::function< wxString()> m_lambdaStr
VALUE(const wxString &aStr, bool aIsWildcard=false)
virtual VALUE * GetValue(CONTEXT *aCtx)=0
virtual VAR_TYPE_T GetType() const =0
virtual ~VAR_REF()=default
#define _(s)
EDA_UNITS
Definition: eda_units.h:48
#define KICOMMON_API
Definition: kicommon.h:28
TREE_NODE * newNode(LIBEVAL::COMPILER *compiler, int op, const T_TOKEN_VALUE &value)
constexpr T_TOKEN defaultToken
constexpr T_TOKEN_VALUE defaultTokenValue
std::function< void(CONTEXT *, void *)> FUNC_CALL_REF
STL namespace.
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:198
COMPILATION_STAGE stage
T_TOKEN_VALUE value
@ VALUE
Field Value of part, i.e. "3.3K".