PageRenderTime 35ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmath/llcalcparser.h

https://bitbucket.org/lindenlab/viewer-beta/
C Header | 191 lines | 124 code | 28 blank | 39 comment | 0 complexity | 453a9d4daa3f39f20e3b74b27ab2cea9 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. * LLCalcParser.h
  3. * Copyright 2008 Aimee Walton.
  4. * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  5. * Second Life Viewer Source Code
  6. * Copyright (C) 2008, Linden Research, Inc.
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation;
  11. * version 2.1 of the License only.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  23. * $/LicenseInfo$
  24. *
  25. */
  26. #ifndef LL_CALCPARSER_H
  27. #define LL_CALCPARSER_H
  28. #include <boost/spirit/include/classic_attribute.hpp>
  29. #include <boost/spirit/include/classic_core.hpp>
  30. #include <boost/spirit/include/classic_error_handling.hpp>
  31. #include <boost/spirit/include/classic_position_iterator.hpp>
  32. #include <boost/spirit/include/phoenix1_binders.hpp>
  33. #include <boost/spirit/include/classic_symbols.hpp>
  34. using namespace boost::spirit::classic;
  35. #include "llcalc.h"
  36. #include "llmath.h"
  37. struct LLCalcParser : grammar<LLCalcParser>
  38. {
  39. LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) :
  40. mResult(result), mConstants(constants), mVariables(vars) {};
  41. struct value_closure : closure<value_closure, F32>
  42. {
  43. member1 value;
  44. };
  45. template <typename ScannerT>
  46. struct definition
  47. {
  48. // Rule declarations
  49. rule<ScannerT> statement, identifier;
  50. rule<ScannerT, value_closure::context_t> expression, term,
  51. power,
  52. unary_expr,
  53. factor,
  54. unary_func,
  55. binary_func,
  56. group;
  57. // start() should return the starting symbol
  58. rule<ScannerT> const& start() const { return statement; }
  59. definition(LLCalcParser const& self)
  60. {
  61. using namespace phoenix;
  62. assertion<std::string> assert_domain("Domain error");
  63. // assertion<std::string> assert_symbol("Unknown symbol");
  64. assertion<std::string> assert_syntax("Syntax error");
  65. identifier =
  66. lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')]
  67. ;
  68. group =
  69. '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')'))
  70. ;
  71. unary_func =
  72. ((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sin)(self,arg1)]) |
  73. (str_p("COS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_cos)(self,arg1)]) |
  74. (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_tan)(self,arg1)]) |
  75. (str_p("ASIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_asin)(self,arg1)]) |
  76. (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_acos)(self,arg1)]) |
  77. (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_atan)(self,arg1)]) |
  78. (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) |
  79. (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) |
  80. (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) |
  81. (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) |
  82. (str_p("FLR") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_floor)(self,arg1)]) |
  83. (str_p("CEIL") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_ceil)(self,arg1)])
  84. ) >> assert_syntax(ch_p(')'))
  85. ;
  86. binary_func =
  87. ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
  88. expression[binary_func.value = bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) |
  89. (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
  90. expression[binary_func.value = bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) |
  91. (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
  92. expression[binary_func.value = bind(&LLCalcParser::_max)(self, binary_func.value, arg1)])
  93. ) >> assert_syntax(ch_p(')'))
  94. ;
  95. // *TODO: Localisation of the decimal point?
  96. // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate
  97. // for the current locale. However to do that here could clash with using
  98. // the comma as a separator when passing arguments to functions.
  99. factor =
  100. (ureal_p[factor.value = arg1] |
  101. group[factor.value = arg1] |
  102. unary_func[factor.value = arg1] |
  103. binary_func[factor.value = arg1] |
  104. // Lookup throws an Unknown Symbol error if it is unknown, while this works fine,
  105. // would be "neater" to handle symbol lookup from here with an assertive parser.
  106. // constants_p[factor.value = arg1]|
  107. identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)]
  108. ) >>
  109. // Detect and throw math errors.
  110. assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value)))
  111. ;
  112. unary_expr =
  113. !ch_p('+') >> factor[unary_expr.value = arg1] |
  114. '-' >> factor[unary_expr.value = -arg1]
  115. ;
  116. power =
  117. unary_expr[power.value = arg1] >>
  118. *('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)]))
  119. ;
  120. term =
  121. power[term.value = arg1] >>
  122. *(('*' >> assert_syntax(power[term.value *= arg1])) |
  123. ('/' >> assert_syntax(power[term.value /= arg1])) |
  124. ('%' >> assert_syntax(power[term.value = bind(&fmodf)(term.value, arg1)]))
  125. )
  126. ;
  127. expression =
  128. assert_syntax(term[expression.value = arg1]) >>
  129. *(('+' >> assert_syntax(term[expression.value += arg1])) |
  130. ('-' >> assert_syntax(term[expression.value -= arg1]))
  131. )
  132. ;
  133. statement =
  134. !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p)
  135. ;
  136. }
  137. };
  138. private:
  139. // Member functions for semantic actions
  140. F32 lookup(const std::string::iterator&, const std::string::iterator&) const;
  141. F32 _min(const F32& a, const F32& b) const { return llmin(a, b); }
  142. F32 _max(const F32& a, const F32& b) const { return llmax(a, b); }
  143. bool checkNaN(const F32& a) const { return !llisnan(a); }
  144. //FIX* non ambigious function fix making SIN() work for calc -Cryogenic Blitz
  145. F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); }
  146. F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); }
  147. F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); }
  148. F32 _asin(const F32& a) const { return asin(a * RAD_TO_DEG); }
  149. F32 _acos(const F32& a) const { return acos(a * RAD_TO_DEG); }
  150. F32 _atan(const F32& a) const { return atan(a * RAD_TO_DEG); }
  151. F32 _sqrt(const F32& a) const { return sqrt(a); }
  152. F32 _log(const F32& a) const { return log(a); }
  153. F32 _exp(const F32& a) const { return exp(a); }
  154. F32 _fabs(const F32& a) const { return fabs(a); }
  155. F32 _floor(const F32& a) const { return llfloor(a); }
  156. F32 _ceil(const F32& a) const { return llceil(a); }
  157. F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); }
  158. LLCalc::calc_map_t* mConstants;
  159. LLCalc::calc_map_t* mVariables;
  160. // LLCalc::calc_map_t* mUserVariables;
  161. F32& mResult;
  162. };
  163. #endif // LL_CALCPARSER_H