You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-30 07:25:34 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			657 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			657 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright (C) 2014 InfiniDB, Inc.
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU General Public License
 | |
|    as published by the Free Software Foundation; version 2 of
 | |
|    the License.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program; if not, write to the Free Software
 | |
|    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | |
|    MA 02110-1301, USA. */
 | |
| 
 | |
| /***********************************************************************
 | |
|  *   $Id: exp_templates.h 9210 2013-01-21 14:10:42Z rdempsey $
 | |
|  *
 | |
|  *
 | |
|  ***********************************************************************/
 | |
| /** @file */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <iostream>
 | |
| #include <fstream>
 | |
| #include <stack>
 | |
| #include <stdexcept>
 | |
| #include <cassert>
 | |
| #include <string>
 | |
| #include <iterator>
 | |
| //#include <parsetree.h>
 | |
| 
 | |
| namespace expression
 | |
| {
 | |
| enum precedence
 | |
| {
 | |
|   none,
 | |
|   lower,
 | |
|   equal,
 | |
|   higher
 | |
| };
 | |
| 
 | |
| struct not_an_acceptor_tag
 | |
| {
 | |
| };
 | |
| struct acceptor_tag
 | |
| {
 | |
| };
 | |
| struct accumulating_acceptor_tag
 | |
| {
 | |
| };
 | |
| 
 | |
| template <typename Acceptor>
 | |
| struct acceptor_traits
 | |
| {
 | |
|   typedef typename Acceptor::acceptor_category acceptor_category;
 | |
|   typedef typename Acceptor::input_symbol_type input_symbol_type;
 | |
|   typedef typename Acceptor::result_type result_type;
 | |
| };
 | |
| 
 | |
| // Constants indicating possible operator placements. An incoming operator
 | |
| // may be ambiguous so its position will be the bitwise or of several of
 | |
| // these positions.
 | |
| const int prefix = 0x01;
 | |
| const int postfix = 0x02;
 | |
| const int infix = 0x04;
 | |
| const int open = 0x08;
 | |
| const int close = 0x10;
 | |
| const int function_open = 0x20;
 | |
| const int function_close = close;
 | |
| 
 | |
| enum associativity
 | |
| {
 | |
|   non_associative,
 | |
|   left_associative,
 | |
|   right_associative
 | |
| };
 | |
| 
 | |
| struct default_expression_parser_error_policy
 | |
| {
 | |
|   template <typename Operand>
 | |
|   void invalid_operand_position(Operand)
 | |
|   {
 | |
|     std::cerr << "Invalid operand position\n";
 | |
|   }
 | |
| 
 | |
|   template <typename Operator>
 | |
|   void invalid_operator_position(Operator)
 | |
|   {
 | |
|     std::cerr << "Invalid operator position\n";
 | |
|   }
 | |
| 
 | |
|   template <typename Operator>
 | |
|   void requires_precedence_relation(Operator, Operator)
 | |
|   {
 | |
|     std::cerr << "Requires precedence relation\n";
 | |
|   }
 | |
| 
 | |
|   template <typename Operator>
 | |
|   void requires_associativity_relation(Operator, Operator)
 | |
|   {
 | |
|     std::cerr << "Requires associativity relation\n";
 | |
|   }
 | |
| 
 | |
|   template <typename Operator>
 | |
|   void ambiguity(Operator, Operator)
 | |
|   {
 | |
|     std::cerr << "Unresolvable ambiguity\n";
 | |
|   }
 | |
| 
 | |
|   template <typename Operator>
 | |
|   void unbalanced_confix(Operator)
 | |
|   {
 | |
|     std::cerr << "Unbalanced confix operator\n";
 | |
|   }
 | |
| 
 | |
|   template <typename Operator>
 | |
|   void missing_operand(Operator)
 | |
|   {
 | |
|     std::cerr << "Missing operand\n";
 | |
|   }
 | |
| };
 | |
| 
 | |
| #define EXP_TEMPLATE                                                                                     \
 | |
|   template <typename Token, typename Operand, typename Operator, typename Policy, typename OperandStack, \
 | |
|             typename OperatorStack>
 | |
| 
 | |
| #define EXP_ACCEPTOR expression_acceptor<Token, Operand, Operator, Policy, OperandStack, OperatorStack>
 | |
| 
 | |
| namespace detail
 | |
| {
 | |
| enum action
 | |
| {
 | |
|   shift,
 | |
|   reduce,
 | |
|   prec,
 | |
|   prec_assoc,
 | |
|   invalid
 | |
| };
 | |
| 
 | |
| // Current larser state
 | |
| enum state
 | |
| {
 | |
|   accepting,
 | |
|   rejected,
 | |
|   pre_operand,
 | |
|   post_operand,
 | |
|   lookahead
 | |
| };
 | |
| 
 | |
| // The operator placements that are allowed for each state
 | |
| const int pre_positions = prefix | open;
 | |
| const int post_positions = postfix | close | infix | function_open;
 | |
| 
 | |
| const action parse_action[6][6] = {
 | |
|     /* prefix   postfix infix       open    close   func open */
 | |
|     /* prefix    */ {shift, prec, prec, shift, reduce, prec},
 | |
|     /* postfix   */ {invalid, reduce, reduce, reduce, reduce, reduce},
 | |
|     /* infix     */ {shift, prec, prec_assoc, shift, reduce, prec},
 | |
|     /* open      */ {shift, shift, shift, shift, shift, shift},
 | |
|     /* close     */ {reduce, reduce, reduce, reduce, reduce, reduce},
 | |
|     /* func open */ {shift, shift, shift, shift, shift, shift}};
 | |
| 
 | |
| template <typename Token, typename Operand, typename Operator, typename Policy,
 | |
|           typename OperandStack = std::stack<Operand>, typename OperatorStack = std::stack<Operator> >
 | |
| class expression_acceptor
 | |
| {
 | |
|  private:
 | |
|   class assignment_proxy
 | |
|   {
 | |
|    public:
 | |
|     explicit assignment_proxy(expression_acceptor* acceptor) : m_expression_acceptor(acceptor)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     assignment_proxy& operator=(const Token& t)
 | |
|     {
 | |
|       m_expression_acceptor->disambiguate_and_parse(t);
 | |
|       return *this;
 | |
|     }
 | |
| 
 | |
|    private:
 | |
|     expression_acceptor* m_expression_acceptor;
 | |
|   };
 | |
| 
 | |
|   friend class assignment_proxy;
 | |
| 
 | |
|  public:
 | |
|   typedef accumulating_acceptor_tag acceptor_category;
 | |
|   typedef Token input_symbol_type;
 | |
|   typedef Operand result_type;
 | |
|   typedef std::output_iterator_tag iterator_category;
 | |
|   typedef Token value_type;
 | |
|   typedef Token& reference;
 | |
|   typedef Token* pointer;
 | |
|   typedef int difference_type;
 | |
| 
 | |
|   explicit expression_acceptor(const Policy& policy, OperandStack& operandStack, OperatorStack& operatorStack)
 | |
|    : m_policy(policy)
 | |
|    , m_operand_stack(operandStack)
 | |
|    , m_operator_stack(operatorStack)
 | |
|    , m_state(detail::pre_operand)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   assignment_proxy operator*()
 | |
|   {
 | |
|     return assignment_proxy(this);
 | |
|   }
 | |
|   expression_acceptor& operator++()
 | |
|   {
 | |
|     return *this;
 | |
|   }
 | |
|   expression_acceptor& operator++(int)
 | |
|   {
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   bool accepted();
 | |
|   bool trapped()
 | |
|   {
 | |
|     return m_state == rejected;
 | |
|   }
 | |
| 
 | |
|   operator Operand()
 | |
|   {
 | |
|     return this->accepted() ? m_operand_stack.top() : Operand();
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   void disambiguate_and_parse(const Token&);
 | |
|   int operator_type_index(int);
 | |
|   void parse_operator(const Operator&);
 | |
|   void do_reduce();
 | |
| 
 | |
|  private:
 | |
|   Policy m_policy;
 | |
|   OperandStack& m_operand_stack;    // changed to reference by Zhixuan Zhu
 | |
|   OperatorStack& m_operator_stack;  // changed to reference by Zhixuan Zhu
 | |
|   state m_state;
 | |
|   Token m_ambiguous_operator;
 | |
| };
 | |
| 
 | |
| EXP_TEMPLATE
 | |
| bool EXP_ACCEPTOR::accepted()
 | |
| {
 | |
|   if (m_state == accepting)
 | |
|   {
 | |
|     return true;
 | |
|   }
 | |
|   else if (m_state == rejected)
 | |
|   {
 | |
|     return false;
 | |
|   }
 | |
|   else if (m_state == lookahead)
 | |
|   {
 | |
|     m_state = post_operand;
 | |
|     int position = m_policy.positions(m_ambiguous_operator);
 | |
|     parse_operator(m_policy.as_operator(m_ambiguous_operator, position & (postfix | close)));
 | |
|   }
 | |
| 
 | |
|   while (!m_operator_stack.empty() && m_state != rejected)
 | |
|   {
 | |
|     do_reduce();
 | |
|   }
 | |
| 
 | |
|   if (m_state == rejected)
 | |
|   {
 | |
|     return false;
 | |
|   }
 | |
|   else if (m_operand_stack.size() > 1 || !m_operator_stack.empty())
 | |
|   {
 | |
|     m_state = rejected;
 | |
|     return false;
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     m_state = accepting;
 | |
|     return true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| EXP_TEMPLATE
 | |
| void EXP_ACCEPTOR::disambiguate_and_parse(const Token& t)
 | |
| {
 | |
|   assert(m_state != accepting);
 | |
| 
 | |
|   if (m_state == rejected)
 | |
|     return;
 | |
| 
 | |
|   if (m_policy.is_operator(t))
 | |
|   {
 | |
|     int operator_positions = m_policy.positions(t);
 | |
| 
 | |
|     if (m_state == lookahead)
 | |
|     {
 | |
|       bool could_be_pre = ((operator_positions & pre_positions) != 0);
 | |
|       bool could_be_post = ((operator_positions & post_positions) != 0);
 | |
| 
 | |
|       int ambiguous_position = m_policy.positions(m_ambiguous_operator);
 | |
| 
 | |
|       if ((could_be_pre && could_be_post) || (!could_be_pre && !could_be_post))
 | |
|       {
 | |
|         m_policy.ambiguity(m_ambiguous_operator, t);
 | |
|         m_state = rejected;
 | |
|         return;
 | |
|       }
 | |
|       else if (could_be_pre)
 | |
|       {
 | |
|         ambiguous_position &= (infix | function_open);
 | |
|         parse_operator(m_policy.as_operator(m_ambiguous_operator, ambiguous_position));
 | |
|         m_state = pre_operand;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         ambiguous_position &= (postfix | close);
 | |
|         parse_operator(m_policy.as_operator(m_ambiguous_operator, ambiguous_position));
 | |
|         m_state = post_operand;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     int valid_positions = (m_state == pre_operand) ? pre_positions : post_positions;
 | |
| 
 | |
|     int positions = operator_positions & valid_positions;
 | |
| 
 | |
|     switch (positions)
 | |
|     {
 | |
|       case infix:
 | |
|       case function_open: m_state = pre_operand;
 | |
| 
 | |
|       // Fall through
 | |
|       case prefix:
 | |
|       case postfix:
 | |
|       case open:
 | |
|       case close: parse_operator(m_policy.as_operator(t, positions)); break;
 | |
| 
 | |
|       case postfix | infix:
 | |
|       case close | infix:
 | |
|       case postfix | function_open:
 | |
|       case function_open | function_close:
 | |
|         m_state = lookahead;
 | |
|         m_ambiguous_operator = t;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         m_policy.invalid_operator_position(t);
 | |
|         m_state = rejected;
 | |
|         return;
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (m_state == lookahead)
 | |
|     {
 | |
|       int positions = m_policy.positions(m_ambiguous_operator);
 | |
|       positions &= (infix | function_open);
 | |
|       parse_operator(m_policy.as_operator(m_ambiguous_operator, positions));
 | |
|       m_state = post_operand;
 | |
|     }
 | |
|     else if (m_state == post_operand)
 | |
|     {
 | |
|       m_policy.invalid_operand_position(m_policy.as_operand(t));
 | |
|       m_state = rejected;
 | |
|       return;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       m_state = post_operand;
 | |
|     }
 | |
| 
 | |
|     m_operand_stack.push(m_policy.as_operand(t));
 | |
|   }
 | |
| }
 | |
| 
 | |
| EXP_TEMPLATE
 | |
| inline int EXP_ACCEPTOR::operator_type_index(int position)
 | |
| {
 | |
|   switch (position)
 | |
|   {
 | |
|     case prefix: return 0;
 | |
| 
 | |
|     case postfix: return 1;
 | |
| 
 | |
|     case infix: return 2;
 | |
| 
 | |
|     case open: return 3;
 | |
| 
 | |
|     case close: return 4;
 | |
| 
 | |
|     case function_open: return 5;
 | |
|   }
 | |
| 
 | |
|   assert(0);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| EXP_TEMPLATE
 | |
| void EXP_ACCEPTOR::parse_operator(const Operator& cur_operator)
 | |
| {
 | |
|   if (m_operator_stack.empty())
 | |
|   {
 | |
|     m_operator_stack.push(cur_operator);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     int cur_index = operator_type_index(m_policy.position(cur_operator));
 | |
| 
 | |
|     Operator& prev_operator = m_operator_stack.top();
 | |
|     int prev_index = operator_type_index(m_policy.position(prev_operator));
 | |
| 
 | |
|     switch (parse_action[prev_index][cur_index])
 | |
|     {
 | |
|       case shift: m_operator_stack.push(cur_operator); break;
 | |
| 
 | |
|       case reduce:
 | |
|         do_reduce();
 | |
|         parse_operator(cur_operator);
 | |
|         break;
 | |
| 
 | |
|       case prec:
 | |
|         switch (m_policy.precedence(prev_operator, cur_operator))
 | |
|         {
 | |
|           case lower: m_operator_stack.push(cur_operator); break;
 | |
| 
 | |
|           case higher:
 | |
|             do_reduce();
 | |
|             parse_operator(cur_operator);
 | |
|             break;
 | |
| 
 | |
|           default:
 | |
|             m_policy.requires_precedence_relation(prev_operator, cur_operator);
 | |
|             m_state = rejected;
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case prec_assoc:
 | |
|         switch (m_policy.precedence(prev_operator, cur_operator))
 | |
|         {
 | |
|           case lower: m_operator_stack.push(cur_operator); break;
 | |
| 
 | |
|           case higher:
 | |
|             do_reduce();
 | |
|             parse_operator(cur_operator);
 | |
|             break;
 | |
| 
 | |
|           case equal:
 | |
|             switch (m_policy.associativity(prev_operator, cur_operator))
 | |
|             {
 | |
|               case left_associative:
 | |
|                 do_reduce();
 | |
|                 parse_operator(cur_operator);
 | |
|                 break;
 | |
| 
 | |
|               case right_associative: m_operator_stack.push(cur_operator); break;
 | |
| 
 | |
|               default:
 | |
|                 m_policy.requires_associativity_relation(prev_operator, cur_operator);
 | |
|                 m_state = rejected;
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             break;
 | |
| 
 | |
|           default:
 | |
|             m_policy.requires_precedence_relation(prev_operator, cur_operator);
 | |
|             m_state = rejected;
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case invalid:
 | |
|         m_policy.invalid_operator_position(cur_operator);
 | |
|         m_state = rejected;
 | |
|         return;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| EXP_TEMPLATE
 | |
| void EXP_ACCEPTOR::do_reduce()
 | |
| {
 | |
|   Operator op = m_operator_stack.top();
 | |
|   m_operator_stack.pop();
 | |
| 
 | |
|   switch (m_policy.position(op))
 | |
|   {
 | |
|     case prefix:
 | |
|     case postfix:
 | |
|     {
 | |
|       if (m_operand_stack.empty())
 | |
|       {
 | |
|         m_policy.missing_operand(op);
 | |
|         m_state = rejected;
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       Operand operand = m_operand_stack.top();
 | |
|       m_operand_stack.pop();
 | |
| 
 | |
|       m_operand_stack.push(m_policy.reduce(op, operand));
 | |
|     }
 | |
|     break;
 | |
| 
 | |
|     case infix:
 | |
|     {
 | |
|       if (m_operand_stack.size() < 2)
 | |
|       {
 | |
|         m_policy.missing_operand(op);
 | |
|         m_state = rejected;
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       Operand rhs = m_operand_stack.top();
 | |
|       m_operand_stack.pop();
 | |
| 
 | |
|       Operand lhs = m_operand_stack.top();
 | |
|       m_operand_stack.pop();
 | |
| 
 | |
|       m_operand_stack.push(m_policy.reduce(op, lhs, rhs));
 | |
|     }
 | |
|     break;
 | |
| 
 | |
|     case open:
 | |
|       m_policy.unbalanced_confix(op);
 | |
|       m_state = rejected;
 | |
|       return;
 | |
| 
 | |
|     case close:
 | |
|       if (m_operator_stack.empty())
 | |
|       {
 | |
|         m_policy.unbalanced_confix(op);
 | |
|         m_state = rejected;
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       if (m_operand_stack.empty())
 | |
|       {
 | |
|         m_policy.missing_operand(op);
 | |
|         m_state = rejected;
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       {
 | |
|         Operator open = m_operator_stack.top();
 | |
|         m_operator_stack.pop();
 | |
| 
 | |
|         Operand operand = m_operand_stack.top();
 | |
|         m_operand_stack.pop();
 | |
| 
 | |
|         if (m_policy.position(open) == function_open)
 | |
|         {
 | |
|           if (m_operand_stack.empty())
 | |
|           {
 | |
|             m_policy.missing_operand(open);
 | |
|             m_state = rejected;
 | |
|             return;
 | |
|           }
 | |
| 
 | |
|           Operand function = m_operand_stack.top();
 | |
|           m_operand_stack.pop();
 | |
| 
 | |
|           m_operand_stack.push(m_policy.reduce(function, open, operand, op));
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           m_operand_stack.push(m_policy.reduce(open, op, operand));
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       return;
 | |
| 
 | |
|     default: assert(0);
 | |
|   }
 | |
| }
 | |
| }  // namespace detail
 | |
| 
 | |
| EXP_TEMPLATE
 | |
| inline bool accepted(const detail::EXP_ACCEPTOR& acceptor)
 | |
| {
 | |
|   return acceptor.accepted();
 | |
| }
 | |
| 
 | |
| EXP_TEMPLATE
 | |
| inline bool trapped(const detail::EXP_ACCEPTOR& acceptor)
 | |
| {
 | |
|   return acceptor.trapped();
 | |
| }
 | |
| 
 | |
| template <typename Token, typename Operand, typename Operator, typename Policy,
 | |
|           typename OperandStack = std::stack<Operand>, typename OperatorStack = std::stack<Operator> >
 | |
| class expression_parser
 | |
| {
 | |
|  public:
 | |
|   typedef detail::EXP_ACCEPTOR acceptor;
 | |
|   typedef Token token_type;
 | |
|   typedef Operand operand_type;
 | |
|   typedef Operator operator_type;
 | |
|   typedef Policy policy_type;
 | |
|   typedef Token input_symbol_type;
 | |
|   typedef Operand result_type;
 | |
| 
 | |
|   expression_parser() : m_policy()
 | |
|   {
 | |
|   }
 | |
|   explicit expression_parser(const Policy& policy) : m_policy(policy)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   template <typename InputIterator>
 | |
|   Operand parse(InputIterator first, InputIterator last)
 | |
|   {
 | |
|     try
 | |
|     {
 | |
|       return std::copy(first, last, start());
 | |
|     }
 | |
|     catch (const std::runtime_error&)
 | |
|     {
 | |
|       m_policy.cleanup(operandStack, operatorStack);
 | |
|       throw;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   acceptor start()
 | |
|   {
 | |
|     // pass in operator and operand stacks to acceptor constructor.
 | |
|     // this is to chean up the pointers in the stack when exception
 | |
|     // is thrown. the exception is then passed to the upper level.
 | |
|     // changed by Zhixuan Zhu 07/03/06
 | |
|     try
 | |
|     {
 | |
|       return acceptor(m_policy, operandStack, operatorStack);
 | |
|     }
 | |
|     catch (const std::runtime_error&)
 | |
|     {
 | |
|       m_policy.cleanup(operandStack, operatorStack);
 | |
|       throw;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   Policy m_policy;
 | |
| 
 | |
|   // added operand and operator stacks by Zhixuan Zhu
 | |
|   OperandStack operandStack;
 | |
|   OperatorStack operatorStack;
 | |
| };
 | |
| 
 | |
| #undef EXP_ACCEPTOR
 | |
| #undef EXP_TEMPLATE
 | |
| }  // namespace expression
 |