Loading...
Searching...
No Matches
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-2023 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) ::Foam::InfoErr
38
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
61Foam::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
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 tokenList(std::move(toks.tokens()));
178}
179
180
181Foam::tokenList Foam::functionEntries::evalEntry::evaluate
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 = Foam::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 );
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));
258 entry.add_tokens(std::move(toks)); // Add at tokenIndex
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.add_tokens(std::move(toks)); // Add at tokenIndex
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.
label lineNumber() const noexcept
Const access to the current stream line number.
Definition IOstream.H:409
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
fileName relativeName(const bool caseTag=false) const
The dictionary name relative to the case.
Definition dictionary.C:179
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
entry(const keyType &keyword)
Construct from keyword.
Definition entry.C:62
static void inplaceExpand(std::string &str, const dictionary &dict, const bool stripComments=true)
Inplace expansion with dictionary variables, and strip any embedded C/C++ comments.
Definition exprString.C:29
Uses expressions::fieldExprDriver to evaluate mathematical expressions with scalars,...
Definition evalEntry.H:82
static bool execute(const dictionary &parentDict, primitiveEntry &thisEntry, Istream &is)
Execute in a primitiveEntry context, extracts token or line.
Definition evalEntry.C:243
A functionEntry causes entries to be added/manipulated on the specified dictionary given an input str...
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read,...
primitiveEntry(const keyType &key)
Construct from keyword and no tokens.
static std::string::size_type length(const char *s)
Length of the character sequence (with nullptr protection).
Definition string.H:259
@ BEGIN_BLOCK
Begin block [isseparator].
Definition token.H:178
@ END_BLOCK
End block [isseparator].
Definition token.H:179
@ DOLLAR
Dollar - start variable or expression.
Definition token.H:150
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
#define DetailInfo
Definition evalEntry.C:30
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.
Namespace for containing a functionEntry.
Definition calcEntry.C:33
void inplaceTrim(std::string &s)
Trim leading and trailing whitespace inplace.
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:40
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
messageStream InfoErr
Information stream (stderr output on master, null elsewhere).
List< token > tokenList
List of token, used for dictionary primitive entry (for example).
Definition tokenList.H:32
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50