File indexing completed on 2024-05-19 04:49:16

0001 /****************************************************************************************
0002  * Copyright (c) 2006 Gbor Lehel <illissius@gmail.com>                                  *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #include "Expression.h"
0018 #include "core/support/Debug.h"
0019 
0020 ExpressionParser::ExpressionParser( const QString &expression )
0021     : m_expression( expression )
0022     , m_state( ExpectMinus )
0023     , m_haveGroup( false )
0024     , m_inQuote( false )
0025     , m_inOrGroup( false )
0026 { }
0027 
0028 ParsedExpression ExpressionParser::parse()
0029 {
0030     const uint length = m_expression.length();
0031     for( uint pos = 0; pos < length; ++pos )
0032         parseChar( m_expression.at( pos ) );
0033     finishedToken();
0034     finishedOrGroup();
0035 
0036     return m_parsed;
0037 }
0038 
0039 ParsedExpression ExpressionParser::parse( const QString &expression ) //static
0040 {
0041     ExpressionParser p( expression );
0042     return p.parse();
0043 }
0044 
0045 bool ExpressionParser::isAdvancedExpression( const QString &expression ) //static
0046 {
0047     return ( expression.contains( '"'   ) ||
0048              expression.contains( ':'   ) ||
0049              expression.contains( '-'   ) ||
0050              expression.contains( QLatin1String("AND") ) ||
0051              expression.contains( QLatin1String("OR")  ) );
0052 }
0053 
0054 /* PRIVATE */
0055 
0056 void ExpressionParser::parseChar( const QChar &c )
0057 {
0058     if( m_inQuote && c != '"' )
0059         m_string += c;
0060     else if( c.isSpace() )
0061         handleSpace( c );
0062     else if( c == '-' )
0063         handleMinus( c );
0064     else if( c == ':' )
0065         handleColon( c );
0066     else if( c == '=' || c == '>' || c == '<' )
0067         handleMod( c );
0068     else if( c == '"' )
0069         handleQuote( c );
0070     else
0071         handleChar( c );
0072 }
0073 
0074 void ExpressionParser::handleSpace( const QChar& )
0075 {
0076     if( m_state > ExpectMinus )
0077         finishedToken();
0078 }
0079 
0080 void ExpressionParser::handleMinus( const QChar &c )
0081 {
0082     if( m_state == ExpectMinus )
0083     {
0084         m_element.negate = true;
0085         m_state = ExpectField;
0086     }
0087     else
0088         handleChar( c );
0089 }
0090 
0091 void ExpressionParser::handleColon( const QChar &c )
0092 {
0093     if( m_state <= ExpectField && !m_string.isEmpty() )
0094     {
0095         m_element.field = m_string;
0096         m_string.clear();
0097         m_state = ExpectMod;
0098     }
0099     else
0100         handleChar( c );
0101 }
0102 
0103 void ExpressionParser::handleMod( const QChar &c )
0104 {
0105     if( m_state == ExpectMod )
0106     {
0107         if( c == '=' )
0108             m_element.match = expression_element::Equals;
0109         else if( c == '>' )
0110             m_element.match = expression_element::More;
0111         else if( c == '<' )
0112             m_element.match = expression_element::Less;
0113         m_state = ExpectText;
0114     }
0115     else
0116         handleChar( c );
0117 }
0118 
0119 void ExpressionParser::handleQuote( const QChar& )
0120 {
0121     if( m_inQuote )
0122     {
0123         finishedElement();
0124         m_inQuote = false;
0125     }
0126     else
0127     {
0128         if( !m_string.isEmpty() )
0129             finishedToken();
0130         m_state = ExpectText;
0131         m_inQuote = true;
0132     }
0133 }
0134 
0135 void ExpressionParser::handleChar( const QChar &c )
0136 {
0137     m_string += c;
0138     if( m_state <= ExpectField )
0139         m_state = ExpectField;
0140     else if( m_state <= ExpectText )
0141         m_state = ExpectText;
0142 }
0143 
0144 void ExpressionParser::finishedToken()
0145 {
0146     enum { And, Or, Neither };
0147     int s;
0148     if( m_haveGroup || !m_element.field.isEmpty() )
0149         s = Neither;
0150     else if( m_string == QLatin1String("AND") )
0151         s = And;
0152     else if( m_string == QLatin1String("OR") )
0153         s = Or;
0154     else
0155         s = Neither;
0156 
0157     if( s == Neither )
0158         finishedElement();
0159     else
0160     {
0161         m_haveGroup = true;
0162 
0163         if( s == Or )
0164             m_inOrGroup = true;
0165         else
0166             finishedOrGroup();
0167 
0168         m_string.clear();
0169         m_state = ExpectMinus;
0170     }
0171 }
0172 
0173 void ExpressionParser::finishedElement()
0174 {
0175     if( !m_inOrGroup )
0176         finishedOrGroup();
0177     m_inOrGroup = m_haveGroup = false;
0178     m_element.text = m_string;
0179     m_string.clear();
0180 
0181     if( !m_element.text.isEmpty() )
0182         m_or.append( m_element );
0183 
0184     //m_element = expression_element();
0185     m_element.field.clear();
0186     m_element.negate = false;
0187     m_element.match = expression_element::Contains;
0188     m_state = ExpectMinus;
0189 }
0190 
0191 void ExpressionParser::finishedOrGroup()
0192 {
0193     if( !m_or.isEmpty() )
0194         m_parsed.append( m_or );
0195     m_or.clear();
0196     m_inOrGroup = false;
0197 }
0198