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.

1221 lines
41KB

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