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.

1179 lines
39KB

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