1 // Created on: 1992-06-24
2 // Created by: Gilles DEBARBOUILLE
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
22 #include <Units_NoSuchType.hxx>
23 #include <Units_Sentence.ixx>
24 #include <Units_Token.hxx>
25 #include <Units_ShiftedToken.hxx>
26 #include <Units_TokensSequence.hxx>
27 #include <Units_Operators.hxx>
30 static Handle(Units_Token) CreateTokenForNumber(const Standard_CString str)
32 TCollection_AsciiString tstr = str[0];
33 Standard_Boolean IsPoint = Standard_False;
34 Standard_Integer len = strlen(str);
35 for(Standard_Integer in=1; in < len; in++) {
36 if( str[in]=='0' || str[in]=='1' || str[in]=='2' || str[in]=='3' ||
37 str[in]=='4' || str[in]=='5' || str[in]=='6' || str[in]=='7' ||
38 str[in]=='8' || str[in]=='9' ) {
39 tstr.AssignCat(str[in]);
41 else if( str[in]=='.' && !IsPoint ) {
42 tstr.AssignCat(str[in]);
43 IsPoint = Standard_True;
48 return new Units_Token(tstr.ToCString(), "0");
52 //=======================================================================
53 //function : Units_Sentence
55 //=======================================================================
57 Units_Sentence::Units_Sentence(const Handle(Units_Lexicon)& alexicon,
58 const Standard_CString astring)
60 Standard_Integer index;
61 Standard_Integer i,k,l,limchain;
63 Handle(Units_Token) token;
64 Handle(Units_Token) referencetoken;
66 thesequenceoftokens = new Units_TokensSequence();
67 Handle(Units_TokensSequence) lstlexicon=alexicon->Sequence();
68 Units_NoSuchType_Raise_if(lstlexicon.IsNull(),"BAD LEXICON descriptor");
69 limchain=strlen(astring);
71 for(l=0; l<255; l++) {
76 TCollection_AsciiString tmpstr = astring;
77 //Handle(Units_Token) tmptoken;
78 TCollection_AsciiString PrevMean;
79 TCollection_AsciiString PrevWord;
81 Standard_Boolean IsFound = Standard_False;
82 TCollection_AsciiString LastWord = "";
83 for(index=1; index<=lstlexicon->Length(); index++) {
84 referencetoken = lstlexicon->Value(index);
85 TCollection_AsciiString aword = referencetoken->Word();
86 int num = tmpstr.Search(aword);
87 if( num==1 && aword.Length()>=LastWord.Length() ) {
88 token = referencetoken->Creates();
90 IsFound = Standard_True;
94 // may be it is a number(degree)?
95 LastWord = tmpstr.SubString(1,1);
96 if(!LastWord.IsIntegerValue()) {
97 // unknown expression - not create sentene
98 thesequenceoftokens->Clear();
100 cout<<"Warning: can not create correct sentence from string: "<<astring<<endl;
105 // create token for number
106 token = CreateTokenForNumber(tmpstr.ToCString());
107 LastWord = token->Word();
111 // make additional checking
112 if( ( token->Mean()=="M" && ( PrevMean=="M" || PrevMean=="MU" || PrevMean=="0" ) ) ||
113 ( token->Mean()=="U" && ( PrevMean=="U" || PrevMean=="0" ) ) ||
114 ( token->Mean()=="O" && ( PrevMean=="M" || PrevMean=="O" ) ) ||
115 ( ( token->Word()=="+" || token->Word()=="-" ) && PrevWord!="(" ) ||
116 ( token->Mean()=="S" && ( PrevMean=="M" ) ) ||
117 ( token->Mean()=="0" && ( PrevMean=="M" || PrevMean=="U" || PrevMean=="MU" ) ) ) {
118 // incorrect situation
119 thesequenceoftokens->Clear();
121 cout<<"Warning: can not create correct sentence from string: "<<astring<<endl;
126 thesequenceoftokens->Append(token);
127 PrevMean = token->Mean();
128 PrevWord = token->Word();
129 i = i + LastWord.Length();
130 tmpstr.Remove(1,LastWord.Length());
133 // for(i=1; i<=thesequenceoftokens->Length(); i++) {
134 // token = thesequenceoftokens->Value(i);
135 // cout<<"i="<<i<<" token: "<<token->Word().ToCString()<<" "<<token->Mean().ToCString()
136 // <<" "<<token->Value()<<endl;
140 while(i < limchain) {
141 Standard_Integer itrouv=0;
142 for(index=1; index<=lstlexicon->Length(); index++) {
143 referencetoken = lstlexicon->Value(index);
144 if(i+referencetoken->Length() <= limchain) {
145 if(referencetoken <= &astring[i]) {
147 token = new Units_Token(chain,"0");
148 thesequenceoftokens->Append(token);
150 for(l=0; l<255; l++) {
154 token = referencetoken->Creates();
155 thesequenceoftokens->Append(token);
156 i = i + token->Length();
163 chain[k++]=astring[i++];
167 token = new Units_Token(chain, "0");
168 thesequenceoftokens->Append(token);
174 //=======================================================================
175 //function : SetConstants
177 //=======================================================================
179 void Units_Sentence::SetConstants()
181 Standard_Integer index;
183 Handle(Units_Token) token;
184 TCollection_AsciiString string;
186 for(index=1;index<=thesequenceoftokens->Length();index++) {
187 token = thesequenceoftokens->Value(index);
188 if(token->Value()==0.) {
189 string = token->Word();
190 if(string.IsRealValue()) {
191 value = string.RealValue();
200 //=======================================================================
201 //function : CalculateLocal
203 //=======================================================================
204 static Handle(Units_Token) CalculateLocal(const Handle(Units_TokensSequence)& aSeq)
207 //for(int index=1; index<=aSeq->Length(); index++) {
208 // Handle(Units_Token) tok = aSeq->Value(index);
209 // cout<<tok->Word()<<" ";
212 Handle(Units_Token) tok1,tok2;
213 Standard_Integer i,j;
215 if(aSeq->Length()==1) {
216 return aSeq->Value(1);
220 if(aSeq->Length()==2) {
221 if(aSeq->Value(1)->Word()=="+")
223 if(aSeq->Value(1)->Word()=="-") {
224 tok2 = aSeq->Value(2);
225 TCollection_AsciiString aword = "-";
226 aword.AssignCat(tok2->Word());
227 tok1 = new Units_Token(aword.ToCString(), tok2->Mean().ToCString(),
228 tok2->Value()*(-1.0), tok2->Dimensions());
230 aSeq->SetValue(1,tok1);
232 return aSeq->Value(1);
235 Standard_Boolean IsBracket = Standard_True;
237 for(i=1; i<=aSeq->Length(); i++) {
238 if(aSeq->Value(i)->Word()=="(") {
239 Handle(Units_TokensSequence) TmpSeq = new Units_TokensSequence;
240 Standard_Integer NbBrackets = 1;
241 for(j=i+1; j<=aSeq->Length(); j++) {
242 if(aSeq->Value(j)->Word()==")")
244 if(aSeq->Value(j)->Word()=="(")
247 TmpSeq->Append(aSeq->Value(j));
251 tok1 = CalculateLocal(TmpSeq);
253 aSeq->SetValue(i,tok1);
257 if(i>aSeq->Length()) {
258 IsBracket = Standard_False;
259 // there are not brackets => make calculations
260 // step 1: operation '**'
261 for(i=1; i<=aSeq->Length(); i++) {
262 if(aSeq->Value(i)->Word()=="**") {
263 tok1 = aSeq->Value(i-1);
264 tok2 = aSeq->Value(i+1);
265 tok1 = pow(tok1,tok2);
268 aSeq->SetValue(i-1,tok1);
272 // step 2: operation '*', '.' and '/'
273 for(i=1; i<=aSeq->Length(); i++) {
274 if(aSeq->Value(i)->Mean()=="O") {
275 tok1 = aSeq->Value(i-1);
276 tok2 = aSeq->Value(i+1);
277 if(aSeq->Value(i)->Word()=="/")
283 aSeq->SetValue(i-1,tok1);
287 // now aSeq have to include only one result token
294 //=======================================================================
295 //function : Evaluate
297 //=======================================================================
299 Handle(Units_Token) Units_Sentence::Evaluate()
301 Handle(Units_Token) rtoken,ktoken;
302 if(thesequenceoftokens->Length()==0)
306 Standard_Integer index;
307 static char *ooper[6] = { "+", "-", "*", ".", "/", "**" };
308 Standard_Integer numterm,i,j,k,maxlevel,curlevel,level[255];
309 Handle(Units_Token) currenttoken;
310 TCollection_AsciiString string;
311 TCollection_AsciiString mean;
312 TCollection_AsciiString oper;
314 numterm=curlevel=i=0;
315 for(index=1;index<=thesequenceoftokens->Length();index++) {
316 string = thesequenceoftokens->Value(index)->Word();
319 level[numterm]=curlevel;
322 else if( string==")" ) {
324 level[numterm]=curlevel;
327 level[numterm]=curlevel;
334 // for(index=1; index<=thesequenceoftokens->Length(); index++) {
335 // Handle(Units_Token) tok = thesequenceoftokens->Value(index);
336 // cout<<tok->Word()<<" ";
339 // for(index=1; index<=thesequenceoftokens->Length(); index++) {
340 // cout<<level[index-1]<<" ";
346 cout<<" Incorrect number of brackets"<<endl;
347 return new Units_Token();
351 for(index=1,i=0; index<=thesequenceoftokens->Length(); index++,i++) {
352 if( thesequenceoftokens->Value(index)->Word() == ooper[k] ) {
355 while(j < numterm && level[j] >= curlevel)
359 while(j >= 0 && level[j] >= curlevel)
365 Handle(Units_Dimensions) aDim;
371 for(i=0; i<=numterm; i++)if(level[i] > maxlevel)
375 while(level[i] != maxlevel)
381 while( k<=numterm && level[k]==maxlevel ) {
382 ktoken=thesequenceoftokens->Value(k+1);
385 oper = ktoken->Word();
388 if (oper == "/") rtoken = rtoken / ktoken;
389 else if(oper == "+") rtoken = rtoken + ktoken;
390 else if(oper == "-") rtoken = rtoken - ktoken;
391 else if(oper == "*") rtoken = rtoken * ktoken;
392 else if(oper == "**") rtoken = pow(rtoken,ktoken);
393 else if(oper == ".") rtoken = rtoken * ktoken;
394 else rtoken = ktoken->Creates();
398 thesequenceoftokens->SetValue(i+1,rtoken);
402 thesequenceoftokens->Remove(i+2,k);
405 level[++j]=level[k++];
410 rtoken = thesequenceoftokens->Value(1)->Creates();
412 if( rtoken->Value()==0. ) {
413 cout << "*BAD token value from unit '" << rtoken->Word() << "'" << endl;
416 */ // end old variant
418 // variant skl 15.09.2005
419 rtoken = CalculateLocal(thesequenceoftokens);