diff --git a/applications/test/dictionary/testDict b/applications/test/dictionary/testDict index 5b27ede5d7..19020de7ed 100644 --- a/applications/test/dictionary/testDict +++ b/applications/test/dictionary/testDict @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDict; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testDict2 b/applications/test/dictionary/testDict2 index 9d481de49a..52967f024d 100644 --- a/applications/test/dictionary/testDict2 +++ b/applications/test/dictionary/testDict2 @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDict; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testDictAPI b/applications/test/dictionary/testDictAPI index d0ae9a9a8c..4c4d56743c 100644 --- a/applications/test/dictionary/testDictAPI +++ b/applications/test/dictionary/testDictAPI @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDict; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testDictCalc1 b/applications/test/dictionary/testDictCalc1 index 85dac5911e..5396d387c2 100644 --- a/applications/test/dictionary/testDictCalc1 +++ b/applications/test/dictionary/testDictCalc1 @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDictCalc1; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testDictEval1 b/applications/test/dictionary/testDictEval1 index bd94dcab6b..13491110df 100644 --- a/applications/test/dictionary/testDictEval1 +++ b/applications/test/dictionary/testDictEval1 @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDictEval1; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testDictEval2 b/applications/test/dictionary/testDictEval2 index d154bf7700..77cefec4c1 100644 --- a/applications/test/dictionary/testDictEval2 +++ b/applications/test/dictionary/testDictEval2 @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDictEval1; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testDictEval3 b/applications/test/dictionary/testDictEval3 index 79bebc9c20..6c6ffe9b61 100644 --- a/applications/test/dictionary/testDictEval3 +++ b/applications/test/dictionary/testDictEval3 @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDictEval1; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testDictEval4 b/applications/test/dictionary/testDictEval4 new file mode 100644 index 0000000000..81a4563ebc --- /dev/null +++ b/applications/test/dictionary/testDictEval4 @@ -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] }}; + } +} + + +// ************************************************************************* // diff --git a/applications/test/dictionary/testDictList b/applications/test/dictionary/testDictList index a8c7197356..08cafe93c0 100644 --- a/applications/test/dictionary/testDictList +++ b/applications/test/dictionary/testDictList @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDict; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Test some parsing diff --git a/applications/test/dictionary/testDictRegex b/applications/test/dictionary/testDictRegex index 15aae07200..3970712478 100644 --- a/applications/test/dictionary/testDictRegex +++ b/applications/test/dictionary/testDictRegex @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDictRegex; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #inputMode merge diff --git a/applications/test/dictionary/testPrimitiveEntry b/applications/test/dictionary/testPrimitiveEntry index f4bffb9cf8..2596012243 100644 --- a/applications/test/dictionary/testPrimitiveEntry +++ b/applications/test/dictionary/testPrimitiveEntry @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDict; + object dictionary; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testSubkeyword b/applications/test/dictionary/testSubkeyword index 21f3579f69..c995e0040f 100644 --- a/applications/test/dictionary/testSubkeyword +++ b/applications/test/dictionary/testSubkeyword @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDict; + object dictionary; note "test with foamDictionary -expand"; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary3/Make/files b/applications/test/dictionary3/Make/files new file mode 100644 index 0000000000..bdcfe73b04 --- /dev/null +++ b/applications/test/dictionary3/Make/files @@ -0,0 +1,3 @@ +Test-dictionary3.C + +EXE = $(FOAM_USER_APPBIN)/Test-dictionary3 diff --git a/applications/test/dictionary3/Make/options b/applications/test/dictionary3/Make/options new file mode 100644 index 0000000000..18e6fe47af --- /dev/null +++ b/applications/test/dictionary3/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = */ +/* EXE_LIBS = */ diff --git a/applications/test/dictionary3/Test-dictionary3.C b/applications/test/dictionary3/Test-dictionary3.C new file mode 100644 index 0000000000..11c1835b28 --- /dev/null +++ b/applications/test/dictionary3/Test-dictionary3.C @@ -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 . + +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("value") << nl; + + Info<< "scalar1: " << dict.get("scalar1") << nl; + Info<< "scalar2: " << dict.get("scalar2") << nl; + + Info<< "vector1: " << dict.get("vector1") << nl; + Info<< "vector2: " << dict.get("vector2") << nl; + } + + return 0; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.C b/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.C index eed1e261cb..f999a3f093 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UIPstream.C @@ -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)); diff --git a/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.C b/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.C index f550056ca0..5480f63a73 100644 --- a/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.C +++ b/src/OpenFOAM/db/IOstreams/Pstreams/UOPstream.C @@ -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 : { diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C index d1c4adc93d..10969f20f2 100644 --- a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C +++ b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.C @@ -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)) { diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/OSstream.C b/src/OpenFOAM/db/IOstreams/Sstreams/OSstream.C index bf7e25c88a..eea67551a8 100644 --- a/src/OpenFOAM/db/IOstreams/Sstreams/OSstream.C +++ b/src/OpenFOAM/db/IOstreams/Sstreams/OSstream.C @@ -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; } diff --git a/src/OpenFOAM/db/IOstreams/token/token.H b/src/OpenFOAM/db/IOstreams/token/token.H index eeb0d342ef..e1ccac5e9f 100644 --- a/src/OpenFOAM/db/IOstreams/token/token.H +++ b/src/OpenFOAM/db/IOstreams/token/token.H @@ -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\ 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 diff --git a/src/OpenFOAM/db/IOstreams/token/tokenI.H b/src/OpenFOAM/db/IOstreams/token/tokenI.H index c55ea6ff8a..aa401e3496 100644 --- a/src/OpenFOAM/db/IOstreams/token/tokenI.H +++ b/src/OpenFOAM/db/IOstreams/token/tokenI.H @@ -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; diff --git a/src/OpenFOAM/db/IOstreams/token/tokenIO.C b/src/OpenFOAM/db/IOstreams/token/tokenIO.C index da1a39a3ca..a37a37cec3 100644 --- a/src/OpenFOAM/db/IOstreams/token/tokenIO.C +++ b/src/OpenFOAM/db/IOstreams/token/tokenIO.C @@ -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); diff --git a/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.C index 6caf662316..837221ad30 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/functionEntry/functionEntry.C @@ -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; diff --git a/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.C index 0115cf0427..ab4979f5a9 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.C @@ -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& 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,35 +288,47 @@ bool Foam::functionEntries::ifeqEntry::evaluate { token t; readToken(t, is); + bool pending = false; - if (t.isWord() && t.wordToken() == "#ifeq") + if (t.isDirective()) { - // Recurse to evaluate - execute(stack, parentDict, is); - } - else if (t.isWord() && t.wordToken() == "#if") - { - // Recurse to evaluate - ifEntry::execute(stack, parentDict, is); - } - else if - ( - doIf - && t.isWord() - && (t.wordToken() == "#else" || t.wordToken() == "#elif") - ) - { - // Now skip until #endif - skipUntil(stack, parentDict, "#endif", is); - stack.remove(); - break; - } - else if (t.isWord() && t.wordToken() == "#endif") - { - stack.remove(); - break; + if (t.wordToken() == "#ifeq") + { + // Recurse to evaluate + execute(stack, parentDict, is); + } + else if (t.wordToken() == "#if") + { + // Recurse to evaluate + ifEntry::execute(stack, parentDict, is); + } + else if + ( + doIf + && (t.wordToken() == "#else" || t.wordToken() == "#elif") + ) + { + // Now skip until #endif + skipUntil(stack, parentDict, "#endif", is); + stack.remove(); + break; + } + 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); diff --git a/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.H index a04b91fc81..a925964fcd 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/ifeqEntry/ifeqEntry.H @@ -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 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& 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& stack, + const dictionary& parentDict, + const word& endDirective, //!< end directive (without '#') + Istream& is + ); + + public: //- Runtime type information diff --git a/src/OpenFOAM/primitives/Scalar/Scalar.C b/src/OpenFOAM/primitives/Scalar/Scalar.C index c276674d1c..cc096ebeb4 100644 --- a/src/OpenFOAM/primitives/Scalar/Scalar.C +++ b/src/OpenFOAM/primitives/Scalar/Scalar.C @@ -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; } diff --git a/src/OpenFOAM/primitives/ints/int32/int32IO.C b/src/OpenFOAM/primitives/ints/int32/int32IO.C index 6ff287a12f..5099d4baa1 100644 --- a/src/OpenFOAM/primitives/ints/int32/int32IO.C +++ b/src/OpenFOAM/primitives/ints/int32/int32IO.C @@ -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; } diff --git a/src/OpenFOAM/primitives/ints/int64/int64IO.C b/src/OpenFOAM/primitives/ints/int64/int64IO.C index 8ffc448b7e..93f73585ce 100644 --- a/src/OpenFOAM/primitives/ints/int64/int64IO.C +++ b/src/OpenFOAM/primitives/ints/int64/int64IO.C @@ -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; }