You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +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
 |