O_Egor

condition_parser.cpp

Oct 15th, 2022
672
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.96 KB | None | 0 0
  1. #include "condition_parser.h"
  2. #include "token.h"
  3.  
  4. #include <map>
  5. using namespace std;
  6.  
  7. template <class It> shared_ptr<Node> ParseComparison(It& current, It end)
  8. {
  9.     if (current == end)
  10.     {
  11.         throw logic_error("Expected column name: date or event");
  12.     }
  13.     // [{"event", COLUMN}, {"==", COMPARE_OP}, {"sport event", EVENT}]
  14.     Token& column = *current; //{"event", COLUMN}
  15.     if (column.type != TokenType::COLUMN)
  16.     {
  17.         throw logic_error("Expected column name: date or event");
  18.     }
  19.     ++current;
  20.  
  21.     if (current == end)
  22.     {
  23.         throw logic_error("Expected comparison operation");
  24.     }
  25.  
  26.     Token& op = *current;//{"==", COMPARE_OP}
  27.     if (op.type != TokenType::COMPARE_OP)
  28.     {
  29.         throw logic_error("Expected comparison operation");
  30.     }
  31.     ++current;// {"sport event", EVENT}
  32.  
  33.     if (current == end)
  34.     {
  35.         throw logic_error("Expected right value of comparison");
  36.     }
  37.  
  38.     Comparison cmp;
  39.     if (op.value == "<")
  40.     {
  41.         cmp = Comparison::Less;
  42.     }
  43.     else if (op.value == "<=")
  44.     {
  45.         cmp = Comparison::LessOrEqual;
  46.     }
  47.     else if (op.value == ">")
  48.     {
  49.         cmp = Comparison::Greater;
  50.     }
  51.     else if (op.value == ">=")
  52.     {
  53.         cmp = Comparison::GreaterOrEqual;
  54.     }
  55.     else if (op.value == "==")
  56.     {
  57.         cmp = Comparison::Equal;
  58.     }
  59.     else if (op.value == "!=")
  60.     {
  61.         cmp = Comparison::NotEqual;
  62.     }
  63.     else
  64.     {
  65.         throw logic_error("Unknown comparison token: " + op.value);
  66.     }
  67.  
  68.     const string& value = current->value;//"sport event"
  69.     ++current;
  70.  
  71.     if (column.value == "date")
  72.     {
  73.         istringstream is(value);
  74.         return make_shared<DateComparisonNode>(cmp, ParseDate(is));
  75.     }
  76.     else
  77.     {
  78.         return make_shared<EventComparisonNode>(cmp, value);//Comparison::Equal, "sport event"
  79.     }
  80. }
  81.  
  82. template <class It>
  83. shared_ptr<Node> ParseExpression(It& current, It end, unsigned precedence)
  84. {
  85.     if (current == end)
  86.     {
  87.         return shared_ptr<Node>();
  88.     }
  89.  
  90.     shared_ptr<Node> left;
  91.  
  92.     if (current->type == TokenType::PAREN_LEFT)
  93.     {
  94.         ++current; // consume '('
  95.         left = ParseExpression(current, end, 0u);
  96.         if (current == end || current->type != TokenType::PAREN_RIGHT)
  97.         {
  98.             throw logic_error("Missing right paren");
  99.         }
  100.         ++current; // consume ')'
  101.     }
  102.     else
  103.     {
  104.         left = ParseComparison(current, end);//Comparison::Equal, "sport event"
  105.     }
  106.  
  107.     const map<LogicalOperation, unsigned> precedences =
  108.     {
  109.         {LogicalOperation::Or, 1}, {LogicalOperation::And, 2}
  110.     };
  111.  
  112.     while (current != end && current->type != TokenType::PAREN_RIGHT)
  113.     {
  114.         if (current->type != TokenType::LOGICAL_OP)
  115.         {
  116.             throw logic_error("Expected logic operation");
  117.         }
  118.  
  119.         const auto logical_operation = current->value == "AND" ? LogicalOperation::And
  120.             : LogicalOperation::Or;
  121.         const auto current_precedence = precedences.at(logical_operation);
  122.         if (current_precedence <= precedence)
  123.         {
  124.             break;
  125.         }
  126.  
  127.         ++current; // consume op
  128.  
  129.         left = make_shared<LogicalOperationNode>(
  130.             logical_operation, left, ParseExpression(current, end, current_precedence)
  131.             );
  132.     }
  133.  
  134.     return left;//Comparison::Equal, "sport event"
  135. }
  136.  
  137. shared_ptr<Node> ParseCondition(istream& is) //event == "sport event"
  138. {
  139.     auto tokens = Tokenize(is);// [{"event", COLUMN}, {"==", COMPARE_OP}, {"sport event", EVENT}]
  140.     auto current = tokens.begin();
  141.     auto top_node = ParseExpression(current, tokens.end(), 0u);//Comparison::Equal, "sport event"
  142.  
  143.     if (!top_node)
  144.     {
  145.         top_node = make_shared<EmptyNode>();
  146.     }
  147.  
  148.     if (current != tokens.end())
  149.     {
  150.         throw logic_error("Unexpected tokens after condition");
  151.     }
  152.  
  153.     return top_node;//Comparison::Equal, "sport event"
  154. }
Advertisement
Add Comment
Please, Sign In to add comment