#include "simple_logic.h" #include ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // logic_expression namespace string_util { // Function: find the ending position in str // // Parameter: str - the string beginning after the first letter 'head' // // head - the leading letter, can be emblaced // // tail - the ending letter // // Return: position at the ending letter, or '\0' in the string int find_end_of_pair(const char* str, char head, char tail) { int end = 0, banlance = 1; while (str[end]) { if (str[end] == '\\') { end++; if (!str[end]) break; // skip this translating-letter end++; continue; } if (str[end] == head) { banlance++; } else if (str[end] == tail) { if (--banlance == 0) break; } end++; } return end; } void skip_space(const char*& ptr, const char* space) { char mark[2] = { 0 }; while (*ptr) { mark[0] = *ptr; if (!strstr(space, mark)) break; ptr++; } } void trim(std::string& str, int type) { int pos = 0; if (type & TRIM_LEFT) { for (; pos < str.length(); ++pos) { if (str[pos] != ' ') break; } if (pos) str.erase(0, pos); } if (type & TRIM_RIGHT) { pos = str.length() - 1; for (; pos >= 0; --pos) { if (str[pos] != ' ') break; } str.erase(pos + 1); } } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // simple_logic simple_logic::simple_logic() : l_(nullptr), r_(nullptr), oper_(LOGIC_OPER_NONE), expr_(""), not_(false) {} simple_logic::simple_logic(const simple_logic& r) : l_(nullptr), r_(nullptr) { copy(r); } simple_logic::~simple_logic() { clear(); } void simple_logic::clear(void) { if (l_) delete l_; if (r_) delete r_; l_ = r_ = nullptr; oper_ = LOGIC_OPER_NONE; expr_ = ""; not_ = false; } void simple_logic::copy(const simple_logic& r) { clear(); oper_ = r.oper_; not_ = r.not_; expr_ = r.expr_; if (r.l_) { l_ = new simple_logic(); l_->copy(*r.l_); } if (r.r_) { r_ = new simple_logic(); r_->copy(*r.r_); } } void simple_logic::set_not(bool notv) { not_ = notv; } bool simple_logic::parse_internal(const char* expr, int* end, void(*leaf)(const char*, void*), void* leaf_param) { const char* ptr = expr, * first = nullptr; std::vector ele; std::vector oper; bool need_oper = false, good = true; string_util::skip_space(ptr); if (*ptr == 0) return false; while (*ptr) { if (*ptr == '(') { if (need_oper) { good = false; *end = ptr - expr; break; } int len = string_util::find_end_of_pair(ptr + 1, '(', ')'); if (ptr[++len] != ')') { *end = ptr - expr + len; good = false; break; } std::string sub(ptr + 1, len - 1); if (sub.find("||") == std::string::npos && sub.find("&&") == std::string::npos && sub.find("^") == std::string::npos) { // count as function ... ptr += len; } else { simple_logic* e = new simple_logic(); int over = 0; bool not_v = false; if (first) { while (first < ptr) { if (*first == '!') not_v ^= true; else break; first++; } if (first < ptr) { *end = first - expr; good = false; delete e; break; } first = nullptr; } if (e->parse(sub.c_str(), &over, leaf, leaf_param)) { e->set_not(not_v); ele.push_back(e); ptr += len; need_oper = true; } else { *end = ptr - expr + 1 + over; good = false; delete e; break; } } } else if (*ptr == '|') { if (*(ptr + 1) == '|') { if (need_oper || first) { if (first) { simple_logic* e = new simple_logic(); e->expr_ = std::string(first, ptr - first); string_util::trim(e->expr_); e->oper_ = LOGIC_OPER_LEAF; ele.push_back(e); first = nullptr; if (leaf) leaf(e->expr_.c_str(), leaf_param); } ptr++; oper.push_back(LOGIC_OPER_OR); need_oper = false; } else { good = false; *end = ptr - expr; break; } } else { good = false; *end = ptr - expr + 1; break; } } else if (*ptr == '&') { if (*(ptr + 1) == '&') { if (need_oper || first) { if (first) { simple_logic* e = new simple_logic(); e->expr_ = std::string(first, ptr - first); string_util::trim(e->expr_); e->oper_ = LOGIC_OPER_LEAF; ele.push_back(e); first = nullptr; if (leaf) leaf(e->expr_.c_str(), leaf_param); } ptr++; oper.push_back(LOGIC_OPER_AND); need_oper = false; } else { good = false; *end = ptr - expr; break; } } else { good = false; *end = ptr - expr + 1; break; } } else if (*ptr == '^') { if (need_oper || first) { if (first) { simple_logic* e = new simple_logic(); e->expr_ = std::string(first, ptr - first); string_util::trim(e->expr_); e->oper_ = LOGIC_OPER_LEAF; ele.push_back(e); first = nullptr; if (leaf) leaf(e->expr_.c_str(), leaf_param); } oper.push_back(LOGIC_OPER_XOR); need_oper = false; } else { good = false; *end = ptr - expr; break; } } else { // expression ... if (need_oper) { good = false; *end = ptr - expr; break; } if (!first) first = ptr; } ptr++; string_util::skip_space(ptr); } if (good && first) { if (need_oper) { *end = first - expr; good = false; } else { simple_logic* e = new simple_logic(); int over = 0; if (e->parse(first, &over)) { ele.push_back(e); if (e->oper_ == LOGIC_OPER_LEAF && leaf) leaf(e->expr_.c_str(), leaf_param); } else { good = false; *end = first - expr + over; delete e; } } } if (good && oper.size() == ele.size() - 1) { simple_logic* root = make_binary(ele, oper); l_ = root->l_; r_ = root->r_; oper_ = root->oper_; expr_ = root->expr_; root->l_ = root->r_ = nullptr; delete root; *end = ptr - expr; } else { for (auto& v : ele) delete v; } return good; } simple_logic* simple_logic::make_binary(const std::vector& eles, const std::vector& opers) { if (eles.size() == 0 && opers.size() == 0) return nullptr; else if (eles.size() == 1) return eles[0]; int or_pos = -1; for (int i = 0; i < opers.size(); ++i) { if (opers[i] == LOGIC_OPER_OR) { or_pos = i; break; } } simple_logic* node = new simple_logic(); if (or_pos == -1) { //node->l_ = eles[0]; //node->oper_ = opers[0]; // //std::vector re; //std::vector ro; //for (int i = 1; i < eles.size(); ++i) // re.push_back(eles[i]); //for (int i = 1; i < opers.size(); ++i) // ro.push_back(opers[i]); //node->r_ = make_binary(re, ro); node->r_ = eles[eles.size() - 1]; node->l_ = eles[eles.size() - 2]; node->oper_ = opers[opers.size() - 1]; simple_logic** left = &node->l_; int cnt = 2; while (++cnt <= eles.size()) { simple_logic* n = new simple_logic(); n->oper_ = opers[opers.size() - cnt + 1]; n->l_ = eles[eles.size() - cnt]; n->r_ = *left; *left = n; left = &n->l_; } } else { std::vector re; std::vector ro; node->oper_ = LOGIC_OPER_OR; for (int i = 0; i < or_pos + 1; ++i) re.push_back(eles[i]); for (int i = 0; i < or_pos; ++i) ro.push_back(opers[i]); node->l_ = make_binary(re, ro); re.clear(); ro.clear(); for (int i = or_pos + 1; i < eles.size(); ++i) re.push_back(eles[i]); for (int i = or_pos + 1; i < opers.size(); ++i) ro.push_back(opers[i]); node->r_ = make_binary(re, ro); } return node; } std::string simple_logic::to_string_internal(bool& single) { single = true; if (oper_ == LOGIC_OPER_LEAF) return expr_; else if (oper_ == LOGIC_OPER_AND || oper_ == LOGIC_OPER_OR || oper_ == LOGIC_OPER_XOR) { std::string exp(""); if (l_) { exp = l_->to_string_internal(single); if (!single) { exp += ")"; exp.insert(0, "("); } } if (oper_ == LOGIC_OPER_AND) exp += " && "; else if (oper_ == LOGIC_OPER_OR) exp += " || "; else exp += " ^ "; if (r_) { bool s = false; std::string r(r_->to_string_internal(s)); if (!s) { r.insert(0, "("); r += ")"; } exp += r; } if (not_) { exp.insert(0, "!("); exp += ")"; single = true; } else single = false; return std::move(exp); } else return ""; } simple_logic& simple_logic::operator=(const simple_logic& r) { copy(r); return *this; } bool simple_logic::parse(const char* expr, int* end_pos, void(*leaf)(const char*, void*), void* leaf_param) { bool ret = false; clear(); if (strstr(expr, "||") == nullptr && strstr(expr, "&&") == nullptr && strstr(expr, "^") == nullptr) { oper_ = LOGIC_OPER_LEAF; expr_ = expr; ret = true; if (leaf) leaf(expr_.c_str(), leaf_param); } else { int end = 0; ret = parse_internal(expr, &end, leaf, leaf_param); if (end_pos) *end_pos = end; } return ret; } bool simple_logic::value(bool(*simple_expr_value)(const char*, void*), void* param) { if (oper_ == LOGIC_OPER_LEAF) return simple_expr_value(expr_.c_str(), param); else if (oper_ == LOGIC_OPER_AND) { bool ret = true; if (l_) ret = l_->value(simple_expr_value, param); if (ret && r_) ret &= r_->value(simple_expr_value, param); return ret ^ not_; } else if (oper_ == LOGIC_OPER_OR) { bool ret = false; if (l_) ret = l_->value(simple_expr_value, param); if (!ret && r_) ret = r_->value(simple_expr_value, param); return ret ^ not_; } else if (oper_ == LOGIC_OPER_XOR) { bool ret = false; if (l_) ret = l_->value(simple_expr_value, param); if (r_) ret ^= r_->value(simple_expr_value, param); return ret ^ not_; } else { return false; } } std::string simple_logic::to_expression(void) { bool single = false; return std::move(to_string_internal(single)); }