mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
247 lines
6.8 KiB
Ragel
247 lines
6.8 KiB
Ragel
/*--------------------------------*- 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"
|
|
|
|
|
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
|
|
int Foam::parsing::evalStringToScalar::scanner::debug = 0;
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
// 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;
|
|
}%%
|
|
|
|
#define TOKEN_OF(T) TOK_##T
|
|
#define EMIT_TOKEN(T) \
|
|
driver.parsePosition() = (ts-buf); \
|
|
DebugInfo<< STRINGIFY(T) << ": " << driver.parsePosition() << nl; \
|
|
parser_->parse(TOKEN_OF(T), 0); \
|
|
driver.parsePosition() = (p-buf);
|
|
|
|
|
|
%%{
|
|
machine evalScanner;
|
|
|
|
action emit_number {
|
|
driver.parsePosition() = (ts-buf);
|
|
|
|
DebugInfo
|
|
<< "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(LPAREN); };
|
|
')' => { EMIT_TOKEN(RPAREN); };
|
|
'+' => { EMIT_TOKEN(PLUS); };
|
|
'-' => { EMIT_TOKEN(MINUS); };
|
|
'*' => { EMIT_TOKEN(TIMES); };
|
|
'/' => { EMIT_TOKEN(DIVIDE); };
|
|
',' => { EMIT_TOKEN(COMMA); };
|
|
|
|
## 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' => { fhold; EMIT_TOKEN(RAND); };
|
|
|
|
## 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;
|
|
}
|
|
|
|
|
|
// ************************************************************************* //
|