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