aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/llcalcparser.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llmath/llcalcparser.h155
1 files changed, 155 insertions, 0 deletions
diff --git a/linden/indra/llmath/llcalcparser.h b/linden/indra/llmath/llcalcparser.h
new file mode 100644
index 0000000..c405b62
--- /dev/null
+++ b/linden/indra/llmath/llcalcparser.h
@@ -0,0 +1,155 @@
1/*
2 * LLCalcParser.h
3 * SecondLife
4 *
5 * Created by Aimee Walton on 28/09/2008.
6 * Copyright 2008 Aimee Walton.
7 *
8 */
9
10#ifndef LL_CALCPARSER_H
11#define LL_CALCPARSER_H
12
13#include <boost/spirit/attribute.hpp>
14#include <boost/spirit/core.hpp>
15#include <boost/spirit/error_handling.hpp>
16#include <boost/spirit/iterator/position_iterator.hpp>
17#include <boost/spirit/phoenix/binders.hpp>
18//#include <boost/spirit/symbols/symbols.hpp>
19#include <map>
20#include <string>
21
22#include "llcalc.h"
23#include "llmath.h"
24
25struct LLCalcParser : boost::spirit::grammar<LLCalcParser>
26{
27 LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) :
28 mResult(result), mConstants(constants), mVariables(vars) {};
29
30 struct value_closure : boost::spirit::closure<value_closure, F32>
31 {
32 member1 value;
33 };
34
35 template <typename ScannerT>
36 struct definition
37 {
38 // Rule declarations
39 boost::spirit::rule<ScannerT> statement, identifier;
40 boost::spirit::rule<ScannerT, value_closure::context_t> expression, term,
41 power,
42 unary_expr,
43 factor,
44 /*unary_func,
45 /binary_func,*/
46 group;
47
48 // start() should return the starting symbol
49 boost::spirit::rule<ScannerT> const& start() const { return statement; }
50
51 definition(LLCalcParser const& self)
52 {
53 using namespace boost::spirit;
54 using namespace phoenix;
55
56 assertion<std::string> assert_domain("Domain error");
57// assertion<std::string> assert_symbol("Unknown symbol");
58 assertion<std::string> assert_syntax("Syntax error");
59
60 identifier =
61 lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')]
62 ;
63
64 group =
65 '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')'))
66 ;
67
68 /*unary_func =
69 ((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&sin)(DEG_TO_RAD * arg1)]) |
70 (str_p("COS") >> '(' >> expression[unary_func.value = bind(&cos)(DEG_TO_RAD * arg1)]) |
71 (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&tan)(DEG_TO_RAD * arg1)]) |
72 (str_p("ASIN") >> '(' >> expression[unary_func.value = (bind(&asin)(arg1)) * RAD_TO_DEG]) |
73 (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&acos)(arg1) * RAD_TO_DEG]) |
74 (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&atan)(arg1) * RAD_TO_DEG]) |
75 (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&sqrt)(arg1)]) |
76 (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&log)(arg1)]) |
77 (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&exp)(arg1)]) |
78 (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&fabs)(arg1)])
79 ) >> assert_syntax(ch_p(')'))
80 ;
81
82 binary_func =
83 ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
84 expression[binary_func.value = bind(&atan2)(binary_func.value, arg1) * RAD_TO_DEG]) |
85 (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
86 expression[binary_func.value = bind(&LLCalcParser::min)(self, binary_func.value, arg1)]) |
87 (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
88 expression[binary_func.value = bind(&LLCalcParser::max)(self, binary_func.value, arg1)])
89 ) >> assert_syntax(ch_p(')'))
90 ;*/
91
92 // *TODO: Localisation of the decimal point?
93 // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate
94 // for the current locale. However to do that here could clash with using
95 // the comma as a separator when passing arguments to functions.
96 factor =
97 (ureal_p[factor.value = arg1] |
98 group[factor.value = arg1] |
99 /*unary_func[factor.value = arg1] |
100 binary_func[factor.value = arg1] |*/
101 // Lookup throws an Unknown Symbol error if it is unknown, while this works fine,
102 // would be "neater" to handle symbol lookup from here with an assertive parser.
103// constants_p[factor.value = arg1]|
104 identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)]
105 ) >>
106 // Detect and throw math errors.
107 assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value)))
108 ;
109
110 unary_expr =
111 !ch_p('+') >> factor[unary_expr.value = arg1] |
112 '-' >> factor[unary_expr.value = -arg1]
113 ;
114
115 power =
116 unary_expr[power.value = arg1] >>
117 *('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)]))
118 ;
119
120 term =
121 power[term.value = arg1] >>
122 *(('*' >> assert_syntax(power[term.value *= arg1])) |
123 ('/' >> assert_syntax(power[term.value /= arg1]))
124 )
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
134 statement =
135 !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p)
136 ;
137 }
138 };
139
140private:
141 // Member functions for semantic actions
142 F32 lookup(const std::string::iterator&, const std::string::iterator&) const;
143 F32 min(const F32& a, const F32& b) const { return llmin(a, b); }
144 F32 max(const F32& a, const F32& b) const { return llmax(a, b); }
145
146 bool checkNaN(const F32& a) const { return !llisnan(a); }
147
148 LLCalc::calc_map_t* mConstants;
149 LLCalc::calc_map_t* mVariables;
150// LLCalc::calc_map_t* mUserVariables;
151
152 F32& mResult;
153};
154
155#endif // LL_CALCPARSER_H