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.

1171 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 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. static void checkRecursionDepth (const int depth)
  68. {
  69. if (depth > 256)
  70. throw EvaluationError ("Recursive symbol references");
  71. }
  72. friend class Expression::Term; // (also only needed as a VC6 workaround)
  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.getObject() : (index == 1 ? right.getObject() : 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 nullptr;
  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.getObject()); }
  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.getObject() : 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 nullptr;
  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 nullptr;
  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 nullptr;
  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 nullptr;
  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. {
  459. Constant* const c = dynamic_cast<Constant*> (term);
  460. if (c != nullptr && (c->isResolutionTarget || ! mustBeFlagged))
  461. return c;
  462. }
  463. if (dynamic_cast<Function*> (term) != nullptr)
  464. return nullptr;
  465. int i;
  466. const int numIns = term->getNumInputs();
  467. for (i = 0; i < numIns; ++i)
  468. {
  469. Constant* const c = dynamic_cast<Constant*> (term->getInput (i));
  470. if (c != nullptr && (c->isResolutionTarget || ! mustBeFlagged))
  471. return c;
  472. }
  473. for (i = 0; i < numIns; ++i)
  474. {
  475. Constant* const c = findTermToAdjust (term->getInput (i), mustBeFlagged);
  476. if (c != nullptr)
  477. return c;
  478. }
  479. return nullptr;
  480. }
  481. static bool containsAnySymbols (const Term* const t)
  482. {
  483. if (t->getType() == Expression::symbolType)
  484. return true;
  485. for (int i = t->getNumInputs(); --i >= 0;)
  486. if (containsAnySymbols (t->getInput (i)))
  487. return true;
  488. return false;
  489. }
  490. //==============================================================================
  491. class SymbolCheckVisitor : public Term::SymbolVisitor
  492. {
  493. public:
  494. SymbolCheckVisitor (const Symbol& symbol_) : wasFound (false), symbol (symbol_) {}
  495. void useSymbol (const Symbol& s) { wasFound = wasFound || s == symbol; }
  496. bool wasFound;
  497. private:
  498. const Symbol& symbol;
  499. JUCE_DECLARE_NON_COPYABLE (SymbolCheckVisitor);
  500. };
  501. //==============================================================================
  502. class SymbolListVisitor : public Term::SymbolVisitor
  503. {
  504. public:
  505. SymbolListVisitor (Array<Symbol>& list_) : list (list_) {}
  506. void useSymbol (const Symbol& s) { list.addIfNotAlreadyThere (s); }
  507. private:
  508. Array<Symbol>& list;
  509. JUCE_DECLARE_NON_COPYABLE (SymbolListVisitor);
  510. };
  511. //==============================================================================
  512. class Parser
  513. {
  514. public:
  515. //==============================================================================
  516. Parser (String::CharPointerType& stringToParse)
  517. : text (stringToParse)
  518. {
  519. }
  520. TermPtr readUpToComma()
  521. {
  522. if (text.isEmpty())
  523. return new Constant (0.0, false);
  524. const TermPtr e (readExpression());
  525. if (e == nullptr || ((! readOperator (",")) && ! text.isEmpty()))
  526. throw ParseError ("Syntax error: \"" + String (text) + "\"");
  527. return e;
  528. }
  529. private:
  530. String::CharPointerType& text;
  531. //==============================================================================
  532. static inline bool isDecimalDigit (const juce_wchar c) noexcept
  533. {
  534. return c >= '0' && c <= '9';
  535. }
  536. bool readChar (const juce_wchar required) noexcept
  537. {
  538. if (*text == required)
  539. {
  540. ++text;
  541. return true;
  542. }
  543. return false;
  544. }
  545. bool readOperator (const char* ops, char* const opType = nullptr) noexcept
  546. {
  547. text = text.findEndOfWhitespace();
  548. while (*ops != 0)
  549. {
  550. if (readChar ((juce_wchar) (uint8) *ops))
  551. {
  552. if (opType != nullptr)
  553. *opType = *ops;
  554. return true;
  555. }
  556. ++ops;
  557. }
  558. return false;
  559. }
  560. bool readIdentifier (String& identifier) noexcept
  561. {
  562. text = text.findEndOfWhitespace();
  563. String::CharPointerType t (text);
  564. int numChars = 0;
  565. if (t.isLetter() || *t == '_')
  566. {
  567. ++t;
  568. ++numChars;
  569. while (t.isLetterOrDigit() || *t == '_')
  570. {
  571. ++t;
  572. ++numChars;
  573. }
  574. }
  575. if (numChars > 0)
  576. {
  577. identifier = String (text, (size_t) numChars);
  578. text = t;
  579. return true;
  580. }
  581. return false;
  582. }
  583. Term* readNumber() noexcept
  584. {
  585. text = text.findEndOfWhitespace();
  586. String::CharPointerType t (text);
  587. const bool isResolutionTarget = (*t == '@');
  588. if (isResolutionTarget)
  589. {
  590. ++t;
  591. t = t.findEndOfWhitespace();
  592. text = t;
  593. }
  594. if (*t == '-')
  595. {
  596. ++t;
  597. t = t.findEndOfWhitespace();
  598. }
  599. if (isDecimalDigit (*t) || (*t == '.' && isDecimalDigit (t[1])))
  600. return new Constant (CharacterFunctions::readDoubleValue (text), isResolutionTarget);
  601. return nullptr;
  602. }
  603. TermPtr readExpression()
  604. {
  605. TermPtr lhs (readMultiplyOrDivideExpression());
  606. char opType;
  607. while (lhs != nullptr && readOperator ("+-", &opType))
  608. {
  609. TermPtr rhs (readMultiplyOrDivideExpression());
  610. if (rhs == nullptr)
  611. throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
  612. if (opType == '+')
  613. lhs = new Add (lhs, rhs);
  614. else
  615. lhs = new Subtract (lhs, rhs);
  616. }
  617. return lhs;
  618. }
  619. TermPtr readMultiplyOrDivideExpression()
  620. {
  621. TermPtr lhs (readUnaryExpression());
  622. char opType;
  623. while (lhs != nullptr && readOperator ("*/", &opType))
  624. {
  625. TermPtr rhs (readUnaryExpression());
  626. if (rhs == nullptr)
  627. throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
  628. if (opType == '*')
  629. lhs = new Multiply (lhs, rhs);
  630. else
  631. lhs = new Divide (lhs, rhs);
  632. }
  633. return lhs;
  634. }
  635. TermPtr readUnaryExpression()
  636. {
  637. char opType;
  638. if (readOperator ("+-", &opType))
  639. {
  640. TermPtr term (readUnaryExpression());
  641. if (term == nullptr)
  642. throw ParseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
  643. if (opType == '-')
  644. term = term->negated();
  645. return term;
  646. }
  647. return readPrimaryExpression();
  648. }
  649. TermPtr readPrimaryExpression()
  650. {
  651. TermPtr e (readParenthesisedExpression());
  652. if (e != nullptr)
  653. return e;
  654. e = readNumber();
  655. if (e != nullptr)
  656. return e;
  657. return readSymbolOrFunction();
  658. }
  659. TermPtr readSymbolOrFunction()
  660. {
  661. String identifier;
  662. if (readIdentifier (identifier))
  663. {
  664. if (readOperator ("(")) // method call...
  665. {
  666. Function* const f = new Function (identifier);
  667. ScopedPointer<Term> func (f); // (can't use ScopedPointer<Function> in MSVC)
  668. TermPtr param (readExpression());
  669. if (param == nullptr)
  670. {
  671. if (readOperator (")"))
  672. return func.release();
  673. throw ParseError ("Expected parameters after \"" + identifier + " (\"");
  674. }
  675. f->parameters.add (Expression (param));
  676. while (readOperator (","))
  677. {
  678. param = readExpression();
  679. if (param == nullptr)
  680. throw ParseError ("Expected expression after \",\"");
  681. f->parameters.add (Expression (param));
  682. }
  683. if (readOperator (")"))
  684. return func.release();
  685. throw ParseError ("Expected \")\"");
  686. }
  687. else if (readOperator ("."))
  688. {
  689. TermPtr rhs (readSymbolOrFunction());
  690. if (rhs == nullptr)
  691. throw ParseError ("Expected symbol or function after \".\"");
  692. if (identifier == "this")
  693. return rhs;
  694. return new DotOperator (new SymbolTerm (identifier), rhs);
  695. }
  696. else // just a symbol..
  697. {
  698. jassert (identifier.trim() == identifier);
  699. return new SymbolTerm (identifier);
  700. }
  701. }
  702. return nullptr;
  703. }
  704. TermPtr readParenthesisedExpression()
  705. {
  706. if (! readOperator ("("))
  707. return nullptr;
  708. const TermPtr e (readExpression());
  709. if (e == nullptr || ! readOperator (")"))
  710. return nullptr;
  711. return e;
  712. }
  713. JUCE_DECLARE_NON_COPYABLE (Parser);
  714. };
  715. };
  716. //==============================================================================
  717. Expression::Expression()
  718. : term (new Expression::Helpers::Constant (0, false))
  719. {
  720. }
  721. Expression::~Expression()
  722. {
  723. }
  724. Expression::Expression (Term* const term_)
  725. : term (term_)
  726. {
  727. jassert (term != nullptr);
  728. }
  729. Expression::Expression (const double constant)
  730. : term (new Expression::Helpers::Constant (constant, false))
  731. {
  732. }
  733. Expression::Expression (const Expression& other)
  734. : term (other.term)
  735. {
  736. }
  737. Expression& Expression::operator= (const Expression& other)
  738. {
  739. term = other.term;
  740. return *this;
  741. }
  742. #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
  743. Expression::Expression (Expression&& other) noexcept
  744. : term (static_cast <ReferenceCountedObjectPtr<Term>&&> (other.term))
  745. {
  746. }
  747. Expression& Expression::operator= (Expression&& other) noexcept
  748. {
  749. term = static_cast <ReferenceCountedObjectPtr<Term>&&> (other.term);
  750. return *this;
  751. }
  752. #endif
  753. Expression::Expression (const String& stringToParse)
  754. {
  755. String::CharPointerType text (stringToParse.getCharPointer());
  756. Helpers::Parser parser (text);
  757. term = parser.readUpToComma();
  758. }
  759. Expression Expression::parse (String::CharPointerType& stringToParse)
  760. {
  761. Helpers::Parser parser (stringToParse);
  762. return Expression (parser.readUpToComma());
  763. }
  764. double Expression::evaluate() const
  765. {
  766. return evaluate (Expression::Scope());
  767. }
  768. double Expression::evaluate (const Expression::Scope& scope) const
  769. {
  770. try
  771. {
  772. return term->resolve (scope, 0)->toDouble();
  773. }
  774. catch (Helpers::EvaluationError&)
  775. {}
  776. return 0;
  777. }
  778. double Expression::evaluate (const Scope& scope, String& evaluationError) const
  779. {
  780. try
  781. {
  782. return term->resolve (scope, 0)->toDouble();
  783. }
  784. catch (Helpers::EvaluationError& e)
  785. {
  786. evaluationError = e.description;
  787. }
  788. return 0;
  789. }
  790. Expression Expression::operator+ (const Expression& other) const { return Expression (new Helpers::Add (term, other.term)); }
  791. Expression Expression::operator- (const Expression& other) const { return Expression (new Helpers::Subtract (term, other.term)); }
  792. Expression Expression::operator* (const Expression& other) const { return Expression (new Helpers::Multiply (term, other.term)); }
  793. Expression Expression::operator/ (const Expression& other) const { return Expression (new Helpers::Divide (term, other.term)); }
  794. Expression Expression::operator-() const { return Expression (term->negated()); }
  795. Expression Expression::symbol (const String& symbol) { return Expression (new Helpers::SymbolTerm (symbol)); }
  796. Expression Expression::function (const String& functionName, const Array<Expression>& parameters)
  797. {
  798. return Expression (new Helpers::Function (functionName, parameters));
  799. }
  800. Expression Expression::adjustedToGiveNewResult (const double targetValue, const Expression::Scope& scope) const
  801. {
  802. ScopedPointer<Term> newTerm (term->clone());
  803. Helpers::Constant* termToAdjust = Helpers::findTermToAdjust (newTerm, true);
  804. if (termToAdjust == nullptr)
  805. termToAdjust = Helpers::findTermToAdjust (newTerm, false);
  806. if (termToAdjust == nullptr)
  807. {
  808. newTerm = new Helpers::Add (newTerm.release(), new Helpers::Constant (0, false));
  809. termToAdjust = Helpers::findTermToAdjust (newTerm, false);
  810. }
  811. jassert (termToAdjust != nullptr);
  812. const Term* const parent = Helpers::findDestinationFor (newTerm, termToAdjust);
  813. if (parent == nullptr)
  814. {
  815. termToAdjust->value = targetValue;
  816. }
  817. else
  818. {
  819. const Helpers::TermPtr reverseTerm (parent->createTermToEvaluateInput (scope, termToAdjust, targetValue, newTerm));
  820. if (reverseTerm == nullptr)
  821. return Expression (targetValue);
  822. termToAdjust->value = reverseTerm->resolve (scope, 0)->toDouble();
  823. }
  824. return Expression (newTerm.release());
  825. }
  826. Expression Expression::withRenamedSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Scope& scope) const
  827. {
  828. jassert (newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_"));
  829. if (oldSymbol.symbolName == newName)
  830. return *this;
  831. Expression e (term->clone());
  832. e.term->renameSymbol (oldSymbol, newName, scope, 0);
  833. return e;
  834. }
  835. bool Expression::referencesSymbol (const Expression::Symbol& symbolToCheck, const Scope& scope) const
  836. {
  837. Helpers::SymbolCheckVisitor visitor (symbolToCheck);
  838. try
  839. {
  840. term->visitAllSymbols (visitor, scope, 0);
  841. }
  842. catch (Helpers::EvaluationError&)
  843. {}
  844. return visitor.wasFound;
  845. }
  846. void Expression::findReferencedSymbols (Array<Symbol>& results, const Scope& scope) const
  847. {
  848. try
  849. {
  850. Helpers::SymbolListVisitor visitor (results);
  851. term->visitAllSymbols (visitor, scope, 0);
  852. }
  853. catch (Helpers::EvaluationError&)
  854. {}
  855. }
  856. String Expression::toString() const { return term->toString(); }
  857. bool Expression::usesAnySymbols() const { return Helpers::containsAnySymbols (term); }
  858. Expression::Type Expression::getType() const noexcept { return term->getType(); }
  859. String Expression::getSymbolOrFunction() const { return term->getName(); }
  860. int Expression::getNumInputs() const { return term->getNumInputs(); }
  861. Expression Expression::getInput (int index) const { return Expression (term->getInput (index)); }
  862. //==============================================================================
  863. ReferenceCountedObjectPtr<Expression::Term> Expression::Term::negated()
  864. {
  865. return new Helpers::Negate (this);
  866. }
  867. //==============================================================================
  868. Expression::ParseError::ParseError (const String& message)
  869. : description (message)
  870. {
  871. DBG ("Expression::ParseError: " + message);
  872. }
  873. //==============================================================================
  874. Expression::Symbol::Symbol (const String& scopeUID_, const String& symbolName_)
  875. : scopeUID (scopeUID_), symbolName (symbolName_)
  876. {
  877. }
  878. bool Expression::Symbol::operator== (const Symbol& other) const noexcept
  879. {
  880. return symbolName == other.symbolName && scopeUID == other.scopeUID;
  881. }
  882. bool Expression::Symbol::operator!= (const Symbol& other) const noexcept
  883. {
  884. return ! operator== (other);
  885. }
  886. //==============================================================================
  887. Expression::Scope::Scope() {}
  888. Expression::Scope::~Scope() {}
  889. Expression Expression::Scope::getSymbolValue (const String& symbol) const
  890. {
  891. throw Helpers::EvaluationError ("Unknown symbol: " + symbol);
  892. }
  893. double Expression::Scope::evaluateFunction (const String& functionName, const double* parameters, int numParams) const
  894. {
  895. if (numParams > 0)
  896. {
  897. if (functionName == "min")
  898. {
  899. double v = parameters[0];
  900. for (int i = 1; i < numParams; ++i)
  901. v = jmin (v, parameters[i]);
  902. return v;
  903. }
  904. else if (functionName == "max")
  905. {
  906. double v = parameters[0];
  907. for (int i = 1; i < numParams; ++i)
  908. v = jmax (v, parameters[i]);
  909. return v;
  910. }
  911. else if (numParams == 1)
  912. {
  913. if (functionName == "sin") return sin (parameters[0]);
  914. else if (functionName == "cos") return cos (parameters[0]);
  915. else if (functionName == "tan") return tan (parameters[0]);
  916. else if (functionName == "abs") return std::abs (parameters[0]);
  917. }
  918. }
  919. throw Helpers::EvaluationError ("Unknown function: \"" + functionName + "\"");
  920. }
  921. void Expression::Scope::visitRelativeScope (const String& scopeName, Visitor&) const
  922. {
  923. throw Helpers::EvaluationError ("Unknown symbol: " + scopeName);
  924. }
  925. String Expression::Scope::getScopeUID() const
  926. {
  927. return String::empty;
  928. }