diff --git a/inc/expression.hpp b/inc/expression.hpp index 1d431ba..caf4911 100644 --- a/inc/expression.hpp +++ b/inc/expression.hpp @@ -292,6 +292,43 @@ public: { return (o == SUB || o == DIV); } + + int is_math_op(void) const + { + if (t != OPERATOR) + { + return 0; + } + + switch (v.o) + { + case OPA: + case CPA: + return 0; + default: + return 1; + } + } + + int is_opa(void) const + { + if (t != OPERATOR) + { + return 0; + } + + return v.o == OPA; + } + + int is_cpa(void) const + { + if (t != OPERATOR) + { + return 0; + } + + return v.o == CPA; + } }; struct Operation diff --git a/src/syntaxer.cpp b/src/syntaxer.cpp index 632600e..1aaec88 100644 --- a/src/syntaxer.cpp +++ b/src/syntaxer.cpp @@ -9,6 +9,20 @@ namespace Syntax { +struct Range +{ + int start, finish; + + Range(void) + { + } + + Range(int start, int finish) + : start(start), finish(finish) + { + } +}; + static int add_bracket_to(std::vector& tv, const int location, const int direction); static int rank_op(const Expression::Token::Operator o) @@ -24,7 +38,7 @@ static int rank_op(const Expression::Token::Operator o) case Expression::Token::POW: return 2; default: - pr_warn("Operator is unrankable"); + //pr_warn("Operator is unrankable"); return -1; } } @@ -121,7 +135,7 @@ static void highlight_issue(const std::vector& tv, const int static int get_mop_location(const std::vector& v, int position) { int i = 0, l = v.size(), p = -1; - for (; p += v[i].t == Expression::Token::OPERATOR + for (; ({if (!(i < l)) return i;}), p += v[i].t == Expression::Token::OPERATOR && v[i].v.o != Expression::Token::OPA && v[i].v.o != Expression::Token::CPA, p != position; i++); return i; @@ -153,6 +167,44 @@ static int get_right_location(const std::vector& v, int locat return -1; } +static int max_rank(const std::vector &tv, const std::vector &mp, const Range &r, const int base_lv) +{ + int m = -1; + + for (int i = r.start; i <= r.finish; i++) + { + if (mp[i] != base_lv) + { + continue; + } + + int rank = rank_op(tv[get_mop_location(tv, i)].v.o); + + m = rank > m ? rank : m; + } + + return m; +} + +static int min_rank(const std::vector &tv, const std::vector &mp, const Range &r, const int base_lv) +{ + int m = 3; + + for (int i = r.start; i <= r.finish; i++) + { + if (mp[i] != base_lv) + { + continue; + } + + int rank = rank_op(tv[get_mop_location(tv, i)].v.o); + + m = rank < m ? rank : m; + } + + return m; +} + static int get_operator_weight(const std::vector& v, int location) { int weight = 0; @@ -487,16 +539,6 @@ static void find_top_prio_op_range(const std::vector& mp, int& start, int& } } -struct Range -{ - int start, finish; - - Range(int start, int finish) - : start(start), finish(finish) - { - } -}; - static void find_select_prio_op_ranges(const std::vector& mp, std::vector& ranges, int target_prio) { for (int i = 0, l = mp.size(), prio = 0, recording_range = 0; i < l; i++) @@ -517,15 +559,28 @@ static void find_select_prio_op_ranges(const std::vector& mp, std::vector& mp, int &p_start, int &p_finish, const int c_start, const int c_finish) +static void find_parent_level_range(const std::vector& tv, int &p_start, int &p_finish, const int c_start, const int c_finish) { // left side - for (int i = c_start; i >= 0; i--) + for (int i = get_mop_location(tv, c_start), p = c_start, lv = 0; i >= 0; i--) { - if (mp[i] < mp[c_start] - 1) + if (tv[i].is_opa()) { - p_start = i + 1; - goto right; + lv--; + + if (lv == -2) + { + p_start = p; + goto right; + } + } + else if (tv[i].is_math_op()) + { + p--; + } + else if (tv[i].is_cpa()) + { + lv++; } } @@ -533,16 +588,85 @@ static void find_parent_level_range(const std::vector& mp, int &p_start, in right: // right side - for (int i = c_finish; i < mp.size(); i++) + int i, p, lv; + for (i = get_mop_location(tv, c_finish), p = c_finish, lv = 0; i < tv.size(); i++) { - if (mp[i] < mp[c_finish] - 1) + if (tv[i].is_cpa()) { - p_finish = i + 1; - break; + lv--; + + if (lv == -2) + { + p_finish = p; + break; + } + } + else if (tv[i].is_math_op()) + { + p++; + } + else if (tv[i].is_opa()) + { + lv++; } } - p_finish = mp.size() - 1; + p_finish = p - 1; +} + +static void find_parent_level_range(const std::vector& tv, Range &p, const Range &c) +{ + // left side + for (int i = get_mop_location(tv, c.start), pc = c.start, lv = 0; i >= 0; i--) + { + if (tv[i].is_opa()) + { + lv--; + + if (lv == -2) + { + p.start = pc; + goto right; + } + } + else if (tv[i].is_math_op()) + { + pc--; + } + else if (tv[i].is_cpa()) + { + lv++; + } + } + + p.start = 0; + +right: + // right side + int i, pc, lv; + for (i = get_mop_location(tv, c.finish), pc = c.finish, lv = 0; i < tv.size(); i++) + { + if (tv[i].is_cpa()) + { + lv--; + + if (lv == -2) + { + p.finish = pc; + break; + } + } + else if (tv[i].is_math_op()) + { + pc++; + } + else if (tv[i].is_opa()) + { + lv++; + } + } + + p.finish = pc - 1; } static void rank_inner_ops_raw(std::vector& inner_op_ranks, const std::vector& mv, const int start, const int finish, const int same_lvl_only = 0) @@ -648,7 +772,7 @@ static void weight_operators(std::vector& operator_weights, const std::vect } } -static int same_inner_level_ops(const std::vector& tv, const std::vector &mp, const Range &r, const int outer_lvl) +static int same_rank_ops(const std::vector& tv, const std::vector &mp, const Range &r, const int outer_lvl) { int first_op_inner_level = rank_op(tv[get_mop_location(tv, r.start)].v.o); @@ -738,6 +862,46 @@ static void open_brackets(std::vector& tv, const Range &r) tv.erase(tv.begin() + brackets.start); } +static int get_max_neighbour_rank(const std::vector& tv, const Range &r) +{ + int rank = -1; + + // left neighbour + //if (r.start - 1 >= 0) + //if () + //{ + int left_bracket = same_lvl_opa_location(tv, get_mop_location(tv, r.start)); + //if (int ro = rank_op(tv[get_mop_location(tv, r.start - 1)].v.o); ro > rank) + if (left_bracket - 1 >= 0) + { + if (int ro = rank_op(tv[left_bracket - 1].v.o); ro > rank) + { + rank = ro; + } + } + //} + + // right neighbour + //if (int rl = get_mop_location(tv, r.finish + 1); rl < tv.size()) + //{ + // if (int ro = rank_op(tv[rl].v.o); ro > rank) + // { + // rank = ro; + // } + //} + + int right_bracket = same_lvl_cpa_location(tv, get_mop_location(tv, r.finish)); + if (right_bracket + 1 < tv.size()) + { + if (int ro = rank_op(tv[right_bracket + 1].v.o); ro > rank) + { + rank = ro; + } + } + + return rank; +} + static void remove_extra_brackets(std::vector& tv) { pr_debug("Processing: removing extra brackets"); @@ -762,25 +926,38 @@ static void remove_extra_brackets(std::vector& tv) find_select_prio_op_ranges(mp, ranges, current_prio); const Range &r = ranges[r_no]; + int max_child_rank = max_rank(tv, mp, r, current_prio); - if (same_inner_level_ops(tv, mp, r, current_prio)) { + // extra logging + pr_debug("Considering option:"); + std::vector hl; + hl.emplace_back(get_mop_location(tv, r.start)); + hl.emplace_back(get_mop_location(tv, r.finish)); + Parser::print_math_vector(tv, hl); + } + + Range parent_r; + find_parent_level_range(tv, parent_r, r); + int max_parent_rank = max_rank(tv, mp, parent_r, current_prio); + + if (max_parent_rank > max_child_rank) + { + pr_debug("Fails in rank comp: parent=" << max_parent_rank << " > child=" << max_child_rank); continue; } - int ps, pf; - find_parent_level_range(mp, ps, pf, r.start, r.finish); - - const Range parent_r(ps, pf); - - if (same_inner_level_ops(tv, mp, parent_r, current_prio - 1)) + int min_child_rank = min_rank(tv, mp, r, current_prio); + if (int nr = get_max_neighbour_rank(tv, r); nr > min_child_rank) { + pr_debug("Fails in neighbour rank: max_neighbour=" << nr << " > min_child=" << min_child_rank); continue; } // check specifically if the opening undoes applied fixes if (Expression::Token::is_negative(get_prior_mop(tv, get_mop_location(tv, r.start)))) { + pr_debug("Fails in prior mop is_negative"); continue; }