3 #include "QtxOperations.h"
5 //================================================================
8 //================================================================
9 QtxParser::QtxParser( QtxOperations* operations,
11 : myOperations( operations )
19 setLastError( OperationsNull );
22 //================================================================
25 //================================================================
26 QtxParser::~QtxParser()
30 //================================================================
33 //================================================================
34 int QtxParser::search( const QStringList& list, const QString& str, int offset,
35 int& matchLen, int& listind )
37 QStringList::const_iterator anIt = list.begin(), aLast = list.end();
39 for( int ind = 0; anIt!=aLast; anIt++, ind++ )
41 //const char* where = str.latin1(), *what = (*anIt).latin1();
42 int pos = str.find( *anIt, offset );
43 if( pos>=0 && ( min < 0 || min > pos ||
44 ( min==pos && matchLen< (int)(*anIt).length() ) ) )
48 matchLen = (*anIt).length();
56 //================================================================
59 //================================================================
60 QString QtxParser::note( const QString& str, int pos, int len )
62 return str.mid( pos, len ).stripWhiteSpace();
65 //================================================================
68 //================================================================
69 bool QtxParser::prepare( const QString& expr, Postfix& post )
71 int pos = 0, len = expr.length();
72 QValueStack< int > aBracketStack;
73 QStringList anOpers, anOpenBr, aCloseBr;
76 myOperations->bracketsList( anOpenBr, true );
77 myOperations->bracketsList( aCloseBr, false );
78 myOperations->opersList( anOpers );
82 setLastError( OperationsNull );
86 while( pos < len && lastError()==OK )
89 while( expr[ pos ].isSpace() && pos<len ) pos++;
93 int mBrLen = 0, mLen = 0, br_ind = -1, op_ind = -1;
94 int oPos = search( anOpenBr, expr, pos, mBrLen, br_ind ),
95 cPos = oPos==pos ? -1 : search( aCloseBr, expr, pos, mBrLen, br_ind ),
96 opPos = search( anOpers, expr, pos, mLen, op_ind );
98 if( expr[ pos ]=="'" )
101 while ( vpos< (int)expr.length() && expr[ vpos ]!="'" )
106 int res = myOperations->createValue( note( expr, pos, mLen ), item.myValue );
107 item.myType = res ? Value : Param;
115 aBracketStack.push( br_ind );
116 item.myValue = note( expr, pos, mBrLen );
123 if( aBracketStack.count()==0 )
125 setLastError( ExcessClose );
128 if( br_ind!=aBracketStack.top() )
130 setLastError( BracketsNotMatch );
136 item.myValue = note( expr, pos, mBrLen );
147 item.myValue = note( expr, pos, mLen );
148 item.myType = Binary;
149 //the type is set by default;
150 //the method setOperationTypes will set correct types
153 post.insert( post.at( post.count()-1 ), item );
160 if( oPos!=pos && cPos!=pos )
163 for( i=pos+1; i<(int)expr.length(); i++ )
164 if( expr[ i ].isSpace() )
168 if( oPos>=0 && oPos<vpos )
170 if( cPos>=0 && cPos<vpos )
172 if( opPos>=0 && opPos<vpos )
175 while( vpos<(int)expr.length() &&
176 ( expr[vpos].isLetter() || expr[vpos].isDigit() || expr[vpos]=='_' ) )
180 bool res = myOperations->createValue( note( expr, pos, mLen ), item.myValue );
181 item.myType = res ? Value : Param;
190 PostfixIterator anIt = post.begin(),
193 for( ; anIt!=aLast; anIt++ )
194 if( (*anIt).myType==Open )
196 else if( (*anIt).myType==Close )
201 setLastError( ExcessClose );
205 setLastError( CloseExpected );
207 return lastError()==OK;
210 //================================================================
213 //================================================================
214 bool QtxParser::setOperationTypes( Postfix& post )
216 Postfix::iterator aStart = post.begin(),
218 anIt = aStart, aPrev, aNext;
219 QStringList anOpen, aClose;
222 myOperations->bracketsList( anOpen, true );
223 myOperations->bracketsList( aClose, false );
228 for( ; anIt!=aLast; anIt++ )
230 aPrev = anIt; aPrev--;
231 aNext = anIt; aNext++;
232 if( (*anIt).myType != Binary )
235 if( ( anIt==aStart || (*aPrev).myType == Open ||
236 (*aPrev).myType == Pre ||
237 (*aPrev).myType == Binary )
239 aNext!=aLast && ( (*aNext).myType == Value ||
240 (*aNext).myType == Param ||
241 (*aNext).myType == Open ||
242 (*aNext).myType == Binary ) )
243 (*anIt).myType = Pre;
245 else if( anIt!=aStart && ( (*aPrev).myType == Close ||
246 (*aPrev).myType == Param ||
247 (*aPrev).myType == Value ||
248 (*aPrev).myType == Pre ||
249 (*aPrev).myType == Post ||
250 (*aPrev).myType == Binary )
252 ( aNext==aLast || (*aNext).myType == Close ) )
253 (*anIt).myType = Post;
255 if( anOpen.contains( ( *anIt ).myValue.toString() )>0 )
256 (*anIt).myType = Pre;
257 else if( aClose.contains( ( *anIt ).myValue.toString() )>0 )
258 (*anIt).myType = Post;
261 return lastError()==OK;
264 //================================================================
267 //================================================================
268 int QtxParser::globalBrackets( const QtxParser::Postfix& post, int f, int l )
275 min_br_num = (l-f+1)*5;
277 for( i=f; i<=l; i++ )
278 if( post[ i ].myType==QtxParser::Open )
282 for( i=l; i>=f; i-- )
283 if( post[ i ].myType==QtxParser::Close )
288 br = start_br<fin_br ? start_br : fin_br;
289 for( i=f+br; i<=l-br; i++ )
291 if( post[i].myType==QtxParser::Open )
293 else if( post[i].myType==QtxParser::Close )
295 if( br_num<min_br_num )
299 return br+min_br_num;
302 //================================================================
305 //================================================================
306 bool QtxParser::sort( const Postfix& post, Postfix& res,
307 const QStringList& anOpen,
308 const QStringList& aClose,
319 int br = globalBrackets( post, f, l );
323 res.append( post[ f ] );
331 QValueList< PostfixItemType > min_types;
333 //Find operation with minimal priority
334 //PostfixIterator anIt = post.at( f ),
335 // aLast = post.at( l+1 );
336 for( int i=0, j=f; j<=l; i++, j++ )
338 const PostfixItem& item = post[ j ];
339 PostfixItemType tt = item.myType;
340 if( tt==Binary || tt==Pre || tt==Post )
342 int cur_pr = myOperations->prior( item.myValue.toString(), tt==Binary );
345 if( min<0 || min>=cur_pr )
349 argmin.append( f+i );
350 min_types.append( tt );
355 argmin.clear(); argmin.append( f+i );
356 min_types.clear(); min_types.append( tt );
362 setLastError( InvalidOperation );
368 QString opBr = item.myValue.toString();
369 int ind = anOpen.findIndex( opBr ), brValue = 0;
372 const PostfixItem& anItem = post[ j ];
373 if( anItem.myType==Open )
376 if( anItem.myType==Close )
379 QString clBr = anItem.myValue.toString();
380 if( aClose.findIndex( clBr )==ind && brValue==0 )
387 setLastError( CloseExpected );
393 if( lastError()==OK )
396 QValueList< Postfix > parts;
397 QIntList::const_iterator anIt = argmin.begin(),
398 aLast = argmin.end();
400 bool ok = sort( post, one, anOpen, aClose, f, *anIt - 1 );
403 for( ; anIt!=aLast && ok; anIt++ )
405 QIntList::const_iterator aNext = anIt; aNext++;
406 ok = sort( post, one, anOpen, aClose, *anIt + 1, aNext==aLast ? l : *aNext - 1 );
413 QValueList< Postfix >::const_iterator aPIt = parts.begin();
414 QValueList< PostfixItemType >::const_iterator aTIt = min_types.begin();
415 QValueStack< PostfixItem > aStack;
416 res += (*aPIt); aPIt++;
417 anIt = argmin.begin();
418 for( ; anIt!=aLast; anIt++, aPIt++, aTIt++ )
421 if( anOpen.contains( post[ *anIt ].myValue.toString() )==0 )
424 aStack.push( post[ *anIt ] );
428 res.append( post[ *anIt ] );
434 while( !aStack.isEmpty() )
436 res.append( aStack.top() );
439 res.append( post[ *anIt ] );
442 while( !aStack.isEmpty() )
444 res.append( aStack.top() );
449 { //there are no operations
450 PostfixIterator anIt = post.at( f ),
451 aLast = post.at( l+1 );
452 for( ; anIt!=aLast; anIt++ )
453 if( (*anIt).myType==Value || (*anIt).myType==Param )
458 setLastError( OperationsNull );
460 return lastError()==OK;
463 //================================================================
466 //================================================================
467 bool QtxParser::parse( const QString& expr )
472 QStringList opens, closes;
477 myOperations->bracketsList( opens, true );
478 myOperations->bracketsList( closes, false );
482 setLastError( OperationsNull );
486 //return prepare( expr, myPost ) && setOperationTypes( myPost );
487 return prepare( expr, p ) && setOperationTypes( p ) &&
488 sort( p, myPost, opens, closes );
491 //================================================================
494 //================================================================
495 bool QtxParser::calculate( const QString& op, QtxValue& v1, QtxValue& v2 )
497 Error err = myOperations->isValid( op, v1.type(), v2.type() );
499 setLastError( myOperations->calculate( op, v1, v2 ) );
503 return lastError()==OK;
506 //================================================================
509 //================================================================
510 QtxValue QtxParser::calculate()
514 QStringList anOpen, aClose;
517 myOperations->bracketsList( anOpen, true );
518 myOperations->bracketsList( aClose, false );
522 setLastError( OperationsNull );
526 QtxValueStack aStack;
527 PostfixIterator anIt = myPost.begin(),
528 aLast = myPost.end();
529 for( ; anIt!=aLast && lastError()==OK; anIt++ )
531 QString nn = (*anIt).myValue.toString();
532 if( (*anIt).myType==Param )
536 QVariant& v = myParameters[ nn ];
540 setLastError( InvalidToken );
543 setLastError( InvalidToken );
546 else if( (*anIt).myType==Value )
547 aStack.push( (*anIt).myValue );
549 else if( (*anIt).myType==Pre || (*anIt).myType==Post )
551 if( anOpen.contains( nn )>0 )
554 if( calculate( nn, inv, inv ) )
555 aStack.push( QtxValue() );
557 else if( aClose.contains( nn )>0 )
559 QValueList< QtxValue > set;
562 if( aStack.count()==0 )
564 setLastError( StackUnderflow );
567 if( aStack.top().isValid() )
569 set.append( aStack.top() );
579 QtxValue qSet = set, inv;
580 if( calculate( nn, qSet, inv ) )
583 else if( aStack.count()>=1 )
586 QtxValue* v1 = &aStack.top(), *v2 = &inv; //"post-" case
587 if( (*anIt).myType==Pre )
589 v2 = &aStack.top(); v1 = &inv;
592 calculate( nn, *v1, *v2 );
595 setLastError( StackUnderflow );
598 else if( (*anIt).myType==Binary )
600 if( aStack.count()>=2 )
602 QVariant v2 = aStack.top(); aStack.pop();
603 calculate( nn, aStack.top(), v2 );
606 setLastError( StackUnderflow );
611 if( lastError()==OK )
613 int count = aStack.count();
615 setLastError( StackUnderflow );
619 setLastError( ExcessData );
624 //================================================================
627 //================================================================
628 QtxValue QtxParser::calculate( const QString& expr )
634 //================================================================
637 //================================================================
638 bool QtxParser::setExpr( const QString& expr )
640 return parse( expr );
643 //================================================================
646 //================================================================
647 bool QtxParser::has( const QString& name ) const
649 return myParameters.contains( name.stripWhiteSpace() );
652 //================================================================
655 //================================================================
656 void QtxParser::set( const QString& name, const QtxValue& value )
658 myParameters[ name.stripWhiteSpace() ] = value;
661 //================================================================
664 //================================================================
665 bool QtxParser::remove( const QString& name )
667 QString sname = name.stripWhiteSpace();
668 bool res = has( sname );
670 myParameters.remove( sname );
674 //================================================================
677 //================================================================
678 QtxValue QtxParser::value( const QString& name ) const
680 QString sname = name.stripWhiteSpace();
682 return myParameters[ sname ].toString();
687 //================================================================
690 //================================================================
691 bool QtxParser::firstInvalid( QString& name ) const
693 QMap< QString, QtxValue >::const_iterator anIt = myParameters.begin(),
694 aLast = myParameters.end();
695 for( ; anIt!=aLast; anIt++ )
696 if( !anIt.data().isValid() )
704 //================================================================
707 //================================================================
708 void QtxParser::removeInvalids()
710 QStringList toDelete;
711 QMap< QString, QtxValue >::const_iterator anIt = myParameters.begin(),
712 aLast = myParameters.end();
713 for( ; anIt!=aLast; anIt++ )
714 if( !anIt.data().isValid() )
715 toDelete.append( anIt.key() );
717 QStringList::const_iterator aLIt = toDelete.begin(),
718 aLLast = toDelete.end();
719 for( ; aLIt!=aLLast; aLIt++ )
720 myParameters.remove( *aLIt );
723 //================================================================
726 //================================================================
727 QtxParser::Error QtxParser::lastError() const
732 //================================================================
735 //================================================================
736 void QtxParser::setLastError( QtxParser::Error err )
741 //================================================================
744 //================================================================
745 QString QtxParser::dump() const
747 return dump( myPost );
750 //================================================================
753 //================================================================
754 QString QtxParser::dump( const Postfix& post ) const
760 PostfixIterator anIt = post.begin(),
762 for( ; anIt!=aLast; anIt++ )
764 if( (*anIt).myType == Value &&
765 ( ( *anIt ).myValue.type()==QVariant::String ||
766 ( *anIt ).myValue.type()==QVariant::CString ) )
767 res += "'" + ( *anIt ).myValue.toString() + "'";
769 res += ( *anIt ).myValue.toString();
770 if( (*anIt).myType == Pre )
772 else if( (*anIt).myType == Post )
774 else if( (*anIt).myType == Binary )
783 //================================================================
786 //================================================================
787 void QtxParser::paramsList( QStringList& list )
789 PostfixIterator anIt = myPost.begin(),
790 aLast = myPost.end();
791 for( ; anIt!=aLast; anIt++ )
792 if( (*anIt).myType==Param )
794 QString name = (*anIt).myValue.toString();
795 if( list.contains( name )==0 )
800 //================================================================
803 //================================================================
804 void QtxParser::clear()
806 myParameters.clear();
809 //================================================================
812 //================================================================
813 QString QtxParser::toString( const QValueList< QtxValue >& list )
815 QValueList< QtxValue >::const_iterator anIt = list.begin(),
817 QString res = "set : [ ";
818 for( ; anIt!=aLast; anIt++ )
819 res+=(*anIt).toString()+" ";