expr_evaluator.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:4k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * expr_evaluator.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: 14f4359f64d36288a65b813fd2099f56726d2367 $
  6.  *
  7.  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. #include "expr_evaluator.hpp"
  24. void ExprEvaluator::parse( const string &rExpr )
  25. {
  26.     m_stack.clear();
  27.     const char *pString = rExpr.c_str();
  28.     list<string> opStack;   // operator stack
  29.     string token;
  30.     // Tokenize the expression
  31.     int begin = 0, end = 0;
  32.     while( pString[begin] )
  33.     {
  34.         // Find the next significant char in the string
  35.         while( pString[begin] == ' ' )
  36.         {
  37.             begin++;
  38.         }
  39.         if( pString[begin] == '(' )
  40.         {
  41.             // '(' found: push it on the stack and continue
  42.             opStack.push_back( "(" );
  43.             begin++;
  44.         }
  45.         else if( pString[begin] == ')' )
  46.         {
  47.             // ')' found: pop the stack until a '(' is found
  48.             while( !opStack.empty() )
  49.             {
  50.                 // Pop the stack
  51.                 string lastOp = opStack.back();
  52.                 opStack.pop_back();
  53.                 if( lastOp == "(" )
  54.                 {
  55.                     break;
  56.                 }
  57.                 // Push the operator on the RPN stack
  58.                 m_stack.push_back( lastOp );
  59.             }
  60.             begin++;
  61.         }
  62.         else
  63.         {
  64.             // Skip white spaces
  65.             end = begin;
  66.             while( pString[end] && pString[end] != ' ' && pString[end] != ')' )
  67.             {
  68.                 end++;
  69.             }
  70.             // Get the next token
  71.             token = rExpr.substr( begin, end - begin );
  72.             begin = end;
  73.             // TODO compare to a set of operators
  74.             if( token == "not" || token == "or" || token == "and" )
  75.             {
  76.                 // Pop the operator stack while the operator has a higher
  77.                 // precedence than the top of the stack
  78.                 while( !opStack.empty() &&
  79.                        hasPrecedency( token, opStack.back() ) )
  80.                 {
  81.                     // Pop the stack
  82.                     string lastOp = opStack.back();
  83.                     opStack.pop_back();
  84.                     m_stack.push_back( lastOp );
  85.                 }
  86.                 opStack.push_back( token );
  87.             }
  88.             else
  89.             {
  90.                 m_stack.push_back( token );
  91.             }
  92.         }
  93.     }
  94.     // Finish popping the operator stack
  95.     while( !opStack.empty() )
  96.     {
  97.         string lastOp = opStack.back();
  98.         opStack.pop_back();
  99.         m_stack.push_back( lastOp );
  100.     }
  101. }
  102. string ExprEvaluator::getToken()
  103. {
  104.     if( !m_stack.empty() )
  105.     {
  106.         string token = m_stack.front();
  107.         m_stack.pop_front();
  108.         return token;
  109.     }
  110.     return "";
  111. }
  112. bool ExprEvaluator::hasPrecedency( const string &op1, const string &op2 ) const
  113. {
  114.     // FIXME
  115.     if( op1 == "(" )
  116.     {
  117.         return true;
  118.     }
  119.     if( op1 == "and" )
  120.     {
  121.         return (op2 == "or") || (op2 == "not" );
  122.     }
  123.     if( op1 == "or" )
  124.     {
  125.         return (op2 == "not" );
  126.     }
  127.     return false;
  128. }