TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
StringTokenizer.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <StringTokenizer.h>
17#include <Char_ptr.h>
18#include <Objet_U.h>
19#include <math.h>
20#include <string.h>
21#include <sstream>
22#include <algorithm>
23
24//using namespace std;
25using std::stringstream;
26
27const int StringTokenizer::NUMBER=-2;
28const int StringTokenizer::STRING=-3;
29const int StringTokenizer::EOS=-1;
30
31
32// On ne definit les identificateurs des operateurs qu'une seule fois entre la classe Parser et StringTokenizer.
33// Pour l'instant, on les place dans cette classe et donc on les supprime de la classe Parser
34// => on pourra envisager de les mettre dans une classe a part entiere si ca parait plus clair.
35/* attention il faut que les constantes suivantes soit superieur a 0 pour eviter les conflits avec les fonctions unaires
36 */
37const int StringTokenizer::ADD = 0;
38const int StringTokenizer::SUBTRACT = 1;
39const int StringTokenizer::MULTIPLY = 2;
40const int StringTokenizer::DIVIDE = 3;
41const int StringTokenizer::POWER = 4;
42const int StringTokenizer::LT = 5;
43const int StringTokenizer::GT = 6;
44const int StringTokenizer::LE = 7;
45const int StringTokenizer::GE = 8;
46const int StringTokenizer::MOD = 9;
47const int StringTokenizer::MAX = 10;
48const int StringTokenizer::MIN = 11;
49const int StringTokenizer::AND = 12;
50const int StringTokenizer::OR = 13;
51const int StringTokenizer::EQ = 14;
52const int StringTokenizer::NEQ = 15;
53// les parentheses :
54const int StringTokenizer::GRP = 1000;
55const int StringTokenizer::ENDGRP = 1001;
56
57
58// Nb d'operateurs et mot-cles pour les identifier (ne concerne pas les parentheses"(" et ")").
59// Attention a l'ordre des operateurs ci dessous : ils doivent etre positionnes dans les tableaux keyword_op et keyword_op_bis en fonction des valeurs des constantes statiques ADD, SUB etc... definies ci-dessus
60//
61const int StringTokenizer::nb_op=16;
62const int StringTokenizer::nb_op_bis=11;
63const char StringTokenizer::keyword_op[][10] = { "ADD", "SUB", "MUL", "DIV" , "POW", "LT", "GT", "LE", "GE", "MOD", "MAX", "MIN", "AND", "OR", "EQ", "NEQ" };
64const char StringTokenizer::keyword_op_bis[][10] = { "+", "-", "*", "/", "^", "<", ">", "[", "]", "%", "$" };
65
66
68{
69 str = std::string("0");
70 init_keyword_op();
71 reste = &str[0];
72}
73
75{
76 str = s;
77 init_keyword_op();
78 reste = &str[0];
79}
80
81StringTokenizer::StringTokenizer(std::string s, std::string sep)
82{
83 str = s;
84 init_keyword_op();
85 reste = &str[0];
86}
87
89{
90
91 for (int i=0; i<StringTokenizer::nb_op; i++)
92 {
93 delete[] op_sep[i];
94 }
95 delete[] op_sep;
96
97}
98
99
100
102{
103 const char* ch = str.c_str();
104 int nb_o=0;
105 int nb_f=0;
106 int sz = (int)strlen(ch);
107 for (int i=0; i<sz; i++)
108 {
109 if (*(ch+i)=='(')
110 nb_o++;
111 else if (*(ch+i)==')')
112 nb_f++;
113 }
114 return (nb_o==nb_f);
115}
116
117
119{
120 char *tmp;
121 int type_sep, length;
122 tmp=find_sep(reste, type_sep, length);
123 if (tmp == nullptr)
124 {
125 //Cout << "Fin ? " << reste << finl;
126 if (reste[0] == '\0')
127 {
128 type = EOS;
129 }
130 else
131 {
132 if ( ((reste[0] >= '0') && ( reste[0] <= '9')) || (reste[0] == '.') )
133 {
134 // ajout OC pour provoquer une erreur avec 2x
135 int ind=(int)strlen(reste)-1;
136 if ( ((reste[ind] < '0') || (reste[ind] > '9')) && (reste[ind] != '.') )
137 {
138 Cerr << "The syntax " << reste << " is not allowed." << finl;
140 }
141 type = NUMBER;
142 stringstream stream;
143 stream << reste ;
144 stream >> nval;
145 if (!stream.eof() )
146 {
147 Cerr<<"Error conversion "<<reste<<" in number"<<finl;
149 }
150 }
151 else
152 {
153 type=STRING;
154 sval = reste;
155 std::transform(sval.begin(), sval.end(), sval.begin(), ::toupper);
156 }
157 while ((*reste++) != '\0') ;
158 reste--;
159 }
160 }
161 else if (tmp==reste)
162 {
163 type = type_sep;
164 reste=reste+length;
165 }
166 else
167 {
168 Char_ptr token;
169 token.allocate((int)(tmp-reste));
170
171 char* tok = token.getChar();;
172 int j=0;
173 for (int i=0; i<tmp-reste; i++)
174 {
175 if ( reste[i] != ' ' ) tok[j++] = reste[i];
176 }
177 tok[j] = '\0';
178 if (((tok[0] >= '0') && ( tok[0] <= '9')) || (tok[0] == '.') )
179 {
180 int ind;
181 double nval_tmp;
182
183 type = NUMBER;
184 stringstream stream;
185 ind = (int)(tmp-reste-1l);
186 reste = tmp;
187 if (tok[ind] == 'e' || tok[ind] == 'E' )
188 {
189 tok[ind]=' ';
190 stream << tok ;
191 stream >> nval_tmp;
192 char c;
193 stream >> c;
194
195 if (!stream.eof() )
196 {
197 Cerr<<"Error conversion "<<tok<<" in number"<<finl;
199 }
200 nextToken();
201 if (type == SUBTRACT)
202 {
203 nextToken();
204 if (type != NUMBER)
205 {
206 Cerr << "Error while interpreting the string " << str << finl;
208 }
209 nval_tmp*=pow(10,-nval);
210 }
211 else if (type == ADD)
212 {
213 nextToken();
214 if (type != NUMBER)
215 {
216 Cerr << "Error while interpreting the string " << str << finl;
218 }
219 nval_tmp*=pow(10.,nval);
220 }
221 else if (type == NUMBER)
222 {
223 // GF suivant les versions on a soit
224 nval_tmp*=pow(10.,nval);
225 // soit
226 //nval_tmp = nval;
227 // J'interdis pour l'instant
228 //Cerr << "Possible Erreur en interpretant la chaine " << str << finl;
229 //Process::exit();
230 }
231 else
232 {
233 Cerr << "Error while interpreting the string " << str << finl;
235 }
236 }
237 else if ( ((tok[ind] < '0') || (tok[ind] > '9')) && (tok[ind] != '.') )
238 {
239 Cerr << " The syntax " << tok << " is not allowed." << finl;
241 throw;
242 }
243 else
244 {
245 stream << tok ;
246 stream >> nval_tmp;
247 if (!stream.eof() )
248 {
249
250 Cerr<<"Error conversion "<<tok<<" in number"<<finl;
252 }
253 }
254 nval = nval_tmp;
255 }
256 else
257 {
258 type=STRING;
259 sval = tok;
260 std::transform(sval.begin(), sval.end(), sval.begin(), ::toupper);
261 reste=tmp;
262 }
263 // delete[] tok;
264 }
265 return type;
266}
267
268
269
270//methodes privees :
271
272void StringTokenizer::init_keyword_op()
273{
274 op_sep = new char*[nb_op];
275 // on encadre le mot-cle de chaque operateur par des "_" :
276 // LT => _LT_ etc...
277 for (int i=0; i<nb_op; i++)
278 {
279 const char* blanc="_";
280 op_sep[i] = new char[strlen(keyword_op[i])+3];
281 strcpy(op_sep[i],blanc);
282 strcat(op_sep[i], keyword_op[i]);
283 strcat(op_sep[i], blanc);
284 }
285}
286
287
288/**
289 * Cherche dans la chaine "ch" la prochaine apparition d'un separateur.
290 * Renvoie dans le parametre "type_sep", le type de separateur ((, ), +, - etc...)
291 * Renvoie egalement la longueur de la chaine correspondante au separateur trouve
292 */
293char* StringTokenizer::find_sep(char* ch, int& type_sep, int& length)
294{
295 char * trouve=nullptr;
296 char * trouve_tmp;
297 type_sep=-1;
298 trouve_tmp = strstr(ch, "(");
299 int pos=100000;
300 if (trouve_tmp != nullptr)
301 {
302 pos = (int)(trouve_tmp-ch);
303 type_sep=GRP;
304 length=1;
305 trouve=trouve_tmp;
306 }
307 trouve_tmp = strstr(ch, ")");
308 if ((trouve_tmp != nullptr) && (trouve_tmp-ch<pos))
309 {
310 pos = (int)(trouve_tmp-ch);
311 type_sep=ENDGRP;
312 length=1;
313 trouve=trouve_tmp;
314 }
315 for (int i=0; i<StringTokenizer::nb_op; i++)
316 {
317 trouve_tmp = strstr(ch, op_sep[i]);
318 if ((trouve_tmp != nullptr) && (trouve_tmp-ch<pos))
319 {
320 pos = (int)(trouve_tmp-ch);
321 type_sep=i;
322 length=(int)strlen(op_sep[i]);
323 trouve=trouve_tmp;
324 }
325 }
326 for (int i=0; i<StringTokenizer::nb_op_bis; i++)
327 {
328 trouve_tmp = strstr(ch, keyword_op_bis[i]);
329 if ((trouve_tmp != nullptr) && ((int)(trouve_tmp-ch)<pos))
330 {
331 pos = (int)(trouve_tmp-ch);
332 type_sep=i;
333 length=(int)strlen(keyword_op_bis[i]);
334 trouve=trouve_tmp;
335 }
336 }
337
338 return trouve;
339}
340
341
342
343/*
344 int main()
345 {
346 //String s("23+34*12-13+COS ( 12 )* 2^3");
347 std::string s("2+3");
348 StringTokenizer tk(s);
349 Cout << StringTokenizer::NUMBER << finl;
350 Cout << StringTokenizer::EOS << finl;
351 Cout << StringTokenizer::STRING << finl;
352
353 while (tk.nextToken()!=StringTokenizer::EOS)
354 {
355 if (tk.type == StringTokenizer::STRING)
356 {
357 Cout << "String = " << tk.getSValue() << finl;
358 }
359 else if (tk.type == StringTokenizer::NUMBER)
360 {
361 Cout << "Value = " << tk.getNValue() << finl;
362 }
363 else
364 {
365 Cout << "Operator = " << (char) tk.type << finl;
366 }
367 }
368 }
369*/
class Char_ptr Une chaine de caractere pour nommer les objets de TRUST
Definition Char_ptr.h:28
void allocate(int n)
Definition Char_ptr.cpp:119
char * getChar()
Definition Char_ptr.h:39
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static const int AND
static const int NUMBER
static const int EOS
static const int STRING
static const int MULTIPLY
static const int MIN
static const int GT
static const int POWER
static const int GRP
static const int GE
static const int LT
static const int LE
static const int MOD
static const int DIVIDE
static const int EQ
static const int ENDGRP
static const int SUBTRACT
static const int ADD
static const int OR
static const int MAX
static const int NEQ