Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

expr_evaluator.cpp

00001 /*****************************************************************************
00002  * expr_evaluator.cpp
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: expr_evaluator.cpp 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Cyril Deguet     <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 #include "expr_evaluator.hpp"
00025 
00026 
00027 void ExprEvaluator::parse( const string &rExpr )
00028 {
00029     m_stack.clear();
00030 
00031     const char *pString = rExpr.c_str();
00032     list<string> opStack;   // operator stack
00033     string token;
00034 
00035     // Tokenize the expression
00036     int begin = 0, end = 0;
00037     while( pString[begin] )
00038     {
00039         // Find the next significant char in the string
00040         while( pString[begin] == ' ' )
00041         {
00042             begin++;
00043         }
00044 
00045         if( pString[begin] == '(' )
00046         {
00047             // '(' found: push it on the stack and continue
00048             opStack.push_back( "(" );
00049             begin++;
00050         }
00051         else if( pString[begin] == ')' )
00052         {
00053             // ')' found: pop the stack until a '(' is found
00054             while( !opStack.empty() )
00055             {
00056                 // Pop the stack
00057                 string lastOp = opStack.back();
00058                 opStack.pop_back();
00059                 if( lastOp == "(" )
00060                 {
00061                     break;
00062                 }
00063                 // Push the operator on the RPN stack
00064                 m_stack.push_back( lastOp );
00065             }
00066             begin++;
00067         }
00068         else
00069         {
00070             // Skip white spaces
00071             end = begin;
00072             while( pString[end] && pString[end] != ' ' && pString[end] != ')' )
00073             {
00074                 end++;
00075             }
00076             // Get the next token
00077             token = rExpr.substr( begin, end - begin );
00078             begin = end;
00079 
00080             // TODO compare to a set of operators
00081             if( token == "not" || token == "or" || token == "and" )
00082             {
00083                 // Pop the operator stack while the operator has a higher
00084                 // precedence than the top of the stack
00085                 while( !opStack.empty() &&
00086                        hasPrecedency( token, opStack.back() ) )
00087                 {
00088                     // Pop the stack
00089                     string lastOp = opStack.back();
00090                     opStack.pop_back();
00091                     m_stack.push_back( lastOp );
00092                 }
00093                 opStack.push_back( token );
00094             }
00095             else
00096             {
00097                 m_stack.push_back( token );
00098             }
00099         }
00100     }
00101     // Finish popping the operator stack
00102     while( !opStack.empty() )
00103     {
00104         string lastOp = opStack.back();
00105         opStack.pop_back();
00106         m_stack.push_back( lastOp );
00107     }
00108 }
00109 
00110 
00111 string ExprEvaluator::getToken()
00112 {
00113     if( !m_stack.empty() )
00114     {
00115         string token = m_stack.front();
00116         m_stack.pop_front();
00117         return token;
00118     }
00119     return "";
00120 }
00121 
00122 
00123 bool ExprEvaluator::hasPrecedency( const string &op1, const string &op2 ) const
00124 {
00125     // FIXME
00126     if( op1 == "(" )
00127     {
00128         return true;
00129     }
00130     if( op1 == "and" )
00131     {
00132         return (op2 == "or") || (op2 == "not" );
00133     }
00134     if( op1 == "or" )
00135     {
00136         return (op2 == "not" );
00137     }
00138     return false;
00139 }
00140 

Generated on Tue Dec 20 10:14:42 2005 for vlc-0.8.4a by  doxygen 1.4.2