mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: generalize string expression evaluation
- replace stringOps::toScalar with a more generic stringOps::evaluate method that handles scalars, vectors etc. - improve #eval to handle various mathematical operations. Previously only handled scalars. Now produce vectors, tensors etc for the entries. These tokens are streamed directly into the entry.
This commit is contained in:
@ -58,5 +58,7 @@ eval8a #eval " pi() * 2 * ${{ ${factor$index} + ${factor10} }}";
|
||||
|
||||
eval8b #eval " pi() * 2 * $factor * ${{ 100 }}";
|
||||
|
||||
eval10a #eval "vector(1,2,3) * 5";
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -132,6 +132,9 @@ int main(int argc, char *argv[])
|
||||
"sqrt(2) = (${{ sqrt(2) }/* Truncated */",
|
||||
"sqrt(2) = (${{ sqrt(2) * foo() }})/* bad expr */",
|
||||
"huge = (${{ sqrt(123E+5000) }})/* range error */",
|
||||
|
||||
"vector=${{ 5 * vector(1,2,3) }}=",
|
||||
"empty=${{ }}=",
|
||||
}
|
||||
)
|
||||
{
|
||||
|
||||
@ -134,10 +134,8 @@ $(strings)/lists/hashedWordList.C
|
||||
$(strings)/parsing/parsing.C
|
||||
$(strings)/parsing/genericRagelLemonDriver.C
|
||||
$(strings)/stringOps/stringOps.C
|
||||
$(strings)/stringOps/stringOpsEvaluate.C
|
||||
$(strings)/stringOps/stringOpsSort.C
|
||||
$(strings)/stringOps/toScalar/evalStringToScalarDriver.C
|
||||
$(strings)/stringOps/toScalar/evalStringToScalarLemonParser.lyy-m4
|
||||
$(strings)/stringOps/toScalar/evalStringToScalarScanner.cc
|
||||
|
||||
expr = expressions
|
||||
$(expr)/exprEntry/expressionEntry.C
|
||||
|
||||
@ -25,24 +25,21 @@ License
|
||||
|
||||
#include "evalEntry.H"
|
||||
#include "dictionary.H"
|
||||
#include "OTstream.H"
|
||||
#include "stringOps.H"
|
||||
#include "fieldExprDriver.H"
|
||||
#include "addToMemberFunctionSelectionTable.H"
|
||||
|
||||
#undef DetailInfo
|
||||
#define DetailInfo if (::Foam::infoDetailLevel > 0) InfoErr
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionEntries
|
||||
{
|
||||
addNamedToMemberFunctionSelectionTable
|
||||
(
|
||||
functionEntry,
|
||||
evalEntry,
|
||||
execute,
|
||||
dictionaryIstream,
|
||||
eval
|
||||
);
|
||||
|
||||
addNamedToMemberFunctionSelectionTable
|
||||
(
|
||||
functionEntry,
|
||||
@ -58,7 +55,7 @@ namespace functionEntries
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::functionEntries::evalEntry::evaluate
|
||||
Foam::tokenList Foam::functionEntries::evalEntry::evaluate
|
||||
(
|
||||
const dictionary& parentDict,
|
||||
Istream& is
|
||||
@ -80,7 +77,8 @@ Foam::scalar Foam::functionEntries::evalEntry::evaluate
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "Bad token - could not get string to evaluate"
|
||||
<< exit(FatalIOError);
|
||||
return 0;
|
||||
|
||||
return tokenList();
|
||||
}
|
||||
|
||||
if (tok.isString())
|
||||
@ -111,7 +109,9 @@ Foam::scalar Foam::functionEntries::evalEntry::evaluate
|
||||
stringOps::inplaceExpand(s, parentDict, true, true);
|
||||
stringOps::inplaceTrim(s);
|
||||
|
||||
// A common input error, so catch it now
|
||||
// An extraneous trailing ';' is a common input error, catch it now.
|
||||
// May need to relax in the future, trim or something else
|
||||
|
||||
if (std::string::npos != s.find(';'))
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
@ -128,13 +128,35 @@ Foam::scalar Foam::functionEntries::evalEntry::evaluate
|
||||
if (s.empty())
|
||||
{
|
||||
InfoErr
|
||||
<< "Empty #eval (treat as 0) - line "
|
||||
<< "Empty #eval - line "
|
||||
<< is.lineNumber() << " in file " << parentDict.name() << nl;
|
||||
|
||||
return scalar(0);
|
||||
return tokenList();
|
||||
}
|
||||
|
||||
return stringOps::toScalar(s);
|
||||
expressions::exprResult result;
|
||||
{
|
||||
expressions::fieldExprDriver driver(1);
|
||||
driver.parse(s);
|
||||
result = std::move(driver.result());
|
||||
}
|
||||
|
||||
if (!result.hasValue() || !result.size())
|
||||
{
|
||||
InfoErr
|
||||
<< "Failed #eval - line "
|
||||
<< is.lineNumber() << " in file " << parentDict.name() << nl;
|
||||
|
||||
return tokenList();
|
||||
}
|
||||
|
||||
// Could average/reduce to a single value, but probably not needed
|
||||
//// result.testIfSingleValue(false); // No parallel check
|
||||
|
||||
OTstream toks;
|
||||
result.writeValue(toks);
|
||||
|
||||
return toks;
|
||||
}
|
||||
|
||||
|
||||
@ -147,37 +169,9 @@ bool Foam::functionEntries::evalEntry::execute
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
const scalar value = evaluate(parentDict, is);
|
||||
tokenList toks(evaluate(parentDict, is));
|
||||
|
||||
// The result as terminated token entry
|
||||
ITstream result
|
||||
(
|
||||
"eval",
|
||||
tokenList({token(value), token(token::END_STATEMENT)})
|
||||
);
|
||||
|
||||
entry.read(parentDict, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionEntries::evalEntry::execute
|
||||
(
|
||||
dictionary& parentDict,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
const scalar value = evaluate(parentDict, is);
|
||||
|
||||
// The result as terminated token entry
|
||||
ITstream result
|
||||
(
|
||||
"eval",
|
||||
tokenList({token(value), token(token::END_STATEMENT)})
|
||||
);
|
||||
|
||||
parentDict.read(result);
|
||||
entry.append(std::move(toks), true); // Lazy resizing
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -27,7 +27,8 @@ Class
|
||||
Foam::functionEntries::evalEntry
|
||||
|
||||
Description
|
||||
Uses stringOps::toScalar to evaluate mathematical expressions.
|
||||
Uses expressions::fieldExprDriver to evaluate mathematical expressions
|
||||
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
|
||||
@ -81,8 +82,8 @@ class evalEntry
|
||||
public functionEntry
|
||||
{
|
||||
|
||||
//- Evaluate and return a scalar
|
||||
static scalar evaluate(const dictionary& parentDict, Istream& is);
|
||||
//- Evaluate and return a token list
|
||||
static tokenList evaluate(const dictionary& parentDict, Istream& is);
|
||||
|
||||
|
||||
public:
|
||||
@ -94,9 +95,6 @@ public:
|
||||
primitiveEntry& thisEntry,
|
||||
Istream& is
|
||||
);
|
||||
|
||||
//- Execute in a sub-dict context
|
||||
static bool execute(dictionary& parentDict, Istream& is);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "genericRagelLemonDriver.H"
|
||||
#include "evalStringToScalarDriver.H"
|
||||
#include "string.H"
|
||||
#include "error.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
@ -570,9 +570,10 @@ static Foam::string recursiveExpand
|
||||
|
||||
///Info<< "eval <" << out << ">" << endl;
|
||||
|
||||
// Even with allow empty, expressions need content
|
||||
const scalar sval = stringOps::toScalar(out);
|
||||
const word val(Foam::name(sval));
|
||||
// Even with allow empty, expressions may need content
|
||||
|
||||
string val(stringOps::evaluate(out));
|
||||
stringOps::inplaceTrim(val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -46,10 +46,9 @@ SourceFiles
|
||||
#include "dictionary.H"
|
||||
#include "HashTable.H"
|
||||
#include "stringOpsSort.H"
|
||||
#include "stringOpsEvaluate.H"
|
||||
#include "wordRes.H"
|
||||
|
||||
#include "evalStringToScalar.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
@ -137,7 +136,7 @@ namespace stringOps
|
||||
// - \c ${VAR}
|
||||
// - \c ${VAR:-defValue}
|
||||
// - \c ${VAR:+altValue}
|
||||
// -# numeric (scalar) evaluation using stringOps::toScalar
|
||||
// -# mathematical evaluation using stringOps::evaluate
|
||||
// - \c ${{EXPR}}
|
||||
// -# current directory
|
||||
// - leading "./"
|
||||
@ -183,7 +182,7 @@ namespace stringOps
|
||||
// \param sigil The leading sigil. Can be changed to avoid conflict
|
||||
// with other string expansions. (default: '$')
|
||||
//
|
||||
// \sa Foam::findEtcEntry(), Foam::findEtcEntries(), stringOps::toScalar()
|
||||
// \sa Foam::findEtcEntry(), Foam::findEtcEntries(), stringOps::evaluate()
|
||||
//
|
||||
// \note this function has too many parameters and should generally
|
||||
// be avoided in user coding.
|
||||
|
||||
@ -25,73 +25,81 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "evalStringToScalar.H"
|
||||
#include "evalStringToScalarDriver.H"
|
||||
#include "evalStringToScalarScanner.H"
|
||||
#include "stringOpsEvaluate.H"
|
||||
#include "stringOps.H"
|
||||
#include "StringStream.H"
|
||||
#include "fieldExprDriver.H"
|
||||
#include "error.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace parsing
|
||||
{
|
||||
|
||||
int evalStringToScalar::debug
|
||||
(
|
||||
::Foam::debug::debugSwitch("stringToScalar", 0)
|
||||
);
|
||||
registerDebugSwitchWithName
|
||||
(
|
||||
evalStringToScalar,
|
||||
evalStringToScalar,
|
||||
"stringToScalar"
|
||||
);
|
||||
|
||||
} // End namespace parsing
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::parsing::evalStringToScalar::parseDriver::parseDriver()
|
||||
:
|
||||
genericRagelLemonDriver(),
|
||||
value_(0)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::parsing::evalStringToScalar::parseDriver::execute
|
||||
(
|
||||
const std::string& s,
|
||||
size_t pos,
|
||||
size_t len
|
||||
)
|
||||
{
|
||||
// scanner::debug = 1;
|
||||
|
||||
scanner().process(s, pos, len, *this);
|
||||
|
||||
return value_;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::stringOps::toScalar
|
||||
Foam::string Foam::stringOps::evaluate
|
||||
(
|
||||
const std::string& s,
|
||||
const std::string& str,
|
||||
size_t pos,
|
||||
size_t len
|
||||
)
|
||||
{
|
||||
parsing::evalStringToScalar::parseDriver driver;
|
||||
/// InfoErr<< "Evaluate " << str.substr(pos, len) << nl;
|
||||
|
||||
driver.execute(s, pos, len);
|
||||
size_t end = str.length();
|
||||
if (pos > end)
|
||||
{
|
||||
pos = end;
|
||||
}
|
||||
else if (len != std::string::npos)
|
||||
{
|
||||
len += pos;
|
||||
|
||||
return driver.value();
|
||||
if (len < end)
|
||||
{
|
||||
end = len;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust like inplaceTrim
|
||||
|
||||
// Right
|
||||
while (pos < end && std::isspace(str[end-1]))
|
||||
{
|
||||
--end;
|
||||
}
|
||||
|
||||
// Left
|
||||
while (pos < end && std::isspace(str[pos]))
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
|
||||
if ((pos >= end) || std::isspace(str[pos]))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
len = (end - pos);
|
||||
|
||||
/// InfoErr<< "Evaluate " << str.substr(pos, len) << nl;
|
||||
|
||||
expressions::exprResult result;
|
||||
{
|
||||
expressions::fieldExprDriver driver(1);
|
||||
driver.parse(str, pos, len);
|
||||
result = std::move(driver.result());
|
||||
}
|
||||
|
||||
if (!result.hasValue() || !result.size())
|
||||
{
|
||||
InfoErr
|
||||
<< "Failed evaluation: "
|
||||
<< str.substr(pos, len) << nl;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
OStringStream os;
|
||||
result.writeValue(os);
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
@ -23,17 +23,17 @@ License
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Namespace
|
||||
Foam::parsing::evalStringToScalar
|
||||
InNamespace
|
||||
Foam::stringOps
|
||||
|
||||
Description
|
||||
Parsing encapsulation for stringOps::toScalar
|
||||
String expression evaluation.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
#ifndef evalStringToScalar_H
|
||||
#define evalStringToScalar_H
|
||||
|
||||
#include "scalar.H"
|
||||
#ifndef stringOpsEvaluate_H
|
||||
#define stringOpsEvaluate_H
|
||||
|
||||
#include "string.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -42,8 +42,7 @@ namespace Foam
|
||||
{
|
||||
namespace stringOps
|
||||
{
|
||||
|
||||
//- A simple string to scalar evaluation that handles various basic
|
||||
//- A simple string evaluation that handles various basic
|
||||
//- expressions. For trivial input, use readScalar instead (faster).
|
||||
//
|
||||
// The evaluation supports the following:
|
||||
@ -52,8 +51,10 @@ namespace stringOps
|
||||
// - trigonometric: sin, cos, tan, asin, acos, atan, atan2, hypot
|
||||
// - hyperbolic: sinh, cosh, tanh
|
||||
// - conversions: degToRad, radToDeg
|
||||
// - type conversion: bool, mag
|
||||
// - constants: pi(), true, false
|
||||
// - misc: floor, ceil, round, rand, rand(seed), bool()
|
||||
// - limits: neg, pos, neg0, pos0, sign, floor, ceil, round
|
||||
// - other: rand, rand(seed)
|
||||
// - logic: ! ? : == != <= => < >
|
||||
//
|
||||
// \note
|
||||
@ -63,7 +64,7 @@ namespace stringOps
|
||||
// \note
|
||||
// The rand() function returns a uniform scalar on [0-1] interval
|
||||
// and uses a constant seed.
|
||||
scalar toScalar
|
||||
string evaluate
|
||||
(
|
||||
const std::string& s,
|
||||
size_t pos = 0,
|
||||
@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
cd "${0%/*}" || exit # Run from this directory
|
||||
|
||||
# Manually create ragel scanner and lemon parser header
|
||||
prefix=evalStringToScalar
|
||||
|
||||
"${WM_PROJECT_DIR:?}/wmake/scripts/makeParser" \
|
||||
-prefix="$prefix" \
|
||||
-scanner=Scanner.rl \
|
||||
-parser=LemonParser.lyy-m4 \
|
||||
"$@"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@ -1,122 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019 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/>.
|
||||
|
||||
Class
|
||||
Foam::parsing::evalStringToScalar::parseDriver
|
||||
|
||||
Description
|
||||
Driver for stringOps::toScalar parsing
|
||||
|
||||
SourceFiles
|
||||
evalStringToScalarDriver.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef evalStringToScalarDriver_H
|
||||
#define evalStringToScalarDriver_H
|
||||
|
||||
#include "scalar.H"
|
||||
#include "className.H"
|
||||
#include "genericRagelLemonDriver.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace parsing
|
||||
{
|
||||
namespace evalStringToScalar
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
//- The debug flag. 2 = debug parser, 4 = debug scanner
|
||||
extern int debug;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class parseDriver Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class parseDriver
|
||||
:
|
||||
public genericRagelLemonDriver
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- The result
|
||||
scalar value_;
|
||||
|
||||
public:
|
||||
|
||||
ClassName("evalStringToScalar::driver");
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
parseDriver();
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~parseDriver() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Perform parsing on (sub) string
|
||||
// \return evaluated value
|
||||
scalar execute
|
||||
(
|
||||
const std::string& s,
|
||||
size_t strPos = 0,
|
||||
size_t strLen = std::string::npos
|
||||
);
|
||||
|
||||
//- Get value
|
||||
scalar value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
//- Set value
|
||||
void setValue(scalar val)
|
||||
{
|
||||
value_ = val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace evalStringToScalar
|
||||
} // End namespace parsing
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,53 +0,0 @@
|
||||
#define TOK_QUESTION 1
|
||||
#define TOK_COLON 2
|
||||
#define TOK_LOR 3
|
||||
#define TOK_LAND 4
|
||||
#define TOK_EQUAL 5
|
||||
#define TOK_NOT_EQUAL 6
|
||||
#define TOK_LESS_EQ 7
|
||||
#define TOK_GREATER_EQ 8
|
||||
#define TOK_LESS 9
|
||||
#define TOK_GREATER 10
|
||||
#define TOK_PLUS 11
|
||||
#define TOK_MINUS 12
|
||||
#define TOK_TIMES 13
|
||||
#define TOK_DIVIDE 14
|
||||
#define TOK_PERCENT 15
|
||||
#define TOK_NEGATE 16
|
||||
#define TOK_NOT 17
|
||||
#define TOK_NUMBER 18
|
||||
#define TOK_LPAREN 19
|
||||
#define TOK_RPAREN 20
|
||||
#define TOK_MAG 21
|
||||
#define TOK_PI 22
|
||||
#define TOK_DEG_TO_RAD 23
|
||||
#define TOK_RAD_TO_DEG 24
|
||||
#define TOK_EXP 25
|
||||
#define TOK_LOG 26
|
||||
#define TOK_LOG10 27
|
||||
#define TOK_SQR 28
|
||||
#define TOK_SQRT 29
|
||||
#define TOK_CBRT 30
|
||||
#define TOK_SIN 31
|
||||
#define TOK_COS 32
|
||||
#define TOK_TAN 33
|
||||
#define TOK_ASIN 34
|
||||
#define TOK_ACOS 35
|
||||
#define TOK_ATAN 36
|
||||
#define TOK_SINH 37
|
||||
#define TOK_COSH 38
|
||||
#define TOK_TANH 39
|
||||
#define TOK_MAGSQR 40
|
||||
#define TOK_FLOOR 41
|
||||
#define TOK_CEIL 42
|
||||
#define TOK_ROUND 43
|
||||
#define TOK_POW 44
|
||||
#define TOK_COMMA 45
|
||||
#define TOK_ATAN2 46
|
||||
#define TOK_HYPOT 47
|
||||
#define TOK_MIN 48
|
||||
#define TOK_MAX 49
|
||||
#define TOK_RAND 50
|
||||
#define TOK_BOOL_FALSE 51
|
||||
#define TOK_BOOL_TRUE 52
|
||||
#define TOK_BOOL 53
|
||||
@ -1,399 +0,0 @@
|
||||
%include
|
||||
{
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019 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/>.
|
||||
|
||||
Description
|
||||
Lemon grammar of a simple string to scalar evaluation.
|
||||
|
||||
The generated parser is localized in an anonymous namespace.
|
||||
Interface code wrapping is near the bottom of the file.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
dnl Begin m4 definitions
|
||||
dnl
|
||||
undefine(`substr')dnl> Avoid collision with C++ string substr() method
|
||||
dnl
|
||||
dnl
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl rule_binary_op(out, in1, in2, tok, op)
|
||||
dnl Production rule for binary field operations
|
||||
dnl
|
||||
dnl Example:
|
||||
dnl rule_binary_op(sfield, sfield, sfield, PLUS, +)
|
||||
dnl
|
||||
dnl sfield (lhs) ::= sfield (a) PLUS sfield (b) .
|
||||
dnl {
|
||||
dnl lhs = (a) + (b);
|
||||
dnl }
|
||||
dnl
|
||||
dnl ---------------------------------------------------------------------------
|
||||
define(`rule_binary_op',
|
||||
`$1 (lhs) ::= $2 (a) $4 $3 (b) .
|
||||
{
|
||||
lhs = (a) $5 (b);
|
||||
}'
|
||||
)dnl>
|
||||
dnl
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl rule_binary_logical_op(type, valType, compare, tok, op)
|
||||
dnl Production rule for binary logical field operations
|
||||
dnl Operates on identical field types, producing an lfield.
|
||||
dnl
|
||||
dnl Example:
|
||||
dnl rule_binary_logical_op(vfield, Foam::vector, greaterOp, GREATER, >)
|
||||
dnl
|
||||
dnl lfield (lhs) ::= vfield (a) GREATER vfield (b) .
|
||||
dnl {
|
||||
dnl lhs = Foam::greaterOp<Foam::vector>()(a, b);
|
||||
dnl }
|
||||
dnl ---------------------------------------------------------------------------
|
||||
define(`rule_binary_logical_op',
|
||||
`lfield (lhs) ::= $1 (a) $4 $1 (b) .
|
||||
{
|
||||
lhs = Foam::$3<$2>()(a, b);
|
||||
}'
|
||||
)dnl>
|
||||
dnl
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl rule_ternary_op(inOut)
|
||||
dnl Production rule for ternary field operations
|
||||
dnl
|
||||
dnl Example:
|
||||
dnl rule_ternary_op(sfield)
|
||||
dnl
|
||||
dnl sfield (lhs) ::= lfield(cond) QUESTION sfield (a) COLON sfield (b) .
|
||||
dnl {
|
||||
dnl lhs = (cond ? a : b);
|
||||
dnl }
|
||||
dnl
|
||||
define(`rule_ternary_op',
|
||||
`$1 (lhs) ::= lfield(cond) QUESTION $1 (a) COLON $1 (b) .
|
||||
{
|
||||
lhs = (cond ? a : b);
|
||||
}'
|
||||
)dnl>
|
||||
dnl
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl rule_unary_func(out, in1, tok, func)
|
||||
dnl Production rule for unary functions:
|
||||
dnl
|
||||
dnl Example:
|
||||
dnl rule_unary_func(sfield, vfield, MAG, Foam::mag)
|
||||
dnl
|
||||
dnl sfield (lhs) ::= MAG LPAREN vfield (a) RPAREN .
|
||||
dnl {
|
||||
dnl lhs = Foam::mag(a);
|
||||
dnl }
|
||||
dnl
|
||||
define(`rule_unary_func',
|
||||
`$1 (lhs) ::= $3 LPAREN $2 (a) RPAREN .
|
||||
{
|
||||
lhs = $4 (a);
|
||||
}'
|
||||
)dnl>
|
||||
dnl
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl rule_binary_func(out, in1, in2, tok, func)
|
||||
dnl Production rule for binary functions:
|
||||
dnl
|
||||
dnl Example:
|
||||
dnl rule_binary_func(sfield, sfield, sfield, POW, Foam::pow)
|
||||
dnl
|
||||
dnl sfield (lhs) ::= POW LPAREN sfield (a) COMMA sfield (b) RPAREN .
|
||||
dnl {
|
||||
dnl lhs = Foam::pow((a), (b));
|
||||
dnl }
|
||||
dnl
|
||||
define(`rule_binary_func',
|
||||
`$1 (lhs) ::= $4 LPAREN $2 (a) COMMA $3 (b) RPAREN .
|
||||
{
|
||||
lhs = $5((a), (b));
|
||||
}'
|
||||
)dnl>
|
||||
dnl
|
||||
dnl End m4 definitions
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
%include
|
||||
{
|
||||
#include "evalStringToScalarDriver.H"
|
||||
#include "evalStringToScalarParser.H"
|
||||
#include "unitConversion.H"
|
||||
#include "Random.H"
|
||||
#include "Switch.H"
|
||||
#include "error.H"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
// Enable ParseTrace
|
||||
#undef NDEBUG
|
||||
|
||||
// Local Functions
|
||||
|
||||
//- Test for value close to zero
|
||||
template<class T>
|
||||
bool equalZero(const T& val)
|
||||
{
|
||||
return (Foam::mag(val) < Foam::ROOTVSMALL);
|
||||
}
|
||||
|
||||
|
||||
} // %include
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
%namespace {}
|
||||
|
||||
// Use extra argument for the return value
|
||||
%extra_context { Foam::parsing::evalStringToScalar::parseDriver* driver }
|
||||
%parse_failure { driver->reportFatal("Parse failure, giving up..."); }
|
||||
%syntax_error { driver->reportFatal("Syntax error"); }
|
||||
|
||||
%token_prefix TOK_
|
||||
|
||||
// Terminals
|
||||
%token_type {Foam::scalar}
|
||||
// Non-terminals
|
||||
%type lfield {bool}
|
||||
%type sfield {Foam::scalar}
|
||||
|
||||
|
||||
// (https://en.cppreference.com/w/cpp/language/operator_precedence)
|
||||
|
||||
%right QUESTION COLON . // 16: right-to-left
|
||||
%left LOR . // 15:
|
||||
%left LAND . // 14:
|
||||
// %left BIT_OR . // 13
|
||||
// %left BIT_XOR . // 12
|
||||
// %left BIT_AND . // 11
|
||||
%left EQUAL NOT_EQUAL . // 10
|
||||
%left LESS_EQ GREATER_EQ LESS GREATER . // 9
|
||||
%left PLUS MINUS . // 6
|
||||
%left TIMES DIVIDE PERCENT . // 5
|
||||
%right NEGATE NOT . // 3: right-to-left
|
||||
|
||||
%start_symbol evaluate
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* Productions (Foam::scalar)
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
evaluate ::= sfield(a).
|
||||
{
|
||||
driver->setValue(a);
|
||||
}
|
||||
|
||||
|
||||
// Basics
|
||||
|
||||
sfield(lhs) ::= NUMBER(a). { lhs = a; } // From scanToken
|
||||
sfield(lhs) ::= LPAREN sfield(a) RPAREN. { lhs = a; }
|
||||
sfield(lhs) ::= MINUS sfield(a). [NEGATE] { lhs = -a; }
|
||||
|
||||
// Conversion (cast)
|
||||
sfield(lhs) ::= MAG LPAREN lfield(a) RPAREN . { lhs = Foam::scalar(a); }
|
||||
|
||||
// Constants
|
||||
|
||||
sfield(lhs) ::= PI LPAREN RPAREN. { lhs = Foam::constant::mathematical::pi; }
|
||||
sfield(lhs) ::= DEG_TO_RAD LPAREN RPAREN. { lhs = Foam::degToRad(); }
|
||||
sfield(lhs) ::= RAD_TO_DEG LPAREN RPAREN. { lhs = Foam::radToDeg(); }
|
||||
|
||||
// Operations
|
||||
|
||||
rule_ternary_op(sfield)
|
||||
|
||||
rule_binary_op(sfield, sfield, sfield, PLUS, +)
|
||||
rule_binary_op(sfield, sfield, sfield, MINUS, -)
|
||||
rule_binary_op(sfield, sfield, sfield, TIMES, *)
|
||||
|
||||
sfield(lhs) ::= sfield(a) DIVIDE sfield(b).
|
||||
{
|
||||
lhs = equalZero(b) ? Foam::scalar(0) : (a / b);
|
||||
}
|
||||
sfield(lhs) ::= sfield(a) PERCENT sfield(b).
|
||||
{
|
||||
lhs = equalZero(b) ? Foam::scalar(0) : std::fmod(a, b);
|
||||
}
|
||||
|
||||
// Functions
|
||||
|
||||
rule_unary_func(sfield, sfield, DEG_TO_RAD, Foam::degToRad)
|
||||
rule_unary_func(sfield, sfield, RAD_TO_DEG, Foam::radToDeg)
|
||||
|
||||
rule_unary_func(sfield, sfield, EXP, Foam::exp)
|
||||
rule_unary_func(sfield, sfield, LOG, Foam::log)
|
||||
rule_unary_func(sfield, sfield, LOG10, Foam::log10)
|
||||
rule_unary_func(sfield, sfield, SQR, Foam::sqr)
|
||||
rule_unary_func(sfield, sfield, SQRT, Foam::sqrt)
|
||||
rule_unary_func(sfield, sfield, CBRT, Foam::cbrt)
|
||||
rule_unary_func(sfield, sfield, SIN, Foam::sin)
|
||||
rule_unary_func(sfield, sfield, COS, Foam::cos)
|
||||
rule_unary_func(sfield, sfield, TAN, Foam::tan)
|
||||
rule_unary_func(sfield, sfield, ASIN, Foam::asin)
|
||||
rule_unary_func(sfield, sfield, ACOS, Foam::acos)
|
||||
rule_unary_func(sfield, sfield, ATAN, Foam::atan)
|
||||
rule_unary_func(sfield, sfield, SINH, Foam::sinh)
|
||||
rule_unary_func(sfield, sfield, COSH, Foam::cosh)
|
||||
rule_unary_func(sfield, sfield, TANH, Foam::tanh)
|
||||
rule_unary_func(sfield, sfield, MAG, Foam::mag)
|
||||
rule_unary_func(sfield, sfield, MAGSQR, Foam::magSqr)
|
||||
rule_unary_func(sfield, sfield, FLOOR, std::floor)
|
||||
rule_unary_func(sfield, sfield, CEIL, std::ceil)
|
||||
rule_unary_func(sfield, sfield, ROUND, std::round)
|
||||
|
||||
rule_binary_func(sfield, sfield, sfield, POW, Foam::pow)
|
||||
rule_binary_func(sfield, sfield, sfield, ATAN2, Foam::atan2)
|
||||
rule_binary_func(sfield, sfield, sfield, HYPOT, Foam::hypot)
|
||||
rule_binary_func(sfield, sfield, sfield, MIN, Foam::min)
|
||||
rule_binary_func(sfield, sfield, sfield, MAX, Foam::max)
|
||||
|
||||
sfield(lhs) ::= RAND LPAREN RPAREN.
|
||||
{
|
||||
lhs = Foam::Random().sample01<Foam::scalar>();
|
||||
}
|
||||
|
||||
sfield(lhs) ::= RAND LPAREN sfield(seed) RPAREN.
|
||||
{
|
||||
lhs = Foam::Random(seed).sample01<Foam::scalar>();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Productions for bool (logical) fields
|
||||
|
||||
evaluate ::= lfield(a).
|
||||
{
|
||||
driver->setValue(Foam::scalar(a));
|
||||
}
|
||||
|
||||
// Basics
|
||||
|
||||
lfield(lhs) ::= BOOL_FALSE . { lhs = false; }
|
||||
lfield(lhs) ::= BOOL_TRUE . { lhs = true; }
|
||||
lfield(lhs) ::= LPAREN lfield(a) RPAREN . { lhs = a; }
|
||||
lfield(lhs) ::= NOT lfield(a). [NEGATE] { lhs = !a; }
|
||||
|
||||
// Conversion (cast)
|
||||
lfield(lhs) ::= BOOL LPAREN lfield(a) RPAREN . { lhs = a; }
|
||||
lfield(lhs) ::= BOOL LPAREN sfield(a) RPAREN . { lhs = Foam::Switch(a); }
|
||||
|
||||
// Operations
|
||||
|
||||
rule_ternary_op(lfield)
|
||||
|
||||
rule_binary_logical_op(lfield, bool, andOp, LAND, &&)
|
||||
rule_binary_logical_op(lfield, bool, orOp, LOR, ||)
|
||||
|
||||
rule_binary_logical_op(sfield, Foam::scalar, equalOp, EQUAL, ==)
|
||||
rule_binary_logical_op(sfield, Foam::scalar, notEqualOp, NOT_EQUAL, !=)
|
||||
rule_binary_logical_op(sfield, Foam::scalar, lessOp, LESS, <)
|
||||
rule_binary_logical_op(sfield, Foam::scalar, lessEqOp, LESS_EQ, <=)
|
||||
rule_binary_logical_op(sfield, Foam::scalar, greaterOp, GREATER, >)
|
||||
rule_binary_logical_op(sfield, Foam::scalar, greaterEqOp, GREATER_EQ, >=)
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
%code
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::parsing::evalStringToScalar::parser::stop()
|
||||
{
|
||||
if (lemon_)
|
||||
{
|
||||
ParseFree(lemon_, ::operator delete);
|
||||
#ifndef NDEBUG
|
||||
ParseTrace(nullptr, nullptr);
|
||||
#endif
|
||||
lemon_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::parsing::evalStringToScalar::parser::start(parseDriver& driver)
|
||||
{
|
||||
this->stop();
|
||||
lemon_ = ParseAlloc(::operator new, &driver);
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
ParseTrace(stderr, const_cast<char*>(prompt_));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::parsing::evalStringToScalar::parser::parse
|
||||
(
|
||||
int tokenId,
|
||||
Foam::scalar val /* The value for the token */
|
||||
)
|
||||
{
|
||||
Parse(lemon_, tokenId, val);
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::parsing::evalStringToScalar::parser::nameOfToken
|
||||
(
|
||||
int tokenId
|
||||
) const
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if
|
||||
(
|
||||
tokenId > 0
|
||||
&& unsigned(tokenId) < (sizeof(yyTokenName) / sizeof(char*))
|
||||
)
|
||||
{
|
||||
return yyTokenName[tokenId];
|
||||
}
|
||||
return "<invalid>";
|
||||
#else
|
||||
return word();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End of %code
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,105 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019 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/>.
|
||||
|
||||
Class
|
||||
Foam::parsing::evalStringToScalar::parser
|
||||
|
||||
Description
|
||||
Interface to lemon parser to simple string to scalar evaluation, which
|
||||
is used by stringOps::toScalar
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef evalStringToScalarParser_H
|
||||
#define evalStringToScalarParser_H
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace parsing
|
||||
{
|
||||
namespace evalStringToScalar
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class parseDriver;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class parser Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class parser
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Prompt for parser tracing
|
||||
static constexpr const char* const prompt_ = "#eval:";
|
||||
|
||||
//- The lemon parser (demand-driven)
|
||||
void* lemon_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
parser() : lemon_(nullptr) {}
|
||||
|
||||
|
||||
//- Destructor, delete lemon parser
|
||||
~parser()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Start parsing, with given driver context
|
||||
void start(parseDriver& driver);
|
||||
|
||||
//- Stop parsing, freeing the allocated parser
|
||||
void stop();
|
||||
|
||||
//- Push token/value to parser
|
||||
void parse(int tokenId, Foam::scalar val);
|
||||
|
||||
//- The text name corresponding to the tokenId
|
||||
word nameOfToken(int tokenId) const;
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace evalStringToScalar
|
||||
} // End namespace parsing
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,118 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019 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/>.
|
||||
|
||||
Class
|
||||
Foam::parsing::evalStringToScalar::scanner
|
||||
|
||||
Description
|
||||
Ragel lexer interface for lemon grammar of a simple string to
|
||||
scalar evaluation, which is used by stringOps::toScalar
|
||||
|
||||
Note
|
||||
Ragel code generated with the ./createCode script.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef evalStringToScalarScanner_H
|
||||
#define evalStringToScalarScanner_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace parsing
|
||||
{
|
||||
namespace evalStringToScalar
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class parser;
|
||||
class parseDriver;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class scanner Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class scanner
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Wrapped lemon parser
|
||||
parser* parser_;
|
||||
|
||||
// Ragel code state, action
|
||||
int cs, act;
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
scanner() : parser_(nullptr) {}
|
||||
|
||||
|
||||
//- Destructor, deletes parser
|
||||
~scanner();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Evaluate sub-string
|
||||
bool process
|
||||
(
|
||||
const std::string& str, size_t pos, size_t len,
|
||||
parseDriver& driver
|
||||
);
|
||||
|
||||
//- Evaluate sub-string
|
||||
bool process
|
||||
(
|
||||
const std::string& str, size_t pos,
|
||||
parseDriver& driver
|
||||
)
|
||||
{
|
||||
return process(str, pos, std::string::npos, driver);
|
||||
}
|
||||
|
||||
//- Evaluate string
|
||||
bool process(const std::string& str, parseDriver& driver)
|
||||
{
|
||||
return process(str, 0, std::string::npos, driver);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace evalStringToScalar
|
||||
} // End namespace parsing
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,267 +0,0 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019 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/>.
|
||||
|
||||
Description
|
||||
Ragel lexer interface for lemon grammar of a simple string to
|
||||
scalar evaluation
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "evalStringToScalarScanner.H"
|
||||
#include "evalStringToScalarDriver.H"
|
||||
#include "evalStringToScalarLemonParser.h"
|
||||
#include "evalStringToScalarParser.H"
|
||||
#include "error.H"
|
||||
#include "macros.H"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
// Ragel lexer with lemon parser integration
|
||||
|
||||
// Ragel machine definition
|
||||
// Ragel variables (p, pe, eof, cs, top, stack, ts, te, act) defined later...
|
||||
//
|
||||
// Can use 'variable p xxx;' etc to change these names
|
||||
|
||||
%%{
|
||||
machine evalScanner;
|
||||
write data;
|
||||
}%%
|
||||
|
||||
|
||||
#undef DebugScannerInfo
|
||||
#define DebugScannerInfo if (debug & 4) InfoErr
|
||||
|
||||
|
||||
#define TOKEN_OF(T) TOK_##T
|
||||
#define EMIT_TOKEN(T) \
|
||||
driver.parsePosition() = (ts-buf); \
|
||||
DebugScannerInfo << STRINGIFY(T) << ": "<< driver.parsePosition() << nl; \
|
||||
parser_->parse(TOKEN_OF(T), 0); \
|
||||
driver.parsePosition() = (p-buf);
|
||||
|
||||
|
||||
%%{
|
||||
machine evalScanner;
|
||||
|
||||
action emit_number {
|
||||
driver.parsePosition() = (ts-buf);
|
||||
|
||||
DebugScannerInfo
|
||||
<< "Number:" << std::string(ts, te-ts).c_str()
|
||||
<< " at " << driver.parsePosition() << nl;
|
||||
|
||||
scalar val(0);
|
||||
|
||||
if (readScalar(std::string(ts, te-ts), val))
|
||||
{
|
||||
// Emit number
|
||||
parser_->parse(TOKEN_OF(NUMBER), val);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Range error
|
||||
driver.reportFatal("Error parsing number");
|
||||
}
|
||||
|
||||
driver.parsePosition() = (p-buf);
|
||||
}
|
||||
|
||||
action emit_ident {
|
||||
driver.parsePosition() = (ts-buf);
|
||||
const word ident = word::validate(ts, te);
|
||||
|
||||
driver.reportFatal("Unknown function/type: " + ident);
|
||||
driver.parsePosition() = (p-buf);
|
||||
}
|
||||
|
||||
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
|
||||
number = (digit+ | decimal) ([Ee][\-+]? digit+)? ;
|
||||
ident = ((alpha|'_') . ((alnum|'_')**)) ;
|
||||
|
||||
|
||||
## The scanner
|
||||
main := |*
|
||||
space*;
|
||||
|
||||
number => emit_number;
|
||||
|
||||
## operators
|
||||
'!' => { EMIT_TOKEN(NOT); };
|
||||
'%' => { EMIT_TOKEN(PERCENT); };
|
||||
'(' => { EMIT_TOKEN(LPAREN); };
|
||||
')' => { EMIT_TOKEN(RPAREN); };
|
||||
'*' => { EMIT_TOKEN(TIMES); };
|
||||
'+' => { EMIT_TOKEN(PLUS); };
|
||||
'-' => { EMIT_TOKEN(MINUS); };
|
||||
',' => { EMIT_TOKEN(COMMA); };
|
||||
'/' => { EMIT_TOKEN(DIVIDE); };
|
||||
'!' => { EMIT_TOKEN(NOT); };
|
||||
'?' => { EMIT_TOKEN(QUESTION); };
|
||||
':' => { EMIT_TOKEN(COLON); };
|
||||
'<' => { EMIT_TOKEN(LESS); };
|
||||
'<=' => { EMIT_TOKEN(LESS_EQ); };
|
||||
'>' => { EMIT_TOKEN(GREATER); };
|
||||
'>=' => { EMIT_TOKEN(GREATER_EQ); };
|
||||
'==' => { EMIT_TOKEN(EQUAL); };
|
||||
'!=' => { EMIT_TOKEN(NOT_EQUAL); };
|
||||
'&&' => { EMIT_TOKEN(LAND); };
|
||||
'||' => { EMIT_TOKEN(LOR); };
|
||||
## Not needed '&' => { EMIT_TOKEN(BIT_AND); };
|
||||
## Not needed '|' => { EMIT_TOKEN(BIT_OR); };
|
||||
## Not needed '^' => { EMIT_TOKEN(BIT_XOR); };
|
||||
|
||||
## Regular functions
|
||||
'pi' => { EMIT_TOKEN(PI); };
|
||||
'degToRad' => { EMIT_TOKEN(DEG_TO_RAD); };
|
||||
'radToDeg' => { EMIT_TOKEN(RAD_TO_DEG); };
|
||||
'exp' => { EMIT_TOKEN(EXP); };
|
||||
'log' => { EMIT_TOKEN(LOG); };
|
||||
'log10' => { EMIT_TOKEN(LOG10); };
|
||||
'pow' => { EMIT_TOKEN(POW); };
|
||||
'sqr' => { EMIT_TOKEN(SQR); };
|
||||
'sqrt' => { EMIT_TOKEN(SQRT); };
|
||||
'cbrt' => { EMIT_TOKEN(CBRT); };
|
||||
'sin' => { EMIT_TOKEN(SIN); };
|
||||
'cos' => { EMIT_TOKEN(COS); };
|
||||
'tan' => { EMIT_TOKEN(TAN); };
|
||||
'asin' => { EMIT_TOKEN(ASIN); };
|
||||
'acos' => { EMIT_TOKEN(ACOS); };
|
||||
'atan' => { EMIT_TOKEN(ATAN); };
|
||||
'atan2' => { EMIT_TOKEN(ATAN2); };
|
||||
'hypot' => { EMIT_TOKEN(HYPOT); };
|
||||
'sinh' => { EMIT_TOKEN(SINH); };
|
||||
'cosh' => { EMIT_TOKEN(COSH); };
|
||||
'tanh' => { EMIT_TOKEN(TANH); };
|
||||
'min' => { EMIT_TOKEN(MIN); };
|
||||
'max' => { EMIT_TOKEN(MAX); };
|
||||
'mag' => { EMIT_TOKEN(MAG); };
|
||||
'magSqr' => { EMIT_TOKEN(MAGSQR); };
|
||||
'floor' => { EMIT_TOKEN(FLOOR); };
|
||||
'ceil' => { EMIT_TOKEN(CEIL); };
|
||||
'round' => { EMIT_TOKEN(ROUND); };
|
||||
'rand' => { EMIT_TOKEN(RAND); };
|
||||
'bool' => { EMIT_TOKEN(BOOL); };
|
||||
|
||||
## Constants
|
||||
'false' =>{ EMIT_TOKEN(BOOL_FALSE); };
|
||||
'true' =>{ EMIT_TOKEN(BOOL_TRUE); };
|
||||
|
||||
## Catch-all for identifiers/errors
|
||||
ident => emit_ident;
|
||||
|
||||
space*;
|
||||
*|;
|
||||
}%%
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::parsing::evalStringToScalar::scanner::~scanner()
|
||||
{
|
||||
if (parser_)
|
||||
{
|
||||
delete parser_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::parsing::evalStringToScalar::scanner::process
|
||||
(
|
||||
const std::string& str,
|
||||
size_t strBeg,
|
||||
size_t strLen,
|
||||
parseDriver& driver
|
||||
)
|
||||
{
|
||||
if (!parser_)
|
||||
{
|
||||
parser_ = new parser();
|
||||
}
|
||||
|
||||
driver.content(str, strBeg, strLen);
|
||||
|
||||
size_t strEnd = str.length();
|
||||
|
||||
if (strBeg > str.length())
|
||||
{
|
||||
strBeg = str.length();
|
||||
}
|
||||
else if (strLen != std::string::npos)
|
||||
{
|
||||
strLen += strBeg;
|
||||
|
||||
if (strLen < str.length())
|
||||
{
|
||||
strEnd = strLen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
parser_->start(driver);
|
||||
|
||||
// Ragel token start/end (required naming)
|
||||
const char* ts;
|
||||
const char* te;
|
||||
|
||||
// Local buffer data.
|
||||
// - p, pe, eof are required Ragel naming
|
||||
// - buf is our own naming
|
||||
|
||||
const char* buf = &(str[strBeg]);
|
||||
const char* eof = &(str[strEnd]);
|
||||
const char* p = buf;
|
||||
const char* pe = eof;
|
||||
|
||||
// Initialize FSM variables
|
||||
%%{write init;}%% /* ^^^ FSM initialization here ^^^ */;
|
||||
|
||||
%%{write exec;}%% /* ^^^ FSM execution here ^^^ */;
|
||||
|
||||
if (%%{write error;}%% == cs)
|
||||
{
|
||||
driver.reportFatal("Parse error while scanning", (p-buf));
|
||||
}
|
||||
|
||||
if (p != eof)
|
||||
{
|
||||
driver.reportFatal("Parsing failed with remaining content", (p-buf));
|
||||
}
|
||||
|
||||
// Terminate parser execution
|
||||
parser_->parse(0, 0);
|
||||
parser_->stop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -36,4 +36,13 @@ FoamFile
|
||||
#endif
|
||||
|
||||
|
||||
// Silly example, but can also force cast from scalar to bool
|
||||
|
||||
#if #eval "bool(2 * pi())"
|
||||
condition true;
|
||||
#else
|
||||
condition false;
|
||||
#endif
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
Reference in New Issue
Block a user