Files
openfoam/applications/test/dictionary/calcEntry/calcEntryParser.atg
2010-01-15 19:25:12 +01:00

261 lines
7.0 KiB
C++

[copy]
/*---------------------------------*- C++ -*---------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@file calcEntryParser.atg
Description
An attributed Coco/R grammar to parse simple arithmetic expressions
Includes support for dictionary $variables and some scalar functions
(eg, sin, pow, ...)
SourceFiles
generated
\*---------------------------------------------------------------------------*/
[/copy]
/*---------------------------------------------------------------------------*\
compile with:
Coco \
[-single] -frames $WM_THIRD_PARTY_DIR/coco-r \
calcEntryParser.atg
\*---------------------------------------------------------------------------*/
#include "dictionary.H"
#include "wchar.H"
#include "calcEntryInternal.H"
COMPILER calcEntry
// grammar pragmas:
$prefix=calcEntry
$namespace=Foam::functionEntries::calcEntryInternal
$explicitEOF=true // grammar handles eof itself
private:
//- The parent dictionary
dictionary* dict_;
//- The calculation result
scalar val;
//- lookup dictionary entry
scalar getDictLookup() const
{
if (!dict_)
{
FatalErrorIn
(
"calcEntry::getDictEntry() const"
) << "No dictionary attached!"
<< exit(FatalError);
return 0;
}
char* str = coco_string_create_char
(
t->val,
1,
(coco_string_length(t->val) - 1)
);
word keyword(str);
coco_string_delete(str);
scalar dictValue = 0;
entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false);
if (entryPtr && !entryPtr->isDict())
{
if (entryPtr->stream().size() != 1)
{
FatalErrorIn
(
"calcEntry::getDictEntry() const"
) << "keyword " << keyword << " has "
<< entryPtr->stream().size() << " values in dictionary "
<< exit(FatalError);
}
entryPtr->stream() >> dictValue;
}
else
{
FatalErrorIn
(
"calcEntry::getDictEntry() const"
) << "keyword " << keyword << " is undefined in dictionary "
<< exit(FatalError);
}
return dictValue;
}
public:
//- attach a dictionary
void dict(const dictionary& dict)
{
dict_ = const_cast<dictionary*>(&dict);
}
//- Return the calculated result
scalar Result() const
{
return val;
}
[initialize]
dict_ = 0;
val = 0;
[/initialize]
/*---------------------------------------------------------------------------*/
CHARACTERS
letter = 'A'..'Z' + 'a'..'z' + '_'.
digit = "0123456789".
alphanum = letter + digit.
sign = '+' + '-'.
cr = '\r'.
lf = '\n'.
tab = '\t'.
stringCh = ANY - '"' - '\\' - cr - lf.
printable = '\u0020' .. '\u007e'.
// * * * * * * * * * * * * * * * * TOKENS * * * * * * * * * * * * * * * * * //
TOKENS
// identifier
ident =
letter { alphanum }.
// string
string =
'"' { stringCh | '\\' printable } '"'.
// dictionary lookup identifier
// starts with '$' and otherwise limited to a normal identifier
variable =
'$' letter { alphanum }.
// floating point and integer numbers
number =
[sign] ('.' digit { digit } ) | ( digit { digit } [ '.' { digit } ])
[ ('E' | 'e') [sign] digit { digit } ].
// * * * * * * * * * * * PRAGMAS / COMMENTS / IGNORE * * * * * * * * * * * //
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
// * * * * * * * * * * * * * * * PRODUCTIONS * * * * * * * * * * * * * * * //
PRODUCTIONS
calcEntry (. val = 0; .)
=
'{' Expr<val> '}' (. // reposition to immediately after the closing '}'
scanner->buffer->SetPos(t->pos + 1);
.)
| ( Expr<val> EOF )
.
/*---------------------------------------------------------------------------*/
Expr<scalar& val> (. scalar val2 = 0; .)
=
Term<val>
{
'+' Term<val2> (. val += val2; .)
| '-' Term<val2> (. val -= val2; .)
}
.
/*---------------------------------------------------------------------------*/
Term<scalar& val> (. scalar val2 = 0; .)
=
Factor<val>
{
'*' Factor<val2> (. val *= val2; .)
| '/' Factor<val2> (. val /= val2; .)
}
.
/*---------------------------------------------------------------------------*/
// Note the treatment of the leading signs is fairly generous
// eg, "10 + - 10" is treated like "10 + -10"
//
Factor<scalar& val> (. bool negative = false; .)
=
['+' | '-' (. negative = true; .)
]
(
Func<val> | '(' Expr<val> ')'
| variable (. val = getDictLookup(); .)
| number (. val = coco_string_toDouble(t->val); .)
) (. if (negative) { val = -val; } .)
.
/*---------------------------------------------------------------------------*/
// functions like sin(x) or pow(x, y) etc.
Func<scalar& val>
=
ident (.
char* str = coco_string_create_char(t->val);
word funcName(str);
coco_string_delete(str);
DynamicList<scalar> stack(4);
.)
'('
[ (. scalar x; .)
Expr<x> (. stack.append(x); .)
{ ',' Expr<x> (. stack.append(x); .)
}
]
')' (. val = dispatch(funcName, stack); .)
.
/*---------------------------------------------------------------------------*/
END calcEntry.
// ************************************************************************* //