1 // Created on: 1992-06-24
2 // Created by: Gilles DEBARBOUILLE
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <Units_Lexicon.hxx>
19 #include <Units_NoSuchType.hxx>
20 #include <Units_Operators.hxx>
21 #include <Units_Sentence.hxx>
22 #include <Units_ShiftedToken.hxx>
23 #include <Units_Token.hxx>
24 #include <Units_TokensSequence.hxx>
26 static Handle(Units_Token) CreateTokenForNumber(const Standard_CString str)
28 TCollection_AsciiString tstr = str[0];
29 Standard_Boolean IsPoint = Standard_False;
30 Standard_Size len = strlen(str);
31 for(Standard_Size in=1; in < len; in++) {
32 if( str[in]=='0' || str[in]=='1' || str[in]=='2' || str[in]=='3' ||
33 str[in]=='4' || str[in]=='5' || str[in]=='6' || str[in]=='7' ||
34 str[in]=='8' || str[in]=='9' ) {
35 tstr.AssignCat(str[in]);
37 else if( str[in]=='.' && !IsPoint ) {
38 tstr.AssignCat(str[in]);
39 IsPoint = Standard_True;
44 return new Units_Token(tstr.ToCString(), "0");
48 //=======================================================================
49 //function : Units_Sentence
51 //=======================================================================
53 Units_Sentence::Units_Sentence(const Handle(Units_Lexicon)& alexicon,
54 const Standard_CString astring)
56 Standard_Integer index;
57 Standard_Size i,limchain;
58 Handle(Units_Token) token;
59 Handle(Units_Token) referencetoken;
61 thesequenceoftokens = new Units_TokensSequence();
62 Handle(Units_TokensSequence) lstlexicon=alexicon->Sequence();
63 if(lstlexicon.IsNull())
64 throw Units_NoSuchType("BAD LEXICON descriptor");
65 limchain=strlen(astring);
68 TCollection_AsciiString tmpstr = astring;
69 //Handle(Units_Token) tmptoken;
70 TCollection_AsciiString PrevMean;
71 TCollection_AsciiString PrevWord;
73 Standard_Boolean IsFound = Standard_False;
74 TCollection_AsciiString LastWord = "";
75 for(index=1; index<=lstlexicon->Length(); index++) {
76 referencetoken = lstlexicon->Value(index);
77 TCollection_AsciiString aword = referencetoken->Word();
78 int num = tmpstr.Search(aword);
79 if( num==1 && aword.Length()>=LastWord.Length() ) {
80 token = referencetoken->Creates();
82 IsFound = Standard_True;
86 // may be it is a number(degree)?
87 LastWord = tmpstr.SubString(1,1);
88 if(!LastWord.IsIntegerValue()) {
89 // unknown expression - not create sentene
90 thesequenceoftokens->Clear();
92 cout<<"Warning: can not create correct sentence from string: "<<astring<<endl;
97 // create token for number
98 token = CreateTokenForNumber(tmpstr.ToCString());
99 LastWord = token->Word();
103 // make additional checking
104 if( ( token->Mean()=="M" && ( PrevMean=="M" || PrevMean=="MU" || PrevMean=="0" ) ) ||
105 ( token->Mean()=="U" && ( PrevMean=="U" || PrevMean=="0" ) ) ||
106 ( token->Mean()=="O" && ( PrevMean=="M" || PrevMean=="O" ) ) ||
107 ( ( token->Word()=="+" || token->Word()=="-" ) && PrevWord!="(" ) ||
108 ( token->Mean()=="S" && ( PrevMean=="M" ) ) ||
109 ( token->Mean()=="0" && ( PrevMean=="M" || PrevMean=="U" || PrevMean=="MU" ) ) ) {
110 // incorrect situation
111 thesequenceoftokens->Clear();
113 cout<<"Warning: can not create correct sentence from string: "<<astring<<endl;
118 thesequenceoftokens->Append(token);
119 PrevMean = token->Mean();
120 PrevWord = token->Word();
121 i = i + LastWord.Length();
122 tmpstr.Remove(1,LastWord.Length());
127 //=======================================================================
128 //function : SetConstants
130 //=======================================================================
132 void Units_Sentence::SetConstants()
134 Standard_Integer index;
136 Handle(Units_Token) token;
137 TCollection_AsciiString string;
139 for(index=1;index<=thesequenceoftokens->Length();index++) {
140 token = thesequenceoftokens->Value(index);
141 if(token->Value()==0.) {
142 string = token->Word();
143 if(string.IsRealValue()) {
144 value = string.RealValue();
153 //=======================================================================
154 //function : CalculateLocal
156 //=======================================================================
157 static Handle(Units_Token) CalculateLocal(const Handle(Units_TokensSequence)& aSeq)
160 //for(int index=1; index<=aSeq->Length(); index++) {
161 // Handle(Units_Token) tok = aSeq->Value(index);
162 // cout<<tok->Word()<<" ";
165 Handle(Units_Token) tok1,tok2;
166 Standard_Integer i,j;
168 if(aSeq->Length()==1) {
169 return aSeq->Value(1);
173 if(aSeq->Length()==2) {
174 if(aSeq->Value(1)->Word()=="+")
176 if(aSeq->Value(1)->Word()=="-") {
177 tok2 = aSeq->Value(2);
178 TCollection_AsciiString aword = "-";
179 aword.AssignCat(tok2->Word());
180 tok1 = new Units_Token(aword.ToCString(), tok2->Mean().ToCString(),
181 tok2->Value()*(-1.0), tok2->Dimensions());
183 aSeq->SetValue(1,tok1);
185 return aSeq->Value(1);
188 Standard_Boolean IsBracket = Standard_True;
190 for(i=1; i<=aSeq->Length(); i++) {
191 if(aSeq->Value(i)->Word()=="(") {
192 Handle(Units_TokensSequence) TmpSeq = new Units_TokensSequence;
193 Standard_Integer NbBrackets = 1;
194 for(j=i+1; j<=aSeq->Length(); j++) {
195 if(aSeq->Value(j)->Word()==")")
197 if(aSeq->Value(j)->Word()=="(")
200 TmpSeq->Append(aSeq->Value(j));
204 tok1 = CalculateLocal(TmpSeq);
206 aSeq->SetValue(i,tok1);
210 if(i>aSeq->Length()) {
211 IsBracket = Standard_False;
212 // there are not brackets => make calculations
213 // step 1: operation '**'
214 for(i=1; i<=aSeq->Length(); i++) {
215 if(aSeq->Value(i)->Word()=="**") {
216 tok1 = aSeq->Value(i-1);
217 tok2 = aSeq->Value(i+1);
218 tok1 = pow(tok1,tok2);
221 aSeq->SetValue(i-1,tok1);
225 // step 2: operation '*', '.' and '/'
226 for(i=1; i<=aSeq->Length(); i++) {
227 if(aSeq->Value(i)->Mean()=="O") {
228 tok1 = aSeq->Value(i-1);
229 tok2 = aSeq->Value(i+1);
230 if(aSeq->Value(i)->Word()=="/")
236 aSeq->SetValue(i-1,tok1);
240 // now aSeq have to include only one result token
247 //=======================================================================
248 //function : Evaluate
250 //=======================================================================
252 Handle(Units_Token) Units_Sentence::Evaluate()
254 Handle(Units_Token) rtoken,ktoken;
255 if(thesequenceoftokens->Length()==0)
259 Standard_Integer index;
260 static char *ooper[6] = { "+", "-", "*", ".", "/", "**" };
261 Standard_Integer numterm,i,j,k,maxlevel,curlevel,level[255];
262 Handle(Units_Token) currenttoken;
263 TCollection_AsciiString string;
264 TCollection_AsciiString mean;
265 TCollection_AsciiString oper;
267 numterm=curlevel=i=0;
268 for(index=1;index<=thesequenceoftokens->Length();index++) {
269 string = thesequenceoftokens->Value(index)->Word();
272 level[numterm]=curlevel;
275 else if( string==")" ) {
277 level[numterm]=curlevel;
280 level[numterm]=curlevel;
287 // for(index=1; index<=thesequenceoftokens->Length(); index++) {
288 // Handle(Units_Token) tok = thesequenceoftokens->Value(index);
289 // cout<<tok->Word()<<" ";
292 // for(index=1; index<=thesequenceoftokens->Length(); index++) {
293 // cout<<level[index-1]<<" ";
299 cout<<" Incorrect number of brackets"<<endl;
300 return new Units_Token();
304 for(index=1,i=0; index<=thesequenceoftokens->Length(); index++,i++) {
305 if( thesequenceoftokens->Value(index)->Word() == ooper[k] ) {
308 while(j < numterm && level[j] >= curlevel)
312 while(j >= 0 && level[j] >= curlevel)
318 Handle(Units_Dimensions) aDim;
324 for(i=0; i<=numterm; i++)if(level[i] > maxlevel)
328 while(level[i] != maxlevel)
334 while( k<=numterm && level[k]==maxlevel ) {
335 ktoken=thesequenceoftokens->Value(k+1);
338 oper = ktoken->Word();
341 if (oper == "/") rtoken = rtoken / ktoken;
342 else if(oper == "+") rtoken = rtoken + ktoken;
343 else if(oper == "-") rtoken = rtoken - ktoken;
344 else if(oper == "*") rtoken = rtoken * ktoken;
345 else if(oper == "**") rtoken = pow(rtoken,ktoken);
346 else if(oper == ".") rtoken = rtoken * ktoken;
347 else rtoken = ktoken->Creates();
351 thesequenceoftokens->SetValue(i+1,rtoken);
355 thesequenceoftokens->Remove(i+2,k);
358 level[++j]=level[k++];
363 rtoken = thesequenceoftokens->Value(1)->Creates();
365 if( rtoken->Value()==0. ) {
366 cout << "*BAD token value from unit '" << rtoken->Word() << "'" << endl;
369 */ // end old variant
371 // variant skl 15.09.2005
372 rtoken = CalculateLocal(thesequenceoftokens);