1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/
20 #include "QtxParser.h"
21 #include "QtxOperations.h"
23 //================================================================
26 //================================================================
27 QtxParser::QtxParser( QtxOperations* operations,
29 : myOperations( operations )
37 setLastError( OperationsNull );
40 //================================================================
43 //================================================================
44 QtxParser::~QtxParser()
48 //================================================================
51 //================================================================
52 int QtxParser::search( const QStringList& list, const QString& str, int offset,
53 int& matchLen, int& listind )
55 QStringList::const_iterator anIt = list.begin(), aLast = list.end();
57 for( int ind = 0; anIt!=aLast; anIt++, ind++ )
59 //const char* where = str.latin1(), *what = (*anIt).latin1();
60 int pos = str.find( *anIt, offset );
61 if( pos>=0 && ( min < 0 || min > pos ||
62 ( min==pos && matchLen< (int)(*anIt).length() ) ) )
66 matchLen = (*anIt).length();
74 //================================================================
77 //================================================================
78 QString QtxParser::note( const QString& str, int pos, int len )
80 return str.mid( pos, len ).stripWhiteSpace();
83 //================================================================
86 //================================================================
87 bool QtxParser::prepare( const QString& expr, Postfix& post )
89 int pos = 0, len = expr.length();
90 QValueStack< int > aBracketStack;
91 QStringList anOpers, anOpenBr, aCloseBr;
94 myOperations->bracketsList( anOpenBr, true );
95 myOperations->bracketsList( aCloseBr, false );
96 myOperations->opersList( anOpers );
100 setLastError( OperationsNull );
104 while( pos < len && lastError()==OK )
107 while( expr[ pos ].isSpace() && pos<len ) pos++;
111 int mBrLen = 0, mLen = 0, br_ind = -1, op_ind = -1;
112 int oPos = search( anOpenBr, expr, pos, mBrLen, br_ind ),
113 cPos = oPos==pos ? -1 : search( aCloseBr, expr, pos, mBrLen, br_ind ),
114 opPos = search( anOpers, expr, pos, mLen, op_ind );
116 if( expr[ pos ]=="'" )
119 while ( vpos< (int)expr.length() && expr[ vpos ]!="'" )
124 int res = myOperations->createValue( note( expr, pos, mLen ), item.myValue );
125 item.myType = res ? Value : Param;
133 aBracketStack.push( br_ind );
134 item.myValue = note( expr, pos, mBrLen );
141 if( aBracketStack.count()==0 )
143 setLastError( ExcessClose );
146 if( br_ind!=aBracketStack.top() )
148 setLastError( BracketsNotMatch );
154 item.myValue = note( expr, pos, mBrLen );
165 item.myValue = note( expr, pos, mLen );
166 item.myType = Binary;
167 //the type is set by default;
168 //the method setOperationTypes will set correct types
171 post.insert( post.at( post.count()-1 ), item );
178 if( oPos!=pos && cPos!=pos )
181 for( i=pos+1; i<(int)expr.length(); i++ )
182 if( expr[ i ].isSpace() )
186 if( oPos>=0 && oPos<vpos )
188 if( cPos>=0 && cPos<vpos )
190 if( opPos>=0 && opPos<vpos )
193 while( vpos<(int)expr.length() &&
194 ( expr[vpos].isLetter() || expr[vpos].isDigit() || expr[vpos]=='_' ) )
198 bool res = myOperations->createValue( note( expr, pos, mLen ), item.myValue );
199 item.myType = res ? Value : Param;
208 PostfixIterator anIt = post.begin(),
211 for( ; anIt!=aLast; anIt++ )
212 if( (*anIt).myType==Open )
214 else if( (*anIt).myType==Close )
219 setLastError( ExcessClose );
223 setLastError( CloseExpected );
225 return lastError()==OK;
228 //================================================================
231 //================================================================
232 bool QtxParser::setOperationTypes( Postfix& post )
234 Postfix::iterator aStart = post.begin(),
236 anIt = aStart, aPrev, aNext;
237 QStringList anOpen, aClose;
240 myOperations->bracketsList( anOpen, true );
241 myOperations->bracketsList( aClose, false );
246 for( ; anIt!=aLast; anIt++ )
248 aPrev = anIt; aPrev--;
249 aNext = anIt; aNext++;
250 if( (*anIt).myType != Binary )
253 if( ( anIt==aStart || (*aPrev).myType == Open ||
254 (*aPrev).myType == Pre ||
255 (*aPrev).myType == Binary )
257 aNext!=aLast && ( (*aNext).myType == Value ||
258 (*aNext).myType == Param ||
259 (*aNext).myType == Open ||
260 (*aNext).myType == Binary ) )
261 (*anIt).myType = Pre;
263 else if( anIt!=aStart && ( (*aPrev).myType == Close ||
264 (*aPrev).myType == Param ||
265 (*aPrev).myType == Value ||
266 (*aPrev).myType == Pre ||
267 (*aPrev).myType == Post ||
268 (*aPrev).myType == Binary )
270 ( aNext==aLast || (*aNext).myType == Close ) )
271 (*anIt).myType = Post;
273 if( anOpen.contains( ( *anIt ).myValue.toString() )>0 )
274 (*anIt).myType = Pre;
275 else if( aClose.contains( ( *anIt ).myValue.toString() )>0 )
276 (*anIt).myType = Post;
279 return lastError()==OK;
282 //================================================================
285 //================================================================
286 int QtxParser::globalBrackets( const QtxParser::Postfix& post, int f, int l )
293 min_br_num = (l-f+1)*5;
295 for( i=f; i<=l; i++ )
296 if( post[ i ].myType==QtxParser::Open )
300 for( i=l; i>=f; i-- )
301 if( post[ i ].myType==QtxParser::Close )
306 br = start_br<fin_br ? start_br : fin_br;
307 for( i=f+br; i<=l-br; i++ )
309 if( post[i].myType==QtxParser::Open )
311 else if( post[i].myType==QtxParser::Close )
313 if( br_num<min_br_num )
317 return br+min_br_num;
320 //================================================================
323 //================================================================
324 bool QtxParser::sort( const Postfix& post, Postfix& res,
325 const QStringList& anOpen,
326 const QStringList& aClose,
337 int br = globalBrackets( post, f, l );
341 res.append( post[ f ] );
349 QValueList< PostfixItemType > min_types;
351 //Find operation with minimal priority
352 //PostfixIterator anIt = post.at( f ),
353 // aLast = post.at( l+1 );
354 for( int i=0, j=f; j<=l; i++, j++ )
356 const PostfixItem& item = post[ j ];
357 PostfixItemType tt = item.myType;
358 if( tt==Binary || tt==Pre || tt==Post )
360 int cur_pr = myOperations->prior( item.myValue.toString(), tt==Binary );
363 if( min<0 || min>=cur_pr )
367 argmin.append( f+i );
368 min_types.append( tt );
373 argmin.clear(); argmin.append( f+i );
374 min_types.clear(); min_types.append( tt );
380 setLastError( InvalidOperation );
386 QString opBr = item.myValue.toString();
387 int ind = anOpen.findIndex( opBr ), brValue = 0;
390 const PostfixItem& anItem = post[ j ];
391 if( anItem.myType==Open )
394 if( anItem.myType==Close )
397 QString clBr = anItem.myValue.toString();
398 if( aClose.findIndex( clBr )==ind && brValue==0 )
405 setLastError( CloseExpected );
411 if( lastError()==OK )
414 QValueList< Postfix > parts;
415 QIntList::const_iterator anIt = argmin.begin(),
416 aLast = argmin.end();
418 bool ok = sort( post, one, anOpen, aClose, f, *anIt - 1 );
421 for( ; anIt!=aLast && ok; anIt++ )
423 QIntList::const_iterator aNext = anIt; aNext++;
424 ok = sort( post, one, anOpen, aClose, *anIt + 1, aNext==aLast ? l : *aNext - 1 );
431 QValueList< Postfix >::const_iterator aPIt = parts.begin();
432 QValueList< PostfixItemType >::const_iterator aTIt = min_types.begin();
433 QValueStack< PostfixItem > aStack;
434 res += (*aPIt); aPIt++;
435 anIt = argmin.begin();
436 for( ; anIt!=aLast; anIt++, aPIt++, aTIt++ )
439 if( anOpen.contains( post[ *anIt ].myValue.toString() )==0 )
442 aStack.push( post[ *anIt ] );
446 res.append( post[ *anIt ] );
452 while( !aStack.isEmpty() )
454 res.append( aStack.top() );
457 res.append( post[ *anIt ] );
460 while( !aStack.isEmpty() )
462 res.append( aStack.top() );
467 { //there are no operations
468 PostfixIterator anIt = post.at( f ),
469 aLast = post.at( l+1 );
470 for( ; anIt!=aLast; anIt++ )
471 if( (*anIt).myType==Value || (*anIt).myType==Param )
476 setLastError( OperationsNull );
478 return lastError()==OK;
481 //================================================================
484 //================================================================
485 bool QtxParser::parse( const QString& expr )
490 QStringList opens, closes;
495 myOperations->bracketsList( opens, true );
496 myOperations->bracketsList( closes, false );
500 setLastError( OperationsNull );
504 //return prepare( expr, myPost ) && setOperationTypes( myPost );
505 return prepare( expr, p ) && setOperationTypes( p ) &&
506 sort( p, myPost, opens, closes );
509 //================================================================
512 //================================================================
513 bool QtxParser::calculate( const QString& op, QtxValue& v1, QtxValue& v2 )
515 Error err = myOperations->isValid( op, v1.type(), v2.type() );
517 setLastError( myOperations->calculate( op, v1, v2 ) );
521 return lastError()==OK;
524 //================================================================
527 //================================================================
528 QtxValue QtxParser::calculate()
532 QStringList anOpen, aClose;
535 myOperations->bracketsList( anOpen, true );
536 myOperations->bracketsList( aClose, false );
540 setLastError( OperationsNull );
544 QtxValueStack aStack;
545 PostfixIterator anIt = myPost.begin(),
546 aLast = myPost.end();
547 for( ; anIt!=aLast && lastError()==OK; anIt++ )
549 QString nn = (*anIt).myValue.toString();
550 if( (*anIt).myType==Param )
554 QVariant& v = myParameters[ nn ];
558 setLastError( InvalidToken );
561 setLastError( InvalidToken );
564 else if( (*anIt).myType==Value )
565 aStack.push( (*anIt).myValue );
567 else if( (*anIt).myType==Pre || (*anIt).myType==Post )
569 if( anOpen.contains( nn )>0 )
572 if( calculate( nn, inv, inv ) )
573 aStack.push( QtxValue() );
575 else if( aClose.contains( nn )>0 )
577 QValueList< QtxValue > set;
580 if( aStack.count()==0 )
582 setLastError( StackUnderflow );
585 if( aStack.top().isValid() )
587 set.append( aStack.top() );
597 QtxValue qSet = set, inv;
598 if( calculate( nn, qSet, inv ) )
601 else if( aStack.count()>=1 )
604 QtxValue* v1 = &aStack.top(), *v2 = &inv; //"post-" case
605 if( (*anIt).myType==Pre )
607 v2 = &aStack.top(); v1 = &inv;
610 calculate( nn, *v1, *v2 );
613 setLastError( StackUnderflow );
616 else if( (*anIt).myType==Binary )
618 if( aStack.count()>=2 )
620 QVariant v2 = aStack.top(); aStack.pop();
621 calculate( nn, aStack.top(), v2 );
624 setLastError( StackUnderflow );
629 if( lastError()==OK )
631 int count = aStack.count();
633 setLastError( StackUnderflow );
637 setLastError( ExcessData );
642 //================================================================
645 //================================================================
646 QtxValue QtxParser::calculate( const QString& expr )
652 //================================================================
655 //================================================================
656 bool QtxParser::setExpr( const QString& expr )
658 return parse( expr );
661 //================================================================
664 //================================================================
665 bool QtxParser::has( const QString& name ) const
667 return myParameters.contains( name.stripWhiteSpace() );
670 //================================================================
673 //================================================================
674 void QtxParser::set( const QString& name, const QtxValue& value )
676 myParameters[ name.stripWhiteSpace() ] = value;
679 //================================================================
682 //================================================================
683 bool QtxParser::remove( const QString& name )
685 QString sname = name.stripWhiteSpace();
686 bool res = has( sname );
688 myParameters.remove( sname );
692 //================================================================
695 //================================================================
696 QtxValue QtxParser::value( const QString& name ) const
698 QString sname = name.stripWhiteSpace();
700 return myParameters[ sname ].toString();
705 //================================================================
708 //================================================================
709 bool QtxParser::firstInvalid( QString& name ) const
711 QMap< QString, QtxValue >::const_iterator anIt = myParameters.begin(),
712 aLast = myParameters.end();
713 for( ; anIt!=aLast; anIt++ )
714 if( !anIt.data().isValid() )
722 //================================================================
725 //================================================================
726 void QtxParser::removeInvalids()
728 QStringList toDelete;
729 QMap< QString, QtxValue >::const_iterator anIt = myParameters.begin(),
730 aLast = myParameters.end();
731 for( ; anIt!=aLast; anIt++ )
732 if( !anIt.data().isValid() )
733 toDelete.append( anIt.key() );
735 QStringList::const_iterator aLIt = toDelete.begin(),
736 aLLast = toDelete.end();
737 for( ; aLIt!=aLLast; aLIt++ )
738 myParameters.remove( *aLIt );
741 //================================================================
744 //================================================================
745 QtxParser::Error QtxParser::lastError() const
750 //================================================================
753 //================================================================
754 void QtxParser::setLastError( QtxParser::Error err )
759 //================================================================
762 //================================================================
763 QString QtxParser::dump() const
765 return dump( myPost );
768 //================================================================
771 //================================================================
772 QString QtxParser::dump( const Postfix& post ) const
778 PostfixIterator anIt = post.begin(),
780 for( ; anIt!=aLast; anIt++ )
782 if( (*anIt).myType == Value &&
783 ( ( *anIt ).myValue.type()==QVariant::String ||
784 ( *anIt ).myValue.type()==QVariant::CString ) )
785 res += "'" + ( *anIt ).myValue.toString() + "'";
787 res += ( *anIt ).myValue.toString();
788 if( (*anIt).myType == Pre )
790 else if( (*anIt).myType == Post )
792 else if( (*anIt).myType == Binary )
801 //================================================================
804 //================================================================
805 void QtxParser::paramsList( QStringList& list )
807 PostfixIterator anIt = myPost.begin(),
808 aLast = myPost.end();
809 for( ; anIt!=aLast; anIt++ )
810 if( (*anIt).myType==Param )
812 QString name = (*anIt).myValue.toString();
813 if( list.contains( name )==0 )
818 //================================================================
821 //================================================================
822 void QtxParser::clear()
824 myParameters.clear();
827 //================================================================
830 //================================================================
831 QString QtxParser::toString( const QValueList< QtxValue >& list )
833 QValueList< QtxValue >::const_iterator anIt = list.begin(),
835 QString res = "set : [ ";
836 for( ; anIt!=aLast; anIt++ )
837 res+=(*anIt).toString()+" ";