evalEntry.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2019-2021 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "evalEntry.H"
29 #include "dictionary.H"
30 #include "OTstream.H"
31 #include "stringOps.H"
32 #include "fieldExprDriver.H"
34 #include <cctype>
35 
36 #undef DetailInfo
37 #define DetailInfo if (::Foam::infoDetailLevel > 0) InfoErr
38 
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 namespace functionEntries
45 {
47  (
48  functionEntry,
49  evalEntry,
50  execute,
51  primitiveEntryIstream,
52  eval
53  );
54 
55 } // End namespace functionEntry
56 } // End namespace Foam
57 
58 
59 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
60 
61 Foam::tokenList Foam::functionEntries::evalEntry::evaluate
62 (
63  const dictionary& parentDict,
64  const string& inputExpr,
65  label fieldWidth,
66  const Istream& is
67 )
68 {
69  // Field width for the result
70  if (fieldWidth < 1)
71  {
73  << "Invalid field width: " << fieldWidth << nl << endl
74  << exit(FatalIOError);
75  }
76 
77  #ifdef FULLDEBUG
79  << "input: " << inputExpr << endl;
80  #endif
81 
82  // Expand with env=true, empty=true, subDict=false
83  // with comments stripped.
84  // Special handling of $[...] syntax enabled.
85 
86  string s;
87 
88  // Passed '${{ expr }}' by accident, or on purpuse
89  if
90  (
91  inputExpr[0] == token::DOLLAR
92  && inputExpr[1] == token::BEGIN_BLOCK
93  && inputExpr[2] == token::BEGIN_BLOCK
94  && inputExpr[inputExpr.length()-1] == token::END_BLOCK
95  && inputExpr[inputExpr.length()-2] == token::END_BLOCK
96  )
97  {
98  s.assign(inputExpr, 3, inputExpr.length()-5);
99  }
100  else
101  {
102  s.assign(inputExpr);
103  }
104 
105  expressions::exprString::inplaceExpand(s, parentDict, true);
107 
108  // An extraneous trailing ';' is a common input error.
109  // - trim if it does not influence the result
110 
111  const auto trailing = s.find(';');
112  if (std::string::npos != trailing)
113  {
114  bool ignore = true;
115  for (size_t other = trailing; ignore && other < s.length(); ++other)
116  {
117  ignore = s[other] == ';' || std::isspace(s[other]);
118  }
119 
120  if (ignore)
121  {
122  // Can trim trailing without semantical change
123  s.erase(trailing);
125  }
126  else
127  {
129  << "Invalid input (after trailing ';') for #eval" << nl
130  << s << endl
131  << exit(FatalIOError);
132  }
133  }
134 
135  #ifdef FULLDEBUG
136  DetailInfo
137  << "expanded: " << s << endl;
138  #endif
139 
140  if (s.empty())
141  {
142  InfoErr
143  << "Empty #eval - line "
144  << is.lineNumber() << " in file "
145  << parentDict.relativeName() << nl;
146 
147  return tokenList();
148  }
149 
150  expressions::exprResult result;
151  {
152  expressions::fieldExprDriver driver(fieldWidth);
153  driver.parse(s);
154  result = std::move(driver.result());
155  }
156 
157  if (!result.hasValue() || !result.size())
158  {
159  InfoErr
160  << "Failed #eval - line "
161  << is.lineNumber() << " in file "
162  << parentDict.relativeName() << nl;
163 
164  return tokenList();
165  }
166 
167  OTstream toks;
168  if (result.size() <= 1)
169  {
170  result.writeValue(toks);
171  }
172  else
173  {
174  result.writeField(toks);
175  }
176 
177  return std::move(toks);
178 }
179 
180 
181 Foam::tokenList Foam::functionEntries::evalEntry::evaluate
182 (
183  const dictionary& parentDict,
184  Istream& is
185 )
186 {
187  #ifdef FULLDEBUG
188  DetailInfo
189  << "Using #eval - line "
190  << is.lineNumber() << " in file "
191  << parentDict.relativeName() << nl;
192  #endif
193 
194  token tok(is);
195  label fieldWidth(1); // Field width for the result
196  if (tok.isLabel())
197  {
198  // - #eval INT "expr"
199  // - #eval INT { expr }
200  // - #eval INT #{ expr #}
201  fieldWidth = max(1, tok.labelToken());
202  is >> tok;
203  }
204 
205 
206  // The string to evaluate
207  string str;
208 
209  if (tok.isStringType()) // Also accepts a single bare word
210  {
211  // - #eval "expr"
212  // - #eval #{ expr #}
213  // - #eval ${{ expr }} - wierd but handled
214  str = tok.stringToken();
215  }
216  else if (tok.isPunctuation(token::BEGIN_BLOCK))
217  {
218  // - #eval { expr }
219  // strip comments
220  if (!continueReadUntilRightBrace(is, str, true))
221  {
222  reportReadWarning
223  (
224  is,
225  "Premature end while reading #eval - missing '}'?"
226  );
227  }
228  }
229  else
230  {
232  << "Invalid input for #eval."
233  " Expecting a string or block to evaluate, but found" << nl
234  << tok.info() << endl
235  << exit(FatalIOError);
236  }
237 
238  tokenList toks
239  (
240  evalEntry::evaluate(parentDict, str, fieldWidth, is)
241  );
242 
243  return toks;
244 }
245 
246 
247 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
248 
250 (
251  const dictionary& parentDict,
253  Istream& is
254 )
255 {
256  tokenList toks(evaluate(parentDict, is));
257 
258  entry.append(std::move(toks), true); // Lazy resizing
259 
260  return true;
261 }
262 
263 
265 (
266  const dictionary& parentDict,
268  const string& inputExpr,
269  label fieldWidth,
270  Istream& is
271 )
272 {
273  tokenList toks(evaluate(parentDict, inputExpr, fieldWidth, is));
274 
275  entry.append(std::move(toks), true); // Lazy resizing
276 
277  return true;
278 }
279 
280 
281 // ************************************************************************* //
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
Foam::primitiveEntry
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read,...
Definition: primitiveEntry.H:63
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::isspace
bool isspace(char c) noexcept
Test for whitespace (C-locale)
Definition: char.H:65
Foam::stringOps::inplaceTrim
void inplaceTrim(std::string &s)
Trim leading and trailing whitespace inplace.
Definition: stringOps.C:1067
evalEntry.H
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::InfoErr
messageStream InfoErr
Information stream (stderr output on master, null elsewhere)
Foam::Istream
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:61
addToMemberFunctionSelectionTable.H
Macros for easy insertion into member function selection tables.
DetailInfo
#define DetailInfo
Definition: evalEntry.C:37
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::token::END_BLOCK
End block [isseparator].
Definition: token.H:160
Foam::token::DOLLAR
Dollar - start variable or expression.
Definition: token.H:131
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::functionEntries::addNamedToMemberFunctionSelectionTable
addNamedToMemberFunctionSelectionTable(functionEntry, calcEntry, execute, dictionaryIstream, calc)
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::token::BEGIN_BLOCK
Begin block [isseparator].
Definition: token.H:159
fieldExprDriver.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::tokenList
List< token > tokenList
List of tokens, used for a IOdictionary entry.
Definition: tokenList.H:44
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
dictionary.H
Foam::functionEntries::evalEntry::execute
static bool execute(const dictionary &parentDict, primitiveEntry &thisEntry, Istream &is)
Execute in a primitiveEntry context, extracts token or line.
Definition: evalEntry.C:250
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::expressions::exprString::inplaceExpand
static void inplaceExpand(std::string &str, const dictionary &dict, const bool stripComments=true)
Definition: exprString.C:35
OTstream.H
stringOps.H
Foam::expressions::fieldExprDriver
fieldExpr::parseDriver fieldExprDriver
Typedef for fieldExpr parseDriver.
Definition: fieldExprFwd.H:61
Foam::stringOps::evaluate
string evaluate(label fieldWidth, const std::string &s, size_t pos=0, size_t len=std::string::npos)
String evaluation with specified (positive, non-zero) field width.
Definition: stringOpsEvaluate.C:37