0ff48a9df2f167e1b64a955dcee530cbae5ac822
[occt.git] / src / Units / Units_Sentence.cxx
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
5 //
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.
10 //
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.
13 //
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.
20
21
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>
28
29
30 static Handle(Units_Token) CreateTokenForNumber(const Standard_CString str)
31 {
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]);
40     }
41     else if( str[in]=='.' && !IsPoint ) {
42       tstr.AssignCat(str[in]);
43       IsPoint = Standard_True;
44     }
45     else
46       break;
47   }
48   return new Units_Token(tstr.ToCString(), "0");
49 }
50
51
52 //=======================================================================
53 //function : Units_Sentence
54 //purpose  : 
55 //=======================================================================
56
57 Units_Sentence::Units_Sentence(const Handle(Units_Lexicon)& alexicon,
58                                const Standard_CString astring)
59 {
60   Standard_Integer index;
61   Standard_Integer i,k,l,limchain;
62   char chain[255];
63   Handle(Units_Token) token;
64   Handle(Units_Token) referencetoken;
65   
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);
70   k=0;
71   for(l=0; l<255; l++) {
72     chain[l]=0;
73   }
74   i=0;
75
76   TCollection_AsciiString tmpstr = astring;
77   //Handle(Units_Token) tmptoken;
78   TCollection_AsciiString PrevMean;
79   TCollection_AsciiString PrevWord;
80   while(i < limchain) {
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();
89         LastWord = aword;
90         IsFound = Standard_True;
91       }
92     }
93     if(!IsFound) {
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();
99 #ifdef DEB
100         cout<<"Warning: can not create correct sentence from string: "<<astring<<endl;
101 #endif
102         return;
103       }
104       else {
105         // create token for number
106         token = CreateTokenForNumber(tmpstr.ToCString());
107         LastWord = token->Word();
108       }
109     }
110     if(i>0) {
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();
120 #ifdef DEB
121         cout<<"Warning: can not create correct sentence from string: "<<astring<<endl;
122 #endif
123         return;
124       }
125     }
126     thesequenceoftokens->Append(token);
127     PrevMean = token->Mean();
128     PrevWord = token->Word();
129     i = i + LastWord.Length();
130     tmpstr.Remove(1,LastWord.Length());
131   }
132
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;
137 //  }
138
139 /*
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]) {
146           if(k) {
147             token = new Units_Token(chain,"0");
148             thesequenceoftokens->Append(token);
149             k=0;
150             for(l=0; l<255; l++) {
151               chain[l]=0;
152             }
153           }
154           token = referencetoken->Creates();
155           thesequenceoftokens->Append(token);
156           i = i + token->Length();
157           itrouv=1;
158           break;
159         }
160       }
161     }
162     if(!itrouv) {
163       chain[k++]=astring[i++];
164     }
165   }
166   if(k) {
167     token = new Units_Token(chain, "0");
168     thesequenceoftokens->Append(token);
169   }
170 */
171 }
172
173
174 //=======================================================================
175 //function : SetConstants
176 //purpose  : 
177 //=======================================================================
178
179 void Units_Sentence::SetConstants()
180 {
181   Standard_Integer index;
182   Standard_Real value;
183   Handle(Units_Token) token;
184   TCollection_AsciiString string;
185
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();
192         token->Mean("K");
193         token->Value(value);
194       }
195     }
196   }
197 }
198
199
200 //=======================================================================
201 //function : CalculateLocal
202 //purpose  : auxilary
203 //=======================================================================
204 static Handle(Units_Token) CalculateLocal(const Handle(Units_TokensSequence)& aSeq)
205 {
206   //cout<<endl;
207   //for(int index=1; index<=aSeq->Length(); index++) {
208   //  Handle(Units_Token) tok = aSeq->Value(index);
209   //  cout<<tok->Word()<<" ";
210   //}
211   //cout<<endl;
212   Handle(Units_Token) tok1,tok2;
213   Standard_Integer i,j;
214
215   if(aSeq->Length()==1) {
216     return aSeq->Value(1);
217   }
218
219   // case of unar sign
220   if(aSeq->Length()==2) {
221     if(aSeq->Value(1)->Word()=="+")
222       aSeq->Remove(1);
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());
229       aSeq->Remove(1);
230       aSeq->SetValue(1,tok1);
231     }
232     return aSeq->Value(1);
233   }
234
235   Standard_Boolean IsBracket = Standard_True;
236   while(IsBracket) {
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()==")")
243             NbBrackets--;
244           if(aSeq->Value(j)->Word()=="(")
245             NbBrackets++;
246           if(NbBrackets>0)
247             TmpSeq->Append(aSeq->Value(j));
248           else
249             break;
250         }
251         tok1 = CalculateLocal(TmpSeq);
252         aSeq->Remove(i+1,j);
253         aSeq->SetValue(i,tok1);
254         break;
255       }
256     }
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);
266           aSeq->Remove(i);
267           aSeq->Remove(i);
268           aSeq->SetValue(i-1,tok1);
269           i--;
270         }
271       }
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()=="/")
278             tok1 = tok1 / tok2;
279           else
280             tok1 = tok1 * tok2;
281           aSeq->Remove(i);
282           aSeq->Remove(i);
283           aSeq->SetValue(i-1,tok1);
284           i--;
285         }
286       }
287       // now aSeq have to include only one result token
288     }
289   }
290   return tok1;
291 }
292
293
294 //=======================================================================
295 //function : Evaluate
296 //purpose  : 
297 //=======================================================================
298
299 Handle(Units_Token) Units_Sentence::Evaluate()
300 {
301   Handle(Units_Token) rtoken,ktoken;
302   if(thesequenceoftokens->Length()==0)
303     return rtoken;
304
305 /* old variant
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;
313   
314   numterm=curlevel=i=0;
315   for(index=1;index<=thesequenceoftokens->Length();index++) {
316     string = thesequenceoftokens->Value(index)->Word();
317
318     if( string=="(" ) {
319       level[numterm]=curlevel;
320       curlevel++;
321     }
322     else if( string==")" ) {
323       curlevel--;
324       level[numterm]=curlevel;
325     }
326     else {
327       level[numterm]=curlevel;
328     }
329     numterm++;
330   }
331
332   //if(IPrint==1) {
333   //  cout<<endl;
334   //  for(index=1; index<=thesequenceoftokens->Length(); index++) {
335   //    Handle(Units_Token) tok = thesequenceoftokens->Value(index);
336   //    cout<<tok->Word()<<" ";
337   //  }
338   //  cout<<endl;
339   //  for(index=1; index<=thesequenceoftokens->Length(); index++) {
340   //    cout<<level[index-1]<<" ";
341   //  }
342   //  cout<<endl;
343   //}
344
345   if(curlevel) {
346     cout<<" Incorrect number of brackets"<<endl;
347     return new Units_Token();
348   }
349
350   for(k=0; k<6; k++) {
351     for(index=1,i=0; index<=thesequenceoftokens->Length(); index++,i++) {
352       if( thesequenceoftokens->Value(index)->Word() == ooper[k] ) {
353         j=i+1;
354         curlevel=level[j];
355         while(j < numterm && level[j] >= curlevel)
356           level[j++]++;
357         j=i-1;
358         curlevel=level[j];
359         while(j >= 0 && level[j] >= curlevel)
360           level[j--]++;
361       }
362     }
363   }
364
365   Handle(Units_Dimensions) aDim;
366
367   numterm--;
368   while(numterm>0) {
369
370     maxlevel=0;
371     for(i=0; i<=numterm; i++)if(level[i] > maxlevel)
372       maxlevel=level[i];
373
374     i=0;
375     while(level[i] != maxlevel)
376       i++;
377
378     oper.Clear();
379
380     k=i;
381     while( k<=numterm && level[k]==maxlevel ) {
382       ktoken=thesequenceoftokens->Value(k+1);
383       mean=ktoken->Mean();
384       if(mean=="O") {
385         oper = ktoken->Word();
386       }
387       else if(mean!="S") {
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();
395       }
396       k++;
397     }
398     thesequenceoftokens->SetValue(i+1,rtoken);
399     level[i]=maxlevel-1;
400
401     if( (i+1) != k ) {
402       thesequenceoftokens->Remove(i+2,k);
403       j=i;
404       while(k <= numterm)
405         level[++j]=level[k++];
406       numterm=j;
407     }
408   }
409
410   rtoken = thesequenceoftokens->Value(1)->Creates();
411
412   if( rtoken->Value()==0. ) {
413     cout << "*BAD token value from unit '" << rtoken->Word() << "'" << endl;
414     rtoken->Value(1.);
415   }
416 */ // end old variant
417
418   // variant skl 15.09.2005
419   rtoken = CalculateLocal(thesequenceoftokens);
420
421   //rtoken->Dump(0,1);
422
423   return rtoken;
424 }