The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

1174 lines
40KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. class Expression::Term : public SingleThreadedReferenceCountedObject
  19. {
  20. public:
  21. Term() {}
  22. virtual ~Term() {}
  23. virtual Type getType() const noexcept = 0;
  24. virtual Term* clone() const = 0;
  25. virtual ReferenceCountedObjectPtr<Term> resolve (const Scope&, int recursionDepth) = 0;
  26. virtual String toString() const = 0;
  27. virtual double toDouble() const { return 0; }
  28. virtual int getInputIndexFor (const Term*) const { return -1; }
  29. virtual int getOperatorPrecedence() const { return 0; }
  30. virtual int getNumInputs() const { return 0; }
  31. virtual Term* getInput (int) const { return nullptr; }
  32. virtual ReferenceCountedObjectPtr<Term> negated();
  33. virtual ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const Scope&, const Term* /*inputTerm*/,
  34. double /*overallTarget*/, Term* /*topLevelTerm*/) const
  35. {
  36. jassertfalse;
  37. return nullptr;
  38. }
  39. virtual String getName() const
  40. {
  41. jassertfalse; // You shouldn't call this for an expression that's not actually a function!
  42. return String::empty;
  43. }
  44. virtual void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
  45. {
  46. for (int i = getNumInputs(); --i >= 0;)
  47. getInput (i)->renameSymbol (oldSymbol, newName, scope, recursionDepth);
  48. }
  49. class SymbolVisitor
  50. {
  51. public:
  52. virtual ~SymbolVisitor() {}
  53. virtual void useSymbol (const Symbol&) = 0;
  54. };
  55. virtual void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
  56. {
  57. for (int i = getNumInputs(); --i >= 0;)
  58. getInput(i)->visitAllSymbols (visitor, scope, recursionDepth);
  59. }
  60. private:
  61. JUCE_DECLARE_NON_COPYABLE (Term);
  62. };
  63. //==============================================================================
  64. struct Expression::Helpers
  65. {
  66. typedef ReferenceCountedObjectPtr<Term> TermPtr;
  67. // This helper function is needed to work around VC6 scoping bugs
  68. static inline const TermPtr& getTermFor (const Expression& exp) noexcept { return exp.term; }
  69. static void checkRecursionDepth (const int depth)
  70. {
  71. if (depth > 256)
  72. throw EvaluationError ("Recursive symbol references");
  73. }
  74. friend class Expression::Term; // (also only needed as a VC6 workaround)
  75. //==============================================================================
  76. /** An exception that can be thrown by Expression::evaluate(). */
  77. class EvaluationError : public std::exception
  78. {
  79. public:
  80. EvaluationError (const String& description_)
  81. : description (description_)
  82. {
  83. DBG ("Expression::EvaluationError: " + description);
  84. }
  85. String description;
  86. };
  87. //==============================================================================
  88. class Constant : public Term
  89. {
  90. public:
  91. Constant (const double value_, const bool isResolutionTarget_)
  92. : value (value_), isResolutionTarget (isResolutionTarget_) {}
  93. Type getType() const noexcept { return constantType; }
  94. Term* clone() const { return new Constant (value, isResolutionTarget); }
  95. TermPtr resolve (const Scope&, int) { return this; }
  96. double toDouble() const { return value; }
  97. TermPtr negated() { return new Constant (-value, isResolutionTarget); }
  98. String toString() const
  99. {
  100. String s (value);
  101. if (isResolutionTarget)
  102. s = "@" + s;
  103. return s;
  104. }
  105. double value;
  106. bool isResolutionTarget;
  107. };
  108. //==============================================================================
  109. class BinaryTerm : public Term
  110. {
  111. public:
  112. BinaryTerm (Term* const l, Term* const r) : left (l), right (r)
  113. {
  114. jassert (l != nullptr && r != nullptr);
  115. }
  116. int getInputIndexFor (const Term* possibleInput) const
  117. {
  118. return possibleInput == left ? 0 : (possibleInput == right ? 1 : -1);
  119. }
  120. Type getType() const noexcept { return operatorType; }
  121. int getNumInputs() const { return 2; }
  122. Term* getInput (int index) const { return index == 0 ? left.getObject() : (index == 1 ? right.getObject() : 0); }
  123. virtual double performFunction (double left, double right) const = 0;
  124. virtual void writeOperator (String& dest) const = 0;
  125. TermPtr resolve (const Scope& scope, int recursionDepth)
  126. {
  127. return new Constant (performFunction (left ->resolve (scope, recursionDepth)->toDouble(),
  128. right->resolve (scope, recursionDepth)->toDouble()), false);
  129. }
  130. String toString() const
  131. {
  132. String s;
  133. const int ourPrecendence = getOperatorPrecedence();
  134. if (left->getOperatorPrecedence() > ourPrecendence)
  135. s << '(' << left->toString() << ')';
  136. else
  137. s = left->toString();
  138. writeOperator (s);
  139. if (right->getOperatorPrecedence() >= ourPrecendence)
  140. s << '(' << right->toString() << ')';
  141. else
  142. s << right->toString();
  143. return s;
  144. }
  145. protected:
  146. const TermPtr left, right;
  147. TermPtr createDestinationTerm (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  148. {
  149. jassert (input == left || input == right);
  150. if (input != left && input != right)
  151. return nullptr;
  152. const Term* const dest = findDestinationFor (topLevelTerm, this);
  153. if (dest == nullptr)
  154. return new Constant (overallTarget, false);
  155. return dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm);
  156. }
  157. };
  158. //==============================================================================
  159. class SymbolTerm : public Term
  160. {
  161. public:
  162. explicit SymbolTerm (const String& symbol_) : symbol (symbol_) {}
  163. TermPtr resolve (const Scope& scope, int recursionDepth)
  164. {
  165. checkRecursionDepth (recursionDepth);
  166. return getTermFor (scope.getSymbolValue (symbol))->resolve (scope, recursionDepth + 1);
  167. }
  168. Type getType() const noexcept { return symbolType; }
  169. Term* clone() const { return new SymbolTerm (symbol); }
  170. String toString() const { return symbol; }
  171. String getName() const { return symbol; }
  172. void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
  173. {
  174. checkRecursionDepth (recursionDepth);
  175. visitor.useSymbol (Symbol (scope.getScopeUID(), symbol));
  176. getTermFor (scope.getSymbolValue (symbol))->visitAllSymbols (visitor, scope, recursionDepth + 1);
  177. }
  178. void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int /*recursionDepth*/)
  179. {
  180. if (oldSymbol.symbolName == symbol && scope.getScopeUID() == oldSymbol.scopeUID)
  181. symbol = newName;
  182. }
  183. String symbol;
  184. };
  185. //==============================================================================
  186. class Function : public Term
  187. {
  188. public:
  189. explicit Function (const String& functionName_) : functionName (functionName_) {}
  190. Function (const String& functionName_, const Array<Expression>& parameters_)
  191. : functionName (functionName_), parameters (parameters_)
  192. {}
  193. Type getType() const noexcept { return functionType; }
  194. Term* clone() const { return new Function (functionName, parameters); }
  195. int getNumInputs() const { return parameters.size(); }
  196. Term* getInput (int i) const { return getTermFor (parameters [i]); }
  197. String getName() const { return functionName; }
  198. TermPtr resolve (const Scope& scope, int recursionDepth)
  199. {
  200. checkRecursionDepth (recursionDepth);
  201. double result = 0;
  202. const int numParams = parameters.size();
  203. if (numParams > 0)
  204. {
  205. HeapBlock<double> params ((size_t) numParams);
  206. for (int i = 0; i < numParams; ++i)
  207. params[i] = getTermFor (parameters.getReference(i))->resolve (scope, recursionDepth + 1)->toDouble();
  208. result = scope.evaluateFunction (functionName, params, numParams);
  209. }
  210. else
  211. {
  212. result = scope.evaluateFunction (functionName, nullptr, 0);
  213. }
  214. return new Constant (result, false);
  215. }
  216. int getInputIndexFor (const Term* possibleInput) const
  217. {
  218. for (int i = 0; i < parameters.size(); ++i)
  219. if (getTermFor (parameters.getReference(i)) == possibleInput)
  220. return i;
  221. return -1;
  222. }
  223. String toString() const
  224. {
  225. if (parameters.size() == 0)
  226. return functionName + "()";
  227. String s (functionName + " (");
  228. for (int i = 0; i < parameters.size(); ++i)
  229. {
  230. s << getTermFor (parameters.getReference(i))->toString();
  231. if (i < parameters.size() - 1)
  232. s << ", ";
  233. }
  234. s << ')';
  235. return s;
  236. }
  237. const String functionName;
  238. Array<Expression> parameters;
  239. };
  240. //==============================================================================
  241. class DotOperator : public BinaryTerm
  242. {
  243. public:
  244. DotOperator (SymbolTerm* const l, Term* const r) : BinaryTerm (l, r) {}
  245. TermPtr resolve (const Scope& scope, int recursionDepth)
  246. {
  247. checkRecursionDepth (recursionDepth);
  248. EvaluationVisitor visitor (right, recursionDepth + 1);
  249. scope.visitRelativeScope (getSymbol()->symbol, visitor);
  250. return visitor.output;
  251. }
  252. Term* clone() const { return new DotOperator (getSymbol(), right); }
  253. String getName() const { return "."; }
  254. int getOperatorPrecedence() const { return 1; }
  255. void writeOperator (String& dest) const { dest << '.'; }
  256. double performFunction (double, double) const { return 0.0; }
  257. void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
  258. {
  259. checkRecursionDepth (recursionDepth);
  260. visitor.useSymbol (Symbol (scope.getScopeUID(), getSymbol()->symbol));
  261. SymbolVisitingVisitor v (right, visitor, recursionDepth + 1);
  262. try
  263. {
  264. scope.visitRelativeScope (getSymbol()->symbol, v);
  265. }
  266. catch (...) {}
  267. }
  268. void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
  269. {
  270. checkRecursionDepth (recursionDepth);
  271. getSymbol()->renameSymbol (oldSymbol, newName, scope, recursionDepth);
  272. SymbolRenamingVisitor visitor (right, oldSymbol, newName, recursionDepth + 1);
  273. try
  274. {
  275. scope.visitRelativeScope (getSymbol()->symbol, visitor);
  276. }
  277. catch (...) {}
  278. }
  279. private:
  280. //==============================================================================
  281. class EvaluationVisitor : public Scope::Visitor
  282. {
  283. public:
  284. EvaluationVisitor (const TermPtr& input_, const int recursionCount_)
  285. : input (input_), output (input_), recursionCount (recursionCount_) {}
  286. void visit (const Scope& scope) { output = input->resolve (scope, recursionCount); }
  287. const TermPtr input;
  288. TermPtr output;
  289. const int recursionCount;
  290. private:
  291. JUCE_DECLARE_NON_COPYABLE (EvaluationVisitor);
  292. };
  293. class SymbolVisitingVisitor : public Scope::Visitor
  294. {
  295. public:
  296. SymbolVisitingVisitor (const TermPtr& input_, SymbolVisitor& visitor_, const int recursionCount_)
  297. : input (input_), visitor (visitor_), recursionCount (recursionCount_) {}
  298. void visit (const Scope& scope) { input->visitAllSymbols (visitor, scope, recursionCount); }
  299. private:
  300. const TermPtr input;
  301. SymbolVisitor& visitor;
  302. const int recursionCount;
  303. JUCE_DECLARE_NON_COPYABLE (SymbolVisitingVisitor);
  304. };
  305. class SymbolRenamingVisitor : public Scope::Visitor
  306. {
  307. public:
  308. SymbolRenamingVisitor (const TermPtr& input_, const Expression::Symbol& symbol_, const String& newName_, const int recursionCount_)
  309. : input (input_), symbol (symbol_), newName (newName_), recursionCount (recursionCount_) {}
  310. void visit (const Scope& scope) { input->renameSymbol (symbol, newName, scope, recursionCount); }
  311. private:
  312. const TermPtr input;
  313. const Symbol& symbol;
  314. const String newName;
  315. const int recursionCount;
  316. JUCE_DECLARE_NON_COPYABLE (SymbolRenamingVisitor);
  317. };
  318. SymbolTerm* getSymbol() const { return static_cast <SymbolTerm*> (left.getObject()); }
  319. JUCE_DECLARE_NON_COPYABLE (DotOperator);
  320. };
  321. //==============================================================================
  322. class Negate : public Term
  323. {
  324. public:
  325. explicit Negate (const TermPtr& input_) : input (input_)
  326. {
  327. jassert (input_ != nullptr);
  328. }
  329. Type getType() const noexcept { return operatorType; }
  330. int getInputIndexFor (const Term* possibleInput) const { return possibleInput == input ? 0 : -1; }
  331. int getNumInputs() const { return 1; }
  332. Term* getInput (int index) const { return index == 0 ? input.getObject() : nullptr; }
  333. Term* clone() const { return new Negate (input->clone()); }
  334. TermPtr resolve (const Scope& scope, int recursionDepth)
  335. {
  336. return new Constant (-input->resolve (scope, recursionDepth)->toDouble(), false);
  337. }
  338. String getName() const { return "-"; }
  339. TermPtr negated() { return input; }
  340. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input_, double overallTarget, Term* topLevelTerm) const
  341. {
  342. (void) input_;
  343. jassert (input_ == input);
  344. const Term* const dest = findDestinationFor (topLevelTerm, this);
  345. return new Negate (dest == nullptr ? new Constant (overallTarget, false)
  346. : dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm));
  347. }
  348. String toString() const
  349. {
  350. if (input->getOperatorPrecedence() > 0)
  351. return "-(" + input->toString() + ")";
  352. else
  353. return "-" + input->toString();
  354. }
  355. private:
  356. const TermPtr input;
  357. };
  358. //==============================================================================
  359. class Add : public BinaryTerm
  360. {
  361. public:
  362. Add (Term* const l, Term* const r) : BinaryTerm (l, r) {}
  363. Term* clone() const { return new Add (left->clone(), right->clone()); }
  364. double performFunction (double lhs, double rhs) const { return lhs + rhs; }
  365. int getOperatorPrecedence() const { return 3; }
  366. String getName() const { return "+"; }
  367. void writeOperator (String& dest) const { dest << " + "; }
  368. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  369. {
  370. const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
  371. if (newDest == nullptr)
  372. return nullptr;
  373. return new Subtract (newDest, (input == left ? right : left)->clone());
  374. }
  375. private:
  376. JUCE_DECLARE_NON_COPYABLE (Add);
  377. };
  378. //==============================================================================
  379. class Subtract : public BinaryTerm
  380. {
  381. public:
  382. Subtract (Term* const l, Term* const r) : BinaryTerm (l, r) {}
  383. Term* clone() const { return new Subtract (left->clone(), right->clone()); }
  384. double performFunction (double lhs, double rhs) const { return lhs - rhs; }
  385. int getOperatorPrecedence() const { return 3; }
  386. String getName() const { return "-"; }
  387. void writeOperator (String& dest) const { dest << " - "; }
  388. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  389. {
  390. const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
  391. if (newDest == nullptr)
  392. return nullptr;
  393. if (input == left)
  394. return new Add (newDest, right->clone());
  395. else
  396. return new Subtract (left->clone(), newDest);
  397. }
  398. private:
  399. JUCE_DECLARE_NON_COPYABLE (Subtract);
  400. };
  401. //==============================================================================
  402. class Multiply : public BinaryTerm
  403. {
  404. public:
  405. Multiply (Term* const l, Term* const r) : BinaryTerm (l, r) {}
  406. Term* clone() const { return new Multiply (left->clone(), right->clone()); }
  407. double performFunction (double lhs, double rhs) const { return lhs * rhs; }
  408. String getName() const { return "*"; }
  409. void writeOperator (String& dest) const { dest << " * "; }
  410. int getOperatorPrecedence() const { return 2; }
  411. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  412. {
  413. const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
  414. if (newDest == nullptr)
  415. return nullptr;
  416. return new Divide (newDest, (input == left ? right : left)->clone());
  417. }
  418. private:
  419. JUCE_DECLARE_NON_COPYABLE (Multiply);
  420. };
  421. //==============================================================================
  422. class Divide : public BinaryTerm
  423. {
  424. public:
  425. Divide (Term* const l, Term* const r) : BinaryTerm (l, r) {}
  426. Term* clone() const { return new Divide (left->clone(), right->clone()); }
  427. double performFunction (double lhs, double rhs) const { return lhs / rhs; }
  428. String getName() const { return "/"; }
  429. void writeOperator (String& dest) const { dest << " / "; }
  430. int getOperatorPrecedence() const { return 2; }
  431. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  432. {
  433. const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
  434. if (newDest == nullptr)
  435. return nullptr;
  436. if (input == left)
  437. return new Multiply (newDest, right->clone());
  438. else
  439. return new Divide (left->clone(), newDest);
  440. }
  441. private:
  442. JUCE_DECLARE_NON_COPYABLE (Divide);
  443. };
  444. //==============================================================================
  445. static Term* findDestinationFor (Term* const topLevel, const Term* const inputTerm)
  446. {
  447. const int inputIndex = topLevel->getInputIndexFor (inputTerm);
  448. if (inputIndex >= 0)
  449. return topLevel;
  450. for (int i = topLevel->getNumInputs(); --i >= 0;)
  451. {
  452. Term* const t = findDestinationFor (topLevel->getInput (i), inputTerm);
  453. if (t != nullptr)
  454. return t;
  455. }
  456. return nullptr;
  457. }
  458. static Constant* findTermToAdjust (Term* const term, const bool mustBeFlagged)
  459. {
  460. {
  461. Constant* const c = dynamic_cast<Constant*> (term);
  462. if (c != nullptr && (c->isResolutionTarget || ! mustBeFlagged))
  463. return c;
  464. }
  465. if (dynamic_cast<Function*> (term) != nullptr)
  466. return nullptr;
  467. int i;
  468. const int numIns = term->getNumInputs();
  469. for (i = 0; i < numIns; ++i)
  470. {
  471. Constant* const c = dynamic_cast<Constant*> (term->getInput (i));
  472. if (c != nullptr && (c->isResolutionTarget || ! mustBeFlagged))
  473. return c;
  474. }
  475. for (i = 0; i < numIns; ++i)
  476. {
  477. Constant* const c = findTermToAdjust (term->getInput (i), mustBeFlagged);
  478. if (c != nullptr)
  479. return c;
  480. }
  481. return nullptr;
  482. }
  483. static bool containsAnySymbols (const Term* const t)
  484. {
  485. if (t->getType() == Expression::symbolType)
  486. return true;
  487. for (int i = t->getNumInputs(); --i >= 0;)
  488. if (containsAnySymbols (t->getInput (i)))
  489. return true;
  490. return false;
  491. }
  492. //==============================================================================
  493. class SymbolCheckVisitor : public Term::SymbolVisitor
  494. {
  495. public:
  496. SymbolCheckVisitor (const Symbol& symbol_) : wasFound (false), symbol (symbol_) {}
  497. void useSymbol (const Symbol& s) { wasFound = wasFound || s == symbol; }
  498. bool wasFound;
  499. private:
  500. const Symbol& symbol;
  501. JUCE_DECLARE_NON_COPYABLE (SymbolCheckVisitor);
  502. };
  503. //==============================================================================
  504. class SymbolListVisitor : public Term::SymbolVisitor
  505. {
  506. public:
  507. SymbolListVisitor (Array<Symbol>& list_) : list (list_) {}
  508. void useSymbol (const Symbol& s) { list.addIfNotAlreadyThere (s); }
  509. private:
  510. Array<Symbol>& list;
  511. JUCE_DECLARE_NON_COPYABLE (SymbolListVisitor);
  512. };
  513. //==============================================================================
  514. class Parser
  515. {
  516. public:
  517. //==============================================================================
  518. Parser (String::CharPointerType& stringToParse)
  519. : text (stringToParse)
  520. {
  521. }
  522. TermPtr readUpToComma()
  523. {
  524. if (text.isEmpty())
  525. return new Constant (0.0, false);
  526. const TermPtr e (readExpression());
  527. if (e == nullptr || ((! readOperator (",")) && ! text.isEmpty()))
  528. throw ParseError ("Syntax error: \"" + String (text) + "\"");
  529. return e;
  530. }
  531. private:
  532. String::CharPointerType& text;
  533. //==============================================================================
  534. static inline bool isDecimalDigit (const juce_wchar c) noexcept
  535. {
  536. return c >= '0' && c <= '9';
  537. }
  538. bool readChar (const juce_wchar required) noexcept
  539. {
  540. if (*text == required)
  541. {
  542. ++text;
  543. return true;
  544. }
  545. return false;
  546. }
  547. bool readOperator (const char* ops, char* const opType = nullptr) noexcept
  548. {
  549. text = text.findEndOfWhitespace();
  550. while (*ops != 0)
  551. {
  552. if (readChar ((juce_wchar) (uint8) *ops))
  553. {
  554. if (opType != nullptr)
  555. *opType = *ops;
  556. return true;
  557. }
  558. ++ops;
  559. }
  560. return false;
  561. }
  562. bool readIdentifier (String& identifier) noexcept
  563. {
  564. text = text.findEndOfWhitespace();
  565. String::CharPointerType t (text);
  566. int numChars = 0;
  567. if (t.isLetter() || *t == '_')
  568. {
  569. ++t;
  570. ++numChars;
  571. while (t.isLetterOrDigit() || *t == '_')
  572. {
  573. ++t;
  574. ++numChars;
  575. }
  576. }
  577. if (numChars > 0)
  578. {
  579. identifier = String (text, (size_t) numChars);
  580. text = t;
  581. return true;
  582. }
  583. return false;
  584. }
  585. Term* readNumber() noexcept
  586. {
  587. text = text.findEndOfWhitespace();
  588. String::CharPointerType t (text);
  589. const bool isResolutionTarget = (*t == '@');
  590. if (isResolutionTarget)
  591. {
  592. ++t;
  593. t = t.findEndOfWhitespace();
  594. text = t;
  595. }
  596. if (*t == '-')
  597. {
  598. ++t;
  599. t = t.findEndOfWhitespace();
  600. }
  601. if (isDecimalDigit (*t) || (*t == '.' && isDecimalDigit (t[1])))
  602. return new Constant (CharacterFunctions::readDoubleValue (text), isResolutionTarget);
  603. return nullptr;
  604. }
  605. TermPtr readExpression()
  606. {
  607. TermPtr lhs (readMultiplyOrDivideExpression());
  608. char opType;
  609. while (lhs != nullptr && readOperator ("+-", &opType))
  610. {
  611. TermPtr rhs (readMultiplyOrDivideExpression());
  612. if (rhs == nullptr)
  613. throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
  614. if (opType == '+')
  615. lhs = new Add (lhs, rhs);
  616. else
  617. lhs = new Subtract (lhs, rhs);
  618. }
  619. return lhs;
  620. }
  621. TermPtr readMultiplyOrDivideExpression()
  622. {
  623. TermPtr lhs (readUnaryExpression());
  624. char opType;
  625. while (lhs != nullptr && readOperator ("*/", &opType))
  626. {
  627. TermPtr rhs (readUnaryExpression());
  628. if (rhs == nullptr)
  629. throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
  630. if (opType == '*')
  631. lhs = new Multiply (lhs, rhs);
  632. else
  633. lhs = new Divide (lhs, rhs);
  634. }
  635. return lhs;
  636. }
  637. TermPtr readUnaryExpression()
  638. {
  639. char opType;
  640. if (readOperator ("+-", &opType))
  641. {
  642. TermPtr term (readUnaryExpression());
  643. if (term == nullptr)
  644. throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
  645. if (opType == '-')
  646. term = term->negated();
  647. return term;
  648. }
  649. return readPrimaryExpression();
  650. }
  651. TermPtr readPrimaryExpression()
  652. {
  653. TermPtr e (readParenthesisedExpression());
  654. if (e != nullptr)
  655. return e;
  656. e = readNumber();
  657. if (e != nullptr)
  658. return e;
  659. return readSymbolOrFunction();
  660. }
  661. TermPtr readSymbolOrFunction()
  662. {
  663. String identifier;
  664. if (readIdentifier (identifier))
  665. {
  666. if (readOperator ("(")) // method call...
  667. {
  668. Function* const f = new Function (identifier);
  669. ScopedPointer<Term> func (f); // (can't use ScopedPointer<Function> in MSVC)
  670. TermPtr param (readExpression());
  671. if (param == nullptr)
  672. {
  673. if (readOperator (")"))
  674. return func.release();
  675. throw ParseError ("Expected parameters after \"" + identifier + " (\"");
  676. }
  677. f->parameters.add (Expression (param));
  678. while (readOperator (","))
  679. {
  680. param = readExpression();
  681. if (param == nullptr)
  682. throw ParseError ("Expected expression after \",\"");
  683. f->parameters.add (Expression (param));
  684. }
  685. if (readOperator (")"))
  686. return func.release();
  687. throw ParseError ("Expected \")\"");
  688. }
  689. else if (readOperator ("."))
  690. {
  691. TermPtr rhs (readSymbolOrFunction());
  692. if (rhs == nullptr)
  693. throw ParseError ("Expected symbol or function after \".\"");
  694. if (identifier == "this")
  695. return rhs;
  696. return new DotOperator (new SymbolTerm (identifier), rhs);
  697. }
  698. else // just a symbol..
  699. {
  700. jassert (identifier.trim() == identifier);
  701. return new SymbolTerm (identifier);
  702. }
  703. }
  704. return nullptr;
  705. }
  706. TermPtr readParenthesisedExpression()
  707. {
  708. if (! readOperator ("("))
  709. return nullptr;
  710. const TermPtr e (readExpression());
  711. if (e == nullptr || ! readOperator (")"))
  712. return nullptr;
  713. return e;
  714. }
  715. JUCE_DECLARE_NON_COPYABLE (Parser);
  716. };
  717. };
  718. //==============================================================================
  719. Expression::Expression()
  720. : term (new Expression::Helpers::Constant (0, false))
  721. {
  722. }
  723. Expression::~Expression()
  724. {
  725. }
  726. Expression::Expression (Term* const term_)
  727. : term (term_)
  728. {
  729. jassert (term != nullptr);
  730. }
  731. Expression::Expression (const double constant)
  732. : term (new Expression::Helpers::Constant (constant, false))
  733. {
  734. }
  735. Expression::Expression (const Expression& other)
  736. : term (other.term)
  737. {
  738. }
  739. Expression& Expression::operator= (const Expression& other)
  740. {
  741. term = other.term;
  742. return *this;
  743. }
  744. #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
  745. Expression::Expression (Expression&& other) noexcept
  746. : term (static_cast <ReferenceCountedObjectPtr<Term>&&> (other.term))
  747. {
  748. }
  749. Expression& Expression::operator= (Expression&& other) noexcept
  750. {
  751. term = static_cast <ReferenceCountedObjectPtr<Term>&&> (other.term);
  752. return *this;
  753. }
  754. #endif
  755. Expression::Expression (const String& stringToParse)
  756. {
  757. String::CharPointerType text (stringToParse.getCharPointer());
  758. Helpers::Parser parser (text);
  759. term = parser.readUpToComma();
  760. }
  761. Expression Expression::parse (String::CharPointerType& stringToParse)
  762. {
  763. Helpers::Parser parser (stringToParse);
  764. return Expression (parser.readUpToComma());
  765. }
  766. double Expression::evaluate() const
  767. {
  768. return evaluate (Expression::Scope());
  769. }
  770. double Expression::evaluate (const Expression::Scope& scope) const
  771. {
  772. try
  773. {
  774. return term->resolve (scope, 0)->toDouble();
  775. }
  776. catch (Helpers::EvaluationError&)
  777. {}
  778. return 0;
  779. }
  780. double Expression::evaluate (const Scope& scope, String& evaluationError) const
  781. {
  782. try
  783. {
  784. return term->resolve (scope, 0)->toDouble();
  785. }
  786. catch (Helpers::EvaluationError& e)
  787. {
  788. evaluationError = e.description;
  789. }
  790. return 0;
  791. }
  792. Expression Expression::operator+ (const Expression& other) const { return Expression (new Helpers::Add (term, other.term)); }
  793. Expression Expression::operator- (const Expression& other) const { return Expression (new Helpers::Subtract (term, other.term)); }
  794. Expression Expression::operator* (const Expression& other) const { return Expression (new Helpers::Multiply (term, other.term)); }
  795. Expression Expression::operator/ (const Expression& other) const { return Expression (new Helpers::Divide (term, other.term)); }
  796. Expression Expression::operator-() const { return Expression (term->negated()); }
  797. Expression Expression::symbol (const String& symbol) { return Expression (new Helpers::SymbolTerm (symbol)); }
  798. Expression Expression::function (const String& functionName, const Array<Expression>& parameters)
  799. {
  800. return Expression (new Helpers::Function (functionName, parameters));
  801. }
  802. Expression Expression::adjustedToGiveNewResult (const double targetValue, const Expression::Scope& scope) const
  803. {
  804. ScopedPointer<Term> newTerm (term->clone());
  805. Helpers::Constant* termToAdjust = Helpers::findTermToAdjust (newTerm, true);
  806. if (termToAdjust == nullptr)
  807. termToAdjust = Helpers::findTermToAdjust (newTerm, false);
  808. if (termToAdjust == nullptr)
  809. {
  810. newTerm = new Helpers::Add (newTerm.release(), new Helpers::Constant (0, false));
  811. termToAdjust = Helpers::findTermToAdjust (newTerm, false);
  812. }
  813. jassert (termToAdjust != nullptr);
  814. const Term* const parent = Helpers::findDestinationFor (newTerm, termToAdjust);
  815. if (parent == nullptr)
  816. {
  817. termToAdjust->value = targetValue;
  818. }
  819. else
  820. {
  821. const Helpers::TermPtr reverseTerm (parent->createTermToEvaluateInput (scope, termToAdjust, targetValue, newTerm));
  822. if (reverseTerm == nullptr)
  823. return Expression (targetValue);
  824. termToAdjust->value = reverseTerm->resolve (scope, 0)->toDouble();
  825. }
  826. return Expression (newTerm.release());
  827. }
  828. Expression Expression::withRenamedSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Scope& scope) const
  829. {
  830. jassert (newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_"));
  831. if (oldSymbol.symbolName == newName)
  832. return *this;
  833. Expression e (term->clone());
  834. e.term->renameSymbol (oldSymbol, newName, scope, 0);
  835. return e;
  836. }
  837. bool Expression::referencesSymbol (const Expression::Symbol& symbolToCheck, const Scope& scope) const
  838. {
  839. Helpers::SymbolCheckVisitor visitor (symbolToCheck);
  840. try
  841. {
  842. term->visitAllSymbols (visitor, scope, 0);
  843. }
  844. catch (Helpers::EvaluationError&)
  845. {}
  846. return visitor.wasFound;
  847. }
  848. void Expression::findReferencedSymbols (Array<Symbol>& results, const Scope& scope) const
  849. {
  850. try
  851. {
  852. Helpers::SymbolListVisitor visitor (results);
  853. term->visitAllSymbols (visitor, scope, 0);
  854. }
  855. catch (Helpers::EvaluationError&)
  856. {}
  857. }
  858. String Expression::toString() const { return term->toString(); }
  859. bool Expression::usesAnySymbols() const { return Helpers::containsAnySymbols (term); }
  860. Expression::Type Expression::getType() const noexcept { return term->getType(); }
  861. String Expression::getSymbolOrFunction() const { return term->getName(); }
  862. int Expression::getNumInputs() const { return term->getNumInputs(); }
  863. Expression Expression::getInput (int index) const { return Expression (term->getInput (index)); }
  864. //==============================================================================
  865. ReferenceCountedObjectPtr<Expression::Term> Expression::Term::negated()
  866. {
  867. return new Helpers::Negate (this);
  868. }
  869. //==============================================================================
  870. Expression::ParseError::ParseError (const String& message)
  871. : description (message)
  872. {
  873. DBG ("Expression::ParseError: " + message);
  874. }
  875. //==============================================================================
  876. Expression::Symbol::Symbol (const String& scopeUID_, const String& symbolName_)
  877. : scopeUID (scopeUID_), symbolName (symbolName_)
  878. {
  879. }
  880. bool Expression::Symbol::operator== (const Symbol& other) const noexcept
  881. {
  882. return symbolName == other.symbolName && scopeUID == other.scopeUID;
  883. }
  884. bool Expression::Symbol::operator!= (const Symbol& other) const noexcept
  885. {
  886. return ! operator== (other);
  887. }
  888. //==============================================================================
  889. Expression::Scope::Scope() {}
  890. Expression::Scope::~Scope() {}
  891. Expression Expression::Scope::getSymbolValue (const String& symbol) const
  892. {
  893. throw Helpers::EvaluationError ("Unknown symbol: " + symbol);
  894. }
  895. double Expression::Scope::evaluateFunction (const String& functionName, const double* parameters, int numParams) const
  896. {
  897. if (numParams > 0)
  898. {
  899. if (functionName == "min")
  900. {
  901. double v = parameters[0];
  902. for (int i = 1; i < numParams; ++i)
  903. v = jmin (v, parameters[i]);
  904. return v;
  905. }
  906. else if (functionName == "max")
  907. {
  908. double v = parameters[0];
  909. for (int i = 1; i < numParams; ++i)
  910. v = jmax (v, parameters[i]);
  911. return v;
  912. }
  913. else if (numParams == 1)
  914. {
  915. if (functionName == "sin") return sin (parameters[0]);
  916. else if (functionName == "cos") return cos (parameters[0]);
  917. else if (functionName == "tan") return tan (parameters[0]);
  918. else if (functionName == "abs") return std::abs (parameters[0]);
  919. }
  920. }
  921. throw Helpers::EvaluationError ("Unknown function: \"" + functionName + "\"");
  922. }
  923. void Expression::Scope::visitRelativeScope (const String& scopeName, Visitor&) const
  924. {
  925. throw Helpers::EvaluationError ("Unknown symbol: " + scopeName);
  926. }
  927. String Expression::Scope::getScopeUID() const
  928. {
  929. return String::empty;
  930. }