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-------------------------------------------------------------------------------
10License
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
42namespace Foam
43{
44namespace functionEntries
45{
47 (
50 execute,
51 primitiveEntryIstream,
52 eval
53 );
54
55} // End namespace functionEntry
56} // End namespace Foam
57
58
59// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
60
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
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
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
182(
183 const dictionary& parentDict,
184 Istream& is
185)
186{
187 #ifdef FULLDEBUG
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// ************************************************************************* //
Macros for easy insertion into member function selection tables.
#define addNamedToMemberFunctionSelectionTable(baseType, thisType, funcName, argNames, lookupName)
Add to hash-table of functions with 'lookupName' as the key.
void evaluate()
Evaluate boundary conditions.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
Uses expressions::fieldExprDriver to evaluate mathematical expressions with scalars,...
Definition: evalEntry.H:86
A functionEntry causes entries to be added/manipulated on the specified dictionary given an input str...
Definition: functionEntry.H:69
virtual bool execute()
Calculate the output fields.
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read,...
@ BEGIN_BLOCK
Begin block [isseparator].
Definition: token.H:159
@ END_BLOCK
End block [isseparator].
Definition: token.H:160
@ DOLLAR
Dollar - start variable or expression.
Definition: token.H:131
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define DetailInfo
Definition: evalEntry.C:37
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))
fieldExpr::parseDriver fieldExprDriver
Typedef for fieldExpr parseDriver.
Definition: fieldExprFwd.H:61
void inplaceTrim(std::string &s)
Trim leading and trailing whitespace inplace.
Definition: stringOps.C:1067
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
IOerror FatalIOError
messageStream InfoErr
Information stream (stderr output on master, null elsewhere)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
List< token > tokenList
List of tokens, used for a IOdictionary entry.
Definition: tokenList.H:44
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53