b311480e |
1 | // Created on: 1992-06-24 |
2 | // Created by: Gilles DEBARBOUILLE |
3 | // Copyright (c) 1992-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
42cf5bc1 |
17 | |
18 | #include <Units_Lexicon.hxx> |
7fd59977 |
19 | #include <Units_NoSuchType.hxx> |
42cf5bc1 |
20 | #include <Units_Operators.hxx> |
21 | #include <Units_Sentence.hxx> |
7fd59977 |
22 | #include <Units_ShiftedToken.hxx> |
42cf5bc1 |
23 | #include <Units_Token.hxx> |
7fd59977 |
24 | #include <Units_TokensSequence.hxx> |
7fd59977 |
25 | |
26 | static Handle(Units_Token) CreateTokenForNumber(const Standard_CString str) |
27 | { |
28 | TCollection_AsciiString tstr = str[0]; |
29 | Standard_Boolean IsPoint = Standard_False; |
60be1f9b |
30 | Standard_Size len = strlen(str); |
31 | for(Standard_Size in=1; in < len; in++) { |
7fd59977 |
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]); |
36 | } |
37 | else if( str[in]=='.' && !IsPoint ) { |
38 | tstr.AssignCat(str[in]); |
39 | IsPoint = Standard_True; |
40 | } |
41 | else |
42 | break; |
43 | } |
44 | return new Units_Token(tstr.ToCString(), "0"); |
45 | } |
46 | |
47 | |
48 | //======================================================================= |
49 | //function : Units_Sentence |
50 | //purpose : |
51 | //======================================================================= |
52 | |
53 | Units_Sentence::Units_Sentence(const Handle(Units_Lexicon)& alexicon, |
54 | const Standard_CString astring) |
55 | { |
56 | Standard_Integer index; |
fb8a7358 |
57 | Standard_Size i,limchain; |
7fd59977 |
58 | Handle(Units_Token) token; |
59 | Handle(Units_Token) referencetoken; |
60 | |
61 | thesequenceoftokens = new Units_TokensSequence(); |
62 | Handle(Units_TokensSequence) lstlexicon=alexicon->Sequence(); |
3d370858 |
63 | if(lstlexicon.IsNull()) |
9775fa61 |
64 | throw Units_NoSuchType("BAD LEXICON descriptor"); |
7fd59977 |
65 | limchain=strlen(astring); |
7fd59977 |
66 | i=0; |
67 | |
68 | TCollection_AsciiString tmpstr = astring; |
69 | //Handle(Units_Token) tmptoken; |
70 | TCollection_AsciiString PrevMean; |
71 | TCollection_AsciiString PrevWord; |
72 | while(i < limchain) { |
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(); |
81 | LastWord = aword; |
82 | IsFound = Standard_True; |
83 | } |
84 | } |
85 | if(!IsFound) { |
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(); |
0797d9d3 |
91 | #ifdef OCCT_DEBUG |
04232180 |
92 | std::cout<<"Warning: can not create correct sentence from string: "<<astring<<std::endl; |
7fd59977 |
93 | #endif |
94 | return; |
95 | } |
96 | else { |
97 | // create token for number |
98 | token = CreateTokenForNumber(tmpstr.ToCString()); |
99 | LastWord = token->Word(); |
100 | } |
101 | } |
102 | if(i>0) { |
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(); |
0797d9d3 |
112 | #ifdef OCCT_DEBUG |
04232180 |
113 | std::cout<<"Warning: can not create correct sentence from string: "<<astring<<std::endl; |
7fd59977 |
114 | #endif |
115 | return; |
116 | } |
117 | } |
118 | thesequenceoftokens->Append(token); |
119 | PrevMean = token->Mean(); |
120 | PrevWord = token->Word(); |
121 | i = i + LastWord.Length(); |
122 | tmpstr.Remove(1,LastWord.Length()); |
123 | } |
7fd59977 |
124 | } |
125 | |
126 | |
127 | //======================================================================= |
128 | //function : SetConstants |
129 | //purpose : |
130 | //======================================================================= |
131 | |
132 | void Units_Sentence::SetConstants() |
133 | { |
134 | Standard_Integer index; |
135 | Standard_Real value; |
136 | Handle(Units_Token) token; |
137 | TCollection_AsciiString string; |
138 | |
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(); |
145 | token->Mean("K"); |
146 | token->Value(value); |
147 | } |
148 | } |
149 | } |
150 | } |
151 | |
152 | |
153 | //======================================================================= |
154 | //function : CalculateLocal |
a25d5aaa |
155 | //purpose : auxiliary |
7fd59977 |
156 | //======================================================================= |
157 | static Handle(Units_Token) CalculateLocal(const Handle(Units_TokensSequence)& aSeq) |
158 | { |
04232180 |
159 | //std::cout<<std::endl; |
7fd59977 |
160 | //for(int index=1; index<=aSeq->Length(); index++) { |
161 | // Handle(Units_Token) tok = aSeq->Value(index); |
04232180 |
162 | // std::cout<<tok->Word()<<" "; |
7fd59977 |
163 | //} |
04232180 |
164 | //std::cout<<std::endl; |
7fd59977 |
165 | Handle(Units_Token) tok1,tok2; |
166 | Standard_Integer i,j; |
167 | |
168 | if(aSeq->Length()==1) { |
169 | return aSeq->Value(1); |
170 | } |
171 | |
172 | // case of unar sign |
173 | if(aSeq->Length()==2) { |
174 | if(aSeq->Value(1)->Word()=="+") |
175 | aSeq->Remove(1); |
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()); |
182 | aSeq->Remove(1); |
183 | aSeq->SetValue(1,tok1); |
184 | } |
185 | return aSeq->Value(1); |
186 | } |
187 | |
188 | Standard_Boolean IsBracket = Standard_True; |
189 | while(IsBracket) { |
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()==")") |
196 | NbBrackets--; |
197 | if(aSeq->Value(j)->Word()=="(") |
198 | NbBrackets++; |
199 | if(NbBrackets>0) |
200 | TmpSeq->Append(aSeq->Value(j)); |
201 | else |
202 | break; |
203 | } |
204 | tok1 = CalculateLocal(TmpSeq); |
205 | aSeq->Remove(i+1,j); |
206 | aSeq->SetValue(i,tok1); |
207 | break; |
208 | } |
209 | } |
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); |
219 | aSeq->Remove(i); |
220 | aSeq->Remove(i); |
221 | aSeq->SetValue(i-1,tok1); |
222 | i--; |
223 | } |
224 | } |
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()=="/") |
231 | tok1 = tok1 / tok2; |
232 | else |
233 | tok1 = tok1 * tok2; |
234 | aSeq->Remove(i); |
235 | aSeq->Remove(i); |
236 | aSeq->SetValue(i-1,tok1); |
237 | i--; |
238 | } |
239 | } |
240 | // now aSeq have to include only one result token |
241 | } |
242 | } |
243 | return tok1; |
244 | } |
245 | |
246 | |
247 | //======================================================================= |
248 | //function : Evaluate |
249 | //purpose : |
250 | //======================================================================= |
251 | |
252 | Handle(Units_Token) Units_Sentence::Evaluate() |
253 | { |
254 | Handle(Units_Token) rtoken,ktoken; |
255 | if(thesequenceoftokens->Length()==0) |
256 | return rtoken; |
257 | |
258 | /* old variant |
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; |
266 | |
267 | numterm=curlevel=i=0; |
268 | for(index=1;index<=thesequenceoftokens->Length();index++) { |
269 | string = thesequenceoftokens->Value(index)->Word(); |
270 | |
271 | if( string=="(" ) { |
272 | level[numterm]=curlevel; |
273 | curlevel++; |
274 | } |
275 | else if( string==")" ) { |
276 | curlevel--; |
277 | level[numterm]=curlevel; |
278 | } |
279 | else { |
280 | level[numterm]=curlevel; |
281 | } |
282 | numterm++; |
283 | } |
284 | |
285 | //if(IPrint==1) { |
04232180 |
286 | // std::cout<<std::endl; |
7fd59977 |
287 | // for(index=1; index<=thesequenceoftokens->Length(); index++) { |
288 | // Handle(Units_Token) tok = thesequenceoftokens->Value(index); |
04232180 |
289 | // std::cout<<tok->Word()<<" "; |
7fd59977 |
290 | // } |
04232180 |
291 | // std::cout<<std::endl; |
7fd59977 |
292 | // for(index=1; index<=thesequenceoftokens->Length(); index++) { |
04232180 |
293 | // std::cout<<level[index-1]<<" "; |
7fd59977 |
294 | // } |
04232180 |
295 | // std::cout<<std::endl; |
7fd59977 |
296 | //} |
297 | |
298 | if(curlevel) { |
04232180 |
299 | std::cout<<" Incorrect number of brackets"<<std::endl; |
7fd59977 |
300 | return new Units_Token(); |
301 | } |
302 | |
303 | for(k=0; k<6; k++) { |
304 | for(index=1,i=0; index<=thesequenceoftokens->Length(); index++,i++) { |
305 | if( thesequenceoftokens->Value(index)->Word() == ooper[k] ) { |
306 | j=i+1; |
307 | curlevel=level[j]; |
308 | while(j < numterm && level[j] >= curlevel) |
309 | level[j++]++; |
310 | j=i-1; |
311 | curlevel=level[j]; |
312 | while(j >= 0 && level[j] >= curlevel) |
313 | level[j--]++; |
314 | } |
315 | } |
316 | } |
317 | |
318 | Handle(Units_Dimensions) aDim; |
319 | |
320 | numterm--; |
321 | while(numterm>0) { |
322 | |
323 | maxlevel=0; |
324 | for(i=0; i<=numterm; i++)if(level[i] > maxlevel) |
325 | maxlevel=level[i]; |
326 | |
327 | i=0; |
328 | while(level[i] != maxlevel) |
329 | i++; |
330 | |
331 | oper.Clear(); |
332 | |
333 | k=i; |
334 | while( k<=numterm && level[k]==maxlevel ) { |
335 | ktoken=thesequenceoftokens->Value(k+1); |
336 | mean=ktoken->Mean(); |
337 | if(mean=="O") { |
338 | oper = ktoken->Word(); |
339 | } |
340 | else if(mean!="S") { |
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(); |
348 | } |
349 | k++; |
350 | } |
351 | thesequenceoftokens->SetValue(i+1,rtoken); |
352 | level[i]=maxlevel-1; |
353 | |
354 | if( (i+1) != k ) { |
355 | thesequenceoftokens->Remove(i+2,k); |
356 | j=i; |
357 | while(k <= numterm) |
358 | level[++j]=level[k++]; |
359 | numterm=j; |
360 | } |
361 | } |
362 | |
363 | rtoken = thesequenceoftokens->Value(1)->Creates(); |
364 | |
365 | if( rtoken->Value()==0. ) { |
04232180 |
366 | std::cout << "*BAD token value from unit '" << rtoken->Word() << "'" << std::endl; |
7fd59977 |
367 | rtoken->Value(1.); |
368 | } |
369 | */ // end old variant |
370 | |
371 | // variant skl 15.09.2005 |
372 | rtoken = CalculateLocal(thesequenceoftokens); |
373 | |
374 | //rtoken->Dump(0,1); |
375 | |
376 | return rtoken; |
377 | } |