ENH: adjust token in preparation for separate expression tokenization

- minor simplification of #if/#endif handling

ENH: improve input robustness with negative-prefixed expansions (#2095)

- especially in blockMeshDict it is useful to negate an value directly.
  Eg,
  ```
     xmax  100;
     xmin  -$xmax;
  ```
  However, this fails since the dictionary expansion is a two-step
  process of tokenization followed by expansion. After the expansion
  the given input would now be the following:
  ```
     xmax  100;
     xmin  - 100;
  ```
  and retrieving a scalar value for 'xmin' fails.

  Counteract this by being more generous on tokenized input when
  attempting to retrieve a label or scalar value.
  If a '-' is found where a number is expected, use it to negate the
  subsequent value.

  The previous solution was to invoke an 'eval':
  ```
     xmax  100;
     xmin  #eval{-$xmax};
  ```
  which adds additional clutter.
This commit is contained in:
Mark Olesen
2021-05-17 16:50:15 +02:00
parent 739c1c1d61
commit efd1ac4b5f
28 changed files with 507 additions and 166 deletions

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDict;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDict;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDict;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDictCalc1;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDictEval1;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDictEval1;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDictEval1;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,121 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2012 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Test expansion with negative signs
value 0.5;
radius 3;
negValue -$value;
select1 10;
sqrt05 #eval{ sqrt(0.5) };
vector ( -10 ${{-$sqrt05}} $value );
corner ( ${{ -$radius*sqrt(0.5) }} 1 0 );
corner2 ${{
vector(-${radius}*sqrt(0.5), ${radius}*sqrt(0.5), 2)
}};
// Just a future idea (2021-05-14) - does not yet work!
#if 0
corner3 #eval #{
variables ( "outer = $radius*sqrt(0.5)" );
vector(-outer, outer, 2)
#};
#endif
// The brace-bracket #eval with multi-lines failed for v2012 and earlier
corner2b #eval
{
vector(-${radius}*sqrt(0.5), $radius*sqrt(0.5), 2)
};
corner2c #eval
${{
vector(-${radius}*sqrt(0.5), $radius*sqrt(0.5), 2)
}};
longSlurp #eval
{
// This is actually a very simple expression
1 + 2
// With a long comment that is stripped out
// during reading anyhow.
};
longVariable
${{
// This is actually a very simple expression in variable syntax
1 + 2
/*
// With a long comment that is stripped out
// during reading anyhow.
*/
}};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Geometric parameters
rxo 2;
ryo 3;
rzo 4;
// Geometric parameters
outerRadius 1;
innerRatio 0.75;
geometry
{
sphere
{
type sphere;
origin (0 0 0);
radius ($rxo $ryo $rzo);
}
innerSphere
{
$sphere
// Different solutions to the same problem
radius_v1
(
${{ $innerRatio*$rxo }}
${{ $innerRatio*$ryo }}
${{ $innerRatio*$rzo }}
);
radius_v2 #eval{ $innerRatio*vector($rxo, $ryo, $rzo) };
radius_v3 ${{ $innerRatio*$[(vector) ../sphere/radius] }};
// Inplace overwrite the same value
radius ${{ $innerRatio*$[(vector) radius] }};
}
}
// ************************************************************************* //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDict;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Test some parsing

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDictRegex;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#inputMode merge

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDict;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDict;
object dictionary;
note "test with foamDictionary -expand";
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,3 @@
Test-dictionary3.C
EXE = $(FOAM_USER_APPBIN)/Test-dictionary3

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,78 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-dictionary3
Description
Test expressions and re-expansions
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "IOstreams.H"
#include "dictionary.H"
#include "vector.H"
#include "StringStream.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
{
IStringStream is
(
"value 10;"
"scalar1 $value;"
"scalar2 -$value;"
// Use #eval expansion entirely
"vector1 ${{vector($value, -$value, $value)}};"
"vector2 ($value -$value $value);"
);
dictionary dict(is);
Info<< "input dictionary:" << dict << nl;
Info<< "value: " << dict.get<scalar>("value") << nl;
Info<< "scalar1: " << dict.get<scalar>("scalar1") << nl;
Info<< "scalar2: " << dict.get<scalar>("scalar2") << nl;
Info<< "vector1: " << dict.get<vector>("vector1") << nl;
Info<< "vector2: " << dict.get<vector>("vector2") << nl;
}
return 0;
}
// ************************************************************************* //

View File

@ -218,8 +218,8 @@ Foam::Istream& Foam::UIPstream::read(token& t)
case token::COLON :
case token::COMMA :
case token::ASSIGN :
case token::ADD :
case token::SUBTRACT :
case token::PLUS :
case token::MINUS :
case token::MULTIPLY :
case token::DIVIDE :
{
@ -227,12 +227,12 @@ Foam::Istream& Foam::UIPstream::read(token& t)
return *this;
}
// Word/directive
// The word-variants
case token::tokenType::WORD :
case token::tokenType::DIRECTIVE :
{
word val;
if (read(val))
if (readStringFromBuffer(val))
{
if (token::compound::isCompound(val))
{
@ -251,13 +251,14 @@ Foam::Istream& Foam::UIPstream::read(token& t)
return *this;
}
// String types
// The string-variants
case token::tokenType::STRING :
case token::tokenType::EXPRESSION :
case token::tokenType::VARIABLE :
case token::tokenType::VERBATIM :
{
string val;
if (read(val))
if (readStringFromBuffer(val))
{
t = std::move(val);
t.setType(token::tokenType(c));

View File

@ -202,14 +202,19 @@ bool Foam::UOPstream::write(const token& tok)
return true;
}
// The word-variants
case token::tokenType::WORD :
case token::tokenType::DIRECTIVE :
{
writeToBuffer(char(token::tokenType::DIRECTIVE));
writeToBuffer(char(tok.type()));
writeStringToBuffer(tok.wordToken());
return true;
}
// The string-variants
case token::tokenType::STRING :
case token::tokenType::EXPRESSION :
case token::tokenType::VARIABLE :
case token::tokenType::VERBATIM :
{

View File

@ -199,8 +199,8 @@ Foam::Istream& Foam::ISstream::read(token& t)
case token::COLON :
case token::COMMA :
case token::ASSIGN :
case token::ADD :
// NB: token::SUBTRACT handled later as the possible start of a Number
case token::PLUS :
// NB: token::MINUS handled later as the possible start of a Number
case token::MULTIPLY :
case token::DIVIDE :
{
@ -368,7 +368,7 @@ Foam::Istream& Foam::ISstream::read(token& t)
if (nChar == 1 && buf[0] == '-')
{
// A single '-' is punctuation
t = token::punctuationToken(token::SUBTRACT);
t = token::punctuationToken(token::MINUS);
}
else if (labelVal && Foam::read(buf, labelVal))
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -47,27 +47,33 @@ bool Foam::OSstream::write(const token& tok)
case token::tokenType::DIRECTIVE :
{
// The '#' sigil is already part of the wordToken
// Token stored with leading '#' sigil - output directly
write(tok.wordToken());
return true;
}
case token::tokenType::VERBATIM :
case token::tokenType::EXPRESSION :
{
// Surrounding '#{ .. #}' to be recognized as verbatim
write(char(token::HASH));
write(char(token::BEGIN_BLOCK));
// Token stored with surrounding '${{ .. }}' - output directly
writeQuoted(tok.stringToken(), false);
write(char(token::HASH));
write(char(token::END_BLOCK));
return true;
}
case token::tokenType::VARIABLE :
{
// Token stored with leading '$' sigil - output directly
writeQuoted(tok.stringToken(), false);
return true;
}
case token::tokenType::VERBATIM :
{
// Token stored without surrounding '#{ .. #}'. Add on output
write(char(token::HASH));
write(char(token::BEGIN_BLOCK));
writeQuoted(tok.stringToken(), false);
write(char(token::HASH));
write(char(token::END_BLOCK));
return true;
}

View File

@ -71,11 +71,13 @@ class token
public:
//- Enumeration defining the types of token.
// Since these values are also used to tag content in Pstream,
// the maximum number of types is limited to 30.
enum tokenType
// Since the enumeration is used to tag content in Pstream, it is of
// type \c char and shall have values that do not overlap with regular
// punctuation characters.
enum tokenType : char
{
UNDEFINED = 0, //!< An undefined token-type
UNDEFINED = '\0', //!< An undefined token-type
ERROR = '\x80', //!< Token error encountered
// Fundamental types
FLAG, //!< stream flag (1-byte bitmask)
@ -86,14 +88,18 @@ public:
DOUBLE, //!< double (double-precision) type
// Pointer types
WORD, //!< A Foam::word
STRING, //!< A string (usually double-quoted)
DIRECTIVE, //!< A dictionary \c \#directive (word variant)
VARIABLE, //!< A dictionary \c \$variable (string variant)
VERBATIM, //!< Verbatim string content
WORD, //!< Foam::word
STRING, //!< Foam::string (usually double-quoted)
COMPOUND, //!< Compound type such as \c List\<label\> etc.
ERROR, //!< A token error encountered
DIRECTIVE, //!< Word-variant: dictionary \c \#directive
//!< stored with sigil
EXPRESSION, //!< String-variant: math expression for evaluation
//!< stored with delimiters
VARIABLE, //!< String-variant: dictionary \c \$variable
//!< stored with sigil
VERBATIM, //!< String-variant: verbatim string content
//!< stored without delimiters
// Aliases
FLOAT_SCALAR = FLOAT,
@ -122,16 +128,16 @@ public:
COLON = ':', //!< Colon [#isseparator]
SEMICOLON = ';', //!< Semicolon [#isseparator]
COMMA = ',', //!< Comma [#isseparator]
HASH = '#', //!< Hash - directive or verbatim string
DOLLAR = '$', //!< Dollar - start variable
HASH = '#', //!< Hash - directive or start verbatim string
DOLLAR = '$', //!< Dollar - start variable or expression
QUESTION = '?', //!< Question mark (eg, ternary)
ATSYM = '@', //!< The 'at' symbol
SQUOTE = '\'', //!< Single quote
DQUOTE = '"', //!< Double quote
ASSIGN = '=', //!< Assignment/equals [#isseparator]
ADD = '+', //!< Addition [#isseparator]
SUBTRACT = '-', //!< Subtract or start of negative number
PLUS = '+', //!< Addition [#isseparator]
MINUS = '-', //!< Subtract or start of negative number
MULTIPLY = '*', //!< Multiply [#isseparator]
DIVIDE = '/', //!< Divide [#isseparator]
@ -144,6 +150,8 @@ public:
// With semantically meaning
ADD = PLUS, //!< Addition [#isseparator]
SUBTRACT = MINUS, //!< Subtract or start of negative number
END_STATEMENT = SEMICOLON, //!< End entry [#isseparator]
BEGIN_LIST = LPAREN, //!< Begin list [#isseparator]
END_LIST = RPAREN, //!< End list [#isseparator]
@ -471,10 +479,10 @@ public:
//- Token is LABEL, FLOAT or DOUBLE
inline bool isNumber() const noexcept;
//- Token is WORD or DIRECTIVE word
//- Token is word-variant (WORD, DIRECTIVE)
inline bool isWord() const noexcept;
//- Token is WORD or DIRECTIVE word and equal to parameter
//- Token is word-variant and equal to parameter
inline bool isWord(const std::string& s) const;
//- Token is DIRECTIVE (word variant)
@ -483,16 +491,20 @@ public:
//- Token is (quoted) STRING (string variant)
inline bool isQuotedString() const noexcept;
//- Token is STRING, VARIABLE or VERBATIM (string variant)
//- Token is string-variant (STRING, EXPRESSION, VARIABLE, VERBATIM)
inline bool isString() const noexcept;
//- Token is EXPRESSION (string variant)
inline bool isExpression() const noexcept;
//- Token is VARIABLE (string variant)
inline bool isVariable() const noexcept;
//- Token is VERBATIM string (string variant)
inline bool isVerbatim() const noexcept;
//- Token is WORD, DIRECTIVE, STRING, VARIABLE or VERBATIM
//- Token is word-variant or string-variant
//- (WORD, DIRECTIVE, STRING, EXPRESSION, VARIABLE, VERBATIM)
inline bool isStringType() const noexcept;
//- Token is COMPOUND
@ -542,7 +554,8 @@ public:
//- Return const reference to the string contents.
// Report FatalIOError and return \b "" if token is not a
// STRING, VARIABLE, VERBATIM or an upcast WORD or DIRECTIVE
// STRING, EXPRESSION, VARIABLE, VERBATIM
// or an upcast WORD or DIRECTIVE
inline const string& stringToken() const;
//- Read access for compound token
@ -599,16 +612,16 @@ public:
//- Copy assign from double
inline void operator=(const doubleScalar val);
//- Copy assign from word
//- Copy assign from word content
inline void operator=(const word& w);
//- Copy assign from string
//- Copy assign from string content
inline void operator=(const string& str);
//- Move assign from word
//- Move assign from word content
inline void operator=(word&& w);
//- Move assign from string
//- Move assign from string content
inline void operator=(string&& str);
//- Assign compound with reference counting to token

View File

@ -66,8 +66,8 @@ inline bool Foam::token::isseparator(int c) noexcept
case token::COLON :
case token::COMMA :
case token::ASSIGN :
case token::ADD :
// Excluded token::SUBTRACT since it could start a number
case token::PLUS :
// Excluded token::MINUS since it could start a number
case token::MULTIPLY :
case token::DIVIDE :
{
@ -121,6 +121,7 @@ inline Foam::token::token(const token& tok)
}
case tokenType::STRING:
case tokenType::EXPRESSION:
case tokenType::VARIABLE:
case tokenType::VERBATIM:
{
@ -265,6 +266,7 @@ inline void Foam::token::reset()
}
case tokenType::STRING:
case tokenType::EXPRESSION:
case tokenType::VARIABLE:
case tokenType::VERBATIM:
{
@ -357,6 +359,7 @@ inline bool Foam::token::setType(token::tokenType tokType) noexcept
break;
case tokenType::STRING:
case tokenType::EXPRESSION:
case tokenType::VARIABLE:
case tokenType::VERBATIM:
{
@ -364,6 +367,7 @@ inline bool Foam::token::setType(token::tokenType tokType) noexcept
{
// could also go from WORD to STRING etc - to be decided
case tokenType::STRING:
case tokenType::EXPRESSION:
case tokenType::VARIABLE:
case tokenType::VERBATIM:
type_ = tokType;
@ -651,12 +655,19 @@ inline bool Foam::token::isString() const noexcept
return
(
type_ == tokenType::STRING
|| type_ == tokenType::EXPRESSION
|| type_ == tokenType::VARIABLE
|| type_ == tokenType::VERBATIM
);
}
inline bool Foam::token::isExpression() const noexcept
{
return (type_ == tokenType::EXPRESSION);
}
inline bool Foam::token::isVariable() const noexcept
{
return (type_ == tokenType::VARIABLE);
@ -680,6 +691,7 @@ inline const Foam::string& Foam::token::stringToken() const
if
(
type_ == tokenType::STRING
|| type_ == tokenType::EXPRESSION
|| type_ == tokenType::VARIABLE
|| type_ == tokenType::VERBATIM
)
@ -754,6 +766,7 @@ inline void Foam::token::operator=(const token& tok)
break;
case tokenType::STRING:
case tokenType::EXPRESSION:
case tokenType::VARIABLE:
case tokenType::VERBATIM:
{
@ -903,6 +916,7 @@ inline bool Foam::token::operator==(const token& tok) const
return *data_.wordPtr == *tok.data_.wordPtr;
case tokenType::STRING:
case tokenType::EXPRESSION:
case tokenType::VARIABLE:
case tokenType::VERBATIM:
return *data_.stringPtr == *tok.data_.stringPtr;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -82,6 +82,10 @@ static OS& printTokenInfo(OS& os, const token& tok)
os << "string " << tok.stringToken();
break;
case token::tokenType::EXPRESSION:
os << "expression " << tok.stringToken();
break;
case token::tokenType::VARIABLE:
os << "variable " << tok.stringToken();
break;
@ -141,6 +145,7 @@ Foam::word Foam::token::name() const
case token::tokenType::WORD: return "word";
case token::tokenType::DIRECTIVE: return "directive";
case token::tokenType::STRING: return "string";
case token::tokenType::EXPRESSION: return "expression";
case token::tokenType::VERBATIM: return "verbatim";
case token::tokenType::VARIABLE: return "variable";
case token::tokenType::COMPOUND: return "compound";
@ -194,8 +199,10 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const token& tok)
os << tok.data_.doubleVal;
break;
// Different behaviour for (serial/parallel) streams: preserve types
// Possibly different behaviour for serial/parallel streams:
// preserve types
case token::tokenType::DIRECTIVE:
case token::tokenType::EXPRESSION:
case token::tokenType::VARIABLE:
case token::tokenType::VERBATIMSTRING:
os.write(tok);

View File

@ -90,7 +90,8 @@ bool Foam::functionEntry::execute
if (!executedictionaryIstreamMemberFunctionTablePtr_)
{
cerr<< FUNCTION_NAME << nl
std::cerr
<< FUNCTION_NAME << nl
<< "Not yet initialized, function = "
<< functionName.c_str() << std::endl;
@ -128,7 +129,8 @@ bool Foam::functionEntry::execute
if (!executeprimitiveEntryIstreamMemberFunctionTablePtr_)
{
cerr<< FUNCTION_NAME << nl
std::cerr
<< FUNCTION_NAME << nl
<< "Not yet initialized, function = "
<< functionName.c_str() << std::endl;

View File

@ -58,12 +58,7 @@ void Foam::functionEntries::ifeqEntry::readToken(token& t, Istream& is)
// Skip dummy tokens - avoids entry::getKeyword consuming #else, #endif
do
{
if
(
is.read(t).bad()
|| is.eof()
|| !t.good()
)
if (is.read(t).bad() || is.eof() || !t.good())
{
return;
}
@ -72,7 +67,7 @@ void Foam::functionEntries::ifeqEntry::readToken(token& t, Istream& is)
}
Foam::token Foam::functionEntries::ifeqEntry::expand
Foam::token Foam::functionEntries::ifeqEntry::expandToken
(
const dictionary& dict,
const string& keyword,
@ -109,7 +104,7 @@ Foam::token Foam::functionEntries::ifeqEntry::expand
}
Foam::token Foam::functionEntries::ifeqEntry::expand
Foam::token Foam::functionEntries::ifeqEntry::expandToken
(
const dictionary& dict,
const token& t
@ -117,15 +112,15 @@ Foam::token Foam::functionEntries::ifeqEntry::expand
{
if (t.isWord())
{
return expand(dict, t.wordToken(), t);
return expandToken(dict, t.wordToken(), t);
}
else if (t.isVariable())
{
return expand(dict, t.stringToken(), t);
return expandToken(dict, t.stringToken(), t);
}
else if (t.isString())
{
return expand(dict, t.stringToken(), t);
return expandToken(dict, t.stringToken(), t);
}
return t;
@ -230,6 +225,9 @@ bool Foam::functionEntries::ifeqEntry::equalToken
}
return false;
case token::EXPRESSION:
return false;
case token::COMPOUND:
return false;
@ -245,7 +243,7 @@ void Foam::functionEntries::ifeqEntry::skipUntil
(
DynamicList<filePos>& stack,
const dictionary& parentDict,
const word& endWord,
const word& endDirective,
Istream& is
)
{
@ -258,28 +256,26 @@ void Foam::functionEntries::ifeqEntry::skipUntil
{
continue;
}
else if
(
t.wordToken() == "#if"
|| t.wordToken() == "#ifeq"
)
else if (t.wordToken() == "#if" || t.wordToken() == "#ifeq")
{
stack.append(filePos(is.name(), is.lineNumber()));
skipUntil(stack, parentDict, "#endif", is);
stack.remove();
}
else if (t.wordToken() == endWord)
else if (t.wordToken() == endDirective)
{
return;
}
}
FatalIOErrorInFunction(parentDict)
<< "Did not find matching " << endWord << nl
<< "Did not find matching " << endDirective << nl
<< exit(FatalIOError);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
bool Foam::functionEntries::ifeqEntry::evaluate
(
const bool doIf,
@ -292,13 +288,16 @@ bool Foam::functionEntries::ifeqEntry::evaluate
{
token t;
readToken(t, is);
bool pending = false;
if (t.isWord() && t.wordToken() == "#ifeq")
if (t.isDirective())
{
if (t.wordToken() == "#ifeq")
{
// Recurse to evaluate
execute(stack, parentDict, is);
}
else if (t.isWord() && t.wordToken() == "#if")
else if (t.wordToken() == "#if")
{
// Recurse to evaluate
ifEntry::execute(stack, parentDict, is);
@ -306,7 +305,6 @@ bool Foam::functionEntries::ifeqEntry::evaluate
else if
(
doIf
&& t.isWord()
&& (t.wordToken() == "#else" || t.wordToken() == "#elif")
)
{
@ -315,12 +313,22 @@ bool Foam::functionEntries::ifeqEntry::evaluate
stack.remove();
break;
}
else if (t.isWord() && t.wordToken() == "#endif")
else if (t.wordToken() == "#endif")
{
stack.remove();
break;
}
else
{
pending = true;
}
}
else
{
pending = true;
}
if (pending)
{
is.putBack(t);
bool ok = entry::New(parentDict, is);
@ -354,21 +362,23 @@ bool Foam::functionEntries::ifeqEntry::execute
{
readToken(t, is);
if
(
t.isWord()
&& (t.wordToken() == "#if" || t.wordToken() == "#ifeq")
)
// Only consider directives
if (!t.isDirective())
{
continue;
}
if (t.wordToken() == "#if" || t.wordToken() == "#ifeq")
{
stack.append(filePos(is.name(), is.lineNumber()));
skipUntil(stack, parentDict, "#endif", is);
stack.remove();
}
else if (t.isWord() && t.wordToken() == "#else")
else if (t.wordToken() == "#else")
{
break;
}
else if (t.isWord() && t.wordToken() == "#elif")
else if (t.wordToken() == "#elif")
{
// const label lineNo = is.lineNumber();
@ -386,7 +396,7 @@ bool Foam::functionEntries::ifeqEntry::execute
break;
}
}
else if (t.isWord() && t.wordToken() == "#endif")
else if (t.wordToken() == "#endif")
{
stack.remove();
break;
@ -421,11 +431,11 @@ bool Foam::functionEntries::ifeqEntry::execute
// Read first token and expand any string
token cond1(is);
cond1 = expand(parentDict, cond1);
cond1 = expandToken(parentDict, cond1);
// Read second token and expand any string
token cond2(is);
cond2 = expand(parentDict, cond2);
cond2 = expandToken(parentDict, cond2);
const bool equal = equalToken(cond1, cond2);

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,7 +32,7 @@ Description
E.g.
\verbatim
a #calc "0.123";
a #eval "0.123";
b 1.23e-1;
#ifeq $a $b
@ -90,46 +91,15 @@ class ifeqEntry
:
public functionEntry
{
protected:
// Data Types
typedef Tuple2<fileName, label> filePos;
// Protected Member Functions
//- Read tokens. Skip dummy tokens
static void readToken(token& t, Istream& is);
//- Expand a variable (string/word/var starting with '$')
static token expand
(
const dictionary& dict,
const string& keyword,
const token& t
);
//- Expand a string/word/var token
static token expand
(
const dictionary& dict,
const token& t
);
static bool equalToken
(
const token& t1,
const token& t2
);
//- Consume tokens until reached a specific word
static void skipUntil
(
DynamicList<filePos>& stack,
const dictionary& parentDict,
const word& endWord,
Istream& is
);
static bool evaluate
(
const bool doIf,
@ -158,6 +128,41 @@ protected:
);
private:
// Private Member Functions
//- Read tokens. Skip dummy tokens
static void readToken(token& t, Istream& is);
//- Expand a variable (string/word/var starting with '$')
static token expandToken
(
const dictionary& dict,
const string& keyword,
const token& t
);
//- Expand a string/word/var token
static token expandToken
(
const dictionary& dict,
const token& t
);
//- Test for equality
static bool equalToken(const token& t1, const token& t2);
//- Consume tokens until reached a specific directive
static void skipUntil
(
DynamicList<filePos>& stack,
const dictionary& parentDict,
const word& endDirective, //!< end directive (without '#')
Istream& is
);
public:
//- Runtime type information

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd.
Copyright (C) 2016-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -145,16 +145,37 @@ Istream& operator>>(Istream& is, Scalar& val)
return is;
}
// Accept separated '-' (or '+') while expecting a number.
// This can arise during dictionary expansions (Eg, -$value)
char prefix = 0;
if (t.isPunctuation())
{
prefix = t.pToken();
if (prefix == token::PLUS || prefix == token::MINUS)
{
is >> t;
}
}
if (t.isNumber())
{
val = t.number();
val =
(
(prefix == token::MINUS)
? (0 - t.number())
: t.number()
);
}
else
{
FatalIOErrorInFunction(is)
<< "Wrong token type - expected scalar value, found "
<< t.info()
<< exit(FatalIOError);
<< "Wrong token type - expected scalar value, found ";
if (prefix == token::PLUS || prefix == token::MINUS)
{
FatalIOError << '\'' << prefix << "' followed by ";
}
FatalIOError << t.info() << exit(FatalIOError);
is.setBad();
return is;
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014-2016 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd.
Copyright (C) 2016-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -100,13 +100,36 @@ Foam::Istream& Foam::operator>>(Istream& is, int32_t& val)
return is;
}
// Accept separated '-' (or '+') while expecting a number.
// This can arise during dictionary expansions (Eg, -$value)
char prefix = 0;
if (t.isPunctuation())
{
prefix = t.pToken();
if (prefix == token::PLUS || prefix == token::MINUS)
{
is >> t;
}
}
if (t.isLabel())
{
val = int32_t(t.labelToken());
val = int32_t
(
(prefix == token::MINUS)
? (0 - t.labelToken())
: t.labelToken()
);
}
else if (t.isScalar())
{
const scalar sval(t.scalarToken());
const scalar sval
(
(prefix == token::MINUS)
? (0 - t.scalarToken())
: t.scalarToken()
);
const intmax_t parsed = intmax_t(std::round(sval));
val = 0 + int32_t(parsed);
@ -135,9 +158,12 @@ Foam::Istream& Foam::operator>>(Istream& is, int32_t& val)
else
{
FatalIOErrorInFunction(is)
<< "Wrong token type - expected label (int32), found "
<< t.info()
<< exit(FatalIOError);
<< "Wrong token type - expected label (int32), found ";
if (prefix == token::PLUS || prefix == token::MINUS)
{
FatalIOError << '\'' << prefix << "' followed by ";
}
FatalIOError << t.info() << exit(FatalIOError);
is.setBad();
return is;
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014-2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -100,13 +100,37 @@ Foam::Istream& Foam::operator>>(Istream& is, int64_t& val)
return is;
}
// Accept separated '-' (or '+') while expecting a number.
// This can arise during dictionary expansions (Eg, -$value)
char prefix = 0;
if (t.isPunctuation())
{
prefix = t.pToken();
if (prefix == token::PLUS || prefix == token::MINUS)
{
is >> t;
}
}
if (t.isLabel())
{
val = int64_t(t.labelToken());
val = int64_t
(
(prefix == token::MINUS)
? (0 - t.labelToken())
: t.labelToken()
);
}
else if (t.isScalar())
{
const scalar sval(t.scalarToken());
const scalar sval
(
(prefix == token::MINUS)
? (0 - t.scalarToken())
: t.scalarToken()
);
const intmax_t parsed = intmax_t(std::round(sval));
val = 0 + int64_t(parsed);
@ -135,9 +159,12 @@ Foam::Istream& Foam::operator>>(Istream& is, int64_t& val)
else
{
FatalIOErrorInFunction(is)
<< "Wrong token type - expected label (int64), found "
<< t.info()
<< exit(FatalIOError);
<< "Wrong token type - expected label (int64), found ";
if (prefix == token::PLUS || prefix == token::MINUS)
{
FatalIOError << '\'' << prefix << "' followed by ";
}
FatalIOError << t.info() << exit(FatalIOError);
is.setBad();
return is;
}