You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

568 lines
12 KiB

  1. /*
  2. This file is part of libeval, a simple math expression evaluator
  3. Copyright (C) 2007 Michael Geselbracht, mgeselbracht3@gmail.com
  4. Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. */
  16. #ifndef __LIBEVAL_COMPILER_H
  17. #define __LIBEVAL_COMPILER_H
  18. #include <cstddef>
  19. #include <functional>
  20. #include <map>
  21. #include <string>
  22. #include <stack>
  23. #include <base_units.h>
  24. #include <wx/intl.h>
  25. #if defined(WIN32)
  26. // This gets leaked by python headers on MSVC only and will cause chaos
  27. #undef COMPILER
  28. #endif
  29. #define TR_OP_BINARY_MASK 0x200
  30. #define TR_OP_UNARY_MASK 0x100
  31. #define TR_OP_MUL 0x201
  32. #define TR_OP_DIV 0x202
  33. #define TR_OP_ADD 0x203
  34. #define TR_OP_SUB 0x204
  35. #define TR_OP_LESS 0x205
  36. #define TR_OP_GREATER 0x206
  37. #define TR_OP_LESS_EQUAL 0x207
  38. #define TR_OP_GREATER_EQUAL 0x208
  39. #define TR_OP_EQUAL 0x209
  40. #define TR_OP_NOT_EQUAL 0x20a
  41. #define TR_OP_BOOL_AND 0x20b
  42. #define TR_OP_BOOL_OR 0x20c
  43. #define TR_OP_BOOL_NOT 0x100
  44. #define TR_OP_FUNC_CALL 24
  45. #define TR_OP_METHOD_CALL 25
  46. #define TR_UOP_PUSH_VAR 1
  47. #define TR_UOP_PUSH_VALUE 2
  48. // This namespace is used for the lemon parser
  49. namespace LIBEVAL
  50. {
  51. class COMPILER;
  52. enum COMPILATION_STAGE
  53. {
  54. CST_PARSE = 0,
  55. CST_CODEGEN,
  56. CST_RUNTIME
  57. };
  58. struct ERROR_STATUS
  59. {
  60. bool pendingError = false;
  61. COMPILATION_STAGE stage;
  62. wxString message;
  63. int srcPos;
  64. };
  65. enum VAR_TYPE_T
  66. {
  67. VT_STRING = 1,
  68. VT_NUMERIC,
  69. VT_UNDEFINED,
  70. VT_PARSE_ERROR
  71. };
  72. enum TOKEN_TYPE_T
  73. {
  74. TR_UNDEFINED = 0,
  75. TR_NUMBER = 1,
  76. TR_IDENTIFIER = 2,
  77. TR_ASSIGN = 3,
  78. TR_STRUCT_REF = 4,
  79. TR_STRING = 5,
  80. TR_UNIT = 6,
  81. TR_ARG_LIST = 7,
  82. TR_NULL = 8
  83. };
  84. class UOP;
  85. class UCODE;
  86. class CONTEXT;
  87. class VAR_REF;
  88. typedef std::function<void( CONTEXT*, void* )> FUNC_CALL_REF;
  89. struct T_TOKEN_VALUE
  90. {
  91. wxString* str;
  92. double num;
  93. int idx;
  94. };
  95. // Lemon can't handle c'tors and d'tors, so we provide a poor-man's version.
  96. constexpr T_TOKEN_VALUE defaultTokenValue = { nullptr, 0.0, 0 };
  97. struct T_TOKEN
  98. {
  99. int token;
  100. T_TOKEN_VALUE value;
  101. };
  102. // Lemon can't handle c'tors and d'tors, so we provide a poor-man's version.
  103. constexpr T_TOKEN defaultToken = { TR_UNDEFINED, defaultTokenValue };
  104. class TREE_NODE
  105. {
  106. public:
  107. T_TOKEN_VALUE value;
  108. int op;
  109. TREE_NODE* leaf[2];
  110. UOP* uop;
  111. bool valid;
  112. bool isTerminal;
  113. bool isVisited;
  114. int srcPos;
  115. void SetUop( int aOp, double aValue );
  116. void SetUop( int aOp, const wxString& aValue, bool aStringIsWildcard );
  117. void SetUop( int aOp, std::unique_ptr<VAR_REF> aRef = nullptr );
  118. void SetUop( int aOp, FUNC_CALL_REF aFunc, std::unique_ptr<VAR_REF> aRef = nullptr );
  119. };
  120. TREE_NODE* newNode( LIBEVAL::COMPILER* compiler, int op,
  121. const T_TOKEN_VALUE& value = defaultTokenValue );
  122. class UNIT_RESOLVER
  123. {
  124. public:
  125. UNIT_RESOLVER()
  126. {
  127. }
  128. virtual ~UNIT_RESOLVER()
  129. {
  130. }
  131. virtual const std::vector<wxString>& GetSupportedUnits() const
  132. {
  133. static const std::vector<wxString> nullUnits;
  134. return nullUnits;
  135. }
  136. virtual wxString GetSupportedUnitsMessage() const
  137. {
  138. return wxEmptyString;
  139. }
  140. virtual double Convert( const wxString& aString, int unitType ) const
  141. {
  142. return 0.0;
  143. };
  144. };
  145. class VALUE
  146. {
  147. public:
  148. VALUE() :
  149. m_type( VT_UNDEFINED ),
  150. m_valueDbl( 0 ),
  151. m_stringIsWildcard( false ),
  152. m_isDeferredDbl( false ),
  153. m_isDeferredStr( false )
  154. {};
  155. VALUE( const wxString& aStr, bool aIsWildcard = false ) :
  156. m_type( VT_STRING ),
  157. m_valueDbl( 0 ),
  158. m_valueStr( aStr ),
  159. m_stringIsWildcard( aIsWildcard ),
  160. m_isDeferredDbl( false ),
  161. m_isDeferredStr( false )
  162. {};
  163. VALUE( const double aVal ) :
  164. m_type( VT_NUMERIC ),
  165. m_valueDbl( aVal ),
  166. m_stringIsWildcard( false ),
  167. m_isDeferredDbl( false ),
  168. m_isDeferredStr( false )
  169. {};
  170. virtual ~VALUE()
  171. {};
  172. virtual double AsDouble() const
  173. {
  174. if( m_isDeferredDbl )
  175. {
  176. m_valueDbl = m_lambdaDbl();
  177. m_isDeferredDbl = false;
  178. }
  179. return m_valueDbl;
  180. }
  181. virtual const wxString& AsString() const
  182. {
  183. if( m_isDeferredStr )
  184. {
  185. m_valueStr = m_lambdaStr();
  186. m_isDeferredStr = false;
  187. }
  188. return m_valueStr;
  189. }
  190. virtual bool EqualTo( CONTEXT* aCtx, const VALUE* b ) const;
  191. // NB: this is not an inverse of EqualTo as they both return false for undefined values.
  192. virtual bool NotEqualTo( CONTEXT* aCtx, const VALUE* b ) const;
  193. VAR_TYPE_T GetType() const { return m_type; };
  194. void Set( double aValue )
  195. {
  196. m_type = VT_NUMERIC;
  197. m_valueDbl = aValue;
  198. }
  199. void SetDeferredEval( std::function<double()> aLambda )
  200. {
  201. m_type = VT_NUMERIC;
  202. m_lambdaDbl = aLambda;
  203. m_isDeferredDbl = true;
  204. }
  205. void SetDeferredEval( std::function<wxString()> aLambda )
  206. {
  207. m_type = VT_STRING;
  208. m_lambdaStr = aLambda;
  209. m_isDeferredStr = true;
  210. }
  211. void Set( const wxString& aValue )
  212. {
  213. m_type = VT_STRING;
  214. m_valueStr = aValue;
  215. }
  216. void Set( const VALUE &val )
  217. {
  218. m_type = val.m_type;
  219. m_valueDbl = val.m_valueDbl;
  220. if( m_type == VT_STRING )
  221. m_valueStr = val.m_valueStr;
  222. }
  223. private:
  224. VAR_TYPE_T m_type;
  225. mutable double m_valueDbl; // mutable to support deferred evaluation
  226. mutable wxString m_valueStr; // mutable to support deferred evaluation
  227. bool m_stringIsWildcard;
  228. mutable bool m_isDeferredDbl;
  229. std::function<double()> m_lambdaDbl;
  230. mutable bool m_isDeferredStr;
  231. std::function<wxString()> m_lambdaStr;
  232. };
  233. class VAR_REF
  234. {
  235. public:
  236. VAR_REF() {};
  237. virtual ~VAR_REF() {};
  238. virtual VAR_TYPE_T GetType() const = 0;
  239. virtual VALUE* GetValue( CONTEXT* aCtx ) = 0;
  240. };
  241. class CONTEXT
  242. {
  243. public:
  244. CONTEXT() :
  245. m_stack(),
  246. m_stackPtr( 0 )
  247. {
  248. m_ownedValues.reserve( 20 );
  249. }
  250. virtual ~CONTEXT()
  251. {
  252. for( VALUE* v : m_ownedValues )
  253. {
  254. delete v;
  255. }
  256. }
  257. VALUE* AllocValue()
  258. {
  259. m_ownedValues.emplace_back( new VALUE );
  260. return m_ownedValues.back();
  261. }
  262. VALUE* StoreValue( VALUE* aValue )
  263. {
  264. m_ownedValues.emplace_back( aValue );
  265. return m_ownedValues.back();
  266. }
  267. void Push( VALUE* v )
  268. {
  269. m_stack[ m_stackPtr++ ] = v;
  270. }
  271. VALUE* Pop()
  272. {
  273. if( m_stackPtr == 0 )
  274. {
  275. ReportError( _( "Malformed expression" ) );
  276. return AllocValue();
  277. }
  278. return m_stack[ --m_stackPtr ];
  279. }
  280. int SP() const
  281. {
  282. return m_stackPtr;
  283. };
  284. void SetErrorCallback( std::function<void( const wxString& aMessage, int aOffset )> aCallback )
  285. {
  286. m_errorCallback = std::move( aCallback );
  287. }
  288. bool HasErrorCallback() { return m_errorCallback != nullptr; }
  289. void ReportError( const wxString& aErrorMsg );
  290. private:
  291. std::vector<VALUE*> m_ownedValues;
  292. VALUE* m_stack[100]; // std::stack not performant enough
  293. int m_stackPtr;
  294. std::function<void( const wxString& aMessage, int aOffset )> m_errorCallback;
  295. };
  296. class UCODE
  297. {
  298. public:
  299. virtual ~UCODE();
  300. void AddOp( UOP* uop )
  301. {
  302. m_ucode.push_back(uop);
  303. }
  304. VALUE* Run( CONTEXT* ctx );
  305. wxString Dump() const;
  306. virtual std::unique_ptr<VAR_REF> CreateVarRef( const wxString& var, const wxString& field )
  307. {
  308. return nullptr;
  309. };
  310. virtual FUNC_CALL_REF CreateFuncCall( const wxString& name )
  311. {
  312. return nullptr;
  313. };
  314. protected:
  315. std::vector<UOP*> m_ucode;
  316. };
  317. class UOP
  318. {
  319. public:
  320. UOP( int op, std::unique_ptr<VALUE> value ) :
  321. m_op( op ),
  322. m_ref(nullptr),
  323. m_value( std::move( value ) )
  324. {};
  325. UOP( int op, std::unique_ptr<VAR_REF> vref ) :
  326. m_op( op ),
  327. m_ref( std::move( vref ) ),
  328. m_value(nullptr)
  329. {};
  330. UOP( int op, FUNC_CALL_REF func, std::unique_ptr<VAR_REF> vref = nullptr ) :
  331. m_op( op ),
  332. m_func( std::move( func ) ),
  333. m_ref( std::move( vref ) ),
  334. m_value(nullptr)
  335. {};
  336. ~UOP()
  337. {
  338. }
  339. void Exec( CONTEXT* ctx );
  340. wxString Format() const;
  341. private:
  342. int m_op;
  343. FUNC_CALL_REF m_func;
  344. std::unique_ptr<VAR_REF> m_ref;
  345. std::unique_ptr<VALUE> m_value;
  346. };
  347. class TOKENIZER
  348. {
  349. public:
  350. void Restart( const wxString& aStr )
  351. {
  352. m_str = aStr;
  353. m_pos = 0;
  354. }
  355. void Clear()
  356. {
  357. m_str = "";
  358. m_pos = 0;
  359. }
  360. int GetChar() const
  361. {
  362. if( m_pos >= m_str.length() )
  363. return 0;
  364. return m_str[m_pos];
  365. }
  366. bool Done() const
  367. {
  368. return m_pos >= m_str.length();
  369. }
  370. void NextChar( int aAdvance = 1 )
  371. {
  372. m_pos += aAdvance;
  373. }
  374. size_t GetPos() const
  375. {
  376. return m_pos;
  377. }
  378. wxString GetChars( const std::function<bool( wxUniChar )>& cond ) const;
  379. bool MatchAhead( const wxString& match,
  380. const std::function<bool( wxUniChar )>& stopCond ) const;
  381. private:
  382. wxString m_str;
  383. size_t m_pos = 0;
  384. };
  385. class COMPILER
  386. {
  387. public:
  388. COMPILER();
  389. virtual ~COMPILER();
  390. /*
  391. * clear() should be invoked by the client if a new input string is to be processed. It
  392. * will reset the parser. User defined variables are retained.
  393. */
  394. void Clear();
  395. /* Used by the lemon parser */
  396. void parseError( const char* s );
  397. void parseOk();
  398. int GetSourcePos() const { return m_sourcePos; }
  399. void setRoot( LIBEVAL::TREE_NODE *root );
  400. void freeTree( LIBEVAL::TREE_NODE *tree );
  401. bool Compile( const wxString& aString, UCODE* aCode, CONTEXT* aPreflightContext );
  402. void SetErrorCallback( std::function<void( const wxString& aMessage, int aOffset )> aCallback )
  403. {
  404. m_errorCallback = std::move( aCallback );
  405. }
  406. bool IsErrorPending() const { return m_errorStatus.pendingError; }
  407. const ERROR_STATUS& GetError() const { return m_errorStatus; }
  408. void GcItem( TREE_NODE* aItem ) { m_gcItems.push_back( aItem ); }
  409. void GcItem( wxString* aItem ) { m_gcStrings.push_back( aItem ); }
  410. protected:
  411. enum LEXER_STATE
  412. {
  413. LS_DEFAULT = 0,
  414. LS_STRING = 1,
  415. };
  416. LEXER_STATE m_lexerState;
  417. bool generateUCode( UCODE* aCode, CONTEXT* aPreflightContext );
  418. void reportError( COMPILATION_STAGE stage, const wxString& aErrorMsg, int aPos = -1 );
  419. /* Begin processing of a new input string */
  420. void newString( const wxString& aString );
  421. /* Tokenizer: Next token/value taken from input string. */
  422. T_TOKEN getToken();
  423. bool lexDefault( T_TOKEN& aToken );
  424. bool lexString( T_TOKEN& aToken );
  425. int resolveUnits();
  426. protected:
  427. /* Token state for input string. */
  428. void* m_parser; // the current lemon parser state machine
  429. TOKENIZER m_tokenizer;
  430. char m_localeDecimalSeparator;
  431. std::unique_ptr<UNIT_RESOLVER> m_unitResolver;
  432. int m_sourcePos;
  433. bool m_parseFinished;
  434. ERROR_STATUS m_errorStatus;
  435. std::function<void( const wxString& aMessage, int aOffset )> m_errorCallback;
  436. TREE_NODE* m_tree;
  437. std::vector<TREE_NODE*> m_gcItems;
  438. std::vector<wxString*> m_gcStrings;
  439. };
  440. } // namespace LIBEVAL
  441. #endif /* LIBEVAL_COMPILER_H_ */