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

« back to all changes in this revision

Viewing changes to src/kvirc/kvs/kvi_kvs_parser_lside.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 : kvi_kvs_parser_lside.cpp
4
 
//   Creation date : Thu 03 Nov 2003 13.11 CEST by Szymon Stefanek
5
 
//
6
 
//   This file is part of the KVirc irc client distribution
7
 
//   Copyright (C) 2003-2008 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 "kvi_kvs_parser.h"
26
 
#include "kvi_kvs_treenode.h"
27
 
#include "kvi_kvs_report.h"
28
 
#include "kvi_kvs_kernel.h"
29
 
#include "kvi_kvs_parser_macros.h"
30
 
#include "kvi_locale.h"
31
 
 
32
 
 
33
 
/*
34
 
        @doc: operators
35
 
        @title:
36
 
                Operators
37
 
        @keyterms:
38
 
                operator,operators,assignment,assign
39
 
        @type:
40
 
                language
41
 
        @short:
42
 
                Variable operators , assignments & co.
43
 
        @body:
44
 
                Operator constructs are commands just like the other ones.
45
 
                All the operators work on local or global variables and dictionaries.[br]
46
 
                The generic operator syntax is:[br]
47
 
                [br]
48
 
                [b]<left_operand> <operator> [right_operand][/b][br]
49
 
                [br]
50
 
                where <left_operand> and [right_operand] depend on the <operator>.[br]
51
 
                Some operators have no [right_operand] and these are called [b]unary operators[/b]:
52
 
                they operate directly on <left_operand>.[br]
53
 
                [br]
54
 
                [table]
55
 
                        [tr][td]Operator[/td][td]document[/td][/tr]
56
 
                        [tr][td]=[/td][td][doc:assignment]assignment operator[/doc][/td][/tr]
57
 
                        [tr][td]++[/td][td][doc:incrementdecrement]Increment and decrement operators[/doc][/td][/tr]
58
 
                        [tr][td]--[/td][td][doc:incrementdecrement]Increment and decrement operators[/doc][/td][/tr]
59
 
                        [tr][td]+=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
60
 
                        [tr][td]-=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
61
 
                        [tr][td]*=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
62
 
                        [tr][td]/=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
63
 
                        [tr][td]%=[/td][td][doc:selfarithmetic]Arithmetic self-operators[/doc][/td][/tr]
64
 
                        [tr][td]|=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
65
 
                        [tr][td]&=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
66
 
                        [tr][td]^=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
67
 
                        [tr][td]<<=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
68
 
                        [tr][td]>>=[/td][td][doc:selfbitwise]Bitwise self-operators[/doc][/td][/tr]
69
 
                        [tr][td].=[/td][td][doc:stringconcatenation]String concatenation operators[/doc][/td][/tr]
70
 
                        [tr][td]<<[/td][td][doc:stringconcatenation]String concatenation operators[/doc][/td][/tr]
71
 
                        [tr][td]<,[/td][td][doc:stringconcatenation]String concatenation operators[/doc][/td][/tr]
72
 
                        [tr][td]<+[/td][td][doc:arrayconcatenation]Array concatenation[/doc][/td][/tr]
73
 
                        [tr][td]=~[/td][td][doc:binding]Binding operator[/doc][/td][/tr]
74
 
                [/table]
75
 
*/
76
 
 
77
 
KviKvsTreeNodeData * KviKvsParser::parseOperationRightSide(bool bPreferNumeric)
78
 
{
79
 
        KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>();
80
 
        l->setAutoDelete(true);
81
 
 
82
 
        const QChar * pBegin = KVSP_curCharPointer;
83
 
 
84
 
        for(;;)
85
 
        {
86
 
                switch(KVSP_curCharUnicode)
87
 
                {
88
 
                        case 0:
89
 
                                goto end_of_the_param;
90
 
                        break;
91
 
                        case '\n':
92
 
                        case '\r':
93
 
                        case ';':
94
 
                                KVSP_skipChar;
95
 
                                goto end_of_the_param;
96
 
                        break;
97
 
                        case ' ':
98
 
                        case '\t':
99
 
                                skipSpaces();
100
 
                                if(KVSP_curCharIsEndOfCommand)
101
 
                                {
102
 
                                        goto end_of_the_param;
103
 
                                } else {
104
 
                                        // separate by single spaces
105
 
                                        bPreferNumeric = false; // this can't be a number
106
 
                                        l->append(new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString(" "))));
107
 
                                }
108
 
                        break;
109
 
                        default:
110
 
                                // anything else is a parameter
111
 
                                KviKvsTreeNodeData * p = parseCommandParameter(bPreferNumeric);
112
 
                                if(!p)
113
 
                                {
114
 
                                        // this is an error
115
 
                                        delete l;
116
 
                                        return 0;
117
 
                                }
118
 
                                l->append(p);
119
 
                        break;
120
 
                }
121
 
        }
122
 
 
123
 
end_of_the_param:
124
 
        if(l->count() > 1)
125
 
        {
126
 
                // complex parameter needed
127
 
                return new KviKvsTreeNodeCompositeData(pBegin,l);
128
 
        } else {
129
 
                if(l->count() > 0)
130
 
                {
131
 
                        // a single parameter in the list
132
 
                        l->setAutoDelete(false);
133
 
                        KviKvsTreeNodeData * p = l->first();
134
 
                        delete l;
135
 
                        return p;
136
 
                } else {
137
 
                        // empty (this should NEVER happen anyway)
138
 
                        delete l;
139
 
                        return new KviKvsTreeNodeConstantData(pBegin,new KviKvsVariant(QString("")));
140
 
                }
141
 
        }
142
 
        // never reached
143
 
        return 0;
144
 
}
145
 
 
146
 
/*
147
 
        @doc: assignment
148
 
        @title:
149
 
                Assignment operation
150
 
        @keyterms:
151
 
                assignment
152
 
        @type:
153
 
                language
154
 
        @short:
155
 
                Assignment operation
156
 
        @body:
157
 
                The assignment is the "plainest" of the operators: it works just like in any other programming language.[br]
158
 
                The syntax is:[br]
159
 
                [br]
160
 
                [b]<target> = <source>[/b]
161
 
                [br][br]
162
 
                <target> must be a variable, <source> can be any parameter.[br]
163
 
                If the <target> variable doesn't exist, it is created.
164
 
                If it already exists, it is eventually converted to the type of <souce> (scalar, hash or array).[br]
165
 
                If <source> evaluates to an empty value then the <target> variable is unset.
166
 
        @examples:
167
 
                [example]
168
 
                [comment]# Assigning a constant to the variable %Tmp[/comment]
169
 
                %Tmp = 1
170
 
                [cmd]echo[/cmd] %Tmp
171
 
                [comment]# Assigning a string constant to the variable %Tmp[/comment]
172
 
                %Tmp = some string
173
 
                [cmd]echo[/cmd] %Tmp
174
 
                [comment]# Assigning a string constant to the variable %Tmp[/comment]
175
 
                %Tmp = "some string with whitespace &nbsp; &nbsp; &nbsp; &nbsp; preserved"
176
 
                [cmd]echo[/cmd] %Tmp
177
 
                [comment]# Assigning a variable to another variable copies its contents[/comment]
178
 
                %Someothervariable = "Contents"
179
 
                %Tmp = %Someothervariable
180
 
                [cmd]echo[/cmd] %Tmp
181
 
                [comment]# Assigning a variable string to the variable %z[/comment]
182
 
                %color = blue
183
 
                %z = my eyes are %color
184
 
                [cmd]echo[/cmd] %z
185
 
                [comment]# Assigning a variable string (with a function call inside) to the variable %x[/comment]
186
 
                %x = the system os is [fnc]$system.osname[/fnc]
187
 
                [cmd]echo[/cmd] %x
188
 
                [comment]# Assigning an empty string to the local variable %y unsets %y[/comment]
189
 
                %x =
190
 
                [cmd]echo[/cmd] %y
191
 
                [comment]# This is equivalent to the above[/comment]
192
 
                %y = ""
193
 
                [comment]# This is equivalent too, if $function evalutates to an empty string[/comment]
194
 
                %y = $function()
195
 
                [comment]# Assigning a variable string to a hash entry[/comment]
196
 
                %Dict{key} = [fnc]$system.osname[/fnc]\ian
197
 
                [comment]# Unsetting an array entry[/comment]
198
 
                %mydict[23] = ""
199
 
                [comment]# Assigning a hash to another: %mydict[] becomes a copy of %anotherdict[][/comment]
200
 
                %anotherdict{"The key"} = "Some dummy value"
201
 
                %mydict = %anotherdict
202
 
                [cmd]echo[/cmd]%mydict{"The key"}
203
 
                [comment]# This will convert %mydict to be a scalar variable (deleting all the %mydict contents!)[/comment]
204
 
                %mydict = "some default value"
205
 
                [comment]# Unsetting a whole hash[/comment]
206
 
                %anotherdict =
207
 
                [/example]
208
 
*/
209
 
 
210
 
 
211
 
/*
212
 
        @doc: incrementdecrement
213
 
        @title:
214
 
                Increment and decrement operations
215
 
        @keyterms:
216
 
                increment, decrement
217
 
        @type:
218
 
                language
219
 
        @short:
220
 
                Increment and decrement operations
221
 
        @body:
222
 
                These two operators work only on numeric operands.[br]
223
 
                The syntax is:[br]
224
 
                [br]
225
 
                [b]<target>++[/b][br]
226
 
                [b]<target>--[/b][br]
227
 
                [br]
228
 
                ++ increments <target> by one, -- decrements <target> by one.[br]
229
 
                These are equivalent to += 1 and -= 1.[br]
230
 
                <target> must be an existing variable and contain an integer value.[br]
231
 
                If <target> contains a real value then the real is truncated to the nearest
232
 
                integer and then incremented or decremented.[br]
233
 
        @examples:
234
 
                [example]
235
 
                %a=10
236
 
                [cmd]echo[/cmd] "Incrementing"
237
 
                [cmd]while[/cmd](%a < 20)
238
 
                {
239
 
                        [cmd]echo[/cmd] %a
240
 
                        [b]%a++[/b]
241
 
                }
242
 
                [cmd]echo[/cmd] "Decrementing"
243
 
                [cmd]while[/cmd](%a > 10)
244
 
                {
245
 
                        [cmd]echo[/cmd] %a
246
 
                        [b]%a--[/b]
247
 
                }
248
 
                [cmd]echo[/cmd] "Testing for loop"
249
 
                [cmd]for[/cmd](%a=0;%a < 10;[b]%a++[/b])
250
 
                {
251
 
                        [cmd]echo[/cmd] %a
252
 
                }
253
 
                [/example]
254
 
        @seealso:
255
 
                [doc:operators]Operators[/doc]
256
 
*/
257
 
 
258
 
 
259
 
/*
260
 
        @doc: selfarithmetic
261
 
        @title:
262
 
                Arithmetic self-operators
263
 
        @type:
264
 
                language
265
 
        @short:
266
 
                Arithmetic self-operators
267
 
        @body:
268
 
                These operators work only on numeric operands.[br]
269
 
                The syntax is:[br]
270
 
                [br]
271
 
                [b]<target> += <right_operand>[/b][br]
272
 
                [b]<target> -= <right_operand>[/b][br]
273
 
                [b]<target> *= <right_operand>[/b][br]
274
 
                [b]<target> /= <right_operand>[/b][br]
275
 
                [b]<target> %= <right_operand>[/b][br]
276
 
                [br]
277
 
                <target> must be an existing variable and contain a numeric value.
278
 
                <right_operand> must evaluate to a numeric value.
279
 
                Note that if you want <right_operand> to be a result of an expression, you must
280
 
                enclose it in the $(*) expression evaluation call.[br]
281
 
                Operator += sums the <right_operand> value to the <target> value and stores the result in <target>.[br]
282
 
                Operator -= subtracts <right_operand> from <target> and stores the result in <target>.[br]
283
 
                Operator *= multiplies <target> by <right_operand> and stores the result in <target>.[br]
284
 
                Operator /= divides <target> by <right_operand> and stores the result in <target>.[br]
285
 
                Operator %= computes <target> modulus <right_operand> and stores the result in <target>.[br]
286
 
                The division and modulus operators fail with an error if <right_operand> is 0.[br]
287
 
                If both <target> and <right_operand> are integer values then the results of the division
288
 
                and modulus are integers (truncated for the division).[br]
289
 
                If <target> or <right_operand> or both are floating point values then the result is a floating point value.[br]
290
 
        @examples:
291
 
                [example]
292
 
                        %a=10
293
 
                        [cmd]echo[/cmd] %a
294
 
                        %a+=20
295
 
                        [cmd]echo[/cmd] %a
296
 
                        %a-=$(%a - 1)
297
 
                        [cmd]echo[/cmd] %a
298
 
                        %a *= 10
299
 
                        [cmd]echo[/cmd] %a
300
 
                        %a /= 21
301
 
                        [cmd]echo[/cmd] %a
302
 
                        %a *= 20
303
 
                        [cmd]echo[/cmd] %a
304
 
                        %a /= 21.0
305
 
                        [cmd]echo[/cmd] %a
306
 
                        %b = 10.0
307
 
                        %a %= %b
308
 
                        [cmd]echo[/cmd] %a
309
 
                        %a = 10
310
 
                        %b = 3
311
 
                        [comment]# nice trick[/comment]
312
 
                        %a /= %b.0
313
 
                        [cmd]echo[/cmd] %a
314
 
                [/example]
315
 
        @seealso:
316
 
                [doc:operators]Operators[/doc]
317
 
*/
318
 
 
319
 
 
320
 
/*
321
 
        @doc: selfbitwise
322
 
        @title:
323
 
                Bitwise self-operators
324
 
        @type:
325
 
                language
326
 
        @short:
327
 
                Bitwise self-operators
328
 
        @body:
329
 
                These operators work only on integer operands.[br]
330
 
                The syntax is:[br]
331
 
                [br]
332
 
                [b]<target> |= <right_operand>[/b][br]
333
 
                [b]<target> &= <right_operand>[/b][br]
334
 
                [b]<target> ^= <right_operand>[/b][br]
335
 
                [b]<target> >>= <right_operand>[/b][br]
336
 
                [b]<target> <<= <right_operand>[/b][br]
337
 
                [br]
338
 
                <target> must be an existing variable and contain a numeric value.
339
 
                <right_operand> must evaluate to a numeric value.
340
 
                If <target> or <right_operand> are floating point values then they are truncated
341
 
                and converted to integers.[br]
342
 
                Note that if you want <right_operand> to be a result of an expression, you must
343
 
                enclose it in the $(*) expression evaluation call.[br]
344
 
                Operator |= computes <target> bitwise-or <right_operand> and stores the result in <target>.[br]
345
 
                Operator &= computes <target> bitwise-and <right_operand> and stores the result in <target>.[br]
346
 
                Operator ^= computes <target> bitwise-xor <right_operand> and stores the result in <target>.[br]
347
 
                Operator >>= shifts <target> <right_operand> bits to the right and stores the result int <target>.[br]
348
 
                Operator <<= shifts <target> <right_operand> bits to the left and stores the result int <target>.[br]
349
 
                Note that "!=" is not available. You must use %a = $(!%b) to implement it.[br]
350
 
                For operators >>= and <<= <right_operand> must be a positive integer.[br]
351
 
        @examples:
352
 
                [example]
353
 
                        %a = 1
354
 
                        [cmd]echo[/cmd] %a
355
 
                        %a |= 2
356
 
                        [cmd]echo[/cmd] %a
357
 
                        %a &= 2
358
 
                        [cmd]echo[/cmd] %a
359
 
                        %a ^= 1
360
 
                        [cmd]echo[/cmd] %a
361
 
                        %a >>= 2
362
 
                        [cmd]echo[/cmd] %a
363
 
                        %a <<= 1
364
 
                        [cmd]echo[/cmd] %a
365
 
                [/example]
366
 
        @seealso:
367
 
                [doc:operators]Operators[/doc]
368
 
*/
369
 
 
370
 
 
371
 
/*
372
 
        @doc: stringconcatenation
373
 
        @title:
374
 
                String concatenation operators
375
 
        @type:
376
 
                language
377
 
        @short:
378
 
                String concatenation operators
379
 
        @body:
380
 
                These operators concatenate strings.
381
 
                The syntax is:[br]
382
 
                [br]
383
 
                [b]<target> .= <right_operand>[/b][br]
384
 
                [b]<target> << <right_operand>[/b][br]
385
 
                [b]<target> <, <right_operand>[/b][br]
386
 
                [br]
387
 
                Operator .= appends <right_operand> to <target>.
388
 
                Operator << appends a space followed by <right_operand> to <target> if <target> is non empty,
389
 
                otherwise sets <target> to <right_operand>.
390
 
                Operator <, is similar to << but uses a comma to separate the two variable contents.
391
 
                The last two operators are useful in creating space-separated or comma-separated lists.
392
 
        @examples:
393
 
                [example]
394
 
                        %a = ""
395
 
                        %a << free
396
 
                        [cmd]echo[/cmd] %a
397
 
                        %a .= bsd
398
 
                        [cmd]echo[/cmd] %a
399
 
                        %a << rox
400
 
                        [cmd]echo[/cmd] %a
401
 
                        %a <, but linux is better!
402
 
                        [cmd]echo[/cmd] %a
403
 
                [/example]
404
 
        @seealso:
405
 
                [doc:operators]Operators[/doc]
406
 
*/
407
 
 
408
 
 
409
 
/*
410
 
        @doc: arrayconcatenation
411
 
        @title:
412
 
                Array concatenation operator
413
 
        @type:
414
 
                language
415
 
        @short:
416
 
                Array concatenation operator
417
 
        @body:
418
 
                This operator concatenates arrays
419
 
                The syntax is:[br]
420
 
                [br]
421
 
                [b]<target> <+ <right_operand>[/b][br]
422
 
                [br]
423
 
                If <target> is not an array, it is converted to one first.
424
 
                After that, if <right_operand> is a scalar then it is appended
425
 
                to the end of the <target> array. If <right_operand> is an array
426
 
                then all of its items are appended to the end of the <target> array.
427
 
                If <right_operand> is a hash then all of its value items
428
 
                are appended to the end of the <target> array.
429
 
        @seealso:
430
 
                [doc:operators]Operators[/doc]
431
 
*/
432
 
 
433
 
 
434
 
 
435
 
/*
436
 
        @doc: binding
437
 
        @title:
438
 
                Binding operator
439
 
        @type:
440
 
                language
441
 
        @short:
442
 
                Binding operator
443
 
        @body:
444
 
                This operator is a really ugly, poor and clueless attempt to reach at least 1% of the
445
 
                power of the perl =~ operator :D[br]
446
 
                It allows some complex string operations to be performed efficently by operating directly
447
 
                on the left operand (in fact this is a lot faster in KVIrc since at least one step of parsing is skipped).[br]
448
 
                Its basic syntax is:[br]
449
 
                [br][b]<left_operand> =~ <operation>[parameters][/b][br][br]
450
 
                Where <operation> may be one of 't','s' and parameters depend on it.[br]
451
 
                <left_operand> is the target of the <operation>.[br]
452
 
                If <left_operand> is an array or dictionary, the <operation> is executed on each item they contain.[br]
453
 
                Operation 't' is the transliteration.[br]
454
 
                The complete syntax with parameters is:[br]
455
 
                [br][b]<left_operand> =~ t/<search characters>/<replacement characters>/[/b][br][br]
456
 
                where <search characters> is a string of characters that are replaced with the corresponding
457
 
                characters in <replacement characters>.[br]
458
 
                This operation can be also named 'y' or 'tr' (to preserve some compatibility with other languages).
459
 
                [example]
460
 
                %A=This is a test string
461
 
                echo %A
462
 
                %A=~ tr/abcdefghi/ABCDEFGHI/
463
 
                echo %A
464
 
                [/example]
465
 
                Operation 's' is the substitution.[br]
466
 
                The complete syntax with parameters is:[br]
467
 
                [br][b]<left_operand> =~ s/<search pattern>/<replacement pattern>/[flags][/b][br][br]
468
 
                where <search pattern> is an extended regular expression to be matched in the <left_operand>
469
 
                and <replacement string> is a special pattern that will replace any occurence found.[br]
470
 
                <search pattern> may contain parentheses to capture parts of the matched text.
471
 
                <replacement string> can contain the escape sequences \\N where N is a number between 1 and 9
472
 
                to be replaced by the captured text.[br]
473
 
                (We use \\N because KVIrc will first unquote the string when parsing...)[br]
474
 
                \\0 is a special escape that will be replaced by the entire match (is always valid!).[br]
475
 
                [flags] may be a combination of the letters 'g','i' and 'w'.[br]
476
 
                'g' causes the search to be global and not stop after the first occurence of <search pattern>.[br]
477
 
                'i' causes the search to be case insensitive.[br]
478
 
                'w' causes the search pattern to be interpreted as a simple wildcard regular expression.
479
 
        @examples:
480
 
                [example]
481
 
                        %A=This is a test string
482
 
                        echo %A
483
 
                        %A=~ s/([a-z])i([a-z])/\\1I\\2/
484
 
                        echo %A
485
 
                        %A=~ s/([a-z])i([a-z])/\\1@\\2/gi
486
 
                        echo %A
487
 
                [/example]
488
 
                [example]
489
 
                        %a = ""
490
 
                        %a << free
491
 
                        [cmd]echo[/cmd] %a
492
 
                        %a .= bsd
493
 
                        [cmd]echo[/cmd] %a
494
 
                        %a << rox
495
 
                        [cmd]echo[/cmd] %a
496
 
                        %a <, but linux is better!
497
 
                        [cmd]echo[/cmd] %a
498
 
                [/example]
499
 
        @seealso:
500
 
                [doc:operators]Operators[/doc]
501
 
*/
502
 
 
503
 
KviKvsTreeNodeData * KviKvsParser::parseBindingOperationParameter()
504
 
{
505
 
        KviPointerList<KviKvsTreeNodeData> * l = new KviPointerList<KviKvsTreeNodeData>;
506
 
        l->setAutoDelete(true);
507
 
 
508
 
        const QChar * pBegin = KVSP_curCharPointer;
509
 
 
510
 
        for(;;)
511
 
        {
512
 
                switch(KVSP_curCharUnicode)
513
 
                {
514
 
                        case 0:
515
 
                        case '/':
516
 
                        case '\n':
517
 
                        case '\r':
518
 
                                // not a part of a parameter
519
 
                                goto end_of_function_parameter;
520
 
                        break;
521
 
                        case '$':
522
 
                        case '%':
523
 
                        case '@':
524
 
                        {
525
 
                                // this may be a data reference
526
 
                                KviKvsTreeNodeData * p = parseParameterPercentOrDollar();
527
 
                                if(!p)
528
 
                                {
529
 
                                        // this is an error
530
 
                                        delete l;
531
 
                                        return 0;
532
 
                                }
533
 
                                l->append(p);
534
 
                        }
535
 
                        break;
536
 
                        case '"':
537
 
                        {
538
 
                                // this is a string
539
 
                                KviKvsTreeNodeData * p = parseStringParameter();
540
 
                                if(!p)
541
 
                                {
542
 
                                        // this is an error
543
 
                                        delete l;
544
 
                                        return 0;
545
 
                                }
546
 
                                l->append(p);
547
 
                        }
548
 
                        break;
549
 
                        default:
550
 
                        {
551
 
                                // anything else is a literal
552
 
                                l->append(parseBindingOperationLiteralParameter());
553
 
                        }
554
 
                        break;
555
 
                }
556
 
        }
557
 
end_of_function_parameter:
558
 
        if(l->count() > 1)
559
 
        {
560
 
                // complex parameter needed
561
 
                return new KviKvsTreeNodeCompositeData(pBegin,l);
562
 
        } else {
563
 
                // a single parameter in the list or empty list at all
564
 
                l->setAutoDelete(false);
565
 
                KviKvsTreeNodeData * p = l->first();
566
 
                delete l;
567
 
                if(!p)p = new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString("")));
568
 
                return p;
569
 
        }
570
 
        // never reached
571
 
        return 0;
572
 
}
573
 
 
574
 
 
575
 
 
576
 
KviKvsTreeNodeOperation * KviKvsParser::parseBindingOperation()
577
 
{
578
 
        // t or tr or y
579
 
        // s
580
 
        const QChar * pBegin = KVSP_curCharPointer;
581
 
 
582
 
        while(KVSP_curCharIsLetter)KVSP_skipChar;
583
 
 
584
 
        QString szOp = QString(pBegin,KVSP_curCharPointer - pBegin).toLower();
585
 
 
586
 
        skipSpaces();
587
 
 
588
 
        if(KVSP_curCharUnicode != '/')
589
 
        {
590
 
                error(KVSP_curCharPointer,__tr2qs_ctx("Found character '%q' (unicode %x) where a slash '/' was expected","kvs"),KVSP_curCharPointer,KVSP_curCharUnicode);
591
 
                return 0;
592
 
        }
593
 
 
594
 
        KVSP_skipChar;
595
 
 
596
 
        KviKvsTreeNodeData * pFirst = parseBindingOperationParameter();
597
 
        if(!pFirst)return 0;
598
 
 
599
 
        if(KVSP_curCharIsEndOfCommand)
600
 
        {
601
 
                error(KVSP_curCharPointer,__tr2qs_ctx("Unexpected end of command in binding operation, at least two slashes are missing","kvs"));
602
 
                delete pFirst;
603
 
                return 0;
604
 
        }
605
 
 
606
 
        if(KVSP_curCharUnicode != '/')
607
 
        {
608
 
                error(KVSP_curCharPointer,__tr2qs_ctx("Found character '%q' (unicode %x) where a slash '/' was expected","kvs"),KVSP_curCharPointer,KVSP_curCharUnicode);
609
 
                delete pFirst;
610
 
                return 0;
611
 
        }
612
 
 
613
 
        KVSP_skipChar;
614
 
 
615
 
        KviKvsTreeNodeData * pSecond = parseBindingOperationParameter();
616
 
        if(!pSecond)
617
 
        {
618
 
                delete pFirst;
619
 
                return 0;
620
 
        }
621
 
 
622
 
        if(KVSP_curCharIsEndOfCommand)
623
 
        {
624
 
                error(KVSP_curCharPointer,__tr2qs_ctx("Unexpected end of command in binding operation, at least one slash is missing","kvs"));
625
 
                delete pFirst;
626
 
                return 0;
627
 
        }
628
 
 
629
 
        if(KVSP_curCharUnicode != '/')
630
 
        {
631
 
                error(KVSP_curCharPointer,__tr2qs_ctx("Found character '%q' (unicode %x) where a slash '/' was expected","kvs"),KVSP_curCharPointer,KVSP_curCharUnicode);
632
 
                delete pFirst;
633
 
                return 0;
634
 
        }
635
 
 
636
 
        KVSP_skipChar;
637
 
 
638
 
        KviKvsTreeNodeData * pThird = parseCommandParameter();
639
 
        if(!pThird)
640
 
        {
641
 
                if(error())
642
 
                {
643
 
                        delete pFirst;
644
 
                        delete pSecond;
645
 
                        return 0;
646
 
                }
647
 
 
648
 
                pThird = new KviKvsTreeNodeConstantData(KVSP_curCharPointer,new KviKvsVariant(QString("")));
649
 
        }
650
 
 
651
 
        while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
652
 
        if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
653
 
 
654
 
        if((szOp == "t") || (szOp == "tr") || (szOp == "y"))
655
 
        {
656
 
                // transliteration  tr/szFirst/szSecond/szFlags
657
 
                return new KviKvsTreeNodeOperationStringTransliteration(pBegin,pFirst,pSecond,pThird);
658
 
        } else if(szOp == "s")
659
 
        {
660
 
                // regexp substitution s/szFirst/szSecond/szFlags
661
 
                return new KviKvsTreeNodeOperationStringSubstitution(pBegin,pFirst,pSecond,pThird);
662
 
        }
663
 
 
664
 
        error(KVSP_curCharPointer,__tr2qs_ctx("Unknown binding operation '%Q'","kvs"),&szOp);
665
 
        return 0;
666
 
}
667
 
 
668
 
 
669
 
KviKvsTreeNodeOperation * KviKvsParser::parseOperation()
670
 
{
671
 
        // find the operator
672
 
        const QChar * pBegin = KVSP_curCharPointer;
673
 
 
674
 
        switch(KVSP_curCharUnicode)
675
 
        {
676
 
                case '=':
677
 
                {
678
 
                        KVSP_skipChar;
679
 
                        if(KVSP_curCharUnicode == '~')
680
 
                        {
681
 
                                KVSP_skipChar;
682
 
                                skipSpaces();
683
 
                                if(KVSP_curCharIsEndOfCommand)
684
 
                                {
685
 
                                        error(KVSP_curCharPointer,__tr2qs_ctx("Missing right side operand for the binding operator '=~'","kvs"));
686
 
                                        return 0;
687
 
                                }
688
 
                                return parseBindingOperation();
689
 
                        } else {
690
 
                                skipSpaces();
691
 
                                KviKvsTreeNodeData * d = parseOperationRightSide(true);
692
 
                                if(!d)return 0; // error
693
 
                                return new KviKvsTreeNodeOperationAssignment(pBegin,d);
694
 
                        }
695
 
                }
696
 
                break;
697
 
                case '+':
698
 
                        KVSP_skipChar;
699
 
                        switch(KVSP_curCharUnicode)
700
 
                        {
701
 
                                case '+':
702
 
                                        // operator ++
703
 
                                        KVSP_skipChar;
704
 
                                        skipSpaces();
705
 
                                        if(!KVSP_curCharIsEndOfCommand)
706
 
                                        {
707
 
                                                warning(KVSP_curCharPointer,__tr2qs_ctx("Trailing garbage ignored after operator '++'","kvs"));
708
 
                                        }
709
 
                                        while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
710
 
                                        if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
711
 
                                        return new KviKvsTreeNodeOperationIncrement(pBegin);
712
 
                                break;
713
 
                                case '=':
714
 
                                        // operator +=
715
 
                                        KVSP_skipChar;
716
 
                                        skipSpaces();
717
 
                                        if(KVSP_curCharIsEndOfCommand)
718
 
                                        {
719
 
                                                error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '+='","kvs"));
720
 
                                                return 0;
721
 
                                        }
722
 
                                        KviKvsTreeNodeData * d = parseOperationRightSide(true);
723
 
                                        if(!d)return 0; // error
724
 
                                        return new KviKvsTreeNodeOperationSelfSum(pBegin,d);
725
 
                                break;
726
 
                        }
727
 
                break;
728
 
                case '-':
729
 
                        KVSP_skipChar;
730
 
                        switch(KVSP_curCharUnicode)
731
 
                        {
732
 
                                case '-':
733
 
                                        KVSP_skipChar;
734
 
                                        // operator --
735
 
                                        skipSpaces();
736
 
                                        if(!KVSP_curCharIsEndOfCommand)
737
 
                                        {
738
 
                                                warning(KVSP_curCharPointer,__tr2qs_ctx("Trailing garbage ignored after operator '--'","kvs"));
739
 
                                        }
740
 
                                        while(!KVSP_curCharIsEndOfCommand)KVSP_skipChar;
741
 
                                        if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
742
 
                                        return new KviKvsTreeNodeOperationDecrement(pBegin);
743
 
                                break;
744
 
                                case '>':
745
 
                                        warning(KVSP_curCharPointer,__tr2qs_ctx("This looks a lot like an object handle dereferencing operator '->' but in fact it isn't. Maybe you forgot a '$' just after?","kvs"));
746
 
                                break;
747
 
                                case '=':
748
 
                                        // operator -=
749
 
                                        KVSP_skipChar;
750
 
                                        skipSpaces();
751
 
                                        if(KVSP_curCharIsEndOfCommand)
752
 
                                        {
753
 
                                                error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '-='","kvs"));
754
 
                                                return 0;
755
 
                                        }
756
 
                                        KviKvsTreeNodeData * d = parseOperationRightSide(true);
757
 
                                        if(!d)return 0; // error
758
 
                                        return new KviKvsTreeNodeOperationSelfSubtraction(pBegin,d);
759
 
                                break;
760
 
                        }
761
 
                break;
762
 
                case '<':
763
 
                        KVSP_skipChar;
764
 
                        switch(KVSP_curCharUnicode)
765
 
                        {
766
 
                                case '<':
767
 
                                        KVSP_skipChar;
768
 
                                        if(KVSP_curCharUnicode == '=')
769
 
                                        {
770
 
                                                KVSP_skipChar;
771
 
                                                skipSpaces();
772
 
                                                if(KVSP_curCharIsEndOfCommand)
773
 
                                                {
774
 
                                                        error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '<<='","kvs"));
775
 
                                                        return 0;
776
 
                                                }
777
 
                                                KviKvsTreeNodeData * d = parseOperationRightSide(true);
778
 
                                                if(!d)return 0; // error
779
 
                                                return new KviKvsTreeNodeOperationSelfShl(pBegin,d);
780
 
                                        } else {
781
 
                                                skipSpaces();
782
 
                                                if(KVSP_curCharIsEndOfCommand)
783
 
                                                {
784
 
                                                        error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '<<'","kvs"));
785
 
                                                        return 0;
786
 
                                                }
787
 
                                                KviKvsTreeNodeData * d = parseOperationRightSide();
788
 
                                                if(!d)return 0; // error
789
 
                                                return new KviKvsTreeNodeOperationStringAppendWithSpace(pBegin,d);
790
 
                                        }
791
 
                                break;
792
 
                                case ',':
793
 
                                {
794
 
                                        KVSP_skipChar;
795
 
                                        skipSpaces();
796
 
                                        if(KVSP_curCharIsEndOfCommand)
797
 
                                        {
798
 
                                                error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '<,'","kvs"));
799
 
                                                return 0;
800
 
                                        }
801
 
                                        KviKvsTreeNodeData * d = parseOperationRightSide();
802
 
                                        if(!d)return 0; // error
803
 
                                        return new KviKvsTreeNodeOperationStringAppendWithComma(pBegin,d);
804
 
                                }
805
 
                                break;
806
 
                                case '+':
807
 
                                {
808
 
                                        KVSP_skipChar;
809
 
                                        skipSpaces();
810
 
                                        if(KVSP_curCharIsEndOfCommand)
811
 
                                        {
812
 
                                                error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '<+'","kvs"));
813
 
                                                return 0;
814
 
                                        }
815
 
                                        KviKvsTreeNodeData * d = parseOperationRightSide();
816
 
                                        if(!d)return 0; // error
817
 
                                        return new KviKvsTreeNodeOperationArrayAppend(pBegin,d);
818
 
                                }
819
 
                                break;
820
 
                        }
821
 
                break;
822
 
                case '>':
823
 
                        KVSP_skipChar;
824
 
                        switch(KVSP_curCharUnicode)
825
 
                        {
826
 
                                case '>':
827
 
                                        KVSP_skipChar;
828
 
                                        if(KVSP_curCharUnicode == '=')
829
 
                                        {
830
 
                                                KVSP_skipChar;
831
 
                                                skipSpaces();
832
 
                                                if(KVSP_curCharIsEndOfCommand)
833
 
                                                {
834
 
                                                        error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '>>='","kvs"));
835
 
                                                        return 0;
836
 
                                                }
837
 
                                                KviKvsTreeNodeData * d = parseOperationRightSide(true);
838
 
                                                if(!d)return 0; // error
839
 
                                                return new KviKvsTreeNodeOperationSelfShr(pBegin,d);
840
 
                                        }
841
 
                                break;
842
 
                        }
843
 
                break;
844
 
                case '.':
845
 
                        KVSP_skipChar;
846
 
                        switch(KVSP_curCharUnicode)
847
 
                        {
848
 
                                case '=':
849
 
                                        KVSP_skipChar;
850
 
                                        skipSpaces();
851
 
                                        if(KVSP_curCharIsEndOfCommand)
852
 
                                        {
853
 
                                                error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '.='","kvs"));
854
 
                                                return 0;
855
 
                                        }
856
 
                                        KviKvsTreeNodeData * d = parseOperationRightSide();
857
 
                                        if(!d)return 0; // error
858
 
                                        return new KviKvsTreeNodeOperationStringAppend(pBegin,d);
859
 
                                break;
860
 
                        }
861
 
                break;
862
 
#define SELF_OPERATOR(__opchar,__opstr,__class) \
863
 
                case __opchar: \
864
 
                        KVSP_skipChar; \
865
 
                        switch(KVSP_curCharUnicode) \
866
 
                        { \
867
 
                                case '=': \
868
 
                                        KVSP_skipChar; \
869
 
                                        skipSpaces(); \
870
 
                                        if(KVSP_curCharIsEndOfCommand) \
871
 
                                        { \
872
 
                                                error(KVSP_curCharPointer,__tr2qs_ctx("Missing right operand for operator '" __opstr "='","kvs")); \
873
 
                                                return 0; \
874
 
                                        } \
875
 
                                        KviKvsTreeNodeData * d = parseOperationRightSide(true); \
876
 
                                        if(!d)return 0; \
877
 
                                        return new __class(pBegin,d); \
878
 
                                break; \
879
 
                        } \
880
 
                break;
881
 
                SELF_OPERATOR('*',"*",KviKvsTreeNodeOperationSelfMultiplication)
882
 
                SELF_OPERATOR('/',"/",KviKvsTreeNodeOperationSelfDivision)
883
 
                SELF_OPERATOR('%',"%",KviKvsTreeNodeOperationSelfModulus)
884
 
                SELF_OPERATOR('|',"|",KviKvsTreeNodeOperationSelfOr)
885
 
                SELF_OPERATOR('&',"&",KviKvsTreeNodeOperationSelfAnd)
886
 
                SELF_OPERATOR('^',"^",KviKvsTreeNodeOperationSelfXor)
887
 
        }
888
 
 
889
 
        error(pBegin,__tr2qs_ctx("Unknown operator","kvs"));
890
 
        return 0;
891
 
}
892
 
 
893
 
KviKvsTreeNodeInstruction * KviKvsParser::parseVoidFunctionCallOrOperation()
894
 
{
895
 
        KVSP_ASSERT((KVSP_curCharUnicode == '$') || (KVSP_curCharUnicode == '%') || (KVSP_curCharUnicode == '@'));
896
 
 
897
 
        const QChar * pBegin = KVSP_curCharPointer;
898
 
 
899
 
        KviKvsTreeNodeData * r = parsePercentOrDollar();
900
 
 
901
 
        if(!r)
902
 
        {
903
 
                // must be an error
904
 
                return 0;
905
 
        }
906
 
 
907
 
        skipSpaces();
908
 
 
909
 
        if(KVSP_curCharIsEndOfCommand)
910
 
        {
911
 
                // the end of the command
912
 
                if(!r->isFunctionCall())
913
 
                {
914
 
                        if(r->isReadOnly())
915
 
                        {
916
 
                                warning(pBegin,__tr2qs_ctx("Unexpected (and senseless) read-only data evaluation","kvs"));
917
 
                                error(KVSP_curCharPointer,__tr2qs_ctx("Syntax error: confused by earlier errors: bailing out","kvs"));
918
 
                        } else {
919
 
                                error(KVSP_curCharPointer,__tr2qs_ctx("Unexpected end of script after a variable reference: expected operator","kvs"));
920
 
                        }
921
 
                        delete r;
922
 
                        return 0;
923
 
                } else {
924
 
                        if(!KVSP_curCharIsEndOfBuffer)KVSP_skipChar;
925
 
                        return new KviKvsTreeNodeVoidFunctionCall(r->location(),(KviKvsTreeNodeFunctionCall *)r);
926
 
                }
927
 
        }
928
 
 
929
 
        // not the end of a command : an operation
930
 
        if(r->isReadOnly())
931
 
        {
932
 
                // must be followed by the end of a command
933
 
                if(r->isFunctionCall())
934
 
                {
935
 
                        error(KVSP_curCharPointer,__tr2qs_ctx("Unexpected character '%q' (unicode %x) after a void function call: end of instruction expected","kvs"),KVSP_curCharPointer,KVSP_curCharUnicode);
936
 
                } else {
937
 
                        warning(pBegin,__tr2qs_ctx("Unexpected (and senseless) read-only data evaluation","kvs"));
938
 
                        warning(pBegin,__tr2qs_ctx("Unexpected character '%q' (unicode %x)","kvs"),KVSP_curCharPointer,KVSP_curCharUnicode);
939
 
                        error(KVSP_curCharPointer,__tr2qs_ctx("Syntax error: confused by earlier errors: bailing out","kvs"));
940
 
                }
941
 
                delete r;
942
 
                return 0;
943
 
        }
944
 
 
945
 
        // ok.. parse the operation
946
 
        KviKvsTreeNodeOperation * op = parseOperation();
947
 
        if(!op)
948
 
        {
949
 
                delete r;
950
 
                return 0;
951
 
        }
952
 
 
953
 
        op->setTargetVariableReference(r);
954
 
        return op;
955
 
}