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.

1180 lines
40KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. BEGIN_JUCE_NAMESPACE
  19. //==============================================================================
  20. class Expression::Term : public SingleThreadedReferenceCountedObject
  21. {
  22. public:
  23. Term() {}
  24. virtual ~Term() {}
  25. virtual Type getType() const noexcept = 0;
  26. virtual Term* clone() const = 0;
  27. virtual ReferenceCountedObjectPtr<Term> resolve (const Scope&, int recursionDepth) = 0;
  28. virtual String toString() const = 0;
  29. virtual double toDouble() const { return 0; }
  30. virtual int getInputIndexFor (const Term*) const { return -1; }
  31. virtual int getOperatorPrecedence() const { return 0; }
  32. virtual int getNumInputs() const { return 0; }
  33. virtual Term* getInput (int) const { return nullptr; }
  34. virtual ReferenceCountedObjectPtr<Term> negated();
  35. virtual ReferenceCountedObjectPtr<Term> createTermToEvaluateInput (const Scope&, const Term* /*inputTerm*/,
  36. double /*overallTarget*/, Term* /*topLevelTerm*/) const
  37. {
  38. jassertfalse;
  39. return nullptr;
  40. }
  41. virtual String getName() const
  42. {
  43. jassertfalse; // You shouldn't call this for an expression that's not actually a function!
  44. return String::empty;
  45. }
  46. virtual void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
  47. {
  48. for (int i = getNumInputs(); --i >= 0;)
  49. getInput (i)->renameSymbol (oldSymbol, newName, scope, recursionDepth);
  50. }
  51. class SymbolVisitor
  52. {
  53. public:
  54. virtual ~SymbolVisitor() {}
  55. virtual void useSymbol (const Symbol&) = 0;
  56. };
  57. virtual void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
  58. {
  59. for (int i = getNumInputs(); --i >= 0;)
  60. getInput(i)->visitAllSymbols (visitor, scope, recursionDepth);
  61. }
  62. private:
  63. JUCE_DECLARE_NON_COPYABLE (Term);
  64. };
  65. //==============================================================================
  66. class Expression::Helpers
  67. {
  68. public:
  69. typedef ReferenceCountedObjectPtr<Term> TermPtr;
  70. // This helper function is needed to work around VC6 scoping bugs
  71. static inline const TermPtr& getTermFor (const Expression& exp) noexcept { return exp.term; }
  72. static void checkRecursionDepth (const int depth)
  73. {
  74. if (depth > 256)
  75. throw EvaluationError ("Recursive symbol references");
  76. }
  77. friend class Expression::Term; // (also only needed as a VC6 workaround)
  78. //==============================================================================
  79. /** An exception that can be thrown by Expression::evaluate(). */
  80. class EvaluationError : public std::exception
  81. {
  82. public:
  83. EvaluationError (const String& description_)
  84. : description (description_)
  85. {
  86. DBG ("Expression::EvaluationError: " + description);
  87. }
  88. String description;
  89. };
  90. //==============================================================================
  91. class Constant : public Term
  92. {
  93. public:
  94. Constant (const double value_, const bool isResolutionTarget_)
  95. : value (value_), isResolutionTarget (isResolutionTarget_) {}
  96. Type getType() const noexcept { return constantType; }
  97. Term* clone() const { return new Constant (value, isResolutionTarget); }
  98. TermPtr resolve (const Scope&, int) { return this; }
  99. double toDouble() const { return value; }
  100. TermPtr negated() { return new Constant (-value, isResolutionTarget); }
  101. String toString() const
  102. {
  103. String s (value);
  104. if (isResolutionTarget)
  105. s = "@" + s;
  106. return s;
  107. }
  108. double value;
  109. bool isResolutionTarget;
  110. };
  111. //==============================================================================
  112. class BinaryTerm : public Term
  113. {
  114. public:
  115. BinaryTerm (Term* const left_, Term* const right_) : left (left_), right (right_)
  116. {
  117. jassert (left_ != nullptr && right_ != nullptr);
  118. }
  119. int getInputIndexFor (const Term* possibleInput) const
  120. {
  121. return possibleInput == left ? 0 : (possibleInput == right ? 1 : -1);
  122. }
  123. Type getType() const noexcept { return operatorType; }
  124. int getNumInputs() const { return 2; }
  125. Term* getInput (int index) const { return index == 0 ? left.getObject() : (index == 1 ? right.getObject() : 0); }
  126. virtual double performFunction (double left, double right) const = 0;
  127. virtual void writeOperator (String& dest) const = 0;
  128. TermPtr resolve (const Scope& scope, int recursionDepth)
  129. {
  130. return new Constant (performFunction (left->resolve (scope, recursionDepth)->toDouble(),
  131. right->resolve (scope, recursionDepth)->toDouble()), false);
  132. }
  133. String toString() const
  134. {
  135. String s;
  136. const int ourPrecendence = getOperatorPrecedence();
  137. if (left->getOperatorPrecedence() > ourPrecendence)
  138. s << '(' << left->toString() << ')';
  139. else
  140. s = left->toString();
  141. writeOperator (s);
  142. if (right->getOperatorPrecedence() >= ourPrecendence)
  143. s << '(' << right->toString() << ')';
  144. else
  145. s << right->toString();
  146. return s;
  147. }
  148. protected:
  149. const TermPtr left, right;
  150. TermPtr createDestinationTerm (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  151. {
  152. jassert (input == left || input == right);
  153. if (input != left && input != right)
  154. return nullptr;
  155. const Term* const dest = findDestinationFor (topLevelTerm, this);
  156. if (dest == nullptr)
  157. return new Constant (overallTarget, false);
  158. return dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm);
  159. }
  160. };
  161. //==============================================================================
  162. class SymbolTerm : public Term
  163. {
  164. public:
  165. explicit SymbolTerm (const String& symbol_) : symbol (symbol_) {}
  166. TermPtr resolve (const Scope& scope, int recursionDepth)
  167. {
  168. checkRecursionDepth (recursionDepth);
  169. return getTermFor (scope.getSymbolValue (symbol))->resolve (scope, recursionDepth + 1);
  170. }
  171. Type getType() const noexcept { return symbolType; }
  172. Term* clone() const { return new SymbolTerm (symbol); }
  173. String toString() const { return symbol; }
  174. String getName() const { return symbol; }
  175. void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
  176. {
  177. checkRecursionDepth (recursionDepth);
  178. visitor.useSymbol (Symbol (scope.getScopeUID(), symbol));
  179. getTermFor (scope.getSymbolValue (symbol))->visitAllSymbols (visitor, scope, recursionDepth + 1);
  180. }
  181. void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int /*recursionDepth*/)
  182. {
  183. if (oldSymbol.symbolName == symbol && scope.getScopeUID() == oldSymbol.scopeUID)
  184. symbol = newName;
  185. }
  186. String symbol;
  187. };
  188. //==============================================================================
  189. class Function : public Term
  190. {
  191. public:
  192. explicit Function (const String& functionName_) : functionName (functionName_) {}
  193. Function (const String& functionName_, const Array<Expression>& parameters_)
  194. : functionName (functionName_), parameters (parameters_)
  195. {}
  196. Type getType() const noexcept { return functionType; }
  197. Term* clone() const { return new Function (functionName, parameters); }
  198. int getNumInputs() const { return parameters.size(); }
  199. Term* getInput (int i) const { return getTermFor (parameters [i]); }
  200. String getName() const { return functionName; }
  201. TermPtr resolve (const Scope& scope, int recursionDepth)
  202. {
  203. checkRecursionDepth (recursionDepth);
  204. double result = 0;
  205. const int numParams = parameters.size();
  206. if (numParams > 0)
  207. {
  208. HeapBlock<double> params ((size_t) numParams);
  209. for (int i = 0; i < numParams; ++i)
  210. params[i] = getTermFor (parameters.getReference(i))->resolve (scope, recursionDepth + 1)->toDouble();
  211. result = scope.evaluateFunction (functionName, params, numParams);
  212. }
  213. else
  214. {
  215. result = scope.evaluateFunction (functionName, nullptr, 0);
  216. }
  217. return new Constant (result, false);
  218. }
  219. int getInputIndexFor (const Term* possibleInput) const
  220. {
  221. for (int i = 0; i < parameters.size(); ++i)
  222. if (getTermFor (parameters.getReference(i)) == possibleInput)
  223. return i;
  224. return -1;
  225. }
  226. String toString() const
  227. {
  228. if (parameters.size() == 0)
  229. return functionName + "()";
  230. String s (functionName + " (");
  231. for (int i = 0; i < parameters.size(); ++i)
  232. {
  233. s << getTermFor (parameters.getReference(i))->toString();
  234. if (i < parameters.size() - 1)
  235. s << ", ";
  236. }
  237. s << ')';
  238. return s;
  239. }
  240. const String functionName;
  241. Array<Expression> parameters;
  242. };
  243. //==============================================================================
  244. class DotOperator : public BinaryTerm
  245. {
  246. public:
  247. DotOperator (SymbolTerm* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
  248. TermPtr resolve (const Scope& scope, int recursionDepth)
  249. {
  250. checkRecursionDepth (recursionDepth);
  251. EvaluationVisitor visitor (right, recursionDepth + 1);
  252. scope.visitRelativeScope (getSymbol()->symbol, visitor);
  253. return visitor.output;
  254. }
  255. Term* clone() const { return new DotOperator (getSymbol(), right); }
  256. String getName() const { return "."; }
  257. int getOperatorPrecedence() const { return 1; }
  258. void writeOperator (String& dest) const { dest << '.'; }
  259. double performFunction (double, double) const { return 0.0; }
  260. void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
  261. {
  262. checkRecursionDepth (recursionDepth);
  263. visitor.useSymbol (Symbol (scope.getScopeUID(), getSymbol()->symbol));
  264. SymbolVisitingVisitor v (right, visitor, recursionDepth + 1);
  265. try
  266. {
  267. scope.visitRelativeScope (getSymbol()->symbol, v);
  268. }
  269. catch (...) {}
  270. }
  271. void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
  272. {
  273. checkRecursionDepth (recursionDepth);
  274. getSymbol()->renameSymbol (oldSymbol, newName, scope, recursionDepth);
  275. SymbolRenamingVisitor visitor (right, oldSymbol, newName, recursionDepth + 1);
  276. try
  277. {
  278. scope.visitRelativeScope (getSymbol()->symbol, visitor);
  279. }
  280. catch (...) {}
  281. }
  282. private:
  283. //==============================================================================
  284. class EvaluationVisitor : public Scope::Visitor
  285. {
  286. public:
  287. EvaluationVisitor (const TermPtr& input_, const int recursionCount_)
  288. : input (input_), output (input_), recursionCount (recursionCount_) {}
  289. void visit (const Scope& scope) { output = input->resolve (scope, recursionCount); }
  290. const TermPtr input;
  291. TermPtr output;
  292. const int recursionCount;
  293. private:
  294. JUCE_DECLARE_NON_COPYABLE (EvaluationVisitor);
  295. };
  296. class SymbolVisitingVisitor : public Scope::Visitor
  297. {
  298. public:
  299. SymbolVisitingVisitor (const TermPtr& input_, SymbolVisitor& visitor_, const int recursionCount_)
  300. : input (input_), visitor (visitor_), recursionCount (recursionCount_) {}
  301. void visit (const Scope& scope) { input->visitAllSymbols (visitor, scope, recursionCount); }
  302. private:
  303. const TermPtr input;
  304. SymbolVisitor& visitor;
  305. const int recursionCount;
  306. JUCE_DECLARE_NON_COPYABLE (SymbolVisitingVisitor);
  307. };
  308. class SymbolRenamingVisitor : public Scope::Visitor
  309. {
  310. public:
  311. SymbolRenamingVisitor (const TermPtr& input_, const Expression::Symbol& symbol_, const String& newName_, const int recursionCount_)
  312. : input (input_), symbol (symbol_), newName (newName_), recursionCount (recursionCount_) {}
  313. void visit (const Scope& scope) { input->renameSymbol (symbol, newName, scope, recursionCount); }
  314. private:
  315. const TermPtr input;
  316. const Symbol& symbol;
  317. const String newName;
  318. const int recursionCount;
  319. JUCE_DECLARE_NON_COPYABLE (SymbolRenamingVisitor);
  320. };
  321. SymbolTerm* getSymbol() const { return static_cast <SymbolTerm*> (left.getObject()); }
  322. JUCE_DECLARE_NON_COPYABLE (DotOperator);
  323. };
  324. //==============================================================================
  325. class Negate : public Term
  326. {
  327. public:
  328. explicit Negate (const TermPtr& input_) : input (input_)
  329. {
  330. jassert (input_ != nullptr);
  331. }
  332. Type getType() const noexcept { return operatorType; }
  333. int getInputIndexFor (const Term* possibleInput) const { return possibleInput == input ? 0 : -1; }
  334. int getNumInputs() const { return 1; }
  335. Term* getInput (int index) const { return index == 0 ? input.getObject() : nullptr; }
  336. Term* clone() const { return new Negate (input->clone()); }
  337. TermPtr resolve (const Scope& scope, int recursionDepth)
  338. {
  339. return new Constant (-input->resolve (scope, recursionDepth)->toDouble(), false);
  340. }
  341. String getName() const { return "-"; }
  342. TermPtr negated() { return input; }
  343. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input_, double overallTarget, Term* topLevelTerm) const
  344. {
  345. (void) input_;
  346. jassert (input_ == input);
  347. const Term* const dest = findDestinationFor (topLevelTerm, this);
  348. return new Negate (dest == nullptr ? new Constant (overallTarget, false)
  349. : dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm));
  350. }
  351. String toString() const
  352. {
  353. if (input->getOperatorPrecedence() > 0)
  354. return "-(" + input->toString() + ")";
  355. else
  356. return "-" + input->toString();
  357. }
  358. private:
  359. const TermPtr input;
  360. };
  361. //==============================================================================
  362. class Add : public BinaryTerm
  363. {
  364. public:
  365. Add (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
  366. Term* clone() const { return new Add (left->clone(), right->clone()); }
  367. double performFunction (double lhs, double rhs) const { return lhs + rhs; }
  368. int getOperatorPrecedence() const { return 3; }
  369. String getName() const { return "+"; }
  370. void writeOperator (String& dest) const { dest << " + "; }
  371. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  372. {
  373. const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
  374. if (newDest == nullptr)
  375. return nullptr;
  376. return new Subtract (newDest, (input == left ? right : left)->clone());
  377. }
  378. private:
  379. JUCE_DECLARE_NON_COPYABLE (Add);
  380. };
  381. //==============================================================================
  382. class Subtract : public BinaryTerm
  383. {
  384. public:
  385. Subtract (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
  386. Term* clone() const { return new Subtract (left->clone(), right->clone()); }
  387. double performFunction (double lhs, double rhs) const { return lhs - rhs; }
  388. int getOperatorPrecedence() const { return 3; }
  389. String getName() const { return "-"; }
  390. void writeOperator (String& dest) const { dest << " - "; }
  391. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  392. {
  393. const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
  394. if (newDest == nullptr)
  395. return nullptr;
  396. if (input == left)
  397. return new Add (newDest, right->clone());
  398. else
  399. return new Subtract (left->clone(), newDest);
  400. }
  401. private:
  402. JUCE_DECLARE_NON_COPYABLE (Subtract);
  403. };
  404. //==============================================================================
  405. class Multiply : public BinaryTerm
  406. {
  407. public:
  408. Multiply (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
  409. Term* clone() const { return new Multiply (left->clone(), right->clone()); }
  410. double performFunction (double lhs, double rhs) const { return lhs * rhs; }
  411. String getName() const { return "*"; }
  412. void writeOperator (String& dest) const { dest << " * "; }
  413. int getOperatorPrecedence() const { return 2; }
  414. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  415. {
  416. const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
  417. if (newDest == nullptr)
  418. return nullptr;
  419. return new Divide (newDest, (input == left ? right : left)->clone());
  420. }
  421. private:
  422. JUCE_DECLARE_NON_COPYABLE (Multiply);
  423. };
  424. //==============================================================================
  425. class Divide : public BinaryTerm
  426. {
  427. public:
  428. Divide (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {}
  429. Term* clone() const { return new Divide (left->clone(), right->clone()); }
  430. double performFunction (double lhs, double rhs) const { return lhs / rhs; }
  431. String getName() const { return "/"; }
  432. void writeOperator (String& dest) const { dest << " / "; }
  433. int getOperatorPrecedence() const { return 2; }
  434. TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
  435. {
  436. const TermPtr newDest (createDestinationTerm (scope, input, overallTarget, topLevelTerm));
  437. if (newDest == nullptr)
  438. return nullptr;
  439. if (input == left)
  440. return new Multiply (newDest, right->clone());
  441. else
  442. return new Divide (left->clone(), newDest);
  443. }
  444. private:
  445. JUCE_DECLARE_NON_COPYABLE (Divide);
  446. };
  447. //==============================================================================
  448. static Term* findDestinationFor (Term* const topLevel, const Term* const inputTerm)
  449. {
  450. const int inputIndex = topLevel->getInputIndexFor (inputTerm);
  451. if (inputIndex >= 0)
  452. return topLevel;
  453. for (int i = topLevel->getNumInputs(); --i >= 0;)
  454. {
  455. Term* const t = findDestinationFor (topLevel->getInput (i), inputTerm);
  456. if (t != nullptr)
  457. return t;
  458. }
  459. return nullptr;
  460. }
  461. static Constant* findTermToAdjust (Term* const term, const bool mustBeFlagged)
  462. {
  463. {
  464. Constant* const c = dynamic_cast<Constant*> (term);
  465. if (c != nullptr && (c->isResolutionTarget || ! mustBeFlagged))
  466. return c;
  467. }
  468. if (dynamic_cast<Function*> (term) != nullptr)
  469. return nullptr;
  470. int i;
  471. const int numIns = term->getNumInputs();
  472. for (i = 0; i < numIns; ++i)
  473. {
  474. Constant* const c = dynamic_cast<Constant*> (term->getInput (i));
  475. if (c != nullptr && (c->isResolutionTarget || ! mustBeFlagged))
  476. return c;
  477. }
  478. for (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 nullptr;
  708. }
  709. TermPtr readParenthesisedExpression()
  710. {
  711. if (! readOperator ("("))
  712. return nullptr;
  713. const TermPtr e (readExpression());
  714. if (e == nullptr || ! readOperator (")"))
  715. return nullptr;
  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. }
  934. END_JUCE_NAMESPACE