10 #include <Teuchos_MathExpr.hpp>
16 Language make_language() {
20 prods[PROD_PROGRAM](
"program") >>
"statements",
"expr?";
21 prods[PROD_NO_STATEMENTS](
"statements");
22 prods[PROD_NEXT_STATEMENT](
"statements") >>
"statements",
"statement",
";",
"S?";
23 prods[PROD_ASSIGN](
"statement") >>
"name",
"S?",
"=",
"S?",
"expr";
24 prods[PROD_NO_EXPR](
"expr?");
25 prods[PROD_YES_EXPR](
"expr?") >>
"expr";
26 prods[PROD_EXPR](
"expr") >>
"ternary";
27 prods[PROD_TERNARY_DECAY](
"ternary") >>
"add_sub";
28 prods[PROD_OR_DECAY](
"or") >>
"and";
29 prods[PROD_AND_DECAY](
"and") >>
"comp";
30 prods[PROD_ADD_SUB_DECAY](
"add_sub") >>
"mul_div";
31 prods[PROD_MUL_DIV_DECAY](
"mul_div") >>
"neg";
32 prods[PROD_NEG_DECAY](
"neg") >>
"pow";
33 prods[PROD_POW_DECAY](
"pow") >>
"scalar";
34 prods[PROD_TERNARY](
"ternary")
35 >>
"or",
"?",
"S?",
"add_sub",
":",
"S?",
"add_sub";
36 prods[PROD_OR](
"or") >>
"or",
"||",
"S?",
"and";
37 prods[PROD_AND](
"and") >>
"and",
"&&",
"S?",
"comp";
38 prods[PROD_GT](
"comp") >>
"add_sub",
">",
"S?",
"add_sub";
39 prods[PROD_LT](
"comp") >>
"add_sub",
"<",
"S?",
"add_sub";
40 prods[PROD_GEQ](
"comp") >>
"add_sub",
">=",
"S?",
"add_sub";
41 prods[PROD_LEQ](
"comp") >>
"add_sub",
"<=",
"S?",
"add_sub";
42 prods[PROD_EQ](
"comp") >>
"add_sub",
"==",
"S?",
"add_sub";
43 prods[PROD_BOOL_PARENS](
"comp") >>
"(",
"S?",
"or",
")",
"S?";
44 prods[PROD_ADD](
"add_sub") >>
"add_sub",
"+",
"S?",
"mul_div";
45 prods[PROD_SUB](
"add_sub") >>
"add_sub",
"-",
"S?",
"mul_div";
46 prods[PROD_MUL](
"mul_div") >>
"mul_div",
"*",
"S?",
"pow";
47 prods[PROD_DIV](
"mul_div") >>
"mul_div",
"/",
"S?",
"pow";
48 prods[PROD_POW](
"pow") >>
"scalar",
"^",
"S?",
"pow";
49 prods[PROD_CALL](
"scalar")
50 >>
"name",
"S?",
"(",
"S?",
"args?",
")",
"S?";
51 prods[PROD_NO_ARGS](
"args?");
52 prods[PROD_SOME_ARGS](
"args?") >>
"args";
53 prods[PROD_FIRST_ARG](
"args") >>
"ternary";
54 prods[PROD_NEXT_ARG](
"args") >>
"args",
",",
"S?",
"ternary";
55 prods[PROD_NEG](
"neg") >>
"-",
"S?",
"neg";
56 prods[PROD_VAL_PARENS](
"scalar") >>
"(",
"S?",
"ternary",
")",
"S?";
57 prods[PROD_CONST](
"scalar") >>
"constant",
"S?";
58 prods[PROD_VAR](
"scalar") >>
"name",
"S?";
59 prods[PROD_NO_SPACES](
"S?");
60 prods[PROD_SPACES](
"S?") >>
"spaces";
61 out.tokens.resize(NTOKS);
62 out.tokens[TOK_SPACE](
"spaces",
"[ \t\n\r]+");
63 out.tokens[TOK_NAME](
"name",
"[_a-zA-Z][_a-zA-Z0-9]*");
64 out.tokens[TOK_ADD](
"+",
"\\+");
65 out.tokens[TOK_SUB](
"-",
"\\-");
66 out.tokens[TOK_MUL](
"*",
"\\*");
67 out.tokens[TOK_DIV](
"/",
"\\/");
68 out.tokens[TOK_POW](
"^",
"\\^");
69 out.tokens[TOK_LPAREN](
"(",
"\\(");
70 out.tokens[TOK_RPAREN](
")",
"\\)");
71 out.tokens[TOK_COMMA](
",",
",");
72 out.tokens[TOK_CHECK](
"?",
"\\?");
73 out.tokens[TOK_CHOOSE](
":",
":");
74 out.tokens[TOK_GT](
">",
">");
75 out.tokens[TOK_LT](
"<",
"<");
76 out.tokens[TOK_GEQ](
">=",
">=");
77 out.tokens[TOK_LEQ](
"<=",
"<=");
78 out.tokens[TOK_EQ](
"==",
"==");
79 out.tokens[TOK_AND](
"&&",
"&&");
80 out.tokens[TOK_OR](
"||",
"\\|\\|");
81 out.tokens[TOK_CONST](
"constant",
82 "(0|([1-9][0-9]*))(\\.[0-9]*)?([eE]\\-?[1-9][0-9]*)?");
83 out.tokens[TOK_SEMICOLON](
";",
";");
84 out.tokens[TOK_ASSIGN](
"=",
"=");
90 if (ptr.strong_count() == 0) {
91 ptr.reset(
new Language(make_language()));
98 if (ptr.strong_count() == 0) {
105 SymbolSetReader::SymbolSetReader():
106 Reader(ask_reader_tables())
110 SymbolSetReader::~SymbolSetReader()
114 void SymbolSetReader::at_shift(any& result,
int token, std::string& text) {
115 if (token == TOK_NAME) result = text;
118 void SymbolSetReader::at_reduce(any& ,
int prod, std::vector<any>& rhs) {
119 if (prod == PROD_VAR) {
120 std::string& name =
any_ref_cast<std::string>(rhs.at(0));
121 variable_names.insert(name);
122 }
else if (prod == PROD_CALL) {
123 std::string& name =
any_ref_cast<std::string>(rhs.at(0));
124 function_names.insert(name);
128 std::set<std::string> get_variables_used(std::string
const& expr) {
129 SymbolSetReader reader;
131 reader.read_string(result, expr,
"get_variables_used");
132 return reader.variable_names;
135 std::set<std::string> get_symbols_used(std::string
const& expr) {
136 SymbolSetReader reader;
138 reader.read_string(result, expr,
"get_symbols_used");
139 auto set = std::move(reader.variable_names);
140 set.insert(reader.function_names.begin(), reader.function_names.end());
144 class CalcReader :
public Reader {
146 CalcReader():Reader(MathExpr::ask_reader_tables()) {
147 unary_function_map[
"sqrt"] = &std::sqrt;
148 unary_function_map[
"sin"] = &std::sin;
149 unary_function_map[
"cos"] = &std::cos;
150 unary_function_map[
"tan"] = &std::tan;
151 unary_function_map[
"asin"] = &std::asin;
152 unary_function_map[
"acos"] = &std::acos;
153 unary_function_map[
"atan"] = &std::atan;
154 unary_function_map[
"exp"] = &std::exp;
155 unary_function_map[
"log"] = &std::log;
156 unary_function_map[
"log10"] = &std::log10;
157 binary_function_map[
"atan2"] = &std::atan2;
159 virtual ~CalcReader() =
default;
166 virtual void at_shift(any& result_any,
int token, std::string& text) {
169 case MathExpr::TOK_NAME: {
170 std::string& result = make_any_ref<std::string>(result_any);
174 case MathExpr::TOK_CONST: {
175 result_any = std::atof(text.c_str());
180 virtual void at_reduce(any& result,
int prod, std::vector<any>& rhs) {
183 case MathExpr::PROD_PROGRAM: {
185 "Calculator needs an expression to evaluate!");
186 swap(result, rhs.at(1));
189 case MathExpr::PROD_NO_STATEMENTS:
190 case MathExpr::PROD_NO_EXPR:
191 case MathExpr::PROD_NEXT_STATEMENT: {
194 case MathExpr::PROD_ASSIGN: {
195 std::string
const& name = any_ref_cast<std::string>(rhs.at(0));
196 double value = any_cast<
double>(rhs.at(4));
197 variable_map[name] = value;
200 case MathExpr::PROD_YES_EXPR:
201 case MathExpr::PROD_EXPR:
202 case MathExpr::PROD_TERNARY_DECAY:
203 case MathExpr::PROD_OR_DECAY:
204 case MathExpr::PROD_AND_DECAY:
205 case MathExpr::PROD_ADD_SUB_DECAY:
206 case MathExpr::PROD_MUL_DIV_DECAY:
207 case MathExpr::PROD_POW_DECAY:
208 case MathExpr::PROD_NEG_DECAY:
209 case MathExpr::PROD_SOME_ARGS:
210 swap(result, rhs.at(0));
212 case MathExpr::PROD_TERNARY:
213 result = any_cast<
bool>(rhs.at(0)) ?
214 any_cast<double>(rhs.at(3)) :
215 any_cast<double>(rhs.at(6));
217 case MathExpr::PROD_OR:
218 result = any_cast<
bool>(rhs.at(0)) || any_cast<bool>(rhs.at(3));
220 case MathExpr::PROD_AND:
221 result = any_cast<
bool>(rhs.at(0)) && any_cast<bool>(rhs.at(3));
223 case MathExpr::PROD_GT:
224 result = any_cast<
double>(rhs.at(0)) > any_cast<double>(rhs.at(3));
226 case MathExpr::PROD_LT:
227 result = any_cast<
double>(rhs.at(0)) < any_cast<double>(rhs.at(3));
229 case MathExpr::PROD_GEQ:
230 result = any_cast<
double>(rhs.at(0)) >= any_cast<double>(rhs.at(3));
232 case MathExpr::PROD_LEQ:
233 result = any_cast<
double>(rhs.at(0)) <= any_cast<double>(rhs.at(3));
235 case MathExpr::PROD_EQ:
236 result = any_cast<
double>(rhs.at(0)) == any_cast<double>(rhs.at(3));
238 case MathExpr::PROD_BOOL_PARENS:
239 result = any_cast<
bool>(rhs.at(2));
241 case MathExpr::PROD_ADD:
242 result = any_cast<
double>(rhs.at(0)) + any_cast<double>(rhs.at(3));
244 case MathExpr::PROD_SUB:
245 result = any_cast<
double>(rhs.at(0)) - any_cast<double>(rhs.at(3));
247 case MathExpr::PROD_MUL:
248 result = any_cast<
double>(rhs.at(0)) * any_cast<double>(rhs.at(3));
250 case MathExpr::PROD_DIV:
251 result = any_cast<
double>(rhs.at(0)) / any_cast<double>(rhs.at(3));
253 case MathExpr::PROD_POW:
254 result = std::pow(any_cast<double>(rhs.at(0)), any_cast<double>(rhs.at(3)));
256 case MathExpr::PROD_CALL: {
257 std::string& name = any_ref_cast<std::string>(rhs.at(0));
258 CallArgs& args = any_ref_cast<CallArgs>(rhs.at(4));
260 "Only unary and binary functions supported!\n");
263 "Unknown unary function name \"" << name <<
"\"\n");
264 Unary fptr = unary_function_map[name];
265 result = (*fptr)(args.a0);
268 "Unknown binary function name \"" << name <<
"\"\n");
269 Binary fptr = binary_function_map[name];
270 result = (*fptr)(args.a0, args.a1);
274 case MathExpr::PROD_NO_ARGS: {
275 CallArgs& args = make_any_ref<CallArgs>(result);
279 case MathExpr::PROD_FIRST_ARG: {
280 CallArgs& args = make_any_ref<CallArgs>(result);
281 args.a0 = any_cast<
double>(rhs.at(0));
285 case MathExpr::PROD_NEXT_ARG: {
286 CallArgs& args = any_ref_cast<CallArgs>(rhs.at(0));
287 args.a1 = any_cast<
double>(rhs.at(3));
289 swap(result, rhs.at(0));
292 case MathExpr::PROD_NEG:
293 result = - any_cast<
double>(rhs.at(2));
295 case MathExpr::PROD_VAL_PARENS:
296 result = any_cast<
double>(rhs.at(2));
298 case MathExpr::PROD_CONST:
299 result = any_cast<
double>(rhs.at(0));
301 case MathExpr::PROD_VAR:
302 std::string
const& name = any_ref_cast<std::string>(rhs.at(0));
303 auto it = variable_map.find(name);
305 "variable " << name <<
" not defined!");
306 double value = it->second;
312 typedef double (*Unary)(double);
313 typedef double (*Binary)(double, double);
314 std::map<std::string, Unary> unary_function_map;
315 std::map<std::string, Binary> binary_function_map;
316 std::map<std::string, double> variable_map;
319 Reader* new_calc_reader() {
320 return new CalcReader();
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Productions productions
vector of productions
ValueType & any_ref_cast(any &operand)
Keep the convenient behavior of Teuchos::any_cast w.r.t. references, but don't confuse it with the be...
RCP< const ReaderTables > ReaderTablesPtr
an RCP to a const ReaderTables
ReaderTablesPtr make_reader_tables(Language const &language)
constructs ReaderTables for the given Language.
RCP< const Language > LanguagePtr
an RCP to a const Language