diff options
Diffstat (limited to 'linden/indra/llmath/llcalcparser.h')
-rw-r--r-- | linden/indra/llmath/llcalcparser.h | 155 |
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 | |||
25 | struct 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 | |||
140 | private: | ||
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 | ||