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.

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