~ubuntu-branches/ubuntu/trusty/kvirc/trusty-proposed

« back to all changes in this revision

Viewing changes to src/kvirc/kvs/parser/KviKvsParser_expression.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kai Wasserbäch, Kai Wasserbäch, Raúl Sánchez Siles
  • Date: 2011-02-12 10:40:21 UTC
  • mfrom: (14.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110212104021-5mh4f75jlku20mnt
The combined "Twisted Experiment" and "Nocturnal Raid" release.

[ Kai Wasserbäch ]
* Synced to upstream's SVN revision 5467.
* debian/rules:
  - Added .PHONY line.
  - Resurrect -DMANUAL_REVISION, got lost somewhere and we build SVN
    revisions again.
  - Replace "-DWITH_NO_EMBEDDED_CODE=YES" with "-DWANT_CRYPTOPP=YES".
  - Change the remaining -DWITH/-DWITHOUT to the new -DWANT syntax.
* debian/control:
  - Removed DMUA, I'm a DD now.
  - Changed my e-mail address.
  - Removed unneeded relationships (no upgrades over two releases are
    supported).
  - Fix Suggests for kvirc-dbg.
  - kvirc-data: Make the "Suggests: kvirc" a Recommends, doesn't make much
    sense to install the -data package without the program.
* debian/source/local-options: Added with "unapply-patches".
* debian/kvirc.lintian-overrides: Updated to work for 4.1.1.
* debian/patches/21_make_shared-mime-info_B-D_superfluous.patch: Updated.
* debian/kvirc-data.install: Added .notifyrc.

[ Raúl Sánchez Siles ]
* Stating the right version where kvirc-data break and replace should happen.
* Fixing link to license file.
* Added French and Portuguese man pages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//=============================================================================
 
2
//
 
3
//   File : KviKvsParser_expression.cpp
 
4
//   Creation date : Mon 6 Oct 2003 01.31 CEST by Szymon Stefanek
 
5
//
 
6
//   This file is part of the KVIrc irc client distribution
 
7
//   Copyright (C) 2003-2010 Szymon Stefanek (pragma at kvirc dot net)
 
8
//
 
9
//   This program is FREE software. You can redistribute it and/or
 
10
//   modify it under the terms of the GNU General Public License
 
11
//   as published by the Free Software Foundation; either version 2
 
12
//   of the License, or (at your opinion) 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.
 
17
//   See the 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 Foundation,
 
21
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
22
//
 
23
//=============================================================================
 
24
 
 
25
#include "KviKvsParser.h"
 
26
#include "KviKvsTreeNode.h"
 
27
#include "KviKvsReport.h"
 
28
#include "KviKvsKernel.h"
 
29
#include "KviKvsParserMacros.h"
 
30
#include "KviLocale.h"
 
31
 
 
32
 
 
33
//#warning "FIXME: expression eval doc!"
 
34
 
 
35
        /*
 
36
                @doc: expressioneval
 
37
                @type:
 
38
                        language
 
39
                @title:
 
40
                        Expression evaluation identifier
 
41
                @syntax:
 
42
                        $(<expression>)
 
43
                @keyterms:
 
44
                        expressions
 
45
                @short:
 
46
                        Expression evaluation identifier
 
47
                @description:
 
48
                        Evaluates <expression> and returns its result.[br]
 
49
                        If <expression> is a single string, array or hash, it is returned unmodified.[br]
 
50
                        In any other case the expression evaluation returns a numeric value, either real or integer.[br]
 
51
                        The expressions are really close to the C ones and have some minor extensions.[br]
 
52
                        The supported operators are +,-,*,/,|,&,^,||,&&,^^,>>,<<,<,>,<=,>=,==,!= and <> (synonim for !=).[br]
 
53
                        The following table describes their meaning.[br]
 
54
                        [table]
 
55
                                [tr][td][b]Operator[/b][/td][td][b]Description[/b][/td][/tr]
 
56
                                [tr][td]a + b[/td][td]Arithmetic sum: valid only for numeric operands[/td][/tr]
 
57
                                [tr][td]a - b[/td][td]Arithmetic subtraction: valid only for numeric operands[/td][/tr]
 
58
                                [tr][td]a / b[/td][td]Arithmetic division: valid only for numeric operands[/td][/tr]
 
59
                                [tr][td]a * b[/td][td]Arithmetic multiplication: valid only for numeric operands[/td][/tr]
 
60
                                [tr][td]a % b[/td][td]Arithmetic modulus: valid only for numeric operands[/td][/tr]
 
61
                                [tr][td]a || b[/td][td]Logical or: valid only for boolean operands[/td][/tr]
 
62
                                [tr][td]a && b[/td][td]Logical and: valid only for boolean operands[/td][/tr]
 
63
                                [tr][td]a ^^ b[/td][td]Logical xor: valid only for boolean operands[/td][/tr]
 
64
                                [tr][td]a >> b[/td][td]Bitwise shift right: valid only for integer operands[/td][/tr]
 
65
                                [tr][td]a << b[/td][td]Bitwise shift left: valid only for integer operands[/td][/tr]
 
66
                                [tr][td]a | b[/td][td]Bitwise or: valid only for integer operands[/td][/tr]
 
67
                                [tr][td]a & b[/td][td]Bitwise and: valid only for integer operands[/td][/tr]
 
68
                                [tr][td]a ^ b[/td][td]Bitwise xor: valid only for integer operands[/td][/tr]
 
69
                                [tr][td]a > b[/td][td]Greater than: valid for numeric or string operands. Case sensitive[/td][/tr]
 
70
                                [tr][td]a < b[/td][td]Lower than: valid for numeric or string operands. Case sensitive[/td][/tr]
 
71
                                [tr][td]a >= b[/td][td]Greater or equal to: valid for numeric or string operands. Case sensitive[/td][/tr]
 
72
                                [tr][td]a <= b[/td][td]Lower or equal to: valid for numeric or string operands. Case sensitive[/td][/tr]
 
73
                                [tr][td]a != b[/td][td]Not equal to: valid for numeric or string operands. Case sensitive[/td][/tr]
 
74
                                [tr][td]a == b[/td][td]Equal to: valid for numeric or string operands. Case sensitive[/td][/tr]
 
75
                        [/table]
 
76
                        The expressions can contain integer, real or string constants and variable operands.[br]
 
77
                        The integer constants can be also specified as hexadecimal numbers by prefixing them by '0x'.[br]
 
78
                        The string constants should be enclosed in quotes.[br]
 
79
                @examples:
 
80
                        [example]
 
81
                                echo $(10 + 5 * 100)
 
82
                                echo $(10 / 3)
 
83
                                echo $(10 / 3.0)
 
84
                                echo $(10.0 + 5 * 100)
 
85
                                echo $(145 & 2)
 
86
                                echo $("hello" > "ciao")
 
87
                                echo $(10 == "10")
 
88
                                %a = 100
 
89
                                %b = 50.3
 
90
                                %c = "test"
 
91
                                echo $(%a + %b)
 
92
                                echo $("%a%b" + 1)
 
93
                                echo $(%a + %b > %c)
 
94
                                echo $(-(10 + 20) * 3)
 
95
                                echo $(1 ^ 2)
 
96
                                echo $(1 ^ 1)
 
97
                                echo $(0xffff == 65535)
 
98
                                ...
 
99
                        [/example]
 
100
        */
 
101
 
 
102
 
 
103
 
 
104
 
 
105
KviKvsTreeNodeExpressionBinaryOperator * KviKvsParser::parseExpressionBinaryOperator()
 
106
{
 
107
        switch(KVSP_curCharUnicode)
 
108
        {
 
109
                case '=':
 
110
                        KVSP_skipChar;
 
111
                        if(KVSP_curCharUnicode == '=')
 
112
                        {
 
113
                                KVSP_skipChar;
 
114
                                return new KviKvsTreeNodeExpressionBinaryOperatorEqualTo(KVSP_curCharPointer);
 
115
                        } else {
 
116
                                error(KVSP_curCharPointer,__tr2qs_ctx("Unknown binary operator '=%q': did you mean '==' ?","kvs"),KVSP_curCharPointer);
 
117
                        }
 
118
                break;
 
119
                case '!':
 
120
                        KVSP_skipChar;
 
121
                        if(KVSP_curCharUnicode == '=')
 
122
                        {
 
123
                                KVSP_skipChar;
 
124
                                return new KviKvsTreeNodeExpressionBinaryOperatorNotEqualTo(KVSP_curCharPointer);
 
125
                        }
 
126
                break;
 
127
                case '+':
 
128
                        KVSP_skipChar;
 
129
                        return new KviKvsTreeNodeExpressionBinaryOperatorSum(KVSP_curCharPointer);
 
130
                break;
 
131
                case '-':
 
132
                        KVSP_skipChar;
 
133
                        return new KviKvsTreeNodeExpressionBinaryOperatorSubtraction(KVSP_curCharPointer);
 
134
                break;
 
135
                case '/':
 
136
                        KVSP_skipChar;
 
137
                        return new KviKvsTreeNodeExpressionBinaryOperatorDivision(KVSP_curCharPointer);
 
138
                break;
 
139
                case '%':
 
140
                        KVSP_skipChar;
 
141
                        return new KviKvsTreeNodeExpressionBinaryOperatorModulus(KVSP_curCharPointer);
 
142
                break;
 
143
                case '*':
 
144
                        KVSP_skipChar;
 
145
                        return new KviKvsTreeNodeExpressionBinaryOperatorMultiplication(KVSP_curCharPointer);
 
146
                break;
 
147
                case '&':
 
148
                        KVSP_skipChar;
 
149
                        if(KVSP_curCharUnicode == '&')
 
150
                        {
 
151
                                KVSP_skipChar;
 
152
                                return new KviKvsTreeNodeExpressionBinaryOperatorAnd(KVSP_curCharPointer);
 
153
                        }
 
154
                        return new KviKvsTreeNodeExpressionBinaryOperatorBitwiseAnd(KVSP_curCharPointer);
 
155
                break;
 
156
                case '|':
 
157
                        KVSP_skipChar;
 
158
                        if(KVSP_curCharUnicode == '|')
 
159
                        {
 
160
                                KVSP_skipChar;
 
161
                                return new KviKvsTreeNodeExpressionBinaryOperatorOr(KVSP_curCharPointer);
 
162
                        }
 
163
                        return new KviKvsTreeNodeExpressionBinaryOperatorBitwiseOr(KVSP_curCharPointer);
 
164
                break;
 
165
                case '^':
 
166
                        KVSP_skipChar;
 
167
                        if(KVSP_curCharUnicode == '^')
 
168
                        {
 
169
                                KVSP_skipChar;
 
170
                                return new KviKvsTreeNodeExpressionBinaryOperatorXor(KVSP_curCharPointer);
 
171
                        }
 
172
                        return new KviKvsTreeNodeExpressionBinaryOperatorBitwiseXor(KVSP_curCharPointer);
 
173
                break;
 
174
                case '>':
 
175
                        KVSP_skipChar;
 
176
                        switch(KVSP_curCharUnicode)
 
177
                        {
 
178
                                case '>':
 
179
                                        KVSP_skipChar;
 
180
                                        return new KviKvsTreeNodeExpressionBinaryOperatorShiftRight(KVSP_curCharPointer);
 
181
                                break;
 
182
                                case '=':
 
183
                                        KVSP_skipChar;
 
184
                                        return new KviKvsTreeNodeExpressionBinaryOperatorGreaterOrEqualTo(KVSP_curCharPointer);
 
185
                                break;
 
186
                                default:
 
187
                                        return new KviKvsTreeNodeExpressionBinaryOperatorGreaterThan(KVSP_curCharPointer);
 
188
                                break;
 
189
                        }
 
190
                break;
 
191
                case '<':
 
192
                        KVSP_skipChar;
 
193
                        switch(KVSP_curCharUnicode)
 
194
                        {
 
195
                                case '>':
 
196
                                        KVSP_skipChar;
 
197
                                        return new KviKvsTreeNodeExpressionBinaryOperatorNotEqualTo(KVSP_curCharPointer);
 
198
                                break;
 
199
                                case '<':
 
200
                                        KVSP_skipChar;
 
201
                                        return new KviKvsTreeNodeExpressionBinaryOperatorShiftLeft(KVSP_curCharPointer);
 
202
                                break;
 
203
                                case '=':
 
204
                                        KVSP_skipChar;
 
205
                                        return new KviKvsTreeNodeExpressionBinaryOperatorLowerOrEqualTo(KVSP_curCharPointer);
 
206
                                break;
 
207
                                default:
 
208
                                        return new KviKvsTreeNodeExpressionBinaryOperatorLowerThan(KVSP_curCharPointer);
 
209
                                break;
 
210
                        }
 
211
                break;
 
212
        }
 
213
 
 
214
        error(KVSP_curCharPointer,__tr2qs_ctx("Unknown binary operator '%q'","kvs"),KVSP_curCharPointer);
 
215
        return 0;
 
216
}
 
217
 
 
218
 
 
219
static unsigned char binary_operator_initial_char[256]=
 
220
{
 
221
        //      000 001 002 003 004 005 006 007   008 009 010 011 012 013 014 015
 
222
        //      NUL SOH STX ETX EOT ENQ ACK BEL   BS  HT  LF  VT  FF  CR  SO  SI
 
223
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
224
        //      016 017 018 019 020 021 022 023   024 025 026 027 028 029 030 031
 
225
        //      DLE DC1 DC2 DC3 DC4 NAK SYN ETB   CAN EM  SUB ESC FS  GS  RS  US
 
226
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
227
        //      032 033 034 035 036 037 038 039   040 041 042 043 044 045 046 047
 
228
        //          !   "   #   $   %   &   '     (   )   *   +   ,   -   .   /
 
229
                0  ,1  ,0  ,0  ,0  ,1  ,1  ,0    ,0  ,0  ,1  ,1  ,0  ,1  ,0  ,1  ,
 
230
        //      048 049 050 051 052 053 054 055   056 057 058 059 060 061 062 063
 
231
        //      0   1   2   3   4   5   6   7     8   9   :   ;   <   =   >   ?
 
232
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,1  ,1  ,1  ,0  ,
 
233
        //      064 065 066 067 068 069 070 071   072 073 074 075 076 077 078 079
 
234
        //      @   A   B   C   D   E   F   G     H   I   J   K   L   M   N   O
 
235
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
236
        //      080 081 082 083 084 085 086 087   088 089 090 091 092 093 094 095
 
237
        //      P   Q   R   S   T   U   V   W     X   Y   Z   [   \   ]   ^   _
 
238
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,1  ,0  ,
 
239
        //      096 097 098 099 100 101 102 103   104 105 106 107 108 109 110 111
 
240
        //      `   a   b   c   d   e   f   g     h   i   j   k   l   m   n   o
 
241
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
242
        //      112 113 114 115 116 117 118 119   120 121 122 123 124 125 126 127
 
243
        //      p   q   r   s   t   u   v   w     x   y   z   {   |   }   ~   
 
244
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,1  ,0  ,0  ,0  ,
 
245
        //      128 129 130 131 132 133 134 135   136 137 138 139 140 141 142 143
 
246
        //
 
247
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
248
        //      144 145 146 147 148 149 150 151   152 153 154 155 156 157 158 159
 
249
        //
 
250
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
251
        //      160 161 162 163 164 165 166 167   168 169 170 171 172 173 174 175
 
252
        //
 
253
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
254
        //      176 177 178 179 180 181 182 183   184 185 186 187 188 189 190 191
 
255
        //
 
256
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
257
        //      192 193 194 195 196 197 198 199   200 201 202 203 204 205 206 207
 
258
        //      �  �  �  �  �  �  �  �    �  �  �  �  �  �  �  �
 
259
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
260
        //      208 209 210 211 212 213 214 215   216 217 218 219 220 221 222 223
 
261
        //      �  �  �  �  �  �  �  �    �  �  �  �  �  �  �  �
 
262
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
263
        //      224 225 226 227 228 229 230 231   232 233 234 235 236 237 238 239
 
264
        //      �  �  �  �  �  �  �  �    �  �  �  �  �  �  �  �
 
265
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
 
266
        //      240 241 242 243 244 245 246 247   248 249 250 251 252 253 254 255
 
267
        //      �  �  �  �  �  �  �  �
 
268
                0  ,0  ,0  ,0  ,0  ,0  ,0  ,0    ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0
 
269
};
 
270
 
 
271
 
 
272
bool KviKvsParser::parseExpressionMightPointToOperator()
 
273
{
 
274
        if(KVSP_curCharUnicode == '%')
 
275
        {
 
276
                KVSP_skipChar;
 
277
                if(KVSP_curCharIsLetter || (KVSP_curCharUnicode == '_'))
 
278
                {
 
279
                        // a variable, probably
 
280
                        KVSP_backChar;
 
281
                        return false;
 
282
                }
 
283
                KVSP_backChar;
 
284
                return true;
 
285
        }
 
286
        if(KVSP_curCharUnicode > 255)return false;
 
287
        return binary_operator_initial_char[KVSP_curCharUnicode] != 0;
 
288
}
 
289
 
 
290
 
 
291
KviKvsTreeNodeExpression * KviKvsParser::parseExpressionOperand(char terminator)
 
292
{
 
293
        switch(KVSP_curCharUnicode)
 
294
        {
 
295
                case 0:
 
296
                case '\r':
 
297
                case '\n':
 
298
                        error(KVSP_curCharPointer,__tr2qs_ctx("Unexpected end of script in expression","kvs"));
 
299
                        return 0;
 
300
                break;
 
301
                case '(':
 
302
                        KVSP_skipChar;
 
303
                        skipSpaces();
 
304
                        return parseExpression(')'); // sub expression
 
305
                break;
 
306
                case '-':
 
307
                {
 
308
                        KVSP_skipChar;
 
309
                        skipSpaces();
 
310
                        KviKvsTreeNodeExpression * d = parseExpressionOperand(terminator);
 
311
                        if(!d)return 0;
 
312
                        return new KviKvsTreeNodeExpressionUnaryOperatorNegate(d->location(),d);
 
313
                }
 
314
                break;
 
315
                case '!':
 
316
                {
 
317
                        KVSP_skipChar;
 
318
                        skipSpaces();
 
319
                        KviKvsTreeNodeExpression * d = parseExpressionOperand(terminator);
 
320
                        if(!d)return 0;
 
321
                        return new KviKvsTreeNodeExpressionUnaryOperatorLogicalNot(d->location(),d);
 
322
                }
 
323
                break;
 
324
                case '~':
 
325
                {
 
326
                        KVSP_skipChar;
 
327
                        skipSpaces();
 
328
                        KviKvsTreeNodeExpression * d = parseExpressionOperand(terminator);
 
329
                        if(!d)return 0;
 
330
                        return new KviKvsTreeNodeExpressionUnaryOperatorBitwiseNot(d->location(),d);
 
331
                }
 
332
                break;
 
333
                default:
 
334
                        // anything else at this point is an operand core
 
335
                        return parseExpressionOperandCore(terminator);
 
336
                break;
 
337
        }
 
338
 
 
339
        // not reached
 
340
        KVSP_ASSERT(false);
 
341
        return 0;
 
342
}
 
343
 
 
344
 
 
345
 
 
346
KviKvsTreeNodeExpression * KviKvsParser::parseExpressionOperandCore(char terminator)
 
347
{
 
348
        KviPointerList<KviKvsTreeNodeData> * pDataList = new KviPointerList<KviKvsTreeNodeData>;
 
349
        pDataList->setAutoDelete(true);
 
350
 
 
351
        static QString szStaticSingleSpace(" ");
 
352
 
 
353
        const QChar * pOperandBegin = KVSP_curCharPointer;
 
354
 
 
355
        bool bHaveVariable = false;
 
356
 
 
357
        for(;;)
 
358
        {
 
359
                switch(KVSP_curCharUnicode)
 
360
                {
 
361
                        case 0:
 
362
                        case '\r':
 
363
                        case '\n':
 
364
                                error(KVSP_curCharPointer,__tr2qs_ctx("Unexpected end of script in expression","kvs"));
 
365
                                delete pDataList;
 
366
                                return 0;
 
367
                        break;
 
368
                        case ' ':
 
369
                        case '\t':
 
370
                                skipSpaces();
 
371
                                if((KVSP_curCharUnicode == terminator) || parseExpressionMightPointToOperator())goto postprocess_operand;
 
372
                                // separate by single spaces
 
373
                                pDataList->append(new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(szStaticSingleSpace)));
 
374
                        break;
 
375
                        case '"':
 
376
                        {
 
377
                                // a string
 
378
                                bHaveVariable = true;
 
379
                                KviKvsTreeNodeData * d = parseStringParameter();
 
380
                                if(!d)
 
381
                                {
 
382
                                        delete pDataList;
 
383
                                        return 0;
 
384
                                }
 
385
                                pDataList->append(d);
 
386
                        }
 
387
                        break;
 
388
                        case '%':
 
389
                        case '$':
 
390
                        case '@':
 
391
                        {
 
392
                                bHaveVariable = true;
 
393
                                KviKvsTreeNodeData * d = parseParameterPercentOrDollar();
 
394
                                if(!d)
 
395
                                {
 
396
                                        delete pDataList;
 
397
                                        return 0;
 
398
                                }
 
399
                                pDataList->append(d);
 
400
                        }
 
401
                        break;
 
402
                        default:
 
403
                                // literal ?
 
404
                                if(KVSP_curCharIsLetterOrNumber || (KVSP_curCharUnicode == '.') || (KVSP_curCharUnicode == '_'))
 
405
                                {
 
406
                                        const QChar * pBegin = KVSP_curCharPointer;
 
407
                                        while(KVSP_curCharIsLetterOrNumber || (KVSP_curCharUnicode == '.') || (KVSP_curCharUnicode == '_'))KVSP_skipChar;
 
408
                                        QString tmp(pBegin,KVSP_curCharPointer - pBegin);
 
409
                                        bool bOk;
 
410
                                        kvs_int_t iVal = tmp.toLong(&bOk);
 
411
                                        if(bOk)
 
412
                                        {
 
413
                                                pDataList->append(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(iVal)));
 
414
                                        } else {
 
415
                                                // bOk is false
 
416
                                                if(pBegin->unicode() == '0')
 
417
                                                {
 
418
                                                        if(tmp.length() > 2)
 
419
                                                        {
 
420
                                                                if((tmp[1] == 'x') || (tmp[1] == 'X'))
 
421
                                                                {
 
422
                                                                        // hexadecimal constant ?
 
423
                                                                        QString hex = tmp.right(tmp.length() - 2);
 
424
                                                                        iVal = hex.toLong(&bOk,16);
 
425
                                                                        if(bOk)
 
426
                                                                        {
 
427
                                                                                pDataList->append(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(iVal)));
 
428
                                                                        }
 
429
                                                                }
 
430
                                                        }
 
431
                                                }
 
432
                                                if(!bOk)
 
433
                                                {
 
434
                                                        kvs_real_t dVal = tmp.toDouble(&bOk);
 
435
                                                        if(bOk)
 
436
                                                        {
 
437
                                                                pDataList->append(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(dVal)));
 
438
                                                        } else {
 
439
                                                                pDataList->append(new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(tmp)));
 
440
                                                        }
 
441
                                                }
 
442
                                        }
 
443
                                } else {
 
444
                                        error(KVSP_curCharPointer,__tr2qs_ctx("Unexpected character %q (unicode %h) in expression. If it meant to be a string use the quotes.","kvs"),KVSP_curCharPointer,KVSP_curCharUnicode);
 
445
                                        delete pDataList;
 
446
                                        return 0;
 
447
                                }
 
448
                        break;
 
449
                }
 
450
 
 
451
                if((KVSP_curCharUnicode == terminator) || parseExpressionMightPointToOperator())break;
 
452
        }
 
453
 
 
454
postprocess_operand:
 
455
 
 
456
        if(pDataList->count() == 0)
 
457
        {
 
458
                delete pDataList;
 
459
                error(KVSP_curCharPointer,__tr2qs_ctx("Unexpected empty expression operand","kvs"));
 
460
                return 0;
 
461
        }
 
462
 
 
463
        if(pDataList->count() > 1)
 
464
                return new KviKvsTreeNodeExpressionVariableOperand(pOperandBegin,new KviKvsTreeNodeCompositeData(pOperandBegin,pDataList));
 
465
 
 
466
        KviKvsTreeNodeData * pUniqueData = pDataList->first();
 
467
 
 
468
        if(bHaveVariable)
 
469
        {
 
470
                pDataList->setAutoDelete(false);
 
471
                delete pDataList;
 
472
                return new KviKvsTreeNodeExpressionVariableOperand(pOperandBegin,pUniqueData);
 
473
        }
 
474
 
 
475
        // a single constant data element
 
476
        KviKvsTreeNodeExpressionConstantOperand * op =  new KviKvsTreeNodeExpressionConstantOperand(pOperandBegin,new KviKvsVariant(*(((KviKvsTreeNodeConstantData *)pUniqueData)->value())));
 
477
        delete pDataList; // auto delete is true
 
478
        return op;
 
479
}
 
480
 
 
481
 
 
482
KviKvsTreeNodeExpression * KviKvsParser::parseExpression(char terminator)
 
483
{
 
484
        // we're inside the expression now
 
485
        skipSpaces();
 
486
 
 
487
        if(KVSP_curCharUnicode == terminator)
 
488
        {
 
489
                // empty expression
 
490
                // constant 0 ?
 
491
                KVSP_skipChar;
 
492
                return new KviKvsTreeNodeExpressionConstantOperand(KVSP_curCharPointer,new KviKvsVariant((kvs_int_t)0));
 
493
        }
 
494
 
 
495
        KviKvsTreeNodeExpression * left = parseExpressionOperand(terminator);
 
496
        if(!left)return 0;
 
497
        QString sz;
 
498
        left->contextDescription(sz);
 
499
 
 
500
        skipSpaces();
 
501
 
 
502
        if(KVSP_curCharUnicode == terminator)
 
503
        {
 
504
                KVSP_skipChar;
 
505
                return left;
 
506
        }
 
507
 
 
508
        // not a terminator... must be an operator (or an error, eventually)
 
509
 
 
510
        KviKvsTreeNodeExpression * curTopOperator = parseExpressionBinaryOperator();
 
511
        if(!curTopOperator)
 
512
        {
 
513
                delete left;
 
514
                return 0; // error
 
515
        }
 
516
        curTopOperator->contextDescription(sz);
 
517
 
 
518
        curTopOperator->setLeft(left);
 
519
 
 
520
        // ok.. parse the right side
 
521
 
 
522
        // Now curTopOperator has the left subtree (one node) set
 
523
        // and it points to the TOP (=ROOT) node
 
524
        // Evaluate the rest
 
525
 
 
526
        KviKvsTreeNodeExpression * operand;
 
527
        KviKvsTreeNodeExpression * incompleteOperator = curTopOperator;
 
528
        KviKvsTreeNodeExpression * auxOperator;
 
529
 
 
530
        for(;;)
 
531
        {
 
532
                skipSpaces();
 
533
 
 
534
                operand = parseExpressionOperand(terminator);
 
535
                if(!operand)
 
536
                {
 
537
                        delete curTopOperator;
 
538
                        return 0;
 
539
                }
 
540
                operand->contextDescription(sz);
 
541
 
 
542
                skipSpaces();
 
543
 
 
544
                if(KVSP_curCharUnicode == terminator)
 
545
                {
 
546
                        KVSP_skipChar;
 
547
                        incompleteOperator->setRight(operand);
 
548
                        return curTopOperator;
 
549
                }
 
550
 
 
551
                auxOperator = parseExpressionBinaryOperator();
 
552
                if(!auxOperator)
 
553
                {
 
554
                        delete curTopOperator;
 
555
                        delete operand;
 
556
                        return 0;
 
557
                }
 
558
 
 
559
                auxOperator->contextDescription(sz);
 
560
 
 
561
 
 
562
                //now compare operators...
 
563
                if(incompleteOperator->precedence() > auxOperator->precedence())
 
564
                {
 
565
                        // This in fact means that incomplete has LOWER precedence than
 
566
                        // aux and thus aux should be done first.
 
567
                        incompleteOperator->setRight(auxOperator);
 
568
                        auxOperator->setLeft(operand);
 
569
                } else {
 
570
                        // incomplete has GREATER precedence than aux and thus aux should be done first
 
571
                        incompleteOperator->setRight(operand); //right tree complete
 
572
                        // go up until we find an operator with lower precedence than auxOperator (>=)
 
573
                        KviKvsTreeNodeExpression * tempOperator = incompleteOperator->parentWithPrecedenceLowerThan(auxOperator->precedence());
 
574
                        if(tempOperator == 0)
 
575
                        {
 
576
                                auxOperator->setLeft(curTopOperator);
 
577
                                curTopOperator = auxOperator;
 
578
                        } else {
 
579
                                KVSP_ASSERT(tempOperator->right());
 
580
                                auxOperator->setLeft(tempOperator->right());
 
581
                                tempOperator->setRight(auxOperator);
 
582
                        }
 
583
                }
 
584
                incompleteOperator = auxOperator;
 
585
                KVSP_ASSERT(incompleteOperator->right() == 0);
 
586
        }
 
587
 
 
588
        KVSP_ASSERT(false);
 
589
 
 
590
        return 0; //newer here
 
591
 
 
592
/*
 
593
 
 
594
 
 
595
        KviKvsTreeNodeExpression * right = parseExpression(terminator);
 
596
        if(!right)
 
597
        {
 
598
                delete op;
 
599
                return 0;
 
600
        }
 
601
 
 
602
        // left * a + b
 
603
 
 
604
        //      *
 
605
        // left      +
 
606
        //         a    b
 
607
 
 
608
*/
 
609
/*
 
610
        // now.. the left side is a single operand for sure
 
611
        // the right side might be a single operand or a sequence of operations
 
612
        if(right->isOperator())
 
613
        {
 
614
                // if the operator has lower precedence than op then
 
615
                if(right->precedence() < op->precedence())
 
616
                {
 
617
                        right->attachHighPrecedenceOperator(op);
 
618
                        return right;
 
619
                }
 
620
        }
 
621
*/
 
622
/*
 
623
        // a single operand or a greater precedence operator
 
624
        op->setRight(right);
 
625
 
 
626
        return op;
 
627
        */
 
628
}
 
629