ENH: support field width for #eval expressions

For example,
```
entry #eval 10 { vector(rand(), 0, 0) };
```

ENH: be more generous and ignore trailing ';' in expressions

STYLE: adjust parse token name for tensor::I
This commit is contained in:
Mark Olesen 2021-03-29 14:03:10 +02:00
parent d4ac96cdf3
commit 21720bea12
18 changed files with 128 additions and 62 deletions

View File

@ -68,4 +68,8 @@ apiMonth #eval{ ($FOAM_API % 100) };
empty #eval "";
// Field of specified length
random #eval 4 { vector(rand(), 0, 0) ; /* trailing rubbish */ ; };
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -97,6 +97,7 @@ int main(int argc, char *argv[])
argList::addBoolOption("rules", "Print parser rules and exit");
argList::addBoolOption("tokens", "Print token names and exit");
argList::addOption("precision", "int", "Output with specified precision");
argList::addOption("size", "int", "Field output width (default: 1)");
// Flag arguments as optional so that -rules and -tokens works
argList::noMandatoryArgs();
@ -110,6 +111,7 @@ int main(int argc, char *argv[])
const bool printRules = args.found("rules");
const bool printNames = args.found("tokens");
const label fieldWidth = args.getOrDefault<label>("size", 1);
if (printNames || printRules)
{
@ -155,7 +157,7 @@ int main(int argc, char *argv[])
return 1;
}
Info<< stringOps::evaluate(expr).c_str() << nl;
Info<< stringOps::evaluate(fieldWidth, expr).c_str() << nl;
return 0;
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,6 +31,7 @@ License
#include "stringOps.H"
#include "fieldExprDriver.H"
#include "addToMemberFunctionSelectionTable.H"
#include <cctype>
#undef DetailInfo
#define DetailInfo if (::Foam::infoDetailLevel > 0) InfoErr
@ -69,34 +70,35 @@ Foam::tokenList Foam::functionEntries::evalEntry::evaluate
<< is.lineNumber() << " in file " << parentDict.name() << nl;
#endif
// String to evaluate
string s;
token tok(is);
if (!tok.good())
label fieldWidth(1); // Field width for the result
if (tok.isLabel())
{
FatalIOErrorInFunction(is)
<< "Bad token - could not get string to evaluate"
<< exit(FatalIOError);
return tokenList();
// - #eval INT "expr"
// - #eval INT { expr }
// - #eval INT #{ expr #}
fieldWidth = max(1, tok.labelToken());
is >> tok;
}
string s; // String to evaluate
if (tok.isString())
{
// - #eval "expr"
// - #eval #{ expr #}
s = tok.stringToken();
}
else if (tok == token::BEGIN_BLOCK)
else if (tok.isPunctuation(token::BEGIN_BLOCK))
{
// - #eval { expr }
dynamic_cast<ISstream&>(is).getLine(s, token::END_BLOCK);
}
else
{
is.putBack(tok);
FatalIOErrorInFunction(is)
<< "Invalid input for #eval" << nl
<< "Invalid input for #eval."
" Expecting a string or block to evaluate, but found" << nl
<< tok.info() << endl
<< exit(FatalIOError);
}
@ -111,16 +113,32 @@ Foam::tokenList Foam::functionEntries::evalEntry::evaluate
expressions::exprString::inplaceExpand(s, parentDict, true);
stringOps::inplaceTrim(s);
// An extraneous trailing ';' is a common input error, catch it now.
// May need to relax in the future, trim or something else
// An extraneous trailing ';' is a common input error.
// - trim if it does not influence the result
if (std::string::npos != s.find(';'))
const auto trailing = s.find(';');
if (std::string::npos != trailing)
{
bool ignore = true;
for (size_t other = trailing; ignore && other < s.length(); ++other)
{
ignore = s[other] == ';' || std::isspace(s[other]);
}
if (ignore)
{
// Can trim trailing without semantical change
s.erase(trailing);
stringOps::inplaceTrim(s);
}
else
{
FatalIOErrorInFunction(is)
<< "Invalid input for #eval" << nl
<< "Invalid input (after trailing ';') for #eval" << nl
<< s << endl
<< exit(FatalIOError);
}
}
#ifdef FULLDEBUG
DetailInfo
@ -138,7 +156,7 @@ Foam::tokenList Foam::functionEntries::evalEntry::evaluate
expressions::exprResult result;
{
expressions::fieldExprDriver driver(1);
expressions::fieldExprDriver driver(fieldWidth);
driver.parse(s);
result = std::move(driver.result());
}
@ -152,11 +170,15 @@ Foam::tokenList Foam::functionEntries::evalEntry::evaluate
return tokenList();
}
// Could average/reduce to a single value, but probably not needed
//// result.testIfSingleValue(false); // No parallel check
OTstream toks;
if (result.size() <= 1)
{
result.writeValue(toks);
}
else
{
result.writeField(toks);
}
return std::move(toks);
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,11 +31,12 @@ Description
with scalars, vectors etc.
The input can any form of string or, for convenience,
a '{}' delimited string literal. In all cases, C/C++ comment stripping
is also performed.
For example,
a '{}' delimited string literal.
In all cases, C/C++ comment stripping is performed.
The default size of the evaluated field is one,
which can be overridden by providing an initial integer value.
Some examples,
\verbatim
a 1;
b 3;
@ -45,12 +46,15 @@ Description
// ignore: sin(pi()*$a/$b)
sin(degToRad(45))
};
// With different field length:
points #eval 4 #{ vector(rand(), 0, 0) #};
\endverbatim
Note
The string expansions support use of environment variables.
Unknown variables will expand to an empty string, so it can be advisable
to an expansion with an alternative. For example,
to expand with an alternative. For example,
\verbatim
d #eval{ sin(degToRad( ${angle:-0} )) };

View File

@ -62,7 +62,7 @@
#define TOK_VECTOR_ID 62
#define TOK_SPH_TENSOR_ID 63
#define TOK_SYM_TENSOR_ID 64
#define TOK_UNIT_TENSOR 65
#define TOK_IDENTITY_TENSOR 65
#define TOK_TENSOR_ID 66
#define TOK_LTRUE 67
#define TOK_LFALSE 68

View File

@ -7,7 +7,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -283,7 +283,7 @@ dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
tfield (lhs) ::= UNIT_TENSOR . { lhs = _new_tfield(Foam::tensor::I); }
tfield (lhs) ::= IDENTITY_TENSOR . { lhs = _new_tfield(Foam::tensor::I); }
rule_get_field(_target_, TENSOR_ID)

View File

@ -7,7 +7,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -471,7 +471,7 @@ tr9:
goto st11;
tr11:
#line 292 "fieldExprScanner.rl"
{te = p+1;{ EMIT_TOKEN(UNIT_TENSOR); }}
{te = p+1;{ EMIT_TOKEN(IDENTITY_TENSOR); }}
goto st11;
tr12:
#line 235 "fieldExprScanner.rl"

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -289,7 +289,7 @@ static int driverTokenType
"Zero" =>{ EMIT_TOKEN(ZERO); };
"true" =>{ EMIT_TOKEN(LTRUE); };
"false" =>{ EMIT_TOKEN(LFALSE); };
"tensor::I" =>{ EMIT_TOKEN(UNIT_TENSOR); };
"tensor::I" =>{ EMIT_TOKEN(IDENTITY_TENSOR); };
"arg" =>{ EMIT_TOKEN(ARG); };
## "time" =>{ EMIT_TOKEN(TIME); };

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,11 +35,17 @@ License
Foam::string Foam::stringOps::evaluate
(
label fieldWidth,
const std::string& str,
size_t pos,
size_t len
)
{
if (fieldWidth < 1)
{
fieldWidth = 1;
}
/// InfoErr<< "Evaluate " << str.substr(pos, len) << nl;
const auto trimPoints = stringOps::findTrim(str, pos, len);
@ -49,14 +55,14 @@ Foam::string Foam::stringOps::evaluate
if (!len)
{
return "";
return string();
}
/// InfoErr<< "Evaluate " << str.substr(pos, len) << nl;
expressions::exprResult result;
{
expressions::fieldExprDriver driver(1);
expressions::fieldExprDriver driver(fieldWidth);
driver.parse(str, pos, len);
result = std::move(driver.result());
}
@ -67,14 +73,32 @@ Foam::string Foam::stringOps::evaluate
<< "Failed evaluation: "
<< str.substr(pos, len) << nl;
return "";
return string();
}
OStringStream os;
if (result.size() <= 1)
{
result.writeValue(os);
}
else
{
result.writeField(os);
}
return os.str();
}
Foam::string Foam::stringOps::evaluate
(
const std::string& str,
size_t pos,
size_t len
)
{
return stringOps::evaluate(1, str, pos, len);
}
// ************************************************************************* //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,6 +34,7 @@ Description
#ifndef stringOpsEvaluate_H
#define stringOpsEvaluate_H
#include "labelFwd.H"
#include "string.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -42,6 +43,15 @@ namespace Foam
{
namespace stringOps
{
//- String evaluation with specified (positive, non-zero) field width
string evaluate
(
label fieldWidth,
const std::string& s,
size_t pos = 0,
size_t len = std::string::npos
);
//- A simple string evaluation that handles various basic
//- expressions. For trivial input, use readScalar instead (faster).
//

View File

@ -67,7 +67,7 @@
#define TOK_SSPH_TENSOR_ID 67
#define TOK_SYM_TENSOR_ID 68
#define TOK_SSYM_TENSOR_ID 69
#define TOK_UNIT_TENSOR 70
#define TOK_IDENTITY_TENSOR 70
#define TOK_TENSOR_ID 71
#define TOK_STENSOR_ID 72
#define TOK_LTRUE 73

View File

@ -7,7 +7,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -242,7 +242,7 @@ dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
tfield (lhs) ::= UNIT_TENSOR . { lhs = _new_tfield(Foam::tensor::I); }
tfield (lhs) ::= IDENTITY_TENSOR . { lhs = _new_tfield(Foam::tensor::I); }
rule_get_field(_target_, TENSOR_ID)
rule_get_field(_target_, STENSOR_ID)

View File

@ -7,7 +7,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -595,7 +595,7 @@ tr9:
goto st11;
tr11:
#line 418 "patchExprScanner.rl"
{te = p+1;{ EMIT_TOKEN(UNIT_TENSOR); }}
{te = p+1;{ EMIT_TOKEN(IDENTITY_TENSOR); }}
goto st11;
tr12:
#line 359 "patchExprScanner.rl"

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -415,7 +415,7 @@ static int driverTokenType
"Zero" =>{ EMIT_TOKEN(ZERO); };
"true" =>{ EMIT_TOKEN(LTRUE); };
"false" =>{ EMIT_TOKEN(LFALSE); };
"tensor::I" =>{ EMIT_TOKEN(UNIT_TENSOR); };
"tensor::I" =>{ EMIT_TOKEN(IDENTITY_TENSOR); };
"arg" =>{ EMIT_TOKEN(ARG); };
"time" =>{ EMIT_TOKEN(TIME); };

View File

@ -63,7 +63,7 @@
#define TOK_VECTOR_ID 63
#define TOK_SPH_TENSOR_ID 64
#define TOK_SYM_TENSOR_ID 65
#define TOK_UNIT_TENSOR 66
#define TOK_IDENTITY_TENSOR 66
#define TOK_TENSOR_ID 67
#define TOK_LTRUE 68
#define TOK_LFALSE 69

View File

@ -7,7 +7,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -274,7 +274,7 @@ dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
tfield (lhs) ::= UNIT_TENSOR . { lhs = _new_tfield(Foam::tensor::I); }
tfield (lhs) ::= IDENTITY_TENSOR . { lhs = _new_tfield(Foam::tensor::I); }
rule_get_field(_target_, TENSOR_ID)

View File

@ -7,7 +7,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -624,7 +624,7 @@ tr9:
goto st11;
tr11:
#line 447 "volumeExprScanner.rl"
{te = p+1;{ EMIT_TOKEN(UNIT_TENSOR); }}
{te = p+1;{ EMIT_TOKEN(IDENTITY_TENSOR); }}
goto st11;
tr12:
#line 388 "volumeExprScanner.rl"

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -444,7 +444,7 @@ static int driverTokenType
"Zero" =>{ EMIT_TOKEN(ZERO); };
"true" =>{ EMIT_TOKEN(LTRUE); };
"false" =>{ EMIT_TOKEN(LFALSE); };
"tensor::I" =>{ EMIT_TOKEN(UNIT_TENSOR); };
"tensor::I" =>{ EMIT_TOKEN(IDENTITY_TENSOR); };
"arg" =>{ EMIT_TOKEN(ARG); };
"time" =>{ EMIT_TOKEN(TIME); };