1 #ifndef _INTERPRETER_CPP_
2 #define _INTERPRETER_CPP_
4 #ifndef _MADARA_NO_KARL_
1160 Symbol* rhs,
int compare_type,
1200 virtual ~List(
void);
1313 virtual ~Both(
void);
1848 const char* fn_name,
fn_type fn)
1864 std::stringstream
str;
1866 <<
" has a left or right child. Likely missing a semi-colon";
1888 : logger_(&
logger), left_(left), right_(right), precedence_(precedence)
1963 if (left_ || right_)
1965 std::string message =
"Number::build: KARL COMPILE ERROR: "
1967 message += item_.to_string();
1968 message +=
" has a left or right child. Likely missing a semi-colon\n";
1975 return new LeafNode(*(this->logger_), item_);
2004 "Negate::build: KARL COMPILE ERROR: "
2005 "Negate(-) has a left child. Likely missing a semi-colon\n");
2008 "Negate::build: KARL COMPILE ERROR: "
2009 "Negate(-) has a left child. Likely missing a semi-colon\n");
2075 if (left_ || right_)
2078 "array[]::build: KARL COMPILE ERROR: "
2079 "array[] has a left or right child. Likely missing a semi-colon\n");
2082 "array[]::build: KARL COMPILE ERROR: "
2083 "array[] has a left or right child. Likely missing a semi-colon\n");
2119 if (left_ || right_)
2122 "#clear_var::build: KARL COMPILE ERROR: "
2123 "#clear_var has a left or right child. Likely missing a semi-colon\n");
2126 "#clear_var::build: KARL COMPILE ERROR: "
2127 "#clear_var has a left or right child. Likely missing a semi-colon\n");
2152 if (left_ || right_)
2155 "#delete_var::build: KARL COMPILE ERROR: "
2156 "#delete_var has a left or right child. Likely missing a semi-colon\n");
2159 "#delete_var::build: KARL COMPILE ERROR: "
2160 "#delete_var has a left or right child. Likely missing a semi-colon\n");
2184 if (left_ || right_)
2187 "#evaluate::build: KARL COMPILE ERROR: "
2188 "#evaluate has a left or right child. Likely missing a semi-colon\n");
2191 "#evaluate::build: KARL COMPILE ERROR: "
2192 "#evaluate has a left or right child. Likely missing a semi-colon\n");
2217 if (left_ || right_)
2220 "#expand_env::build: KARL COMPILE ERROR: "
2221 "#expand_env has a left or right child. Likely missing a semi-colon\n");
2224 "#expand_env::build: KARL COMPILE ERROR: "
2225 "#expand_env has a left or right child. Likely missing a semi-colon\n");
2250 if (left_ || right_)
2253 "#expand::build: KARL COMPILE ERROR: "
2254 "#expand has a left or right child. Likely missing a semi-colon\n");
2257 "#expand::build: KARL COMPILE ERROR: "
2258 "#expand has a left or right child. Likely missing a semi-colon\n");
2283 if (left_ || right_)
2286 "#fragment::build: KARL COMPILE ERROR: "
2287 "#fragment has a left or right child. Likely missing a semi-colon\n");
2290 "#fragment::build: KARL COMPILE ERROR: "
2291 "#fragment has a left or right child. Likely missing a semi-colon\n");
2316 if (left_ || right_)
2319 "#log_level::build: KARL COMPILE ERROR: "
2320 "#log_level has a left or right child. Likely missing a semi-colon\n");
2323 "#log_level::build: KARL COMPILE ERROR: "
2324 "#log_level has a left or right child. Likely missing a semi-colon\n");
2349 if (left_ || right_)
2352 "#get_clock::build: KARL COMPILE ERROR: "
2353 "#get_clock has a left or right child. Likely missing a semi-colon\n");
2356 "#get_clock::build: KARL COMPILE ERROR: "
2357 "#get_clock has a left or right child. Likely missing a semi-colon\n");
2382 if (left_ || right_)
2385 "#get_time::build: KARL COMPILE ERROR: "
2386 "#get_time has a left or right child. Likely missing a semi-colon\n");
2389 "#get_time::build: KARL COMPILE ERROR: "
2390 "#get_time has a left or right child. Likely missing a semi-colon\n");
2415 if (left_ || right_)
2418 "#get_time_s::build: KARL COMPILE ERROR: "
2419 "#get_time_s has a left or right child. Likely missing a semi-colon\n");
2422 "#get_time_s::build: KARL COMPILE ERROR: "
2423 "#get_time_s has a left or right child. Likely missing a semi-colon\n");
2448 if (left_ || right_)
2451 "#set_clock::build: KARL COMPILE ERROR: "
2452 "#set_clock has a left or right child. Likely missing a semi-colon\n");
2455 "#set_clock::build: KARL COMPILE ERROR: "
2456 "#set_clock has a left or right child. Likely missing a semi-colon\n");
2481 if (left_ || right_)
2484 "#set_fixed::build: KARL COMPILE ERROR: "
2485 "#set_fixed has a left or right child. Likely missing a semi-colon\n");
2488 "#set_fixed::build: KARL COMPILE ERROR: "
2489 "#set_fixed has a left or right child. Likely missing a semi-colon\n");
2514 if (left_ || right_)
2517 "#set_precision::build: KARL COMPILE ERROR: "
2518 "#set_precision has a left or right child. Likely missing a "
2522 "#set_precision::build: KARL COMPILE ERROR: "
2523 "#set_precision has a left or right child. Likely missing a "
2549 if (left_ || right_)
2552 "#scientific::build: KARL COMPILE ERROR: "
2553 "#scientific has a left or right child. Likely missing a semi-colon\n");
2556 "#scientific::build: KARL COMPILE ERROR: "
2557 "#scientific has a left or right child. Likely missing a semi-colon\n");
2581 if (left_ || right_)
2584 "#print::build: KARL COMPILE ERROR: "
2585 "#print has a left or right child. Likely missing a semi-colon\n");
2588 "#print::build: KARL COMPILE ERROR: "
2589 "#print has a left or right child. Likely missing a semi-colon\n");
2613 if (left_ || right_)
2616 "#cos::build: KARL COMPILE ERROR: "
2617 "#cos has a left or right child. Likely missing a semi-colon\n");
2620 "#cos::build: KARL COMPILE ERROR: "
2621 "#cos has a left or right child. Likely missing a semi-colon\n");
2645 if (left_ || right_)
2648 "#sin::build: KARL COMPILE ERROR: "
2649 "#sin has a left or right child. Likely missing a semi-colon\n");
2652 "#sin::build: KARL COMPILE ERROR: "
2653 "#sin has a left or right child. Likely missing a semi-colon\n");
2677 if (left_ || right_)
2680 "#tan::build: KARL COMPILE ERROR: "
2681 "#tan has a left or right child. Likely missing a semi-colon\n");
2684 "#tan::build: KARL COMPILE ERROR: "
2685 "#tan has a left or right child. Likely missing a semi-colon\n");
2709 if (left_ || right_)
2712 "#pow::build: KARL COMPILE ERROR: "
2713 "#pow has a left or right child. Likely missing a semi-colon\n");
2716 "#pow::build: KARL COMPILE ERROR: "
2717 "#pow has a left or right child. Likely missing a semi-colon\n");
2742 if (left_ || right_)
2745 "#sqrt::build: KARL COMPILE ERROR: "
2746 "#sqrt has a left or right child. Likely missing a semi-colon\n");
2749 "#sqrt::build: KARL COMPILE ERROR: "
2750 "#sqrt has a left or right child. Likely missing a semi-colon\n");
2775 if (left_ || right_)
2778 "#print_system_calls::build: KARL COMPILE ERROR: "
2779 "#print_system_calls has a left or right child. Likely missing a "
2783 "#print_system_calls::build: KARL COMPILE ERROR: "
2784 "#print_system_calls has a left or right child. Likely missing a "
2810 if (left_ || right_)
2813 "#rand_double::build: KARL COMPILE ERROR: "
2814 "#rand_double has a left or right child. Likely missing a "
2818 "#rand_double has a left or right child. "
2819 "Likely missing a semi-colon\n");
2844 if (left_ || right_)
2847 "#rand_int::build: KARL COMPILE ERROR: "
2848 "#rand_int has a left or right child. Likely missing a semi-colon\n");
2851 "#rand_int::build: KARL COMPILE ERROR: "
2852 "#rand_int has a left or right child. Likely missing a semi-colon\n");
2877 if (left_ || right_)
2880 "#read_file::build: KARL COMPILE ERROR: "
2881 "#read_file has a left or right child. Likely missing a semi-colon\n");
2884 "#read_file::build: KARL COMPILE ERROR: "
2885 "#read_file has a left or right child. Likely missing a semi-colon\n");
2910 if (left_ || right_)
2913 "#write_file::build: KARL COMPILE ERROR: "
2914 "#write_file has a left or right child. Likely missing a semi-colon\n");
2917 "#write_file::build: KARL COMPILE ERROR: "
2918 "#write_file has a left or right child. Likely missing a semi-colon\n");
2942 if (left_ || right_)
2945 "#size::build: KARL COMPILE ERROR: "
2946 "#size has a left or right child. Likely missing a semi-colon\n");
2949 "#size::build: KARL COMPILE ERROR: "
2950 "#size has a left or right child. Likely missing a semi-colon\n");
2974 if (left_ || right_)
2977 "#sleep::build: KARL COMPILE ERROR: "
2978 "#sleep has a left or right child. Likely missing a semi-colon\n");
2981 "#sleep::build: KARL COMPILE ERROR: "
2982 "#sleep has a left or right child. Likely missing a semi-colon\n");
3007 if (left_ || right_)
3010 "#to_buffer::build: KARL COMPILE ERROR: "
3011 "#to_buffer has a left or right child. Likely missing a semi-colon\n");
3014 "#to_buffer::build: KARL COMPILE ERROR: "
3015 "#to_buffer has a left or right child. Likely missing a semi-colon\n");
3040 if (left_ || right_)
3043 "#to_double::build: KARL COMPILE ERROR: "
3044 "#to_double has a left or right child. Likely missing a semi-colon\n");
3047 "#to_double::build: KARL COMPILE ERROR: "
3048 "#to_double has a left or right child. Likely missing a semi-colon\n");
3073 if (left_ || right_)
3076 "#to_doubles::build: KARL COMPILE ERROR: "
3077 "#to_doubles has a left or right child. Likely missing a semi-colon\n");
3080 "#to_doubles::build: KARL COMPILE ERROR: "
3081 "#to_doubles has a left or right child. Likely missing a semi-colon\n");
3106 if (left_ || right_)
3109 "#to_host_dirs::build: KARL COMPILE ERROR: "
3110 "#to_host_dirs has a left or right child. Likely missing a "
3114 "#to_host_dirs has a left or right child. "
3115 "Likely missing a semi-colon\n");
3140 if (left_ || right_)
3143 "#to_integer::build: KARL COMPILE ERROR: "
3144 "#to_integer has a left or right child. Likely missing a semi-colon\n");
3147 "#to_integer::build: KARL COMPILE ERROR: "
3148 "#to_integer has a left or right child. Likely missing a semi-colon\n");
3173 if (left_ || right_)
3176 "#to_integers::build: KARL COMPILE ERROR: "
3177 "#to_integers has a left or right child. Likely missing a "
3181 "#to_integers has a left or right child. "
3182 "Likely missing a semi-colon\n");
3207 if (left_ || right_)
3210 "#to_string::build: KARL COMPILE ERROR: "
3211 "#to_string has a left or right child. Likely missing a semi-colon\n");
3214 "#to_string::build: KARL COMPILE ERROR: "
3215 "#to_string has a left or right child. Likely missing a semi-colon\n");
3239 if (left_ || right_)
3242 "#type::build: KARL COMPILE ERROR: "
3243 "#type has a left or right child. Likely missing a semi-colon\n");
3246 "#type::build: KARL COMPILE ERROR: "
3247 "#type has a left or right child. Likely missing a semi-colon\n");
3271 if (left_ || right_)
3274 "#is_inf::build: KARL COMPILE ERROR: "
3275 "#is_inf has a left or right child. Likely missing a semi-colon\n");
3278 "#is_inf::build: KARL COMPILE ERROR: "
3279 "#is_inf has a left or right child. Likely missing a semi-colon\n");
3290 precondition_(precondition),
3291 condition_(condition),
3292 postcondition_(postcondition),
3301 delete precondition_;
3302 delete postcondition_;
3318 postcondition_->build(), body_->build(),
context_);
3324 left = precondition_->left_->build();
3327 right = condition_->right_->build();
3356 "var--::build: KARL COMPILE ERROR: "
3357 "var-- has a left child. Likely missing a semi-colon\n");
3360 "#var--::build: KARL COMPILE ERROR: "
3361 "#var-- has a left child. Likely missing a semi-colon\n");
3365 right = right_->build();
3393 "var++::build: KARL COMPILE ERROR: "
3394 "var++ has a left child. Likely missing a semi-colon\n");
3397 "#var++::build: KARL COMPILE ERROR: "
3398 "#var++ has a left child. Likely missing a semi-colon\n");
3402 right = right_->build();
3430 "--var::build: KARL COMPILE ERROR: "
3431 "--var has a left child. Likely missing a semi-colon\n");
3434 "--var::build: KARL COMPILE ERROR: "
3435 "--var has a left child. Likely missing a semi-colon\n");
3439 right = right_->build();
3467 "++var::build: KARL COMPILE ERROR: "
3468 "++var has a left child. Likely missing a semi-colon\n");
3471 "++var::build: KARL COMPILE ERROR: "
3472 "++var has a left child. Likely missing a semi-colon\n");
3476 right = right_->build();
3500 Not* next =
dynamic_cast<Not*
>(right_);
3507 "Not(!)::build: KARL COMPILE ERROR: "
3508 "Logical Not(!) has a left child. Likely missing a semi-colon\n");
3511 "Not(!)::build: KARL COMPILE ERROR: "
3512 "Logical Not(!) has a left child. Likely missing a semi-colon\n");
3557 "sqrt::build: KARL COMPILE ERROR: "
3558 "sqrt has a left child. Likely missing a semi-colon\n");
3561 "sqrt::build: KARL COMPILE ERROR: "
3562 "sqrt has a left child. Likely missing a semi-colon\n");
3566 right = right_->build();
3592 if (left_ || right_)
3594 std::string message =
"Variable::build: KARL COMPILE ERROR: "
3597 message +=
") has a left or right child. Likely missing a semi-colon\n";
3609 else if (key_ ==
"false")
3613 else if (key_ ==
"nan")
3617 else if (key_ ==
"inf")
3649 if (left_ || right_)
3651 std::string message =
"ArrayRef::build: KARL COMPILE ERROR: ";
3653 message +=
"[] has a left or right child. Likely missing a semi-colon\n";
3689 left_->build(), value_, this->right_->build(),
context_);
3720 left_->build(), value_, this->right_->build(),
context_);
3751 left_->build(), value_, this->right_->build(),
context_);
3782 left_->build(), value_, this->right_->build(),
context_);
3795 compare_type_(compare_type),
3815 left_->build(), value_, compare_type_, rhs_->build(),
context_);
3818 left_->build(), value_, compare_type_, 0,
context_);
3860 if (left_ && right_)
3863 Add* next =
dynamic_cast<Add*
>(left_);
3867 nodes_.push_back(right_->build());
3871 for (; next; next =
dynamic_cast<Add*
>(left))
3891 nodes_.push_front(left->
build());
3901 return left_->build();
3905 return right_->build();
3932 if (left_ && right_)
3935 And* next =
dynamic_cast<And*
>(left_);
3939 nodes_.push_back(right_->build());
3943 for (; next; next =
dynamic_cast<And*
>(left))
3963 nodes_.push_front(left->
build());
3973 return left_->build();
3977 return right_->build();
4004 if (left_ && right_)
4007 Or* next =
dynamic_cast<Or*
>(left_);
4011 nodes_.push_back(right_->build());
4015 for (; next; next =
dynamic_cast<Or*
>(left))
4035 nodes_.push_front(left->
build());
4045 return left_->build();
4049 return right_->build();
4079 if (left_ && right_)
4082 Both* next =
dynamic_cast<Both*
>(left_);
4090 for (; next; next =
dynamic_cast<Both*
>(left))
4110 nodes_.push_front(left->
build());
4115 next =
dynamic_cast<Both*
>(right_);
4118 for (; next; next =
dynamic_cast<Both*
>(right))
4138 nodes_.push_back(right->
build());
4148 return left_->build();
4152 return right_->build();
4181 if (left_ && right_)
4192 for (; next; next =
dynamic_cast<ReturnRight*
>(left))
4212 nodes_.push_front(left->
build());
4220 for (; next; next =
dynamic_cast<ReturnRight*
>(right))
4240 nodes_.push_back(right->
build());
4250 return left_->build();
4254 return right_->build();
4283 if (left_ && right_)
4294 for (; next; next =
dynamic_cast<Sequence*
>(left))
4314 nodes_.push_front(left->
build());
4319 next =
dynamic_cast<Sequence*
>(right_);
4322 for (; next; next =
dynamic_cast<Sequence*
>(right))
4342 nodes_.push_back(right->
build());
4352 return left_->build();
4356 return right_->build();
4385 left = left_->build();
4388 right = right_->build();
4414 left = left_->build();
4417 right = right_->build();
4443 left = left_->build();
4446 right = right_->build();
4472 left = left_->build();
4475 right = right_->build();
4502 left = left_->build();
4505 right = right_->build();
4531 left = left_->build();
4534 right = right_->build();
4561 left = left_->build();
4564 right = right_->build();
4590 left = left_->build();
4593 right = right_->build();
4619 left = left_->build();
4622 right = right_->build();
4645 if (left_ && right_)
4649 nodes_.push_back(left_->build());
4653 nodes_.insert(nodes_.end(), rhs->
nodes_.begin(), rhs->
nodes_.end());
4658 nodes_.push_back(right_->build());
4689 left = left_->build();
4692 right = right_->build();
4718 left = left_->build();
4721 right = right_->build();
4735 const std::string& input, std::string::size_type& i,
4736 int& accumulated_precedence, ::std::list<Symbol*>& list,
4737 Symbol*& returnableInput)
4739 ::std::list<Symbol*> substr_list;
4740 Symbol* lastValidInput(0);
4741 std::string::size_type begin = i;
4743 Symbol *body(0), *user_pre(0), *user_cond(0), *user_post(0);
4746 std::string::size_type count(0);
4751 variable =
".MADARA_I";
4754 bool delimiter_found =
false, handled =
false, equal_to =
false;
4755 std::string::size_type delimiter_begin = 0;
4756 std::string::size_type delimiter_end = 0;
4757 int paren_depth = 0;
4758 int index_depth = 0;
4761 for (; i < input.length(); ++i)
4763 if (index_depth == 0 && paren_depth == 0 && input[i] ==
'-' &&
4766 delimiter_found =
true;
4767 delimiter_begin = i;
4769 else if (index_depth == 0 && paren_depth == 0 && delimiter_found &&
4774 else if (input[i] ==
']')
4776 if (index_depth == 0 && paren_depth == 0)
4785 else if (input[i] ==
'(')
4789 else if (input[i] ==
'[')
4793 else if (input[i] ==
')')
4795 if (paren_depth == 0)
4810 if (delimiter_found && delimiter_end == 0)
4812 delimiter_found =
false;
4816 if (!delimiter_found)
4820 substr = input.substr(begin, i - begin);
4824 for (count = 0; count < substr.length();)
4826 main_loop(context, substr, count, lastValidInput, handled,
4827 accumulated_precedence, substr_list);
4831 "madara::expression::Interpreter: "
4832 "KaRL: For loop: Array reference created at %s\n",
4836 if (!substr_list.empty())
4838 index = substr_list.back();
4839 substr_list.clear();
4846 if (i + 2 < input.size())
4848 if (input[i + 1] ==
'+' && input[i + 2] ==
'+')
4856 else if (input[i + 1] ==
'-' && input[i + 2] ==
'-')
4866 lastValidInput = op;
4868 precedence_insert(context, op, list);
4870 returnableInput = op;
4876 "madara::expression::Interpreter: "
4877 "KaRL: For loop: Within input string, the for loop delimiter begins at %d"
4878 " and ends at %d (should be at least 1). Loop construct begins at "
4879 "%d and ends at %d\n",
4880 (
int)delimiter_begin, (
int)delimiter_end, (
int)begin, (
int)i);
4883 if (input[i] ==
']')
4885 else if (input[i] !=
')')
4890 "madara::expression::Interpreter: "
4891 "KARL COMPILE ERROR:: No closing delimiter (']' or ')')"
4892 " has been specified on the for loop.\n");
4895 "madara::expression::Interpreter: "
4896 "KARL COMPILE ERROR:: No closing delimiter (']' or ')')"
4897 " has been specified on the for loop.\n");
4905 if (delimiter_found)
4908 if (delimiter_begin - begin > 0)
4911 substr = input.substr(begin, delimiter_begin - begin);
4913 for (count = 0; count < substr.length();)
4915 main_loop(context, substr, count, lastValidInput, handled,
4916 accumulated_precedence, substr_list);
4920 "madara::expression::Interpreter: "
4921 "KaRL: For loop: Precondition is set to %s\n",
4925 if (!substr_list.empty())
4927 user_pre = substr_list.back();
4928 substr_list.clear();
4934 "madara::expression::Interpreter: "
4935 "KaRL: For loop: No loop precondition was specified\n");
4939 if (delimiter_end - delimiter_begin > 1)
4943 substr = input.substr(
4944 delimiter_begin + 1, delimiter_end - (delimiter_begin + 1));
4946 for (count = 0; count < substr.length();)
4948 main_loop(context, substr, count, lastValidInput, handled,
4949 accumulated_precedence, substr_list);
4953 "madara::expression::Interpreter: "
4954 "KaRL: For loop: Postcondition is set to %s\n",
4958 if (!substr_list.empty())
4960 user_post = substr_list.back();
4962 substr_list.clear();
4968 "KaRL: For loop: No loop special increment was specified\n");
4972 if (i - delimiter_end >= 2)
4975 substr = input.substr(delimiter_end + 1, i - (delimiter_end + 1));
4977 for (count = 0; count < substr.length();)
4979 main_loop(context, substr, count, lastValidInput, handled,
4980 accumulated_precedence, substr_list);
4984 if (!substr_list.empty())
4987 "KaRL: For loop: Condition is set to %s\n", substr.c_str());
4989 user_cond = substr_list.back();
4990 substr_list.clear();
4995 "KaRL: For loop: Condition was not set to %s\n", substr.c_str());
5001 "KaRL: For loop: No loop condition was specified\n");
5008 substr = input.substr(begin, i - begin);
5010 for (count = 0; count < substr.length();)
5012 main_loop(context, substr, count, lastValidInput, handled,
5013 accumulated_precedence, substr_list);
5017 "KaRL: For loop: Condition only is set to %s\n", substr.c_str());
5020 if (!substr_list.empty())
5022 user_cond = substr_list.back();
5023 substr_list.clear();
5047 "KaRL: For loop: Postcondition is set to 1 (def)\n");
5051 for (++i; i < input.length() && is_whitespace(input[i]); ++i)
5055 if (i < input.length() && input[i] ==
'(')
5061 "KaRL: For loop: Body is reading from %s\n",
5062 input.substr(i, input.size() - i).c_str());
5065 handle_parenthesis(context, input, i, lastValidInput, handled,
5066 accumulated_precedence, substr_list);
5068 if (!substr_list.empty())
5070 body = substr_list.back();
5071 substr_list.clear();
5084 if (variable_node && number)
5087 "KaRL: For loop: Body is a simple assignment of variable %s to "
5094 "KaRL: For loop: For loop has a complex body\n");
5098 precondition->
right_ = user_pre;
5106 post_val = number->
item_;
5112 number =
dynamic_cast<Number*
>(user_cond);
5115 cond_val = number->
item_;
5120 int compare_type(0);
5132 var_node, cond_val, user_cond, compare_type, context);
5136 new ForLoop(precondition, condition, postcondition, body, context);
5139 precedence_insert(context, op, list);
5172 delete precondition->
right_;
5173 precondition->
right_ = user_cond;
5176 precedence_insert(context, precondition, list);
5185 std::string::size_type& i,
int& accumulated_precedence,
5186 ::std::list<Symbol*>& list,
Symbol*& lastValidInput)
5189 std::string::size_type j = 1;
5191 for (; i + j < input.length() && is_alphanumeric(input[i + j]); ++j)
5202 for (; i < input.length() && is_whitespace(input[i]); ++i)
5206 if (is_reserved_word(name))
5211 "madara::expression::Interpreter: "
5212 "Inserting true(1) into expression tree.\n");
5216 lastValidInput = number;
5218 precedence_insert(context, number, list);
5220 else if (name ==
"false")
5223 "madara::expression::Interpreter: "
5224 "Inserting false(0) into expression tree.\n");
5228 lastValidInput = number;
5230 precedence_insert(context, number, list);
5232 else if (name ==
"nan")
5235 "madara::expression::Interpreter: "
5236 "Inserting NAN into expression tree.\n");
5240 lastValidInput = number;
5242 precedence_insert(context, number, list);
5244 else if (name ==
"inf")
5247 "madara::expression::Interpreter: "
5248 "Inserting INFINITY into expression tree.\n");
5252 lastValidInput = number;
5254 precedence_insert(context, number, list);
5258 else if (i < input.length() && input[i] ==
'(')
5262 function->add_precedence(accumulated_precedence);
5264 bool handled =
false;
5266 ::std::list<Symbol*> param_list;
5268 int local_precedence = 0;
5269 Symbol* local_last_valid = 0;
5274 handle_parenthesis(context, input, i, local_last_valid, handled,
5275 local_precedence, param_list,
true);
5280 function->nodes_.resize(param_list.size());
5283 for (::std::list<Symbol*>::iterator arg = param_list.begin();
5284 arg != param_list.end(); ++arg, ++cur)
5286 function->nodes_[cur] = (*arg)->build();
5291 precedence_insert(context,
function, list);
5294 else if (i < input.length() && input[i] ==
'[')
5298 context, name, input, i, accumulated_precedence, list, lastValidInput);
5306 if (i + 1 < input.size())
5308 if (input[i] ==
'+' && input[i + 1] ==
'+')
5316 else if (input[i] ==
'-' && input[i + 1] ==
'-')
5326 lastValidInput = op;
5328 precedence_insert(context, op, list);
5335 std::string::size_type& i,
int& accumulated_precedence,
5336 ::std::list<madara::expression::Symbol*>& list,
5339 std::string::size_type j = 0;
5342 for (; i + j < input.length(); ++j)
5344 if (input[i + j] == opener && input[i + j - 1] !=
'\\')
5352 lastValidInput = number;
5358 precedence_insert(context, number, list);
5364 std::string::size_type& i,
int& accumulated_precedence,
5365 ::std::list<Symbol*>& list,
Symbol*& lastValidInput)
5368 std::string::size_type j = 1;
5370 for (; i + j < input.length() && is_alphanumeric(input[i + j]); ++j)
5381 for (; i < input.length() && is_whitespace(input[i]); ++i)
5384 if (i < input.length() && input[i] ==
'(')
5388 char first_char = 0;
5390 if (name.size() > 1)
5392 first_char = name[1];
5398 if (name ==
"#buffer")
5404 if (name ==
"#clear_var" || name ==
"#clear_variable")
5408 else if (name ==
"#cos")
5410 call =
new Cos(context);
5414 if (name ==
"#delete_var" || name ==
"#delete_variable")
5418 else if (name ==
"#double")
5422 else if (name ==
"#doubles")
5428 if (name ==
"#eval" || name ==
"#evaluate")
5430 call =
new Eval(context);
5432 else if (name ==
"#expand" || name ==
"#expand_statement")
5436 else if (name ==
"#expand_env" || name ==
"#expand_envs")
5442 if (name ==
"#fragment")
5446 else if (name ==
"#fixed")
5452 if (name ==
"#get_clock")
5456 else if (name ==
"#get_time" || name ==
"#get_time_ns" ||
5457 name ==
"#get_time_nano")
5461 else if (name ==
"#get_time_seconds" || name ==
"#get_time_s")
5467 if (name ==
"#integer")
5471 else if (name ==
"#integers")
5475 else if (name ==
"#isinf")
5477 call =
new Isinf(context);
5481 if (name ==
"#log_level")
5489 call =
new Power(context);
5491 else if (name ==
"#print")
5493 call =
new Print(context);
5495 else if (name ==
"#print_system_calls" || name ==
"#print_system_call")
5499 else if (name ==
"#precision")
5505 if (name ==
"#rand_double")
5509 else if (name ==
"#rand_int" || name ==
"#rand_integer")
5513 else if (name ==
"#read_file")
5519 if (name ==
"#scientific")
5523 else if (name ==
"#set_clock")
5527 else if (name ==
"#set_fixed")
5531 else if (name ==
"#set_precision")
5535 else if (name ==
"#set_scientific")
5539 else if (name ==
"#sin")
5541 call =
new Sin(context);
5543 else if (name ==
"#size")
5545 call =
new Size(context);
5547 else if (name ==
"#sleep")
5549 call =
new Sleep(context);
5551 else if (name ==
"#sqrt")
5555 else if (name ==
"#string")
5563 call =
new Tan(context);
5565 else if (name ==
"#to_buffer")
5569 else if (name ==
"#to_double")
5573 else if (name ==
"#to_doubles")
5577 else if (name ==
"#to_host_dirs")
5581 else if (name ==
"#to_integer")
5585 else if (name ==
"#to_integers")
5589 else if (name ==
"#to_string")
5593 else if (name ==
"#type")
5595 call =
new Type(context);
5599 if (name ==
"#write_file")
5611 "madara::expression::Interpreter: "
5612 "System call %s is unsupported in this version of MADARA, "
5613 "defaulting to print_system_calls help menu.\n",
5617 "System call %s does not exist.");
5624 bool handled =
false;
5626 ::std::list<Symbol*> param_list;
5631 handle_parenthesis(context, input, i, lastValidInput, handled,
5632 accumulated_precedence, param_list,
true);
5634 call->
nodes_.resize(param_list.size());
5637 for (::std::list<Symbol*>::iterator arg = param_list.begin();
5638 arg != param_list.end(); ++arg, ++cur)
5640 call->
nodes_[cur] = (*arg)->build();
5643 precedence_insert(context, call, list);
5648 std::string message =
"madara::expression::Interpreter: "
5649 "KARL COMPILE ERROR: System call ";
5651 message +=
" does not have appropriate parentheses\n";
5662 std::string::size_type& i,
int& accumulated_precedence,
5663 ::std::list<madara::expression::Symbol*>& list,
5670 std::string::size_type j = 1;
5673 for (; i + j <= input.length() && is_number(input[i + j]); ++j)
5677 if ((i + j <= input.length() && input[i + j] ==
'.') || input[i] ==
'.')
5679 if (input[i] !=
'.')
5682 for (; i + j <= input.length() && is_number(input[i + j]); ++j)
5686 if (i + j <= input.length() && (input[i + j] ==
'e' || input[i + j] ==
'E'))
5689 if (i + j <= input.length() &&
5690 (input[i + j] ==
'+' || input[i + j] ==
'-'))
5695 for (; i + j <= input.length() && is_number(input[i + j]); ++j)
5701 std::stringstream buffer;
5702 buffer << input.substr(i, j);
5703 buffer >> new_number;
5713 std::stringstream buffer;
5714 buffer << input.substr(i, j);
5715 buffer >> new_number;
5722 lastValidInput = number;
5728 precedence_insert(context, number, list);
5734 ::std::list<madara::expression::Symbol*>& list)
5740 Symbol* parent = list.back();
5754 for (child = parent->
right_;
5757 grandparent = parent;
5765 if (child && (child_operator == 0 && child_ternary == 0))
5768 "Interpreter::precedence_insert: "
5769 "Level 1: child is neither an operator or ternary\n");
5774 if (op_assignment || op_implies || op_unary)
5783 for (child = parent->
right_;
5787 grandparent = parent;
5792 child_operator =
dynamic_cast<Operator*
>(child);
5795 if (child && (child_operator == 0 && child_ternary == 0))
5798 "Interpreter::precedence_insert: "
5799 "Level 2: child is neither an operator or ternary\n");
5809 (op_assignment || op_implies || op_unary)))
5821 if (parent_binary && !parent->
left_)
5824 Both* parent_both =
dynamic_cast<Both*
>(parent);
5828 "KARL COMPILE WARNING: Empty statements between ';' may"
5829 " cause slower execution, attempting to prune away the extra "
5835 "madara::expression::Interpreter: "
5836 "KARL COMPILE WARNING: Binary operation has no left child. "
5837 "Inserting a zero\n");
5847 if (parent_unary && parent->
left_)
5850 "madara::expression::Interpreter: "
5851 "KARL COMPILE ERROR: Unary operation shouldn't have a left "
5855 "madara::expression::Interpreter: "
5856 "KARL COMPILE ERROR: "
5857 "Parent unary node has a left child, shouldn't be possible\n");
5870 "madara::expression::Interpreter: "
5871 "KARL COMPILE ERROR: unary operation shouldn't have a left "
5875 "madara::expression::Interpreter: "
5876 "KARL COMPILE ERROR: "
5877 "Unary node has a left child, shouldn't be possible\n");
5882 "Interpreter::precedence_insert: "
5883 "Level 3: op is setting its left to the existing child\n");
5890 "Interpreter::precedence_insert: "
5891 "Level 3: parent->right is being set to current operator\n");
5904 grandparent->
right_ = op;
5921 bool& handled,
int& accumulated_precedence,
5922 ::std::list<madara::expression::Symbol*>& list,
bool build_argument_list)
5925 if (is_number(input[i]) ||
5926 (i + 1 < input.size() && input[i] ==
'.' && is_number(input[i + 1])))
5931 context, input, i, accumulated_precedence, list, lastValidInput);
5933 else if (is_alphanumeric(input[i]))
5938 context, input, i, accumulated_precedence, list, lastValidInput);
5940 else if (is_string_literal(input[i]))
5942 char opener = input[i];
5946 string_insert(opener, context, input, i, accumulated_precedence, list,
5949 else if (i < input.length() && input[i] ==
'[')
5953 object->add_precedence(accumulated_precedence);
5957 ::std::list<Symbol*> param_list;
5959 int local_precedence = 0;
5960 Symbol* local_last_valid = 0;
5965 handle_array(context, input, i, local_last_valid, handled, local_precedence,
5968 object->nodes_.resize(param_list.size());
5971 for (::std::list<Symbol*>::iterator arg = param_list.begin();
5972 arg != param_list.end(); ++arg, ++cur)
5974 object->nodes_[cur] = (*arg)->build();
5977 precedence_insert(context,
object, list);
5980 else if (input[i] ==
'#')
5985 context, input, i, accumulated_precedence, list, lastValidInput);
5987 else if (input[i] ==
'+')
5993 if (i + 1 < input.size() && input[i + 1] ==
'+')
5999 else if (i + 1 < input.size() && input[i + 1] ==
'=')
6003 if (var || array_ref)
6011 "madara::expression::Interpreter: "
6012 "KARL COMPILE ERROR (+=): "
6013 "Assignments must have a variable left hand side.\n");
6016 "madara::expression::Interpreter: "
6017 "KARL COMPILE ERROR (+=): "
6018 "Assignments must have a variable left hand side");
6028 precedence_insert(context, op, list);
6031 else if (input[i] ==
'-')
6037 if (i + 1 < input.size() && input[i + 1] ==
'-')
6043 else if (i + 1 < input.size() && input[i + 1] ==
'=')
6047 if (var || array_ref)
6055 "madara::expression::Interpreter: "
6056 "KARL COMPILE ERROR (-=): "
6057 "Assignments must have a variable left hand side.\n");
6060 "madara::expression::Interpreter: "
6061 "KARL COMPILE ERROR (-=): "
6062 "Assignments must have a variable left hand side");
6067 else if (i + 1 < input.size() && is_number(input[i + 1]))
6072 context, input, i, accumulated_precedence, list, lastValidInput);
6075 else if (!lastValidInput)
6086 precedence_insert(context, op, list);
6090 else if (input[i] ==
'*')
6096 if (i + 1 < input.size() && input[i + 1] ==
'=')
6100 if (var || array_ref)
6108 "madara::expression::Interpreter: "
6109 "KARL COMPILE ERROR (*=): "
6110 "Assignments must have a variable left hand side.\n");
6113 "madara::expression::Interpreter: "
6114 "KARL COMPILE ERROR (*=): "
6115 "Assignments must have a variable left hand side");
6126 precedence_insert(context, op, list);
6129 else if (input[i] ==
'%')
6138 precedence_insert(context, op, list);
6141 else if (input[i] ==
'/')
6144 if (i + 1 < input.size() && input[i + 1] ==
'/')
6147 for (; i < input.size() && input[i] !=
'\n'; ++i)
6151 else if (i + 1 < input.size() && input[i + 1] ==
'*')
6154 std::string::size_type found = input.find(
"*/", i + 1);
6158 if (found != std::string::npos)
6174 if (i + 1 < input.size() && input[i + 1] ==
'=')
6178 if (var || array_ref)
6186 "madara::expression::Interpreter: "
6187 "KARL COMPILE ERROR (/=): "
6188 "Assignments must have a variable left hand side.\n");
6191 "madara::expression::Interpreter: "
6192 "KARL COMPILE ERROR (/=): "
6193 "Assignments must have a variable left hand side");
6202 precedence_insert(context, op, list);
6206 else if (input[i] ==
'=')
6212 if (i + 1 < input.size() && input[i + 1] ==
'=')
6221 precedence_insert(context, op, list);
6224 else if (i + 1 < input.size() && input[i + 1] ==
'>')
6233 precedence_insert(context, op, list);
6245 precedence_insert(context, op, list);
6249 else if (input[i] ==
'!')
6255 if (i + 1 < input.size() && input[i + 1] ==
'=')
6269 precedence_insert(context, op, list);
6273 else if ((uint8_t)input[i] == 251)
6283 precedence_insert(context, op, list);
6286 else if (input[i] ==
'&')
6289 if (i + 1 < input.size() && input[i + 1] ==
'&')
6298 precedence_insert(context, op, list);
6304 "madara::expression::Interpreter: "
6305 "KARL COMPILE ERROR: "
6306 "Logical And (&) not available. "
6307 "You may want to use && instead in %s.\n",
6311 "KARL COMPILE ERROR: "
6312 "Logical And (&) not available.");
6316 else if (input[i] ==
'|')
6319 if (i + 1 < input.size() && input[i + 1] ==
'|')
6328 precedence_insert(context, op, list);
6334 "KARL COMPILE ERROR: "
6335 "Logical Or (|) not available. "
6336 "You may want to use || instead in %s.\n",
6340 "KARL COMPILE ERROR: "
6341 "Logical Or (|) not available.");
6345 else if (input[i] ==
';')
6351 if (i + 1 < input.size() && input[i + 1] ==
'>')
6364 precedence_insert(context, op, list);
6367 else if (input[i] ==
',')
6369 if (build_argument_list)
6378 precedence_insert(context, op, list);
6381 else if (input[i] ==
'<')
6387 if (i + 1 < input.size() && input[i + 1] ==
'=')
6399 precedence_insert(context, op, list);
6402 else if (input[i] ==
'>')
6408 if (i + 1 < input.size() && input[i + 1] ==
'=')
6420 precedence_insert(context, op, list);
6423 else if (input[i] ==
'(')
6427 handle_parenthesis(context, input, i, lastValidInput, handled,
6428 accumulated_precedence, list);
6430 else if (input[i] ==
'\t' || input[i] ==
' ' || input[i] ==
'\r' ||
6442 bool& handled,
int& accumulated_precedence,
6443 ::std::list<madara::expression::Symbol*>& master_list)
6450 int initial_precedence = accumulated_precedence;
6452 ::std::list<Symbol*> list;
6455 bool closed =
false;
6456 while (i < input.length())
6458 main_loop(context, input, i, lastValidInput, handled,
6459 accumulated_precedence, list,
true);
6461 if (input[i] ==
']')
6469 else if (input[i] ==
',')
6474 master_list.push_back(list.back());
6477 accumulated_precedence = initial_precedence;
6479 else if (i == input.length() - 1)
6488 "madara::expression::Interpreter: "
6489 "KARL COMPILE ERROR: "
6490 "Forgot to close parenthesis in %s.\n",
6494 if (list.size() > 0)
6496 if (list.size() > 1)
6499 "madara::expression::Interpreter: "
6500 "KARL COMPILE ERROR: "
6501 "A parenthesis was closed, leaving multiple list items (there should "
6502 "be a max of 1) in %s.\n",
6508 master_list.push_back(list.back());
6519 bool& handled,
int& accumulated_precedence,
6520 ::std::list<madara::expression::Symbol*>& master_list,
6521 bool build_argument_list)
6528 int initial_precedence = accumulated_precedence;
6530 ::std::list<Symbol*> list;
6533 bool closed =
false;
6534 while (i < input.length())
6536 main_loop(context, input, i, lastValidInput, handled,
6537 accumulated_precedence, list, build_argument_list);
6539 if (input[i] ==
')')
6547 else if (build_argument_list && input[i] ==
',')
6552 master_list.push_back(list.back());
6555 accumulated_precedence = initial_precedence;
6557 else if (i == input.length() - 1)
6563 if (!build_argument_list && !closed)
6566 "madara::expression::Interpreter: "
6567 "KARL COMPILE ERROR: "
6568 "Forgot to close parenthesis in %s.\n",
6572 if (!build_argument_list && master_list.size() > 0 && list.size() > 0)
6574 Symbol* lastSymbol = master_list.back();
6581 precedence_insert(context, list.back(), master_list);
6589 else if (list.size() > 0)
6591 if (list.size() > 1)
6594 "madara::expression::Interpreter: "
6595 "KARL COMPILE ERROR: "
6596 "A parenthesis was closed, leaving multiple list items (there should "
6597 "be a max of 1) in %s.\n",
6603 master_list.push_back(list.back());
6617 ExpressionTreeMap::const_iterator found = cache_.find(input);
6618 if (found != cache_.end())
6619 return found->second;
6621 ::std::list<Symbol*> list;
6623 Symbol* lastValidInput = 0;
6624 bool handled =
false;
6625 int accumulated_precedence = 0;
6626 std::string::size_type last_i = 0;
6628 for (std::string::size_type i = 0; i < input.length();)
6633 main_loop(context, input, i, lastValidInput, handled,
6634 accumulated_precedence, list);
6638 size_t start = i > 10 ? i - 10 : 0;
6639 size_t end = input.size() - i > 10 ? i + 10 : input.size();
6641 std::string snippet = input.substr(start, end - start);
6645 "madara::expression::Interpreter: "
6647 "Compilation is spinning at %d in %s. Char is %c. Breaking out.\n",
6648 (
int)i, snippet.c_str(), input[i]);
6675 cache_[input] = tree;
madara::knowledge::KnowledgeRecord::Integer Integer
#define madara_logger_ptr_log(loggering, level,...)
Fast version of the madara::logger::log method for Logger pointers.
#define madara_logger_log(loggering, level,...)
Fast version of the madara::logger::log method.
madara::knowledge::KnowledgeRecord::Integer Integer
const ThreadSafeContext * context_
An exception for unrecoverable KaRL compilation issues.
Addition node of the parse tree.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Add(void)
destructor
Add(logger::Logger &logger)
constructor
Logically and node of the parse tree.
virtual ~And(void)
destructor
And(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Leaf node for an array reference.
madara::knowledge::ThreadSafeContext & context_
Context for variables.
ArrayRef(const std::string &key, Symbol *index, madara::knowledge::ThreadSafeContext &context)
constructors
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
const std::string key_
Key for retrieving value of this variable.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~ArrayRef(void)
destructor
Assign the value of an expression to a variable.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Assignment(logger::Logger &logger)
constructor
virtual ~Assignment(void)
destructor
Evaluates both left and right children, regardless of values.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Both(void)
destructor
Both(logger::Logger &logger)
constructor
Clears a variable in the knowledge base.
virtual ~ClearVariable(void)
destructor
ClearVariable(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
An abstract base class defines a simple abstract implementation of an expression tree node.
A composite node that encompasses addition of two expressions.
A composite node that performs a logical and.
Defines a terminal node of that references the current value stored in a variable.
A composite node that allows for variable assignment.
A composite node that evaluates both left and right expressions regardless of their evaluations.
A composite node that contains an array of values.
A composite node that divides a left expression by a right one.
A composite node that compares left and right expressions for equality.
A composite node that iterates until a condition is met.
A composite node that calls a function.
A composite node that compares left and right expressions for greater than or equal to.
A composite node that compares left and right children for greater than.
A composite node that performs an implication (inference rule)
A composite node that compares left and right children for inequality.
A composite node that compares left and right children for less than or equal to.
A composite node that compares left and right children for less than.
A composite node that divides a left expression by a right expression and returns the remainder of th...
A composite node that multiplies a left expression by a right expression.
A composite node that integrally negates a right expression.
A composite node that logically nots a right expression.
A composite node that performs a logical or.
A composite node that decrements a left expression.
A composite node that increments a right expression.
A composite node that decrements a right expression.
A composite node that increments a right expression.
A composite node that evaluates both left and right expressions regardless of their evaluations.
A composite node that evaluates both left and right expressions regardless of their evaluations.
A composite node that takes the square root of a term.
A composite node that encompasses subtraction of a right expression from a left expression.
A constant array that should not be changed.
virtual ~ConstArray(void)
destructor
ConstArray(madara::knowledge::ThreadSafeContext &context)
constructor
madara::knowledge::ThreadSafeContext & context_
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Returns the cosine of a term (radians)
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Cos(void)
destructor
Cos(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Deletes a variable from the knowledge base.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~DeleteVariable(void)
destructor
DeleteVariable(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Division node of the parse tree.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Divide(logger::Logger &logger)
constructor
virtual ~Divide(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Check and left and right arguments for equality.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Equality(logger::Logger &logger)
constructor
virtual ~Equality(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Evaluates a Knowledge Record and returns result.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Eval(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~Eval(void)
destructor
Expands a statement, e.g.
ExpandEnv(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~ExpandEnv(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Expands a statement, e.g.
virtual ~ExpandStatement(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
ExpandStatement(madara::knowledge::ThreadSafeContext &context_)
constructor
Encapsulates a MADARA KaRL expression into an evaluatable tree.
madara::knowledge::KnowledgeRecord prune(void)
Prunes the expression tree of unnecessary nodes.
Iterative looping node of the parse tree.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
madara::knowledge::ThreadSafeContext & context_
ForLoop(Symbol *precondition, Symbol *condition, Symbol *postcondition, Symbol *body, madara::knowledge::ThreadSafeContext &context)
constructor
virtual ~ForLoop(void)
destructor
Fragment the Knowledge Record.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Fragment(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~Fragment(void)
destructor
Function node of the parse tree.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Function(const std::string &name, madara::knowledge::ThreadSafeContext &context)
constructor
madara::knowledge::ThreadSafeContext & context_
virtual ~Function(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
GenericSystemCall(madara::knowledge::ThreadSafeContext &context, const char *fn_name, fn_type fn)
SystemCallGeneric::fn_type fn_type
SystemCallGeneric::fn_signature fn_signature
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns the clock of the argument or the system clock.
GetClock(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~GetClock(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Returns the wall clock time in seconds.
GetTimeSeconds(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~GetTimeSeconds(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns the wall clock time.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~GetTime(void)
destructor
GetTime(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Check and left and right arguments for greater than or equal to.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~GreaterThanEqual(void)
destructor
GreaterThanEqual(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Check and left and right arguments for greater than.
virtual ~GreaterThan(void)
destructor
GreaterThan(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Assign the value of an expression to a variable.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Implies(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Implies(logger::Logger &logger)
constructor
Check and left and right arguments for inequality.
virtual ~Inequality(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Inequality(logger::Logger &logger)
constructor
void variable_insert(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, int &accumulated_precedence, ::std::list< Symbol * > &list, Symbol *&lastValidInput)
Inserts a variable into the tree.
void number_insert(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, int &accumulated_precedence, ::std::list< Symbol * > &list, Symbol *&lastValidInput)
Inserts a number into the tree.
void handle_parenthesis(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, Symbol *&lastValidInput, bool &handled, int &accumulated_precedence, ::std::list< Symbol * > &list, bool build_argument_list=false)
Handles a parenthesis.
void handle_array(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, Symbol *&lastValidInput, bool &handled, int &accumulated_precedence, ::std::list< Symbol * > &list)
Handles a parenthesis.
void system_call_insert(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, int &accumulated_precedence, ::std::list< Symbol * > &list, Symbol *&lastValidInput)
Inserts a system call into the tree.
void precedence_insert(madara::knowledge::ThreadSafeContext &context, Symbol *op, ::std::list< Symbol * > &list)
Inserts a mathematical operator into the tree.
ExpressionTree interpret(madara::knowledge::ThreadSafeContext &context, const std::string &input)
Compiles an expression into an expression tree.
void handle_for_loop(madara::knowledge::ThreadSafeContext &context, std::string &variable, const std::string &input, std::string::size_type &i, int &accumulated_precedence, ::std::list< Symbol * > &list, Symbol *&returnableInput)
extracts precondition, condition, postcondition, and body from input
void string_insert(char opener, madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, int &accumulated_precedence, ::std::list< Symbol * > &list, Symbol *&lastValidInput)
Inserts a variable into the tree.
virtual ~Interpreter()
Destructor.
void main_loop(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, Symbol *&lastValidInput, bool &handled, int &accumulated_precedence, ::std::list< Symbol * > &list, bool build_argument_list=false)
Inserts a variable into the tree.
Interpreter()
Constructor.
Returns whether the first argument is an infinite number.
virtual ~Isinf(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Isinf(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Defines a node that contains a madara::knowledge::KnowledgeRecord::Integer value.
Check and left and right arguments for less than or equal to.
LessThanEqual(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~LessThanEqual(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Check and left and right arguments for less than.
LessThan(logger::Logger &logger)
constructor
virtual ~LessThan(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Defines a terminal node that contains a list.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~List(void)
destructor
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
List(madara::knowledge::ThreadSafeContext &context)
constructors
Reads or sets the MADARA log level.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~LogLevel(void)
destructor
LogLevel(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Modulus node of the parse tree (10 % 4 == 2)
Modulus(logger::Logger &logger)
constructor
virtual ~Modulus(void)
destructorm
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Multiplication node of the parse tree.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Multiply(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Multiply(logger::Logger &logger)
constructor
Negate node of the parse tree.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Negate(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Negate(void)
destructor
Logically not the right node.
virtual ~Not(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Not(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
madara::knowledge::KnowledgeRecord item_
contains the value of the leaf node
Number(logger::Logger &logger, std::string input)
constructors
virtual ~Number(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Abstract base class for all parse tree node operators.
virtual ~Operator(void)
destructor
Operator(logger::Logger &logger, Symbol *left, Symbol *right, int precedence_=1)
constructor
Logically or node of the parse tree.
Or(logger::Logger &logger)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Or(void)
destructor
Postdecrement node of the parse tree.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Postdecrement(void)
destructor
Postdecrement(logger::Logger &logger)
constructor
Postincrement node of the parse tree.
virtual ~Postincrement(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Postincrement(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Returns a base term taken to a power (exponent)
virtual ~Power(void)
destructor
Power(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Predecrement node of the parse tree.
virtual ~Predecrement(void)
destructor
Predecrement(logger::Logger &logger)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Preincrement node of the parse tree.
virtual ~Preincrement(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Preincrement(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Prints a help menu for all system calls.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~PrintSystemCalls(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
PrintSystemCalls(madara::knowledge::ThreadSafeContext &context_)
constructor
Prints a Knowledge Record to the stderr.
Print(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~Print(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Generates a random double.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~RandDouble(void)
destructor
RandDouble(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Generates a random integer.
virtual ~RandInt(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
RandInt(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~ReadFile(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
ReadFile(madara::knowledge::ThreadSafeContext &context_)
constructor
Evaluates both left and right children and returns right value.
virtual ~ReturnRight(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ReturnRight(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Evaluates both left and right children, regardless of values.
Sequence(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Sequence(void)
destructor
Sets the system or a variable clock.
SetClock(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~SetClock(void)
destructor
Sets the output format to std::fixed.
SetFixed(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~SetFixed(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Sets the precision of doubles.
SetPrecision(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~SetPrecision(void)
destructor
Sets the output to std::scientific.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
SetScientific(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~SetScientific(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Returns the sin of a term (radians)
Sin(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Sin(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Returns the size of a record.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Size(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~Size(void)
destructor
Sleeps for a certain amount of time.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Sleep(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~Sleep(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
SquareRootUnary(logger::Logger &logger)
constructor
virtual ~SquareRootUnary(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns the square root of a term.
SquareRoot(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~SquareRoot(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Subtraction node of the parse tree.
Subtract(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Subtract(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Abstract base class of all parse tree nodes.
virtual int add_precedence(int accumulated_precedence)=0
virtual ComponentNode * build(void)=0
abstract method for building an Expression ExpressionTree Node
Symbol(logger::Logger &logger, Symbol *left, Symbol *right, int precedence_=0)
constructor
virtual ~Symbol(void)
destructor
virtual int precedence(void)
abstract method for returning precedence level (higher value means higher precedence
logger::Logger * logger_
left and right pointers
Attempts to clear a variable.
Returns the cosine of a term in radians.
Attempts to delete a variable.
Evaluates a knowledge::KnowledgeRecord and returns the evaluation result.
Returns the expansion of a statement with environment vars.
Returns the expansion of a statement.
Returns a fragment of the knowledge record.
General purpose system call KaRL node.
madara::knowledge::KnowledgeRecord(std::vector< madara::knowledge::KnowledgeRecord >) fn_signature
std::function< fn_signature > fn_type
Returns the system clock or a variable clock.
Returns the current time in seconds since epoch.
Returns the time in nanoseconds since epoch.
Returns the type of a specified knowledge record.
Sets or returns the current MADARA logging level.
Calculates a base term taken to a power.
Prints all supported system calls.
Prints a Knowledge Record.
Returns a random integer.
Reads a file from an user-provided file name.
Sets the system clock or a variable clock.
Sets the output format to use std::fixed.
Sets the double precision for converting doubles to a string and for printing.
Sets the output format to use std::scientific.
Returns the sin of a term in radians.
Returns the size of a specified knowledge record.
Sleeps for a certain amount of time.
Returns the square root of a term.
Returns the tangent of a term in radians.
Converts an argument into an unsigned char buffer.
Converts an argument to a double.
Converts an argument to an array of doubles.
Ensures the directory delimiters are appropriate for the host operating system (e....
Converts an argument to an integer.
Converts an argument to an array of integers.
Converts an argument to a string.
Returns the type of a specified knowledge record.
Writes a knowledge record to an user-specified file name.
Abstract base class for operators with 3+ potential subnodes.
SystemCall(madara::knowledge::ThreadSafeContext &context_)
constructor
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual ~SystemCall(void)
destructor
Returns the tangent of a term (radians)
virtual ~Tan(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Tan(madara::knowledge::ThreadSafeContext &context_)
constructor
Abstract base class for operators with 3+ potential subnodes.
virtual ~TernaryOperator(void)
destructor
TernaryOperator(logger::Logger &logger, Symbol *left, Symbol *right, int precedence_=1)
constructor
virtual ~ToBuffer(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ToBuffer(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~ToDouble(void)
destructor
ToDouble(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ToDoubles(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~ToDoubles(void)
destructor
Returns a version that has a directory structure appropriate to the OS.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
ToHostDirs(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~ToHostDirs(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~ToInteger(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ToInteger(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~ToIntegers(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ToIntegers(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~ToString(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ToString(madara::knowledge::ThreadSafeContext &context_)
constructor
Returns the type of a record.
virtual ~Type(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Type(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Abstract base class for all parse tree node operators.
virtual ~UnaryOperator(void)
destructor
UnaryOperator(logger::Logger &logger, Symbol *right, int precedence_=1)
constructor
Defines a terminal node of that references the current value stored in a variable.
Increment a variable by a certain amount.
virtual ~VariableCompare(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
madara::knowledge::ThreadSafeContext & context_
Context for variables.
VariableCompare(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, int compare_type, madara::knowledge::ThreadSafeContext &context)
constructors
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
int compare_type_
type of comparison. See madara/Globals.h
Symbol * rhs_
rhs is used for complex rhs types (not a simple number)
Composite node that subtracts a variable by some right hand side.
Decrement a variable by a certain amount.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~VariableDecrement(void)
destructor
madara::knowledge::ThreadSafeContext & context_
Context for variables.
VariableDecrement(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, madara::knowledge::ThreadSafeContext &context)
constructors
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
Composite node that divides a variable by some right hand side.
Divide a variable by a certain amount.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
virtual ~VariableDivide(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
VariableDivide(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, madara::knowledge::ThreadSafeContext &context)
constructors
madara::knowledge::ThreadSafeContext & context_
Context for variables.
Defines a terminal node of that references the current value stored in a variable.
Increment a variable by a certain amount.
VariableIncrement(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, madara::knowledge::ThreadSafeContext &context)
constructors
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual ~VariableIncrement(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
Composite node that multiplies a variable by some right hand side.
Multiply a variable by a certain amount.
VariableMultiply(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, madara::knowledge::ThreadSafeContext &context)
constructors
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
virtual ~VariableMultiply(void)
destructor
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Defines a terminal node of that references the current value stored in a variable.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Variable(const std::string &key, madara::knowledge::ThreadSafeContext &context)
constructors
virtual ~Variable(void)
destructor
const std::string key_
Key for retrieving value of this variable.
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
WriteFile(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~WriteFile(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
This class encapsulates an entry in a KnowledgeBase.
std::string to_string(const std::string &delimiter=", ") const
converts the value to a string.
void set_value(const KnowledgeRecord &new_value)
Sets the value from another KnowledgeRecord, does not copy toi, clock, and write_quality.
This class stores variables and their values for use by any entity needing state information in a thr...
logger::Logger & get_logger(void) const
Gets the logger used for information printing.
A multi-threaded logger for logging to one or more destinations.
std::deque< ComponentNode * > ComponentNodes
a vector of Component Nodes
std::vector< Symbol * > Symbols
Provides knowledge logging services to files and terminals.
Copyright(c) 2020 Galois.