1
/****************************************************************************************
2
 * Copyright (c) 2006 Gbor Lehel <illissius@gmail.com>                                  *
3
 *                                                                                      *
4
 * This program is free software; you can redistribute it and/or modify it under        *
5
 * the terms of the GNU General Public License as published by the Free Software        *
6
 * Foundation; either version 2 of the License, or (at your option) any later           *
7
 * version.                                                                             *
8
 *                                                                                      *
9
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
10
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
11
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
12
 *                                                                                      *
13
 * You should have received a copy of the GNU General Public License along with         *
14
 * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
15
 ****************************************************************************************/
16
17
#include "Expression.h"
18
#include "core/support/Debug.h"
19
20
ExpressionParser::ExpressionParser( const QString &expression )
21
    : m_expression( expression )
22
    , m_state( ExpectMinus )
23
    , m_haveGroup( false )
24
    , m_inQuote( false )
25
    , m_inOrGroup( false )
26
{ }
27
28
ParsedExpression ExpressionParser::parse()
29
{
30
    const uint length = m_expression.length();
31
    for( uint pos = 0; pos < length; ++pos )
32
        parseChar( m_expression.at( pos ) );
33
    finishedToken();
34
    finishedOrGroup();
35
36
    return m_parsed;
37
}
38
39
ParsedExpression ExpressionParser::parse( const QString &expression ) //static
40
{
41
    ExpressionParser p( expression );
42
    return p.parse();
43
}
44
45
bool ExpressionParser::isAdvancedExpression( const QString &expression ) //static
46
{
47
    return ( expression.contains( '"'   ) ||
48
             expression.contains( ':'   ) ||
49
             expression.contains( '-'   ) ||
50
             expression.contains( "AND" ) ||
51
             expression.contains( "OR"  ) );
52
}
53
54
/* PRIVATE */
55
56
void ExpressionParser::parseChar( const QChar &c )
57
{
58
    if( m_inQuote && c != '"' )
59
        m_string += c;
60
    else if( c.isSpace() )
61
        handleSpace( c );
62
    else if( c == '-' )
63
        handleMinus( c );
64
    else if( c == ':' )
65
        handleColon( c );
66
    else if( c == '>' || c == '<' )
67
        handleMod( c );
68
    else if( c == '"' )
69
        handleQuote( c );
70
    else
71
        handleChar( c );
72
}
73
74
void ExpressionParser::handleSpace( const QChar& )
75
{
76
    if( m_state > ExpectMinus )
77
        finishedToken();
78
}
79
80
void ExpressionParser::handleMinus( const QChar &c )
81
{
82
    if( m_state == ExpectMinus )
83
    {
84
        m_element.negate = true;
85
        m_state = ExpectField;
86
    }
87
    else
88
        handleChar( c );
89
}
90
91
void ExpressionParser::handleColon( const QChar &c )
92
{
93
    if( m_state <= ExpectField && !m_string.isEmpty() )
94
    {
95
        m_element.field = m_string;
96
        m_string.clear();
97
        m_state = ExpectMod;
98
    }
99
    else
100
        handleChar( c );
101
}
102
103
void ExpressionParser::handleMod( const QChar &c )
104
{
105
    if( m_state == ExpectMod )
106
    {
107
        m_element.match = ( c == '>' ) ? expression_element::More : expression_element::Less;
108
        m_state = ExpectText;
109
    }
110
    else
111
        handleChar( c );
112
}
113
114
void ExpressionParser::handleQuote( const QChar& )
115
{
116
    if( m_inQuote )
117
    {
118
        finishedElement();
119
        m_inQuote = false;
120
    }
121
    else
122
    {
123
        if( !m_string.isEmpty() )
124
            finishedToken();
125
        m_state = ExpectText;
126
        m_inQuote = true;
127
    }
128
}
129
130
void ExpressionParser::handleChar( const QChar &c )
131
{
132
    m_string += c;
133
    if( m_state <= ExpectField )
134
        m_state = ExpectField;
135
    else if( m_state <= ExpectText )
136
        m_state = ExpectText;
137
}
138
139
void ExpressionParser::finishedToken()
140
{
141
    enum { And, Or, Neither };
142
    int s;
143
    if( m_haveGroup || !m_element.field.isEmpty() )
144
        s = Neither;
145
    else if( m_string == "AND" )
146
        s = And;
147
    else if( m_string == "OR" )
148
        s = Or;
149
    else
150
        s = Neither;
151
152
    if( s == Neither )
153
        finishedElement();
154
    else
155
    {
156
        m_haveGroup = true;
157
158
        if( s == Or )
159
            m_inOrGroup = true;
160
        else
161
            finishedOrGroup();
162
163
        m_string.clear();
164
        m_state = ExpectMinus;
165
    }
166
}
167
168
void ExpressionParser::finishedElement()
169
{
170
    if( !m_inOrGroup )
171
        finishedOrGroup();
172
    m_inOrGroup = m_haveGroup = false;
173
    m_element.text = m_string;
174
    m_string.clear();
175
176
    if( !m_element.text.isEmpty() )
177
        m_or.append( m_element );
178
179
    //m_element = expression_element();
180
    m_element.field.clear();
181
    m_element.negate = false;
182
    m_element.match = expression_element::Contains;
183
    m_state = ExpectMinus;
184
}
185
186
void ExpressionParser::finishedOrGroup()
187
{
188
    if( !m_or.isEmpty() )
189
        m_parsed.append( m_or );
190
    m_or.clear();
191
    m_inOrGroup = false;
192
}