ifeqEntry.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2018-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "ifeqEntry.H"
27 #include "ifEntry.H"
28 #include "elifEntry.H"
29 #include "elseEntry.H"
30 #include "endifEntry.H"
31 #include "stringOps.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39 namespace functionEntries
40 {
43 
45  (
47  ifeqEntry,
48  execute,
49  primitiveEntryIstream
50  );
51 }
52 }
53 
54 
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 
57 Foam::tokenList Foam::functionEntries::ifeqEntry::readArgList
58 (
59  Istream& is
60 ) const
61 {
63 
64  {
65  const token startArgs(is);
66 
67  if
68  (
69  startArgs.isPunctuation()
70  && startArgs.pToken() == token::BEGIN_LIST
71  )
72  {
73  args.append(startArgs);
74  }
75  else
76  {
78  << "Expected " << token::BEGIN_LIST
79  << " to start the argument list but found " << startArgs
80  << " in " << typeName
81  << exit(FatalIOError);
82  }
83  }
84 
85  // Read the two arguments
86  args.append(token(is));
87  args.append(token(is));
88 
89  {
90  const token endArgs(is);
91 
92  if
93  (
94  endArgs.isPunctuation()
95  && endArgs.pToken() == token::END_LIST
96  )
97  {
98  args.append(endArgs);
99  }
100  else
101  {
103  << "Expected " << token::END_LIST
104  << " to end the argument list but found " << endArgs
105  << " in " << typeName
106  << exit(FatalIOError);
107  }
108  }
109 
110  return args;
111 }
112 
113 
114 void Foam::functionEntries::ifeqEntry::readToken(token& t, Istream& is) const
115 {
116  // Skip dummy tokens - avoids entry::getKeyword consuming #else, #endif
117  do
118  {
119  if( is.read(t).bad() || is.eof() || !t.good())
120  {
121  return;
122  }
123  }
124  while (t == token::END_STATEMENT);
125 }
126 
127 
128 Foam::token Foam::functionEntries::ifeqEntry::expand
129 (
130  const dictionary& dict,
131  const token& t
132 ) const
133 {
134  if (t.isVariable())
135  {
136  const variable& var = t.variableToken();
137 
138  word varName = var(1, var.size() - 1);
139 
140  // Lookup the variable name in the given dictionary
141  const entry* ePtr = dict.lookupScopedEntryPtr
142  (
143  varName,
144  true,
145  true
146  );
147 
148  if (ePtr)
149  {
150  return token(ePtr->stream());
151  }
152  else
153  {
154  // String expansion. Allow unset variables
155  string expanded(var);
156  stringOps::inplaceExpandEntry(expanded, dict, true, true);
157 
158  // Re-form as a string token so we can compare to string
159  return token(expanded, t.lineNumber());
160  }
161  }
162  else
163  {
164  return t;
165  }
166 }
167 
168 
169 bool Foam::functionEntries::ifeqEntry::equalToken
170 (
171  const token& t1,
172  const token& t2
173 ) const
174 {
175  const bool eqType = (t1.type() == t2.type());
176 
177  switch (t1.type())
178  {
179  case token::UNDEFINED:
180  return eqType;
181 
182  case token::PUNCTUATION:
183  return (eqType && t1.pToken() == t2.pToken());
184 
185  case token::WORD:
186  case token::FUNCTIONNAME:
187  case token::STRING:
189  if (t2.isAnyString())
190  {
191  return t1.anyStringToken() == t2.anyStringToken();
192  }
193  else
194  {
195  return false;
196  }
197 
198  case token::VARIABLE:
200  << "Attempt to compare an un-expanded variable"
201  << InfoProxy<token>(t1)
202  << exit(FatalIOError);
203  return false;
204 
205  case token::INTEGER_32:
206  if (eqType)
207  {
208  return t1.integer32Token() == t2.integer32Token();
209  }
210  else if (t2.isLabel())
211  {
212  return t1.labelToken() == t2.labelToken();
213  }
214  else if (t2.isScalar())
215  {
216  return t1.labelToken() == t2.scalarToken();
217  }
218  else
219  {
220  return false;
221  }
222 
223  case token::INTEGER_64:
224  if (eqType)
225  {
226  return t1.integer64Token() == t2.integer64Token();
227  }
228  else if (t2.isLabel())
229  {
230  return t1.labelToken() == t2.labelToken();
231  }
232  else if (t2.isScalar())
233  {
234  return t1.labelToken() == t2.scalarToken();
235  }
236  else
237  {
238  return false;
239  }
240 
242  if (eqType)
243  {
244  return
245  t1.unsignedInteger32Token() == t2.unsignedInteger32Token();
246  }
247  else if (t2.isLabel())
248  {
249  return t1.labelToken() == t2.labelToken();
250  }
251  else if (t2.isScalar())
252  {
253  return t1.labelToken() == t2.scalarToken();
254  }
255  else
256  {
257  return false;
258  }
259 
261  if (eqType)
262  {
263  return
264  t1.unsignedInteger64Token() == t2.unsignedInteger64Token();
265  }
266  else if (t2.isLabel())
267  {
268  return t1.labelToken() == t2.labelToken();
269  }
270  else if (t2.isScalar())
271  {
272  return t1.labelToken() == t2.scalarToken();
273  }
274  else
275  {
276  return false;
277  }
278 
279  case token::FLOAT_SCALAR:
280  if (eqType)
281  {
282  return equal(t1.floatScalarToken(), t2.floatScalarToken());
283  }
284  else if (t2.isScalar())
285  {
286  return t1.scalarToken() == t2.scalarToken();
287  }
288  else
289  {
290  return false;
291  }
292 
294  if (eqType)
295  {
296  return equal(t1.doubleScalarToken(), t2.doubleScalarToken());
297  }
298  else if (t2.isScalar())
299  {
300  return t1.scalarToken() == t2.scalarToken();
301  }
302  else
303  {
304  return false;
305  }
306 
308  if (eqType)
309  {
310  return equal
311  (
312  t1.longDoubleScalarToken(),
313  t2.longDoubleScalarToken()
314  );
315  }
316  else if (t2.isScalar())
317  {
318  return t1.scalarToken() == t2.scalarToken();
319  }
320  else
321  {
322  return false;
323  }
324 
325  case token::COMPOUND:
326  return false;
327 
328  case token::ERROR:
329  return eqType;
330  }
331 
332  return false;
333 }
334 
335 
336 void Foam::functionEntries::ifeqEntry::skipUntil
337 (
338  DynamicList<filePos>& stack,
339  const dictionary& contextDict,
340  const functionName& endWord,
341  Istream& is
342 ) const
343 {
344  while (!is.eof())
345  {
346  token t;
347  readToken(t, is);
348  if (t.isFunctionName())
349  {
350  if
351  (
352  t.functionNameToken() == ifEntry::typeName
353  || t.functionNameToken() == ifeqEntry::typeName
354  )
355  {
356  stack.append(filePos(is.name(), is.lineNumber()));
357  skipUntil(stack, contextDict, endifEntry::typeName, is);
358  stack.remove();
359  }
360  else if (t.functionNameToken() == endWord)
361  {
362  return;
363  }
364  }
365  }
366 
367  FatalIOErrorInFunction(contextDict)
368  << "Did not find matching " << endWord
369  << " for " << typeName << " condition"
370  << exit(FatalIOError);
371 }
372 
373 
374 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
375 
377 (
378  const functionName& functionType,
379  const label lineNumber,
380  const dictionary& parentDict,
381  const Istream& is,
382  const tokenList& tokens
383 )
384 :
385  functionEntry(functionType, lineNumber, parentDict, is, tokens)
386 {}
387 
388 
390 (
391  const label lineNumber,
392  const dictionary& parentDict,
393  Istream& is
394 )
395 :
396  ifeqEntry(typeName, lineNumber, parentDict, is, readArgList(is))
397 {}
398 
399 
400 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
401 
402 bool Foam::functionEntries::ifeqEntry::execute
403 (
404  dictionary& contextDict,
405  Istream& is
406 )
407 {
408  DynamicList<filePos> stack(10);
409  return execute(stack, contextDict, contextDict, is);
410 }
411 
412 
413 bool Foam::functionEntries::ifeqEntry::execute
414 (
415  const dictionary& contextDict,
416  primitiveEntry& contextEntry,
417  Istream& is
418 )
419 {
420  DynamicList<filePos> stack(10);
421  const ifeqEntry ifeqe(is.lineNumber(), contextDict, is);
422 
423  return ifeqe.execute(stack, contextDict, contextEntry, is);
424 }
425 
426 
427 // ************************************************************************* //
Macros for easy insertion into member function selection tables.
Macros for easy insertion into run-time selection tables.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
label lineNumber() const
Return current stream line number.
Definition: IOstream.H:450
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Conditional parsing of and within dictionary entries.
Definition: ifeqEntry.H:89
ifeqEntry(const functionName &functionType, const label lineNumber, const dictionary &parentDict, const Istream &is, const tokenList &tokens)
Construct from function type, dictionary and tokenList.
Definition: ifeqEntry.C:377
A functionEntry causes entries to be added/manipulated on the specified dictionary given an input str...
Definition: functionEntry.H:66
A functionName is a word starting with '#'.
Definition: functionName.H:60
A keyword and a list of tokens is a 'primitiveEntry'. An primitiveEntry can be read,...
A token holds items read from Istream.
Definition: token.H:74
const variable & variableToken() const
Definition: tokenI.H:383
@ ERROR
Definition: token.H:98
@ VARIABLE
Definition: token.H:86
@ WORD
Definition: token.H:84
@ UNSIGNED_INTEGER_32
Definition: token.H:91
@ UNDEFINED
Definition: token.H:81
@ COMPOUND
Definition: token.H:96
@ FLOAT_SCALAR
Definition: token.H:93
@ INTEGER_64
Definition: token.H:90
@ DOUBLE_SCALAR
Definition: token.H:94
@ LONG_DOUBLE_SCALAR
Definition: token.H:95
@ VERBATIMSTRING
Definition: token.H:88
@ FUNCTIONNAME
Definition: token.H:85
@ UNSIGNED_INTEGER_64
Definition: token.H:92
@ INTEGER_32
Definition: token.H:89
@ STRING
Definition: token.H:87
@ PUNCTUATION
Definition: token.H:83
@ END_STATEMENT
Definition: token.H:109
@ BEGIN_LIST
Definition: token.H:110
@ END_LIST
Definition: token.H:111
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
defineFunctionTypeNameAndDebug(includeFvConstraintEntry, 0)
addToMemberFunctionSelectionTable(functionEntry, calcEntry, execute, primitiveEntryIstream)
addToRunTimeSelectionTable(functionEntry, includeFvConstraintEntry, dictionary)
string & inplaceExpandEntry(string &s, const dictionary &dict, const bool allowEnvVars, const bool allowEmpty, const char sigil='$')
Inplace expand occurrences of variables according to the dictionary.
Definition: stringOps.C:760
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
bool equal(const T &s1, const T &s2)
Definition: doubleFloat.H:62
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
IOerror FatalIOError
List< token > tokenList
List of tokens, used for a IOdictionary entry.
Definition: tokenList.H:42
dictionary dict
Foam::argList args(argc, argv)