home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / include / k3d / k3dsdk / expression_grammar.h < prev    next >
C/C++ Source or Header  |  2008-01-23  |  7KB  |  215 lines

  1. #ifndef K3DSDK_EXPRESSION_GRAMMAR_H
  2. #define K3DSDK_EXPRESSION_GRAMMAR_H
  3.  
  4. // K-3D
  5. // Copyright (c) 1995-2004, Timothy M. Shead
  6. //
  7. // Contact: tshead@k-3d.com
  8. //
  9. // This program is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17. // General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public
  20. // License along with this program; if not, write to the Free Software
  21. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22.  
  23. #include <boost/spirit/core.hpp>
  24. #include <cmath>
  25. #include <functional>
  26. #include <iostream>
  27. #include <stack>
  28. #include <string>
  29. #include <vector>
  30.  
  31. namespace k3d
  32. {
  33.  
  34. namespace expression
  35. {
  36.  
  37. using namespace boost::spirit;
  38.  
  39. /// Defines a stack for holding intermediate values during parsing
  40. typedef std::stack<double> stack_t;
  41.  
  42. /// Inserts a parsed numeric value onto the stack
  43. class push_number
  44. {
  45. public:
  46.     push_number(stack_t& Stack) :
  47.         m_stack(Stack)
  48.     {
  49.     }
  50.  
  51.     void operator()(const double Constant) const
  52.     {
  53.         m_stack.push(Constant);
  54.     }
  55.  
  56. private:
  57.     stack_t& m_stack;
  58. };
  59.  
  60. /// Inserts a constant numeric value onto the stack
  61. class push_constant
  62. {
  63. public:
  64.     push_constant(const double Constant, stack_t& Stack) :
  65.         m_constant(Constant),
  66.         m_stack(Stack)
  67.     {
  68.     }
  69.  
  70.     template<typename iterator_t>
  71.     void operator()(iterator_t, iterator_t) const
  72.     {
  73.         m_stack.push(m_constant);
  74.     }
  75.  
  76. private:
  77.     const double m_constant;
  78.     stack_t& m_stack;
  79. };
  80.  
  81. /// Applies a unary function to the top of the stack
  82. template<typename operator_t>
  83. class unary_operator_t
  84. {
  85. public:
  86.     explicit unary_operator_t(operator_t Operator, stack_t& Stack) :
  87.         m_operator(Operator),
  88.         m_stack(Stack)
  89.     {
  90.     }
  91.  
  92.     template<typename iterator_t>
  93.     void operator()(iterator_t, iterator_t) const
  94.     {
  95.         const double rhs = m_stack.top(); m_stack.pop();
  96.         m_stack.push(m_operator(rhs));
  97.     }
  98.  
  99. private:
  100.     operator_t m_operator;
  101.     stack_t& m_stack;
  102. };
  103.  
  104. /// Convenience factory function for instantiating unary_operator_t objects
  105. template<typename operator_t>
  106. unary_operator_t<operator_t> unary_operator(operator_t Operator, stack_t& Stack)
  107. {
  108.     return unary_operator_t<operator_t>(Operator, Stack);
  109. }
  110.  
  111. /// Applies a binary function to the top two values of the stack
  112. template<typename operator_t>
  113. class binary_operator_t
  114. {
  115. public:
  116.     explicit binary_operator_t(operator_t Operator, stack_t& Stack) :
  117.         m_operator(Operator),
  118.         m_stack(Stack)
  119.     {
  120.     }
  121.  
  122.     template<typename iterator_t>
  123.     void operator()(iterator_t, iterator_t) const
  124.     {
  125.         const double rhs = m_stack.top(); m_stack.pop();
  126.         const double lhs = m_stack.top(); m_stack.pop();
  127.         m_stack.push(m_operator(lhs, rhs));
  128.     }
  129.  
  130. private:
  131.     operator_t m_operator;
  132.     stack_t& m_stack;
  133. };
  134.  
  135. /// Convenience factory function for instantiating binary_operator_t objects
  136. template<typename operator_t>
  137. binary_operator_t<operator_t> binary_operator(operator_t Operator, stack_t& Stack)
  138. {
  139.     return binary_operator_t<operator_t>(Operator, Stack);
  140. }
  141.  
  142. /// Encapsulates a grammar for evaluating basic mathematics expressions
  143. struct expression_grammar :
  144.     public grammar<expression_grammar>
  145. {
  146.     expression_grammar(stack_t& Stack) :
  147.         m_stack(Stack)
  148.     {
  149.     }
  150.  
  151.     template<typename ScannerT>
  152.     struct definition
  153.     {
  154.         definition(const expression_grammar& self)
  155.         {
  156.             number = (real_p)[push_number(self.m_stack)];
  157.  
  158.             pi = (nocase_d[str_p("pi")])[push_constant(3.14159265358979323846, self.m_stack)];
  159.  
  160.             constant = number
  161.                  | pi;
  162.  
  163.             primary_expression = constant
  164.                                | (ch_p('(') >> expression >> ch_p(')'))
  165.                        | (ch_p('-') >> expression)[unary_operator(std::negate<double>(), self.m_stack)]
  166.                        | (ch_p('+') >> expression);
  167.  
  168.             unary_function_arguments = ch_p('(') >> expression >> ch_p(')');
  169.  
  170.             binary_function_arguments = ch_p('(') >> expression >> ch_p(',') >> expression >> ch_p(')');
  171.  
  172.             builtins = primary_expression
  173.                  | (str_p("abs") >> unary_function_arguments)[unary_operator((double(*)(double))&fabs, self.m_stack)]
  174.                  | (str_p("acos") >> unary_function_arguments)[unary_operator((double(*)(double))&acos, self.m_stack)]
  175.                  | (str_p("asin") >> unary_function_arguments)[unary_operator((double(*)(double))&asin, self.m_stack)]
  176.                  | (str_p("atan") >> unary_function_arguments)[unary_operator((double(*)(double))&atan, self.m_stack)]
  177.                  | (str_p("ceil") >> unary_function_arguments)[unary_operator((double(*)(double))&ceil, self.m_stack)]
  178.                  | (str_p("cos") >> unary_function_arguments)[unary_operator((double(*)(double))&cos, self.m_stack)]
  179.                  | (str_p("cosh") >> unary_function_arguments)[unary_operator((double(*)(double))&cosh, self.m_stack)]
  180.                  | (str_p("exp") >> unary_function_arguments)[unary_operator((double(*)(double))&exp, self.m_stack)]
  181.                  | (str_p("floor") >> unary_function_arguments)[unary_operator((double(*)(double))&floor, self.m_stack)]
  182.                  | (str_p("log") >> unary_function_arguments)[unary_operator((double(*)(double))&::log, self.m_stack)]
  183.                  | (str_p("log10") >> unary_function_arguments)[unary_operator((double(*)(double))&log10, self.m_stack)]
  184.                  | (str_p("pow") >> binary_function_arguments)[binary_operator((double(*)(double, double))&pow, self.m_stack)]
  185.                  | (str_p("sin") >> unary_function_arguments)[unary_operator((double(*)(double))&sin, self.m_stack)]
  186.                  | (str_p("sinh") >> unary_function_arguments)[unary_operator((double(*)(double))&sinh, self.m_stack)]
  187.                  | (str_p("sqrt") >> unary_function_arguments)[unary_operator((double(*)(double))&sqrt, self.m_stack)]
  188.                  | (str_p("tan") >> unary_function_arguments)[unary_operator((double(*)(double))&tan, self.m_stack)]
  189.                  | (str_p("tanh") >> unary_function_arguments)[unary_operator((double(*)(double))&tanh, self.m_stack)];
  190.  
  191.             multiplicative_expression = builtins >>
  192.                 *((ch_p('*') >> builtins)[binary_operator(std::multiplies<double>(), self.m_stack)]
  193.                 | (ch_p('/') >> builtins)[binary_operator(std::divides<double>(), self.m_stack)]);
  194.  
  195.             additive_expression = multiplicative_expression >>
  196.                 *((ch_p('+') >> multiplicative_expression)[binary_operator(std::plus<double>(), self.m_stack)]
  197.                 | (ch_p('-') >> multiplicative_expression)[binary_operator(std::minus<double>(), self.m_stack)]);
  198.  
  199.             expression = (additive_expression);
  200.         }
  201.  
  202.         rule<ScannerT> const& start() const { return expression; }
  203.         rule<ScannerT> number, pi, constant, primary_expression, unary_function_arguments, binary_function_arguments, builtins, multiplicative_expression, additive_expression, expression;
  204.     };
  205.  
  206.     stack_t& m_stack;
  207. };
  208.  
  209. } //namespace expression
  210.  
  211. } // namespace k3d
  212.  
  213. #endif // !K3DSDK_EXPRESSION_GRAMMAR_H
  214.  
  215.