~ubuntu-branches/ubuntu/hoary/kvirc/hoary

« back to all changes in this revision

Viewing changes to src/kvirc/kvi_expression.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Robin Verduijn
  • Date: 2004-12-14 15:32:19 UTC
  • mfrom: (0.2.1 upstream) (1.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20041214153219-fdink3gyp2s20b6g
Tags: 2:2.1.3.1-2
* Change Recommends on xmms to a Suggests.
* Rebuild against KDE 3.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
//   File : kvi_expression.cpp (/usr/build/NEW_kvirc/kvirc/src/kvirc/kvi_expression.cpp)
3
 
//   Last major modification : Sat Feb 27 1999 19:31:10 by Szymon Stefanek
4
 
//
5
 
//   This file is part of the KVirc irc client distribution
 
1
// =============================================================================
 
2
//
 
3
//      --- kvi_expression.cpp ---
 
4
//
 
5
//   This file is part of the KVIrc IRC client distribution
6
6
//   Copyright (C) 1999-2000 Szymon Stefanek (stefanek@tin.it)
7
7
//
8
8
//   This program is FREE software. You can redistribute it and/or
17
17
//
18
18
//   You should have received a copy of the GNU General Public License
19
19
//   along with this program. If not, write to the Free Software Foundation,
20
 
//   Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
20
//   Inc, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
21
//
 
22
// =============================================================================
22
23
 
23
24
#define _KVI_DEBUG_CHECK_RANGE_
 
25
#define _KVI_DEBUG_CLASS_NAME_ "KviExpression"
 
26
 
 
27
#include "kvi_command.h"
24
28
#include "kvi_debug.h"
25
 
 
26
 
#include "kvi_app.h"
27
 
#include "kvi_uparser.h"
28
 
#include "kvi_ircsocket.h"
29
 
#include "kvi_console.h"
30
 
#include "kvi_defines.h"
31
 
#include "kvi_frame.h"
32
 
#include "kvi_options.h"
33
29
#include "kvi_error.h"
 
30
#include "kvi_exprtree.h"
34
31
#include "kvi_locale.h"
35
 
#include "kvi_exprtree.h"
36
 
 
37
 
 
38
 
bool KviUserParser::evaluateExpr(KviCommand *c,long * result)
 
32
#include "kvi_userparser.h"
 
33
 
 
34
bool KviUserParser::evaluateExpr(KviCommand *cmd, long *result)
39
35
{
40
36
        // This one evaluates an expression
41
 
        KviExprTree * root = evaluateExpression(c);
42
 
        if(!root)return false;
43
 
        if(*(c->m_ptr) != ')'){
44
 
                c->setError(KVI_ERROR_ParenthesisMismatch,_i18n_("EXPRESSION-END"),c->m_ptr);
 
37
        KviExprTree *root = evaluateExpression(cmd);
 
38
        if( !root ) return false;
 
39
 
 
40
        if( *(cmd->m_ptr) != ')' ) {
 
41
                cmd->setError(KVI_ERROR_ParenthesisMismatch, _i18n_("EXPRESSION-END"), cmd->m_ptr);
45
42
                return false;
46
43
        }
47
 
        *result = root->calculate(c);
 
44
        *result = root->calculate(cmd);
48
45
        delete root;
49
 
        ++(c->m_ptr);
50
 
        return (!c->hasError());
 
46
        ++(cmd->m_ptr);
 
47
        return (!cmd->hasError());
51
48
}
52
49
 
53
 
KviExprTree * KviUserParser::evaluateExpression(KviCommand *c)
 
50
KviExprTree *KviUserParser::evaluateExpression(KviCommand *cmd)
54
51
{
55
52
        // This one evaluates the expression up to a (not matching) ')' or a \0
56
 
        KviExprTree * op = evaluateOperand(c);
57
 
        if(!op)return 0;
58
 
        c->skipSpace();
59
 
        if((*(c->m_ptr) == ')')||(*(c->m_ptr) == '\0'))return op;//single operand
60
 
        KviExprTree * curOper = evaluateOperator(c);
61
 
        if(!curOper){
 
53
        KviExprTree *op = evaluateOperand(cmd);
 
54
        if( !op ) return 0;
 
55
 
 
56
        cmd->skipSpace();
 
57
        if( (*(cmd->m_ptr) == ')') || (*(cmd->m_ptr) == '\0') )
 
58
                return op; // Single operand
 
59
        KviExprTree *curOper = evaluateOperator(cmd);
 
60
        if( !curOper ) {
62
61
                delete op;
63
62
                return 0;
64
63
        }
65
64
        curOper->setLeft(op);
66
 
        return evaluateExpression_RightOperand(curOper,c);
 
65
        return evaluateExpression_RightOperand(curOper, cmd);
67
66
}
68
67
 
69
 
KviExprTree * KviUserParser::evaluateOperand(KviCommand *c)
 
68
KviExprTree *KviUserParser::evaluateOperand(KviCommand *cmd)
70
69
{
71
 
        // This one tries to extract a numeric operand from the data buffer
72
 
        // Moves m_ptr to the character after the last char of the operand
73
 
        // Returns a valid KviExprTreeNode of succesful 
74
 
        // otherwise returns 0 and sets c->m_err appropriately
75
 
        c->skipSpace();
 
70
        // This one tries to extract a numeric operand from the data buffer.
 
71
        // Moves m_ptr to the character after the last char of the operand.
 
72
        // Returns a valid KviExprTreeNode of successful,
 
73
        // otherwise returns 0 and sets cmd->m_err appropriately.
 
74
        cmd->skipSpace();
76
75
 
77
 
        KviExprTree * pTop = 0;
78
 
        KviExprTree * pCur = 0;
79
 
        KviExprTree * pLast = 0;
 
76
        KviExprTree *pTop  = 0;
 
77
        KviExprTree *pCur  = 0;
 
78
        KviExprTree *pLast = 0;
80
79
 
81
80
        // Check for unary ops...
82
 
        while(*(c->m_ptr) == '-' || *(c->m_ptr) == '~' || *(c->m_ptr) == '!'){
 
81
        while( *(cmd->m_ptr) == '-' || *(cmd->m_ptr) == '~' || *(cmd->m_ptr) == '!' ) {
83
82
                // Unary op
84
 
                switch(*(c->m_ptr)){
 
83
                switch( *(cmd->m_ptr) ) {
85
84
                        case '-':
86
 
                                pCur = new KviExprTree(KviExprTree::UnaryOperator,OP_NEGATE);
87
 
                        break;
 
85
                                pCur = new KviExprTree(KviExprTree::UnaryOperator, OP_NEGATE);
 
86
                                break;
88
87
                        case '~':
89
 
                                pCur = new KviExprTree(KviExprTree::UnaryOperator,OP_BITNOT);
90
 
                        break;
 
88
                                pCur = new KviExprTree(KviExprTree::UnaryOperator, OP_BITNOT);
 
89
                                break;
91
90
                        case '!':
92
 
                                pCur = new KviExprTree(KviExprTree::UnaryOperator,OP_NOT);
93
 
                        break;
 
91
                                pCur = new KviExprTree(KviExprTree::UnaryOperator, OP_NOT);
 
92
                                break;
94
93
                }
95
94
                // And we work with the child
96
 
                if(pTop == 0)pTop = pCur;
97
 
                else pLast->setLeft(pCur);
 
95
                if( !pTop )
 
96
                        pTop = pCur;
 
97
                else
 
98
                        pLast->setLeft(pCur);
98
99
                pLast = pCur;
99
 
                ++(c->m_ptr);
100
 
                c->skipSpace();
 
100
                ++(cmd->m_ptr);
 
101
                cmd->skipSpace();
101
102
        }
102
103
 
103
 
        if(*(c->m_ptr) == '('){
104
 
                // subexpression
105
 
                ++(c->m_ptr);
106
 
                pCur = evaluateExpression(c);
107
 
                if(!pCur){                              // failed somewhere in the call
108
 
                        if(pTop)delete pTop;
 
104
        if( *(cmd->m_ptr) == '(' ) {
 
105
                // Subexpression
 
106
                ++(cmd->m_ptr);
 
107
                pCur = evaluateExpression(cmd);
 
108
                if( !pCur ) { // Failed somewhere in the call
 
109
                        if( pTop )
 
110
                                delete pTop;
109
111
                        return 0;
110
112
                }
111
 
                if(*(c->m_ptr) != ')'){                         // failed here
112
 
                        if(pTop)delete pTop;
 
113
                if( *(cmd->m_ptr) != ')' ) { // Failed here
 
114
                        if( pTop )
 
115
                                delete pTop;
113
116
                        delete pCur;
114
 
                        c->setError(KVI_ERROR_ParenthesisMismatch,_i18n_("SUBEXPRESSION"));
 
117
                        cmd->setError(KVI_ERROR_ParenthesisMismatch, _i18n_("SUBEXPRESSION"));
115
118
                        return 0;
116
119
                }
117
 
                ++(c->m_ptr);
 
120
                ++(cmd->m_ptr);
118
121
        } else {
119
 
                // here *m_ptr may be something that is not a digit too!
120
 
                pCur = evaluateSimpleOperand(c);
121
 
                if(!pCur){                            // failed somewere
122
 
                        if(pTop)delete pTop;
 
122
                // Here *m_ptr may be something that is not a digit too!
 
123
                pCur = evaluateSimpleOperand(cmd);
 
124
                if( !pCur ) { // Failed somewere
 
125
                        if( pTop )
 
126
                                delete pTop;
123
127
                        return 0;
124
128
                }
125
129
        }
126
 
        if(pTop)pLast->setLeft(pCur);
127
 
        else return pCur;
 
130
        if( pTop )
 
131
                pLast->setLeft(pCur);
 
132
        else
 
133
                return pCur;
128
134
        return pTop;
129
135
}
130
136
 
131
 
KviExprTree * KviUserParser::evaluateStringOperand(KviCommand *c)
 
137
KviExprTree *KviUserParser::evaluateStringOperand(KviCommand *cmd)
132
138
{
133
 
        __range_valid(*(c->m_ptr) == '"');
134
 
        KviExprTree * node = new KviExprTree(KviExprTree::StringOperand,0);
135
 
        const char *aux_ptr = ++(c->m_ptr);
 
139
        __range_valid(*(cmd->m_ptr) == '"');
 
140
        KviExprTree *node = new KviExprTree(KviExprTree::StringOperand, 0);
 
141
        const char *aux_ptr = ++(cmd->m_ptr);
136
142
 
137
 
        for(;;){
138
 
                // Now skip all the non interesting chars
139
 
                while(*aux_ptr && (*aux_ptr != '\\') && (*aux_ptr != '\n') &&
140
 
                                (*aux_ptr != '"') && (*aux_ptr != '$') && (*aux_ptr != KVI_GLOBAL_VAR_CHAR))++aux_ptr;
 
143
        for( ;; ) {
 
144
                // Now skip all the uninteresting chars
 
145
                while( *aux_ptr && (*aux_ptr != '\\') &&
 
146
                      (*aux_ptr != '\n') && (*aux_ptr != '"') &&
 
147
                          (*aux_ptr != '$')  && (*aux_ptr != KVI_GLOBAL_VAR_CHAR)
 
148
                ) {
 
149
                        ++aux_ptr;
 
150
                }
141
151
                // Interesting char
142
 
                switch(*aux_ptr){
 
152
                switch( *aux_ptr ) {
143
153
                        case '\n':
144
 
                        case '\0': // end of command buffer...append the last block to the buffer and return
145
 
                                c->setError(KVI_ERROR_UnexpectedEndInString,_i18n_("EXPRESSION-STRING-OPERAND"));
 
154
                        case '\0': // End of command buffer... append the last block to the buffer and return
 
155
                                cmd->setError(KVI_ERROR_UnexpectedEndInString, _i18n_("EXPRESSION-STRING-OPERAND"));
146
156
                                delete node;
147
157
                                return 0;
148
 
                        break;
149
 
                        case '"' : // append the last block to the buffer and return
150
 
                                node->m_string.append(c->m_ptr,aux_ptr - c->m_ptr);
151
 
                                c->m_ptr = ++aux_ptr; //don't forget to point to next char
 
158
                                break;
 
159
                        case '"' : // Append the last block to the buffer and return
 
160
                                node->m_string.append(cmd->m_ptr, aux_ptr - cmd->m_ptr);
 
161
                                cmd->m_ptr = ++aux_ptr; // Do not forget to point to next char
152
162
                                return node;
153
 
                        break;
154
 
                        case KVI_GLOBAL_VAR_CHAR: //variable: append the last block to the buffer and process the var
155
 
                                node->m_string.append(c->m_ptr,aux_ptr - c->m_ptr);
156
 
                                c->m_ptr = aux_ptr;
157
 
                                if(!processVariable(c,node->m_string)){
158
 
                                        delete node;
159
 
                                        return 0;
160
 
                                }
161
 
                                aux_ptr = c->m_ptr;
162
 
                        break;
163
 
                        case '$': //system identifier: append the last block to the buffer and process the ident
164
 
                                node->m_string.append(c->m_ptr,aux_ptr - c->m_ptr);
165
 
                                c->m_ptr = aux_ptr;
166
 
                                if(!processIdentifier(c,node->m_string)){
167
 
                                        delete node;
168
 
                                        return 0;
169
 
                                }
170
 
                                aux_ptr = c->m_ptr;
171
 
                        break;
172
 
                        case '\\': //escape character: append the last block to the processed buffer...
173
 
                                node->m_string.append(c->m_ptr,aux_ptr - c->m_ptr);
174
 
                                c->m_ptr = ++aux_ptr;
175
 
                                switch(*aux_ptr){
 
163
                                break;
 
164
                        case KVI_GLOBAL_VAR_CHAR: // Variable: append the last block to the buffer and process the var
 
165
                                node->m_string.append(cmd->m_ptr, aux_ptr - cmd->m_ptr);
 
166
                                cmd->m_ptr = aux_ptr;
 
167
                                if( !processVariable(cmd, node->m_string) ) {
 
168
                                        delete node;
 
169
                                        return 0;
 
170
                                }
 
171
                                aux_ptr = cmd->m_ptr;
 
172
                                break;
 
173
                        case '$': // System identifier: append the last block to the buffer and process the ident
 
174
                                node->m_string.append(cmd->m_ptr, aux_ptr - cmd->m_ptr);
 
175
                                cmd->m_ptr = aux_ptr;
 
176
                                if( !processIdentifier(cmd, node->m_string) ) {
 
177
                                        delete node;
 
178
                                        return 0;
 
179
                                }
 
180
                                aux_ptr = cmd->m_ptr;
 
181
                                break;
 
182
                        case '\\': // Escape character: append the last block to the processed buffer...
 
183
                                node->m_string.append(cmd->m_ptr, aux_ptr - cmd->m_ptr);
 
184
                                cmd->m_ptr = ++aux_ptr;
 
185
                                switch( *aux_ptr ) {
176
186
                                        case '\0':
177
 
                                                c->setError(KVI_ERROR_UnexpectedEndInString,_i18n_("EXPRESSION-STRING-OPERAND"));
 
187
                                                cmd->setError(KVI_ERROR_UnexpectedEndInString, _i18n_("EXPRESSION-STRING-OPERAND"));
178
188
                                                delete node;
179
189
                                                return 0;
180
 
                                        break;
181
 
                                        case '\n':  //escaped newline
182
 
                                                c->m_ptr = ++aux_ptr; //skip it
183
 
                                                c->skipSpace();       //skip leading spaces
184
 
                                                aux_ptr = c->m_ptr;   //continue
185
 
                                        break;
 
190
                                                break;
 
191
                                        case '\n':  // Escaped newline
 
192
                                                cmd->m_ptr = ++aux_ptr; // Skip it
 
193
                                                cmd->skipSpace();       // Skip leading spaces
 
194
                                                aux_ptr = cmd->m_ptr;   // Continue
 
195
                                                break;
186
196
                                        default: // Must be copied to the buffer without modification
187
197
                                                node->m_string.append(*aux_ptr);
188
 
                                                c->m_ptr = ++aux_ptr;
189
 
                                        break;
 
198
                                                cmd->m_ptr = ++aux_ptr;
 
199
                                                break;
190
200
                                }
191
201
                        break;
192
202
                }
193
203
        }
194
 
        return 0; //Newer here
 
204
        return 0;
195
205
}
196
206
 
197
 
KviExprTree * KviUserParser::evaluateSimpleOperand(KviCommand *c)
 
207
KviExprTree *KviUserParser::evaluateSimpleOperand(KviCommand *cmd)
198
208
{
199
209
        // This one extracts a number from the data buffer
200
210
        KviStr tempNum;
201
 
        const char *aux =  c->m_ptr;
202
 
        switch(*aux){
203
 
                case '%': if(!processVariable(c,tempNum))return 0; break;
204
 
                case '$': if(!processIdentifier(c,tempNum))return 0; break;
205
 
                case '"': return evaluateStringOperand(c); break;
 
211
        const char *aux =  cmd->m_ptr;
 
212
        switch( *aux ) {
 
213
                case '%': if( !processVariable(cmd, tempNum)   ) return 0; break;
 
214
                case '$': if( !processIdentifier(cmd, tempNum) ) return 0; break;
 
215
                case '"': return evaluateStringOperand(cmd); break;
206
216
                case '0':
207
 
                        ++(c->m_ptr);
208
 
                        if(! (  isalpha(*(c->m_ptr))  ||   isxdigit(*(c->m_ptr))  )  )tempNum = "0";
 
217
                        ++(cmd->m_ptr);
 
218
                        if( !(isalpha(*(cmd->m_ptr)) || isxdigit(*(cmd->m_ptr))) )
 
219
                                tempNum = "0";
209
220
                        else {
210
 
                                ++(c->m_ptr);
211
 
                                if(isalpha(*(c->m_ptr))||isxdigit(*(c->m_ptr)))++(c->m_ptr);
212
 
                                while(isxdigit(*(c->m_ptr)))++(c->m_ptr);
213
 
                                tempNum.setStr(aux,(c->m_ptr) - aux);
 
221
                                ++(cmd->m_ptr);
 
222
                                if( isalpha(*(cmd->m_ptr)) || isxdigit(*(cmd->m_ptr)) )
 
223
                                        ++(cmd->m_ptr);
 
224
                                while( isxdigit(*(cmd->m_ptr)) )
 
225
                                        ++(cmd->m_ptr);
 
226
                                tempNum.setStr(aux, (cmd->m_ptr) - aux);
214
227
                        }
215
 
                break;
 
228
                        break;
216
229
                default:
217
 
                        if(!isxdigit(*(c->m_ptr))){
218
 
                                c->setError(KVI_ERROR_UnexpectedCharacter,_i18n_("EXPRESSION-OPERAND"),c->m_ptr);
 
230
                        if( !isxdigit(*(cmd->m_ptr)) ) {
 
231
                                cmd->setError(KVI_ERROR_UnexpectedCharacter, _i18n_("EXPRESSION-OPERAND"), cmd->m_ptr);
219
232
                                return 0;
220
233
                        }
221
 
                        while(isxdigit(*(c->m_ptr)))++(c->m_ptr);
222
 
                        tempNum.setStr(aux,(c->m_ptr) - aux);
223
 
                break;
 
234
                        while( isxdigit(*(cmd->m_ptr)) )
 
235
                                ++(cmd->m_ptr);
 
236
                        tempNum.setStr(aux, (cmd->m_ptr) - aux);
 
237
                        break;
224
238
        }
225
239
 
226
240
        aux = tempNum.ptr();
227
241
        int base = 10;
228
 
        if(*aux == '0'){
 
242
        if( *aux == '0' ) {
229
243
                ++aux;
230
 
                switch(tolower(*aux)){
 
244
                switch( tolower(*aux) ) {
231
245
                        case 'x': tempNum.cutLeft(2); base = 16; break;
232
246
                        case 'h': tempNum.cutLeft(2); base = 16; break;
233
247
 
234
 
                        case 'i': tempNum.cutLeft(2); base = 2;  break; // can not use b because it is a hex digit
235
 
                        case 'j': tempNum.cutLeft(2); base = 3;  break;
236
 
                        case 'k': tempNum.cutLeft(2); base = 4;  break;
237
 
                        case 'l': tempNum.cutLeft(2); base = 5;  break;
238
 
                        case 'm': tempNum.cutLeft(2); base = 6;  break;
239
 
                        case 'n': tempNum.cutLeft(2); base = 7;  break;
240
 
                        case 'o': tempNum.cutLeft(2); base = 8;  break;
241
 
                        case 'p': tempNum.cutLeft(2); base = 9;  break;
 
248
                        case 'i': tempNum.cutLeft(2); base =  2; break; // Cannot use b because it is a hex digit
 
249
                        case 'j': tempNum.cutLeft(2); base =  3; break;
 
250
                        case 'k': tempNum.cutLeft(2); base =  4; break;
 
251
                        case 'l': tempNum.cutLeft(2); base =  5; break;
 
252
                        case 'm': tempNum.cutLeft(2); base =  6; break;
 
253
                        case 'n': tempNum.cutLeft(2); base =  7; break;
 
254
                        case 'o': tempNum.cutLeft(2); base =  8; break;
 
255
                        case 'p': tempNum.cutLeft(2); base =  9; break;
242
256
                        case 'q': tempNum.cutLeft(2); base = 10; break;
243
257
                        case 'r': tempNum.cutLeft(2); base = 11; break;
244
258
                        case 's': tempNum.cutLeft(2); base = 12; break;
245
259
                        case 't': tempNum.cutLeft(2); base = 13; break;
246
260
                        case 'u': tempNum.cutLeft(2); base = 14; break;
247
261
                        case 'v': tempNum.cutLeft(2); base = 15; break;
248
 
                        default: break; // unknown ...maybe a single 0
 
262
                        default: break; // Unknown... maybe a single 0
249
263
                }
250
264
        }
251
265
        bool bOk;
252
 
        long res = tempNum.toLongExt(&bOk,base);
253
 
        if(!bOk){
254
 
                c->setError(KVI_ERROR_UnexpectedCharacter,_i18n_("EXPRESSION-OPERAND"),tempNum.ptr());
 
266
        long res = tempNum.toLongExt(&bOk, base);
 
267
        if( !bOk ) {
 
268
                cmd->setError(KVI_ERROR_UnexpectedCharacter, _i18n_("EXPRESSION-OPERAND"), tempNum.ptr());
255
269
                return 0;
256
270
        }
257
 
        return new KviExprTree(KviExprTree::NumericOperand,res);
 
271
        return new KviExprTree(KviExprTree::NumericOperand, res);
258
272
}
259
273
 
260
 
KviExprTree * KviUserParser::evaluateExpression_RightOperand(KviExprTree * curTopOperator,KviCommand *c)
 
274
KviExprTree *KviUserParser::evaluateExpression_RightOperand(KviExprTree *curTopOperator, KviCommand *cmd)
261
275
{
262
276
        __range_valid(curTopOperator);
263
277
        // Now curTopOperator has the left subtree (one node) set
264
 
        // and it points to the TOP (=ROOT) node
265
 
        // Evaluate the rest
266
 
        KviExprTree * operand;
267
 
        KviExprTree * incompleteOperator = curTopOperator;
268
 
        KviExprTree * auxOperator;
269
 
 
270
 
        for(;;){
271
 
                operand = evaluateOperand(c);
272
 
                if(!operand){ delete curTopOperator; return 0; }
273
 
                c->skipSpace();
274
 
                if(*(c->m_ptr) == ')' || *(c->m_ptr) == '\0'){ incompleteOperator->setRight(operand); return curTopOperator; }
275
 
 
276
 
                auxOperator = evaluateOperator(c);
277
 
                if(!auxOperator){ delete curTopOperator; delete operand; return 0; }
278
 
 
279
 
                //now compare operators...
280
 
                if(incompleteOperator->firstBinaryOperator() >= auxOperator->firstBinaryOperator()){
 
278
        // and it points to the TOP (=ROOT) node.
 
279
        // Evaluate the rest.
 
280
        KviExprTree *operand;
 
281
        KviExprTree *incompleteOperator = curTopOperator;
 
282
        KviExprTree *auxOperator;
 
283
 
 
284
        for( ;; ) {
 
285
                operand = evaluateOperand(cmd);
 
286
                if( !operand ) {
 
287
                        delete curTopOperator;
 
288
                        return 0;
 
289
                }
 
290
                cmd->skipSpace();
 
291
                if( *(cmd->m_ptr) == ')' || *(cmd->m_ptr) == '\0' ) {
 
292
                        incompleteOperator->setRight(operand);
 
293
                        return curTopOperator;
 
294
                }
 
295
 
 
296
                auxOperator = evaluateOperator(cmd);
 
297
                if( !auxOperator ) {
 
298
                        delete curTopOperator;
 
299
                        delete operand;
 
300
                        return 0;
 
301
                }
 
302
 
 
303
                // Now compare operators...
 
304
                if( incompleteOperator->firstBinaryOperator() >= auxOperator->firstBinaryOperator() ) {
281
305
                        incompleteOperator->setRight(auxOperator);
282
306
                        auxOperator->setLeft(operand);
283
307
                } else {
284
 
                        // precedence of operators...
285
 
                        incompleteOperator->setRight(operand); //right tree complete
286
 
                        // go up until we find an operator with lower precedence than auxOperator (>=)
287
 
                        KviExprTree * tempOperator = incompleteOperator->parentWithPrecedenceLowerThan(auxOperator->m_value);
288
 
                        if(tempOperator == 0){ //reached the top
 
308
                        // Precedence of operators...
 
309
                        incompleteOperator->setRight(operand); // Right tree complete
 
310
                        // Go up until we find an operator with lower precedence than auxOperator (>=)
 
311
                        KviExprTree *tempOperator = incompleteOperator->parentWithPrecedenceLowerThan(auxOperator->m_value);
 
312
                        if( !tempOperator ) { // Reached the top
289
313
                                auxOperator->setLeft(curTopOperator);
290
314
                                curTopOperator = auxOperator;
291
315
                        } else {
297
321
                incompleteOperator = auxOperator;
298
322
                __range_valid(incompleteOperator->right() == 0);
299
323
        }
300
 
        return 0; //newer here
 
324
        return 0;
301
325
}
302
326
 
303
 
KviExprTree * KviUserParser::evaluateOperator(KviCommand *c)
 
327
KviExprTree *KviUserParser::evaluateOperator(KviCommand *cmd)
304
328
{
305
 
        // This one extracts the first operator it finds        
306
 
        c->skipSpace();
 
329
        // This one extracts the first operator it finds
 
330
        cmd->skipSpace();
307
331
        long op;
308
 
        switch(*(c->m_ptr)){
309
 
                // single ops
310
 
                case '^': op = OP_POWER; ++(c->m_ptr); break;
311
 
                case '*': op = OP_MUL;   ++(c->m_ptr); break;
312
 
                case '/': op = OP_DIV;   ++(c->m_ptr); break;
313
 
                case '%': op = OP_MOD;   ++(c->m_ptr); break;
314
 
                case '+': op = OP_ADD;   ++(c->m_ptr); break;
315
 
                case '-': op = OP_SUB;   ++(c->m_ptr); break;
 
332
        switch( *(cmd->m_ptr) ) {
 
333
                // Single operators
 
334
                case '^': op = OP_POWER; ++(cmd->m_ptr); break;
 
335
                case '*': op = OP_MUL;   ++(cmd->m_ptr); break;
 
336
                case '/': op = OP_DIV;   ++(cmd->m_ptr); break;
 
337
                case '%': op = OP_MOD;   ++(cmd->m_ptr); break;
 
338
                case '+': op = OP_ADD;   ++(cmd->m_ptr); break;
 
339
                case '-': op = OP_SUB;   ++(cmd->m_ptr); break;
316
340
                case '@':
317
 
                        ++(c->m_ptr);
318
 
                        if(*(c->m_ptr) == '=')op = OP_CSEQ , ++(c->m_ptr);
319
 
                        else {
320
 
                                c->setError(KVI_ERROR_UnknownOperator,_i18n_("EXPRESSION-OPERATOR"),c->m_ptr);
 
341
                        ++(cmd->m_ptr);
 
342
                        if( *(cmd->m_ptr) == '=' ) {
 
343
                                op = OP_CSEQ;
 
344
                                ++(cmd->m_ptr);
 
345
                        } else {
 
346
                                cmd->setError(KVI_ERROR_UnknownOperator, _i18n_("EXPRESSION-OPERATOR"), cmd->m_ptr);
321
347
                                return 0;
322
348
                        }
323
 
                break;
 
349
                        break;
324
350
                case '=':
325
 
                        ++(c->m_ptr);
326
 
                        if(*(c->m_ptr) == '=')op = OP_EQ , ++(c->m_ptr);
327
 
                        else {
328
 
                                c->setError(KVI_ERROR_UnknownOperator,_i18n_("EXPRESSION-OPERATOR"),c->m_ptr);
 
351
                        ++(cmd->m_ptr);
 
352
                        if( *(cmd->m_ptr) == '=' ) {
 
353
                                op = OP_EQ;
 
354
                                ++(cmd->m_ptr);
 
355
                        } else {
 
356
                                cmd->setError(KVI_ERROR_UnknownOperator, _i18n_("EXPRESSION-OPERATOR"), cmd->m_ptr);
329
357
                                return 0;
330
358
                        }
331
 
                break;
 
359
                        break;
332
360
                case '!':
333
 
                        ++(c->m_ptr);
334
 
                        if(*(c->m_ptr) == '=')op = OP_NE , ++(c->m_ptr);
335
 
                        else {
336
 
                                c->setError(KVI_ERROR_UnknownOperator,_i18n_("EXPRESSION-OPERATOR"),c->m_ptr);
 
361
                        ++(cmd->m_ptr);
 
362
                        if( *(cmd->m_ptr) == '=' ) {
 
363
                                op = OP_NE;
 
364
                                ++(cmd->m_ptr);
 
365
                        } else {
 
366
                                cmd->setError(KVI_ERROR_UnknownOperator, _i18n_("EXPRESSION-OPERATOR"), cmd->m_ptr);
337
367
                                return 0;
338
368
                        }
339
 
                break;
 
369
                        break;
340
370
                case '>':
341
 
                        ++(c->m_ptr);
342
 
                        if(*(c->m_ptr) == '=')op = OP_GE , ++(c->m_ptr);
343
 
                        else if(*(c->m_ptr) == '>')op = OP_SHR , ++(c->m_ptr);
344
 
                        else op = OP_GT;
345
 
                break;
 
371
                        ++(cmd->m_ptr);
 
372
                        if( *(cmd->m_ptr) == '=' ) {
 
373
                                op = OP_GE;
 
374
                                ++(cmd->m_ptr);
 
375
                        } else if( *(cmd->m_ptr) == '>' ) {
 
376
                                op = OP_SHR;
 
377
                                ++(cmd->m_ptr);
 
378
                        } else op = OP_GT;
 
379
                        break;
346
380
                case '<':
347
 
                        ++(c->m_ptr);
348
 
                        if(*(c->m_ptr) == '=')op = OP_LE , ++(c->m_ptr);
349
 
                        else if(*(c->m_ptr) == '<')op = OP_SHL , ++(c->m_ptr);
350
 
                        else op = OP_LT;
351
 
                break;
 
381
                        ++(cmd->m_ptr);
 
382
                        if( *(cmd->m_ptr) == '=' ) {
 
383
                                op = OP_LE;
 
384
                                ++(cmd->m_ptr);
 
385
                        } else if( *(cmd->m_ptr) == '<' ) {
 
386
                                op = OP_SHL;
 
387
                                ++(cmd->m_ptr);
 
388
                        } else op = OP_LT;
 
389
                        break;
352
390
                case '&':
353
 
                        ++(c->m_ptr);
354
 
                        if(*(c->m_ptr) == '&')op = OP_AND , ++(c->m_ptr);
355
 
                        else op = OP_BITAND;
356
 
                break;
 
391
                        ++(cmd->m_ptr);
 
392
                        if( *(cmd->m_ptr) == '&' ) {
 
393
                                op = OP_AND;
 
394
                                ++(cmd->m_ptr);
 
395
                        } else op = OP_BITAND;
 
396
                        break;
357
397
                case '|':
358
 
                        ++(c->m_ptr);
359
 
                        if(*(c->m_ptr) == '|')op = OP_OR  , ++(c->m_ptr);
360
 
                        else op = OP_BITOR;
361
 
                break;
 
398
                        ++(cmd->m_ptr);
 
399
                        if( *(cmd->m_ptr) == '|' ) {
 
400
                                op = OP_OR;
 
401
                                ++(cmd->m_ptr);
 
402
                        } else op = OP_BITOR;
 
403
                        break;
362
404
                default:
363
 
                        c->setError(KVI_ERROR_UnknownOperator,_i18n_("EXPRESSION-OPERATOR"),c->m_ptr);
 
405
                        cmd->setError(KVI_ERROR_UnknownOperator, _i18n_("EXPRESSION-OPERATOR"), cmd->m_ptr);
364
406
                        return 0;
365
 
                break;
 
407
                        break;
366
408
        }
367
409
 
368
 
        return new KviExprTree(KviExprTree::BinaryOperator,op);
 
410
        return new KviExprTree(KviExprTree::BinaryOperator, op);
369
411
}
370
 
 
371