Salome HOME
Base implementation of Notebook
[modules/kernel.git] / src / Notebook / SALOME_EvalParser.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SALOME_EvalParser.cxx
23 //  Author : Peter KURNEV
24 //  Module : SALOME
25
26 #include <SALOME_EvalParser.hxx>
27
28 #include <stack>
29 #include <list>
30
31 bool          contains(const SALOME_StringList& aLS, const SALOME_String& aS);
32 SALOME_String trimmed(const SALOME_String& str);
33 SALOME_String trimmed(const SALOME_String& str, const char aWhat);
34 bool          isSpace(const char aC);
35 int           indexOf(const SALOME_StringList& aLS, const SALOME_String& aS);
36
37 //=======================================================================
38 //function :
39 //purpose  :
40 //=======================================================================
41 SALOME_EvalParser::SALOME_EvalParser()
42 : myAutoDel( false )
43 {
44   setError( EvalExpr_OK );
45 }
46 //=======================================================================
47 //function : ~
48 //purpose  :
49 //=======================================================================
50 SALOME_EvalParser::~SALOME_EvalParser()
51 {
52   if (autoDeleteOperationSets()) {
53     //qDeleteAll( mySets );// !!!
54     SALOME_ListOfEvalSet::const_iterator aIt = mySets.begin();
55     for (; aIt != mySets.end() ; ++aIt )  {
56       SALOME_EvalSet* pEvalSet=*aIt;
57       if (pEvalSet) {
58         delete pEvalSet;
59         pEvalSet=NULL;
60       }
61     }
62   }
63 }
64 //=======================================================================
65 //function : operationSets
66 //purpose  :
67 //=======================================================================
68 SALOME_ListOfEvalSet SALOME_EvalParser::operationSets() const
69 {
70   return mySets;
71 }
72 //=======================================================================
73 //function : operationSet
74 //purpose  :
75 //=======================================================================
76 SALOME_EvalSet* SALOME_EvalParser::operationSet(const SALOME_String& theName) const
77 {
78   SALOME_EvalSet* pSet;
79   //
80   pSet = NULL;
81   SALOME_ListOfEvalSet::const_iterator it = mySets.begin();
82   for (; it != mySets.end() && !pSet; ++it )  {
83     if ( (*it)->name()==theName ) {
84       pSet = *it;
85     }
86   }
87   return pSet;
88 }
89 //=======================================================================
90 //function : insertOperationSet
91 //purpose  :
92 //=======================================================================
93 void SALOME_EvalParser::insertOperationSet(SALOME_EvalSet* theSet,
94                                        const int idx)
95 {
96   if (SALOME_EvalSet::contains(mySets, theSet)) {
97     return;
98   }
99   //
100   int iSize=(int)mySets.size();
101   int index = idx < 0 ? iSize : idx;
102   if (index>iSize) {
103     index=iSize;
104   }
105   SALOME_EvalSet::insert(mySets, index, theSet);
106 }
107 //=======================================================================
108 //function : removeOperationSet
109 //purpose  :
110 //=======================================================================
111 void SALOME_EvalParser::removeOperationSet(SALOME_EvalSet* theSet)
112 {
113   //mySets.removeAll( theSet );
114   mySets.remove(theSet);
115 }
116 //=======================================================================
117 //function : autoDeleteOperationSets
118 //purpose  :
119 //=======================================================================
120 bool SALOME_EvalParser::autoDeleteOperationSets() const
121 {
122   return myAutoDel;
123 }
124 //=======================================================================
125 //function : setAutoDeleteOperationSets
126 //purpose  :
127 //=======================================================================
128 void SALOME_EvalParser::setAutoDeleteOperationSets( const bool theOn )
129 {
130   myAutoDel = theOn;
131 }
132 //=======================================================================
133 //function : search
134 //purpose  :
135 //=======================================================================
136 int SALOME_EvalParser::search(const SALOME_StringList& aList, const SALOME_String& aStr, int offset,  int& matchLen, int& listind )
137 {
138   int min = -1;
139   int ind = 0;
140   int pos;
141   //static const basic_string <char>::size_type npos = -1;
142   //
143   SALOME_StringList::const_iterator aIt = aList.begin(), aLast = aList.end();
144   for (ind = 0; aIt != aLast; aIt++, ind++ )
145   {
146     const SALOME_String& aStrX=*aIt;
147
148     pos=(int)aStr.find(aStrX, offset);
149     if ( pos >= 0 &&
150          ( min < 0 || min > pos ||
151           ( min == pos && matchLen < (int)aStrX.length())
152          )
153        )  {
154       min = pos;
155       listind = ind;
156       matchLen = (int)aStrX.length();
157     }
158
159   }
160   if ( min < 0 ){
161     matchLen = 0;
162   }
163   return min;
164 }
165 //=======================================================================
166 //function : note
167 //purpose  :
168 //=======================================================================
169 SALOME_String SALOME_EvalParser::note(const SALOME_String& aStr, int pos, int len )
170 {
171   SALOME_String aStr1;
172   //
173   aStr1=aStr.substr(pos, len);
174   aStr1=trimmed(aStr1);
175
176   return aStr1;
177 }
178
179 //=======================================================================
180 //function : prepare
181 //purpose  :
182 //=======================================================================
183 bool SALOME_EvalParser::prepare(const SALOME_String& expr, Postfix& post)
184 {
185   int pos = 0;
186   int len =(int)expr.length();
187   stack<int> aBracketStack;
188   SALOME_StringList anOpers, anOpenBr, aCloseBr;
189   if ( !checkOperations() )
190     return false;
191
192   bracketsList( anOpenBr, true );
193   bracketsList( aCloseBr, false );
194   operationList( anOpers );
195
196   while ( pos < len && error() == EvalExpr_OK )  {
197     PostfixItem item;
198     char aC=expr[pos];
199     //
200     while ( pos < len && isSpace(aC) ) {
201       pos++;
202     }
203     //
204     if ( pos >= len ) {
205       break;
206     }
207     //
208     int mBrLen = 0, mLen = 0, br_ind = -1, op_ind = -1;
209     int oPos = search( anOpenBr, expr, pos, mBrLen, br_ind );
210     int cPos = oPos == pos ? -1 : search( aCloseBr, expr, pos, mBrLen, br_ind );
211     int opPos = search( anOpers, expr, pos, mLen, op_ind );
212     //
213     if ( aC=='\'')  {
214       int vpos = pos + 1;
215       while ( vpos < (int)expr.length() && expr[vpos] != '\'' ) {
216         vpos++;
217       }
218       //
219       mLen = vpos - pos + 1;
220       //
221       int res = createValue( note( expr, pos, mLen ), item.myValue );
222       item.myType = res ? Value : Param;
223       post.push_back( item );
224       pos = vpos + 1;
225       continue;
226     }
227     //
228     if ( oPos == pos )  {
229       aBracketStack.push( br_ind );
230       item.myValue = note( expr, pos, mBrLen );
231       item.myType = Open;
232       post.push_back( item );
233     }
234     else if ( cPos == pos )  {
235       if ( aBracketStack.size() == 0 )  {
236         setError( EvalExpr_ExcessClose );
237         break;
238       }
239       if ( br_ind != aBracketStack.top() )  {
240         setError( EvalExpr_BracketsNotMatch );
241         break;
242       }
243       else {
244         aBracketStack.pop();
245         item.myValue = note( expr, pos, mBrLen );
246         item.myType = Close;
247         post.push_back( item );
248       }
249     }
250     else {
251       mBrLen = 0;
252     }
253     //
254     if ( opPos == pos ) {
255       mBrLen = 0;
256       item.myValue = note( expr, pos, mLen );
257       item.myType = Binary;
258
259       if ( oPos == pos ) {
260         insert(post, (int)(post.size()-1), item);
261       }
262       else
263         post.push_back( item );
264     }
265     else  {
266       mLen = 0;
267       if ( oPos != pos && cPos != pos )   {
268               int i;
269         for ( i = pos + 1; i < (int)expr.length(); i++ )  {
270           if ( isSpace(expr[i]) ) {
271             break;
272           }
273         }
274         //
275         int vpos = i;
276         if ( oPos >= 0 && oPos < vpos ) {
277           vpos = oPos;
278         }
279         if ( cPos >= 0 && cPos < vpos ){
280           vpos = cPos;
281         }
282         if ( opPos >= 0 && opPos < vpos ){
283           vpos = opPos;
284         }
285
286         while( vpos < (int)expr.length() &&
287                ( isalpha(expr[vpos]) ||
288                  isdigit(expr[vpos]) ||
289                  expr[vpos]=='_' )
290                 ) {
291           vpos++;
292         }
293         //
294         mLen = vpos - pos;
295         bool res = createValue( note( expr, pos, mLen ), item.myValue );
296         item.myType = res ? Value : Param;
297         post.push_back( item );
298       }
299     }
300     pos += mBrLen + mLen;
301   }
302
303   //Bracket checking
304   int brValue = 0;
305   for ( Postfix::iterator anIt = post.begin(); anIt != post.end(); ++anIt ) {
306     if ( (*anIt).myType == Open ){
307       brValue++;
308     }
309     else if ( (*anIt).myType == Close ) {
310       if ( brValue > 0 ){
311         brValue--;
312       }
313       else {
314         setError( EvalExpr_ExcessClose );
315         break;
316       }
317     }
318   }
319   //
320   if ( brValue > 0 )
321   {
322     setError( EvalExpr_CloseExpected );
323   }
324   //
325   return error() == EvalExpr_OK;
326 }
327 //=======================================================================
328 //function : setOperationTypes
329 //purpose  :
330 //=======================================================================
331 bool SALOME_EvalParser::setOperationTypes( Postfix& post )
332 {
333   if ( !checkOperations() )
334     return false;
335
336   SALOME_StringList anOpen, aClose;
337   //
338   bracketsList( anOpen, true );
339   bracketsList( aClose, false );
340
341   Postfix::iterator aPrev, aNext;
342   Postfix::iterator anIt = post.begin();
343   for (; anIt != post.end(); ++anIt )  {
344     aPrev = anIt;
345     aPrev--;
346     aNext = anIt;
347     aNext++;
348     if ( (*anIt).myType != Binary ){
349       continue;
350     }
351     //
352     if ( ( anIt == post.begin() || (*aPrev).myType == Open ||
353            (*aPrev).myType == Pre || (*aPrev).myType == Binary ) &&  aNext != post.end() &&
354          ( (*aNext).myType == Value || (*aNext).myType == Param ||
355            (*aNext).myType == Open  || (*aNext).myType == Binary ) )
356       (*anIt).myType = Pre;
357     //
358     else if ( anIt != post.begin() && ( (*aPrev).myType == Close || (*aPrev).myType == Param ||
359                                         (*aPrev).myType == Value || (*aPrev).myType == Pre ||
360                                         (*aPrev).myType == Post || (*aPrev).myType == Binary ) &&
361               ( aNext == post.end() || (*aNext).myType == Close ) )
362       (*anIt).myType = Post;
363     //
364     SALOME_EvalVariant& aRV=(*anIt).myValue;
365     SALOME_String  aRVS=aRV.toString();
366     //
367     if ( contains(anOpen, aRVS) ) {
368       (*anIt).myType = Pre;
369     }
370     else if ( contains(aClose, aRVS) ) {
371       (*anIt).myType = Post;
372     }
373   }
374
375   return error() == EvalExpr_OK;
376 }
377 //=======================================================================
378 //function : globalBrackets
379 //purpose  :
380 //=======================================================================
381 int SALOME_EvalParser::globalBrackets(const Postfix& post,
382                                   int f,
383                                   int l )
384 {
385   int i;
386   int start_br = 0;
387   int fin_br = 0;
388   int br = 0;
389   int br_num = 0;
390   int min_br_num = (l-f+1)*5;
391
392   PostfixItem *pPost;
393   pPost=new PostfixItem[post.size()];
394   //
395   Postfix::const_iterator aIt = post.begin();
396   for (i=0; aIt != post.end(); ++aIt, ++i)  {
397     const PostfixItem& aPostfixItem=*aIt;
398     pPost[i]=aPostfixItem;
399   }
400
401   for( i=f; i<=l; i++ )
402     if( pPost[ i ].myType==SALOME_EvalParser::Open )
403       start_br++;
404     else
405       break;
406   for( i=l; i>=f; i-- )
407     if( pPost[ i ].myType==SALOME_EvalParser::Close )
408       fin_br++;
409     else
410       break;
411
412   br = start_br<fin_br ? start_br : fin_br;
413   for( i=f+br; i<=l-br; i++ )
414   {
415     if( pPost[i].myType==SALOME_EvalParser::Open )
416       br_num++;
417     else if( pPost[i].myType==SALOME_EvalParser::Close )
418       br_num--;
419     if( br_num<min_br_num )
420       min_br_num = br_num;
421   }
422
423   //delete pPost;
424   delete [] (PostfixItem *)pPost;
425   return br+min_br_num;
426 }
427 //=======================================================================
428 //function : sort
429 //purpose  :
430 //=======================================================================
431 bool SALOME_EvalParser::sort( const Postfix& post, Postfix& res, const SALOME_StringList& anOpen,
432                               const SALOME_StringList& aClose, int f, int l )
433 {
434   if ( l < f ){
435     return true;
436   }
437   if ( f < 0 ) {
438     f = 0;
439   }
440   if ( l < 0 ) {
441     l = (int)(post.size() - 1);
442   }
443
444   int br = globalBrackets( post, f, l );
445   f += br;
446   l -= br;
447
448   if ( f == l && f >= 0 ) {
449     res.push_back(at(post,f));
450   }
451   if ( l <= f ) {
452     return true;
453   }
454
455   if ( !checkOperations() ) {
456     return false;
457   }
458
459   int min = -1;
460   list<int> argmin;
461   list<PostfixItemType> min_types;
462   //
463   for ( int i = 0, j = f; j <= l; i++, j++ )  {
464     const PostfixItem& item = at(post,j);//!!!
465     PostfixItemType tt = item.myType;
466     if ( tt == Binary || tt == Pre || tt == Post )  {
467       int cur_pr = priority( item.myValue.toString(), tt == Binary );
468       if ( cur_pr > 0 ) {
469         if ( min < 0 || min >= cur_pr ) {
470           if ( min == cur_pr ) {
471             argmin.push_back( f + i );
472             min_types.push_back( tt );
473           }
474           else {
475             min = cur_pr;
476             argmin.clear();
477             argmin.push_back( f + i );
478             min_types.clear();
479             min_types.push_back( tt );
480           }
481         }
482       }
483       else {
484         setError( EvalExpr_InvalidOperation );
485         break;
486       }
487     }
488     else if ( tt == Open ){
489       SALOME_String opBr = item.myValue.toString();
490       int ind, brValue = 0;
491       ind = indexOf(anOpen, opBr );
492       while ( j <= l ) {
493         const PostfixItem& anItem = at(post,j);
494         if ( anItem.myType == Open )
495           brValue++;
496
497         if ( anItem.myType == Close ) {
498           brValue--;
499           SALOME_String clBr = anItem.myValue.toString();
500           if ( indexOf(aClose, clBr ) == ind && brValue == 0 ){
501             break;
502           }
503         }
504         i++; j++;
505       }
506       //
507       if ( brValue > 0 )      {
508         setError( EvalExpr_CloseExpected );
509         break;
510       }
511     }
512   }
513   //
514   if ( error() == EvalExpr_OK ) {
515     if ( min >= 0 )  {
516       Postfix one;
517       list<Postfix> parts;
518       list<int>::const_iterator anIt = argmin.begin(), aLast = argmin.end();
519       bool ok = sort( post, one, anOpen, aClose, f, *anIt - 1 );
520       parts.push_back( one );
521       one.clear();
522       for ( ; anIt != aLast && ok; anIt++ )      {
523         list<int>::const_iterator aNext = anIt; aNext++;
524         ok = sort( post, one, anOpen, aClose, *anIt + 1, aNext == aLast ? l : *aNext - 1 );
525         parts.push_back( one );
526         one.clear();
527       }
528       //
529       if ( !ok ){
530         return false;
531       }
532       //
533       stack<PostfixItem> aStack;
534       list<Postfix>::const_iterator aPIt = parts.begin();
535       list<PostfixItemType>::const_iterator aTIt = min_types.begin();
536       //
537       append(res,*aPIt);
538       aPIt++;
539       anIt = argmin.begin();
540       for ( ; anIt != aLast; anIt++, aPIt++, aTIt++ )  {
541         if ( *aTIt == Pre ) {
542           if (!contains(anOpen, at(post,*anIt).myValue.toString())) {
543             append(res,*aPIt);
544             aStack.push( at(post, *anIt) );
545           }
546           else {
547             res.push_back( at(post, *anIt) );
548             append(res,*aPIt);
549           }
550         }
551         else {
552           append(res,*aPIt);
553           while (!aStack.empty() ) {
554             res.push_back( aStack.top() );
555             aStack.pop();
556           }
557           res.push_back( at(post, *anIt) );
558         }
559       }
560       while ( !aStack.empty() ) {
561         res.push_back( aStack.top() );
562         aStack.pop();
563       }
564     }
565     else { //there are no operations
566       for ( int k = f; k <= l; k++ ) {
567         const PostfixItem& aItem=at(post, k);
568         if ( aItem.myType==Value || aItem.myType == Param ){
569           res.push_back( aItem );
570         }
571       }
572     }
573   }
574   return error() == EvalExpr_OK;
575 }
576 //=======================================================================
577 //function : parse
578 //purpose  :
579 //=======================================================================
580 bool SALOME_EvalParser::parse( const SALOME_String& expr )
581 {
582   myPostfix.clear();
583
584   if ( !checkOperations() )
585     return false;
586
587   Postfix p;
588   SALOME_StringList opens, closes;
589
590   setError( EvalExpr_OK );
591   bracketsList( opens, true );
592   bracketsList( closes, false );
593
594   return prepare( expr, p ) && setOperationTypes( p ) && sort( p, myPostfix, opens, closes );
595 }
596 //=======================================================================
597 //function : calculate
598 //purpose  :
599 //=======================================================================
600 bool SALOME_EvalParser::calculate(const SALOME_String& op, SALOME_EvalVariant& v1, SALOME_EvalVariant& v2 )
601 {
602   SALOME_EvalExprError aErr;
603   SALOME_EvalVariantType aType1, aType2;
604   //
605   aType1=v1.type();
606   aType2=v2.type();
607   //
608   aErr = isValid( op, aType1, aType2 );
609   if ( aErr == EvalExpr_OK ){
610     aErr=calculation( op, v1, v2 );
611     setError( aErr );
612   }
613   else{
614     setError( aErr );
615   }
616   return error() == EvalExpr_OK;
617 }
618 //=======================================================================
619 //function : calculate
620 //purpose  :
621 //=======================================================================
622 SALOME_EvalVariant SALOME_EvalParser::calculate()
623 {
624   if ( !checkOperations() )
625     return SALOME_EvalVariant();
626
627   setError( EvalExpr_OK );
628   //
629   SALOME_StringList anOpen, aClose;
630   PostfixItemType aType;
631   //
632   bracketsList( anOpen, true );
633   bracketsList( aClose, false );
634
635   stack<SALOME_EvalVariant> aStack;
636   Postfix::iterator anIt = myPostfix.begin(), aLast = myPostfix.end();
637   for ( ; anIt != aLast && error() == EvalExpr_OK; anIt++ )  {
638     const PostfixItem& aPostfixItem=*anIt;
639     aType=aPostfixItem.myType;
640     SALOME_String nn = aPostfixItem.myValue.toString();
641     //
642     if ( aType == Param ) {
643       if ( hasParameter( nn ) )  {
644         SALOME_EvalVariant& v = myParams[nn];
645         if ( v.isValid() ) {
646           aStack.push( v );
647         }
648         else {
649           setError( EvalExpr_InvalidToken );
650         }
651       }
652       else {
653         setError( EvalExpr_InvalidToken );
654       }
655     }
656     //
657     else if ( aType == Value ) {
658       aStack.push( (*anIt).myValue );
659     }
660     //
661     else if ( aType == Pre || aType == Post )  {
662       if ( contains(anOpen, nn ) )  {
663         SALOME_EvalVariant inv;
664         if ( calculate( nn, inv, inv ) ) {
665           aStack.push( SALOME_EvalVariant() );
666         }
667       }
668       else if ( contains(aClose, nn ) )  {
669         SALOME_ListOfEvalVariant aSet;
670         while ( true ) {
671           if ( aStack.empty() ) {
672             setError( EvalExpr_StackUnderflow );
673             break;
674           }
675           if ( aStack.top().isValid() ) {
676             aSet.push_back( aStack.top() );
677             aStack.pop();
678           }
679           else {
680             aStack.pop();
681             break;
682           }
683         }
684
685         SALOME_EvalVariant qSet = aSet, inv;
686         if ( calculate( nn, qSet, inv ) ) {
687           aStack.push( aSet );
688         }
689       }
690       else if ( aStack.size() >= 1 )  {
691         SALOME_EvalVariant inv;
692         SALOME_EvalVariant *v1, *v2;
693         v1=&aStack.top();
694         v2 = &inv; //"post-" case
695         if ( aType == Pre ) {
696           v2 = &aStack.top();
697           v1 = &inv;
698         }
699         calculate( nn, *v1, *v2 );
700       }
701       else {
702         setError( EvalExpr_StackUnderflow );
703       }
704     }//else if ( aType== Pre || aType == Post )  {
705     else if ( aType == Binary )  {
706       if ( aStack.size() >= 2 )  {
707         SALOME_EvalVariant v2= aStack.top();
708         aStack.pop();
709         calculate( nn, aStack.top(), v2 );
710       }
711       else {
712         setError( EvalExpr_StackUnderflow );
713       }
714     }
715   }
716   //
717   SALOME_EvalVariant res;
718   if ( error() == EvalExpr_OK )  {
719     int count;
720
721     count = (int)aStack.size();
722     if ( count == 0 ) {
723       setError( EvalExpr_StackUnderflow );
724     }
725     else if( count == 1 ) {
726       res = aStack.top();
727     }
728     else{
729       setError( EvalExpr_ExcessData );
730     }
731   }
732   return res;
733 }
734 //=======================================================================
735 //function : calculate
736 //purpose  :
737 //=======================================================================
738 SALOME_EvalVariant SALOME_EvalParser::calculate( const SALOME_String& expr )
739 {
740   setExpression( expr );
741   return calculate();
742 }
743 //=======================================================================
744 //function : setExpression
745 //purpose  :
746 //=======================================================================
747 bool SALOME_EvalParser::setExpression( const SALOME_String& expr )
748 {
749   return parse( expr );
750 }
751 //=======================================================================
752 //function : hasParameter
753 //purpose  :
754 //=======================================================================
755 bool SALOME_EvalParser::hasParameter( const SALOME_String& name ) const
756 {
757   bool bRet;
758   SALOME_String aStr;
759   ParamMap::const_iterator aIt;
760   aStr=trimmed(name);
761   aIt=myParams.find(aStr);
762   bRet=(aIt!=myParams.end());
763   return bRet;
764 }
765 //=======================================================================
766 //function : setParameter
767 //purpose  :
768 //=======================================================================
769 void SALOME_EvalParser::setParameter( const SALOME_String& name, const SALOME_EvalVariant& value )
770 {
771   SALOME_String aStr;
772   //
773   aStr=trimmed(name);
774   myParams[aStr] = value;
775 }
776 //=======================================================================
777 //function : removeParameter
778 //purpose  :
779 //=======================================================================
780 bool SALOME_EvalParser::removeParameter( const SALOME_String& name )
781 {
782   int iRet;
783   SALOME_String aStr;
784   //
785   aStr=trimmed(name);
786   iRet=(int)myParams.erase(aStr);
787   return iRet? true : false;
788
789 }
790 //=======================================================================
791 //function : parameter
792 //purpose  :
793 //=======================================================================
794 SALOME_EvalVariant SALOME_EvalParser::parameter( const SALOME_String& theName ) const
795 {
796   SALOME_EvalVariant res;
797   ParamMap::const_iterator aIt;
798   SALOME_String aStr;
799   aStr=trimmed(theName);
800   aIt=myParams.find(theName);
801   if (aIt!=myParams.end()) {
802     const PairParamMap& aVT=*aIt;
803     const SALOME_EvalVariant& aRV=aVT.second;
804     res=aRV;
805   }
806   return res;
807 }
808 //=======================================================================
809 //function : firstInvalid
810 //purpose  :
811 //=======================================================================
812 bool SALOME_EvalParser::firstInvalid( SALOME_String& name ) const
813 {
814   ParamMap::const_iterator aIt = myParams.begin();
815   for (; aIt != myParams.end(); aIt++ )  {
816     const PairParamMap& aVT=*aIt;
817     const SALOME_EvalVariant& aRV=aVT.second;
818     if ( !aRV.isValid() )  {
819       name = aVT.first;
820       return true;
821     }
822   }
823   return false;
824 }
825 //=======================================================================
826 //function : removeInvalids
827 //purpose  :
828 //=======================================================================
829 void SALOME_EvalParser::removeInvalids()
830 {
831   ParamMap aM;
832   //
833   ParamMap::const_iterator aIt = myParams.begin();
834   for (; aIt != myParams.end(); aIt++ )  {
835     const PairParamMap& aVT=*aIt;
836     const SALOME_EvalVariant& aRV=aVT.second;
837     if (aRV.isValid() )  {
838       aM.insert(aVT);
839     }
840   }
841   myParams.clear();
842   myParams=aM;
843 }
844 //=======================================================================
845 //function : error
846 //purpose  :
847 //=======================================================================
848 SALOME_EvalExprError SALOME_EvalParser::error() const
849 {
850   return myError;
851 }
852 //=======================================================================
853 //function : setError
854 //purpose  :
855 //=======================================================================
856
857 void SALOME_EvalParser::setError(SALOME_EvalExprError err)
858 {
859   myError = err;
860 }
861 //=======================================================================
862 //function : dump
863 //purpose  :
864 //=======================================================================
865 SALOME_String SALOME_EvalParser::dump() const
866 {
867   return dump( myPostfix );
868 }
869 //=======================================================================
870 //function : dump
871 //purpose  :
872 //=======================================================================
873 SALOME_String SALOME_EvalParser::dump( const Postfix& post ) const
874 {
875   SALOME_String res;
876   //
877   if ( !checkOperations() ) {
878     return res;
879   }
880   //
881   Postfix::const_iterator anIt = post.begin();
882   for (; anIt != post.end(); anIt++ )  {
883     if ((*anIt).myType == Value &&
884         (*anIt).myValue.type() == SALOME_EvalVariant_String ) {
885       res += "'" + (*anIt).myValue.toString() + "'";
886     }
887     else{
888       res += (*anIt).myValue.toString();
889     }
890     if ( (*anIt).myType == Pre ){
891       res += "(pre)";
892     }
893     else if ( (*anIt).myType == Post ){
894       res += "(post)";
895     }
896     else if ( (*anIt).myType == Binary ){
897       res += "(bin)";
898     }
899
900     res += "_";
901   }
902
903   return res;
904 }
905 //=======================================================================
906 //function : parameters
907 //purpose  :
908 //=======================================================================
909 SALOME_StringList SALOME_EvalParser::parameters() const
910 {
911   SALOME_StringList lst;
912   Postfix::const_iterator anIt = myPostfix.begin();
913   for (; anIt != myPostfix.end(); anIt++ )  {
914     if ( (*anIt).myType == Param )    {
915       SALOME_String name = (*anIt).myValue.toString();
916       if ( !contains(lst, name ) ) {
917         lst.push_back( name );
918       }
919     }
920   }
921   return lst;
922 }
923 //=======================================================================
924 //function : clearParameters
925 //purpose  :
926 //=======================================================================
927 void SALOME_EvalParser::clearParameters()
928 {
929   myParams.clear();
930 }
931 //=======================================================================
932 //function : toString
933 //purpose  :
934 //=======================================================================
935 SALOME_String SALOME_EvalParser::toString( const SALOME_ListOfEvalVariant& theList )
936 {
937   SALOME_String res = "set : [ ";
938   SALOME_ListOfEvalVariant::const_iterator aIt = theList.begin();
939   for ( ; aIt != theList.end(); aIt++ )
940     res += (*aIt).toString() + " ";
941   res += "]";
942   return res;
943 }
944 //=======================================================================
945 //function : operationList
946 //purpose  :
947 //=======================================================================
948 void SALOME_EvalParser::operationList( SALOME_StringList& theList ) const
949 {
950   SALOME_ListOfEvalSet::const_iterator aIt = mySets.begin();
951   for (; aIt != mySets.end(); ++aIt )  {
952     SALOME_StringList custom;
953     SALOME_EvalSet* aSet = *aIt;
954     aSet->operationList( custom );
955     SALOME_StringList::const_iterator sIt = custom.begin();
956     for ( ; sIt != custom.end(); ++sIt )    {
957       if ( !contains(theList, *sIt ) ) {
958         theList.push_back( *sIt );
959       }
960     }
961   }
962 }
963 //=======================================================================
964 //function : operationList
965 //purpose  :
966 //=======================================================================
967 void SALOME_EvalParser::bracketsList( SALOME_StringList& theList, bool open ) const
968 {
969   SALOME_ListOfEvalSet::const_iterator it = mySets.begin();
970   for (; it != mySets.end(); ++it ) {
971     SALOME_StringList custom;
972     SALOME_EvalSet* aSet = *it;
973     aSet->bracketsList( custom, open );
974     SALOME_StringList::const_iterator sIt = custom.begin();
975     for (; sIt != custom.end(); ++sIt )    {
976       if ( !contains(theList, *sIt ) )
977         theList.push_back( *sIt );
978     }
979   }
980 }
981 //=======================================================================
982 //function : createValue
983 //purpose  :
984 //=======================================================================
985 bool SALOME_EvalParser::createValue( const SALOME_String& str, SALOME_EvalVariant& val ) const
986 {
987   bool ok = false;
988   //
989   SALOME_ListOfEvalSet::const_iterator it = mySets.begin();
990   for (; it != mySets.end() && !ok; ++it ) {
991     ok = (*it)->createValue( str, val );
992   }
993   return ok;
994 }
995 //=======================================================================
996 //function : priority
997 //purpose  :
998 //=======================================================================
999 int SALOME_EvalParser::priority( const SALOME_String& op, bool isBin ) const
1000 {
1001   int i = 0;
1002   int priority = 0;
1003   SALOME_ListOfEvalSet::const_iterator it = mySets.begin();
1004   for (; it != mySets.end() && priority <= 0; ++it, i++ ){
1005     priority = (*it)->priority( op, isBin );
1006   }
1007   return priority > 0 ? priority + i * 50 : 0;
1008 }
1009 //=======================================================================
1010 //function : isValid
1011 //purpose  :
1012 //=======================================================================
1013 SALOME_EvalExprError SALOME_EvalParser::isValid( const SALOME_String& op, const SALOME_EvalVariantType t1,
1014                                                  const SALOME_EvalVariantType t2 ) const
1015 {
1016   SALOME_EvalExprError err = EvalExpr_OK;
1017   //
1018   SALOME_ListOfEvalSet::const_iterator it = mySets.begin();
1019   for (; it != mySets.end(); ++it )  {
1020     SALOME_EvalSet *pSet=*it;
1021     err = pSet->isValid( op, t1, t2 );
1022     if ( err == EvalExpr_OK ){
1023       break;
1024     }
1025   }
1026   return err;
1027 }
1028 //=======================================================================
1029 //function : calculation
1030 //purpose  :
1031 //=======================================================================
1032 SALOME_EvalExprError SALOME_EvalParser::calculation( const SALOME_String& op, SALOME_EvalVariant& v1, SALOME_EvalVariant& v2 ) const
1033 {
1034   SALOME_EvalVariant nv1, nv2;
1035   SALOME_EvalSet *pSet;
1036   SALOME_EvalVariantType aType1, aType2;
1037   SALOME_EvalExprError aErr;
1038   //
1039   aType1=v1.type();
1040   aType2=v2.type();
1041   //
1042   SALOME_ListOfEvalSet::const_iterator aIt = mySets.begin();
1043   for (; aIt != mySets.end(); ++aIt )  {
1044     pSet=*aIt;
1045     nv1 = v1;
1046     nv2 = v2;
1047     aErr=pSet->isValid( op, aType1, aType2);
1048     if ( aErr == EvalExpr_OK ) {
1049       aErr = pSet->calculate( op, nv1, nv2 );
1050       if ( aErr == EvalExpr_OK || aErr == EvalExpr_InvalidResult )  {
1051         v1 = nv1;
1052         v2 = nv2;
1053         return aErr;
1054       }
1055     }
1056   }
1057   //
1058   return EvalExpr_InvalidOperation;
1059 }
1060 //=======================================================================
1061 //function : checkOperations
1062 //purpose  :
1063 //=======================================================================
1064 bool SALOME_EvalParser::checkOperations() const
1065 {
1066   if ( mySets.size() )
1067     return true;
1068
1069   SALOME_EvalParser* that = (SALOME_EvalParser*)this;
1070   that->setError( EvalExpr_OperationsNull );
1071   return false;
1072 }
1073 //=======================================================================
1074 //function : append
1075 //purpose  :
1076 //=======================================================================
1077 void SALOME_EvalParser::append(Postfix& aL,
1078                            const Postfix& aL1)
1079 {
1080   Postfix::const_iterator aIt=aL1.begin();
1081   for(; aIt!=aL1.end(); ++aIt) {
1082     aL.push_back(*aIt);
1083   }
1084 }
1085 //=======================================================================
1086 //function : at
1087 //purpose  :
1088 //=======================================================================
1089 const SALOME_EvalParser::PostfixItem& SALOME_EvalParser::at(const Postfix& aL,
1090                                                     const int aIndex)
1091 {
1092   int i;
1093   Postfix::const_iterator aIt=aL.begin();
1094   for(i=0; aIt!=aL.end(); ++aIt, ++i) {
1095     if (i==aIndex) {
1096       break;
1097     }
1098   }
1099   return *aIt;
1100 }
1101 //=======================================================================
1102 //function : insert
1103 //purpose  :
1104 //=======================================================================
1105 void SALOME_EvalParser::insert(Postfix& aL,
1106                             const int aIndex,
1107                             PostfixItem& pS)
1108 {
1109   int i;
1110   //
1111   if (!aIndex) {
1112     aL.push_front(pS);
1113   }
1114   else if (aIndex==aL.size()) {
1115     aL.push_back(pS);
1116   }
1117   else {
1118     Postfix::iterator aIt=aL.begin();
1119     for(i=0; aIt!=aL.end(); ++aIt, ++i) {
1120       if (i==aIndex) {
1121         aL.insert( aIt, pS );
1122         break;
1123       }
1124     }
1125   }
1126 }
1127 //=======================================================================
1128 //function : indexOf
1129 //purpose  :
1130 //=======================================================================
1131 int indexOf( const SALOME_StringList& aLS, const SALOME_String& aS )
1132 {
1133   int i, iRet;
1134   SALOME_StringList::const_iterator aIt;
1135   //
1136   iRet=-1;
1137   //
1138   aIt=aLS.begin();
1139   for (i=0; aIt!=aLS.end(); ++aIt, ++i)
1140   {
1141     const SALOME_String aSx=*aIt;
1142     if (aSx==aS) {
1143       iRet=i;
1144       break;
1145     }
1146   }
1147   return iRet;
1148 }
1149 //=======================================================================
1150 //function : contains
1151 //purpose  :
1152 //=======================================================================
1153 bool contains( const SALOME_StringList& aLS, const SALOME_String& aS )
1154 {
1155   bool bRet;
1156   //
1157   bRet=false;
1158   SALOME_StringList::const_iterator aIt;
1159   //
1160   aIt=aLS.begin();
1161   for (; aIt!=aLS.end(); ++aIt) {
1162     const SALOME_String aSx=*aIt;
1163     if (aSx==aS) {
1164       bRet=!bRet;
1165       break;
1166     }
1167   }
1168   return bRet;
1169 }
1170
1171
1172 //=======================================================================
1173 //function : isSpace
1174 //purpose  :
1175 //=======================================================================
1176 bool isSpace(const char aC)
1177 {
1178   bool bRet;
1179   char aWhat[]={
1180     '\t', '\n', '\v', '\f', '\r', ' '
1181   };
1182   int i, aNb;
1183   //
1184   bRet=false;
1185   aNb=sizeof(aWhat)/sizeof(aWhat[0]);
1186   for (i=0; i<aNb; ++i) {
1187     bRet=(aC==aWhat[i]);
1188     if (bRet) {
1189       break;
1190     }
1191   }
1192   return bRet;
1193 }
1194 //=======================================================================
1195 //function : trimmed
1196 //purpose  :
1197 //=======================================================================
1198 SALOME_String trimmed(const SALOME_String& str)
1199 {
1200   char aWhat[]={
1201     '\t', '\n', '\v', '\f', '\r', ' '
1202   };
1203   int i, aNb;
1204   SALOME_String aRet;
1205   //
1206   aRet=str;
1207   aNb=sizeof(aWhat)/sizeof(aWhat[0]);
1208   for (i=0; i<aNb; ++i) {
1209     aRet=trimmed(aRet, aWhat[i]);
1210   }
1211   return aRet;
1212 }
1213 //=======================================================================
1214 //function : trimmed
1215 //purpose  :
1216 //=======================================================================
1217 SALOME_String trimmed(const SALOME_String& str, const char aWhat)
1218 {
1219   char aX[2];
1220   size_t mylength, i;
1221   SALOME_String aRet;
1222   //
1223   const char* mystring=str.c_str();
1224   if(!mystring) {
1225     return aRet;
1226   }
1227   //
1228   mylength=strlen(mystring);
1229   if (!mylength) {
1230     return aRet;
1231   }
1232   //
1233   aX[1]=0;
1234   for (i=0; i<mylength; ++i) {
1235     char aC=mystring[i];
1236     if (aC != aWhat) {
1237       aX[0]=aC;
1238       aRet.append(aX);
1239     }
1240   }
1241   return aRet;
1242 }
1243
1244