mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge commit 'gitbundle/home' into olesenm
This commit is contained in:
@ -1,15 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
cd ${0%/*} || exit 1 # run from this directory
|
|
||||||
|
|
||||||
# this will have to do until we have a makefile rule
|
|
||||||
|
|
||||||
if type Coco > /dev/null 2>&1
|
|
||||||
then
|
|
||||||
Coco \
|
|
||||||
-frames $WM_THIRD_PARTY_DIR/coco-r \
|
|
||||||
calcEntry/calcEntry.atg
|
|
||||||
else
|
|
||||||
echo "Coco not installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
wmake
|
|
||||||
@ -1,7 +1,3 @@
|
|||||||
dictionaryTest.C
|
dictionaryTest.C
|
||||||
|
|
||||||
calcEntry/calcEntry.C
|
|
||||||
calcEntry/calcEntryParser.cpp
|
|
||||||
calcEntry/calcEntryScanner.cpp
|
|
||||||
|
|
||||||
EXE = $(FOAM_USER_APPBIN)/dictionaryTest
|
EXE = $(FOAM_USER_APPBIN)/dictionaryTest
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
EXE_INC =
|
||||||
|
|||||||
@ -1,252 +0,0 @@
|
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
compile with:
|
|
||||||
Coco \
|
|
||||||
-frames $WM_THIRD_PARTY_DIR/coco-r \
|
|
||||||
calcEntry.atg
|
|
||||||
-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "dictionary.H"
|
|
||||||
#include "scalar.H"
|
|
||||||
#include "error.H"
|
|
||||||
#include "wchar.H"
|
|
||||||
|
|
||||||
|
|
||||||
COMPILER calcEntry
|
|
||||||
$prefix=calcEntry
|
|
||||||
$namespace=Foam::functionEntries::calcEntryInternal
|
|
||||||
$eof=true // grammar handles eof itself
|
|
||||||
|
|
||||||
// Simple four function calculator for OpenFOAM dictionaries
|
|
||||||
|
|
||||||
//! with debug
|
|
||||||
static const int debug = 0;
|
|
||||||
|
|
||||||
//! The parent dictionary
|
|
||||||
mutable dictionary* dict_;
|
|
||||||
|
|
||||||
//! Track that parent dictionary was set
|
|
||||||
bool hasDict_;
|
|
||||||
|
|
||||||
//! The calculation result
|
|
||||||
scalar val;
|
|
||||||
|
|
||||||
|
|
||||||
//! token -> scalar
|
|
||||||
scalar getScalar() const
|
|
||||||
{
|
|
||||||
return coco_string_toDouble(t->val);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! token -> string
|
|
||||||
std::string getString() const
|
|
||||||
{
|
|
||||||
char* str = coco_string_create_char(t->val);
|
|
||||||
std::string s(str);
|
|
||||||
coco_string_delete(str);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! attach a dictionary
|
|
||||||
void dict(const dictionary& dict)
|
|
||||||
{
|
|
||||||
dict_ = const_cast<dictionary*>(&dict);
|
|
||||||
hasDict_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! lookup dictionary entry
|
|
||||||
scalar getDictLookup() const
|
|
||||||
{
|
|
||||||
scalar dictValue = 0;
|
|
||||||
|
|
||||||
if (!hasDict_)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"calcEntry::getDictEntry() const"
|
|
||||||
) << "No dictionary attached!"
|
|
||||||
<< exit(FatalError);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* chars = coco_string_create_char
|
|
||||||
(
|
|
||||||
t->val,
|
|
||||||
1,
|
|
||||||
(coco_string_length(t->val) - 1)
|
|
||||||
);
|
|
||||||
word keyword(chars);
|
|
||||||
coco_string_delete(chars);
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<<"lookup: " << keyword << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar Result() const
|
|
||||||
{
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
CHARACTERS
|
|
||||||
letter = 'A'..'Z' + 'a'..'z'.
|
|
||||||
qualifier = '_' + ':'.
|
|
||||||
dollar = '$'.
|
|
||||||
digit = "0123456789".
|
|
||||||
sign = '+' + '-'.
|
|
||||||
cr = '\r'.
|
|
||||||
lf = '\n'.
|
|
||||||
tab = '\t'.
|
|
||||||
stringCh = ANY - '"' - '\\' - cr - lf.
|
|
||||||
printable = '\u0020' .. '\u007e'.
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * TOKENS * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
TOKENS
|
|
||||||
|
|
||||||
// identifier
|
|
||||||
ident =
|
|
||||||
letter { letter | digit | qualifier }.
|
|
||||||
|
|
||||||
// string
|
|
||||||
string =
|
|
||||||
'"' { stringCh | '\\' printable } '"'.
|
|
||||||
|
|
||||||
// dictionary lookup identifier
|
|
||||||
// starts with '$' and otherwise limited to a normal indentifier
|
|
||||||
variable =
|
|
||||||
dollar letter { letter | digit | qualifier }.
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
if (debug){Info<<"start val pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
=
|
|
||||||
'{' Expr<val> '}' (.
|
|
||||||
if (debug){
|
|
||||||
Info<<"end {} at pos:"<< t->pos
|
|
||||||
<<" val:"<< t->val
|
|
||||||
<<" len:"<< coco_string_length(t->val)
|
|
||||||
<<" la pos:"<< la->pos << nl;
|
|
||||||
}
|
|
||||||
// reposition to immediately after the closing '}'
|
|
||||||
scanner->buffer->SetPos
|
|
||||||
(
|
|
||||||
t->pos + coco_string_length(t->val)
|
|
||||||
);
|
|
||||||
.)
|
|
||||||
| ( Expr<val> EOF )
|
|
||||||
.
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
Expr<scalar& val> (. scalar val2 = 0;
|
|
||||||
if (debug) {Info<<"Expr:"<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
=
|
|
||||||
Term<val>
|
|
||||||
{
|
|
||||||
"+" Term<val2> (. if (debug) {Info<<"+Term:"<<val2 << " pos:"<< t->pos << nl;}
|
|
||||||
val += val2;
|
|
||||||
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
| "-" Term<val2> (. if (debug) {Info<<"-Term:"<<val2<< " pos:"<< t->pos << nl;}
|
|
||||||
val -= val2;
|
|
||||||
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
}
|
|
||||||
.
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
Term<scalar& val> (. scalar val2 = 0;
|
|
||||||
if (debug) {Info<<"Term:"<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
=
|
|
||||||
Factor<val>
|
|
||||||
{
|
|
||||||
"*" Factor<val2> (. if (debug) {Info<<"*Factor:"<<val2<< " pos:"<< t->pos << nl;}
|
|
||||||
val *= val2;
|
|
||||||
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
| "/" Factor<val2> (. if (debug) {Info<<"/Factor:"<<val2<< " pos:"<< t->pos << nl;}
|
|
||||||
val /= val2;
|
|
||||||
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
}
|
|
||||||
.
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
Factor<scalar& val>
|
|
||||||
=
|
|
||||||
variable (. val = getDictLookup();
|
|
||||||
if (debug) {Info<<"lookup:"<<val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
| number (. val = getScalar();
|
|
||||||
if (debug) {Info<<"got num:"<<val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
| '-' '(' Expr<val> ')' (. val = -val;
|
|
||||||
if (debug) {Info<<"inv:"<<val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
| '(' Expr<val> ')' (. if (debug){Info<<"got Expr:"<<val<< " pos:"<< t->pos << nl;}
|
|
||||||
.)
|
|
||||||
.
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
END calcEntry.
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,339 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
#include "calcEntryParser.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Foam {
|
|
||||||
namespace functionEntries {
|
|
||||||
namespace calcEntryInternal {
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Parser Implementation
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void Parser::SynErr(int n) {
|
|
||||||
if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n);
|
|
||||||
errDist = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Parser::SemErr(const wchar_t* msg) {
|
|
||||||
if (errDist >= minErrDist) errors->Error(t->line, t->col, msg);
|
|
||||||
errDist = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Parser::Get() {
|
|
||||||
for (;;) {
|
|
||||||
t = la;
|
|
||||||
la = scanner->Scan();
|
|
||||||
if (la->kind <= maxT) {
|
|
||||||
++errDist;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dummyToken != t) {
|
|
||||||
dummyToken->kind = t->kind;
|
|
||||||
dummyToken->pos = t->pos;
|
|
||||||
dummyToken->col = t->col;
|
|
||||||
dummyToken->line = t->line;
|
|
||||||
dummyToken->next = NULL;
|
|
||||||
coco_string_delete(dummyToken->val);
|
|
||||||
dummyToken->val = coco_string_create(t->val);
|
|
||||||
t = dummyToken;
|
|
||||||
}
|
|
||||||
la = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Parser::Expect(int n) {
|
|
||||||
if (la->kind == n) {
|
|
||||||
Get();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SynErr(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Parser::ExpectWeak(int n, int follow) {
|
|
||||||
if (la->kind == n) {
|
|
||||||
Get();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SynErr(n);
|
|
||||||
while (!StartOf(follow)) {
|
|
||||||
Get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Parser::WeakSeparator(int n, int syFol, int repFol) {
|
|
||||||
if (la->kind == n) {
|
|
||||||
Get();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (StartOf(repFol)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SynErr(n);
|
|
||||||
while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) {
|
|
||||||
Get();
|
|
||||||
}
|
|
||||||
return StartOf(syFol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Parser::calcEntry() {
|
|
||||||
val = 0;
|
|
||||||
if (debug){Info<<"start val pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
if (la->kind == 5) {
|
|
||||||
Get();
|
|
||||||
Expr(val);
|
|
||||||
Expect(6);
|
|
||||||
if (debug){
|
|
||||||
Info<<"end {} at pos:"<< t->pos
|
|
||||||
<<" val:"<< t->val
|
|
||||||
<<" len:"<< coco_string_length(t->val)
|
|
||||||
<<" la pos:"<< la->pos << nl;
|
|
||||||
}
|
|
||||||
// reposition to immediately after the closing '}'
|
|
||||||
scanner->buffer->SetPos
|
|
||||||
(
|
|
||||||
t->pos + coco_string_length(t->val)
|
|
||||||
);
|
|
||||||
|
|
||||||
} else if (StartOf(1)) {
|
|
||||||
Expr(val);
|
|
||||||
Expect(0);
|
|
||||||
} else SynErr(14);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::Expr(scalar& val) {
|
|
||||||
scalar val2 = 0;
|
|
||||||
if (debug) {Info<<"Expr:"<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
Term(val);
|
|
||||||
while (la->kind == 7 || la->kind == 8) {
|
|
||||||
if (la->kind == 7) {
|
|
||||||
Get();
|
|
||||||
Term(val2);
|
|
||||||
if (debug) {Info<<"+Term:"<<val2 << " pos:"<< t->pos << nl;}
|
|
||||||
val += val2;
|
|
||||||
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Get();
|
|
||||||
Term(val2);
|
|
||||||
if (debug) {Info<<"-Term:"<<val2<< " pos:"<< t->pos << nl;}
|
|
||||||
val -= val2;
|
|
||||||
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::Term(scalar& val) {
|
|
||||||
scalar val2 = 0;
|
|
||||||
if (debug) {Info<<"Term:"<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
Factor(val);
|
|
||||||
while (la->kind == 9 || la->kind == 10) {
|
|
||||||
if (la->kind == 9) {
|
|
||||||
Get();
|
|
||||||
Factor(val2);
|
|
||||||
if (debug) {Info<<"*Factor:"<<val2<< " pos:"<< t->pos << nl;}
|
|
||||||
val *= val2;
|
|
||||||
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Get();
|
|
||||||
Factor(val2);
|
|
||||||
if (debug) {Info<<"/Factor:"<<val2<< " pos:"<< t->pos << nl;}
|
|
||||||
val /= val2;
|
|
||||||
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::Factor(scalar& val) {
|
|
||||||
if (la->kind == 3) {
|
|
||||||
Get();
|
|
||||||
val = getDictLookup();
|
|
||||||
if (debug) {Info<<"lookup:"<<val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
} else if (la->kind == 4) {
|
|
||||||
Get();
|
|
||||||
val = getScalar();
|
|
||||||
if (debug) {Info<<"got num:"<<val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
} else if (la->kind == 8) {
|
|
||||||
Get();
|
|
||||||
Expect(11);
|
|
||||||
Expr(val);
|
|
||||||
Expect(12);
|
|
||||||
val = -val;
|
|
||||||
if (debug) {Info<<"inv:"<<val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
} else if (la->kind == 11) {
|
|
||||||
Get();
|
|
||||||
Expr(val);
|
|
||||||
Expect(12);
|
|
||||||
if (debug){Info<<"got Expr:"<<val<< " pos:"<< t->pos << nl;}
|
|
||||||
|
|
||||||
} else SynErr(15);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Parser::Parse() {
|
|
||||||
t = NULL;
|
|
||||||
if (dummyToken) { // safety: someone might call Parse() twice
|
|
||||||
delete dummyToken;
|
|
||||||
}
|
|
||||||
la = dummyToken = new Token();
|
|
||||||
la->val = coco_string_create(L"Dummy Token");
|
|
||||||
Get();
|
|
||||||
calcEntry();
|
|
||||||
// let grammar deal with end-of-file expectations
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Parser::Parser(Scanner* scan, Errors* err)
|
|
||||||
:
|
|
||||||
dummyToken(NULL),
|
|
||||||
deleteErrorsDestruct_(!err),
|
|
||||||
errDist(minErrDist),
|
|
||||||
scanner(scan),
|
|
||||||
errors(err),
|
|
||||||
t(NULL),
|
|
||||||
la(NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!errors) { // add in default error handling
|
|
||||||
errors = new Errors();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Parser::StartOf(int s) {
|
|
||||||
const bool T = true;
|
|
||||||
const bool x = false;
|
|
||||||
|
|
||||||
static bool set[2][15] = {
|
|
||||||
{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
|
|
||||||
{x,x,x,T, T,x,x,x, T,x,x,T, x,x,x}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return set[s][la->kind];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Parser::~Parser() {
|
|
||||||
if (deleteErrorsDestruct_) { // delete default error handling
|
|
||||||
delete errors;
|
|
||||||
}
|
|
||||||
delete dummyToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Errors Implementation
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Errors::Errors()
|
|
||||||
:
|
|
||||||
count(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
Errors::~Errors()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
void Errors::clear() {
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wchar_t* Errors::strerror(int n)
|
|
||||||
{
|
|
||||||
wchar_t* s;
|
|
||||||
switch (n) {
|
|
||||||
case 0: s = coco_string_create(L"EOF expected"); break;
|
|
||||||
case 1: s = coco_string_create(L"ident expected"); break;
|
|
||||||
case 2: s = coco_string_create(L"string expected"); break;
|
|
||||||
case 3: s = coco_string_create(L"variable expected"); break;
|
|
||||||
case 4: s = coco_string_create(L"number expected"); break;
|
|
||||||
case 5: s = coco_string_create(L"\"{\" expected"); break;
|
|
||||||
case 6: s = coco_string_create(L"\"}\" expected"); break;
|
|
||||||
case 7: s = coco_string_create(L"\"+\" expected"); break;
|
|
||||||
case 8: s = coco_string_create(L"\"-\" expected"); break;
|
|
||||||
case 9: s = coco_string_create(L"\"*\" expected"); break;
|
|
||||||
case 10: s = coco_string_create(L"\"/\" expected"); break;
|
|
||||||
case 11: s = coco_string_create(L"\"(\" expected"); break;
|
|
||||||
case 12: s = coco_string_create(L"\")\" expected"); break;
|
|
||||||
case 13: s = coco_string_create(L"??? expected"); break;
|
|
||||||
case 14: s = coco_string_create(L"invalid calcEntry"); break;
|
|
||||||
case 15: s = coco_string_create(L"invalid Factor"); break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
wchar_t format[20];
|
|
||||||
coco_swprintf(format, 20, L"error %d", n);
|
|
||||||
s = coco_string_create(format);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Errors::Warning(const wchar_t* msg) {
|
|
||||||
wprintf(L"%ls\n", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Errors::Warning(int line, int col, const wchar_t* msg) {
|
|
||||||
wprintf(L"-- line %d col %d: %ls\n", line, col, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Errors::Error(int line, int col, const wchar_t* msg) {
|
|
||||||
wprintf(L"-- line %d col %d: %ls\n", line, col, msg);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Errors::SynErr(int line, int col, int n) {
|
|
||||||
wchar_t* msg = this->strerror(n);
|
|
||||||
this->Error(line, col, msg);
|
|
||||||
coco_string_delete(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Errors::Exception(const wchar_t* msg) {
|
|
||||||
wprintf(L"%ls", msg);
|
|
||||||
::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,206 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef COCO_calcEntryPARSER_H__
|
|
||||||
#define COCO_calcEntryPARSER_H__
|
|
||||||
|
|
||||||
#include "dictionary.H"
|
|
||||||
#include "scalar.H"
|
|
||||||
#include "error.H"
|
|
||||||
#include "wchar.H"
|
|
||||||
|
|
||||||
|
|
||||||
#include "calcEntryScanner.h"
|
|
||||||
|
|
||||||
namespace Foam {
|
|
||||||
namespace functionEntries {
|
|
||||||
namespace calcEntryInternal {
|
|
||||||
|
|
||||||
|
|
||||||
//! Parser error handing
|
|
||||||
class Errors {
|
|
||||||
public:
|
|
||||||
int count; //!< The number of errors detected
|
|
||||||
|
|
||||||
//! Allocate and return a string describing the given error code.
|
|
||||||
/** It is the responsibility of the caller to free this string,
|
|
||||||
* eg, with coco_string_delete()
|
|
||||||
*/
|
|
||||||
static wchar_t* strerror(int n);
|
|
||||||
|
|
||||||
Errors(); //!< Construct null - start with no errors
|
|
||||||
virtual ~Errors(); //!< Destructor
|
|
||||||
virtual void clear(); //!< Clear the error count
|
|
||||||
|
|
||||||
//! Handle a general warning 'msg'
|
|
||||||
virtual void Warning(const wchar_t* msg);
|
|
||||||
//! Handle a general warning 'msg'
|
|
||||||
virtual void Warning(int line, int col, const wchar_t* msg);
|
|
||||||
//! Handle general error 'msg' (eg, a semantic error)
|
|
||||||
virtual void Error(int line, int col, const wchar_t* msg);
|
|
||||||
//! Handle syntax error 'n', uses strerror for the message, calls Error()
|
|
||||||
virtual void SynErr(int line, int col, int n);
|
|
||||||
//! Handle a general exception 'msg'
|
|
||||||
virtual void Exception(const wchar_t* msg);
|
|
||||||
|
|
||||||
}; // Errors
|
|
||||||
|
|
||||||
|
|
||||||
//! A Coco/R Parser
|
|
||||||
class Parser {
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
_EOF=0,
|
|
||||||
_ident=1,
|
|
||||||
_string=2,
|
|
||||||
_variable=3,
|
|
||||||
_number=4,
|
|
||||||
};
|
|
||||||
static const int maxT = 13;
|
|
||||||
|
|
||||||
static const int minErrDist = 2; //!< min. distance before reporting errors
|
|
||||||
|
|
||||||
Token *dummyToken;
|
|
||||||
bool deleteErrorsDestruct_; //!< delete the 'errors' member in destructor
|
|
||||||
int errDist;
|
|
||||||
|
|
||||||
void SynErr(int n); //!< Handle syntax error 'n'
|
|
||||||
void Get();
|
|
||||||
void Expect(int n);
|
|
||||||
bool StartOf(int s);
|
|
||||||
void ExpectWeak(int n, int follow);
|
|
||||||
bool WeakSeparator(int n, int syFol, int repFol);
|
|
||||||
|
|
||||||
public:
|
|
||||||
Scanner *scanner;
|
|
||||||
Errors *errors;
|
|
||||||
|
|
||||||
Token *t; //!< last recognized token
|
|
||||||
Token *la; //!< lookahead token
|
|
||||||
|
|
||||||
static const int debug = 0;
|
|
||||||
|
|
||||||
//! The parent dictionary
|
|
||||||
mutable dictionary* dict_;
|
|
||||||
|
|
||||||
//! Track that parent dictionary was set
|
|
||||||
bool hasDict_;
|
|
||||||
|
|
||||||
//! The calculation result
|
|
||||||
scalar val;
|
|
||||||
|
|
||||||
|
|
||||||
//! token -> scalar
|
|
||||||
scalar getScalar() const
|
|
||||||
{
|
|
||||||
return coco_string_toDouble(t->val);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! token -> string
|
|
||||||
std::string getString() const
|
|
||||||
{
|
|
||||||
char* str = coco_string_create_char(t->val);
|
|
||||||
std::string s(str);
|
|
||||||
coco_string_delete(str);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! attach a dictionary
|
|
||||||
void dict(const dictionary& dict)
|
|
||||||
{
|
|
||||||
dict_ = const_cast<dictionary*>(&dict);
|
|
||||||
hasDict_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! lookup dictionary entry
|
|
||||||
scalar getDictLookup() const
|
|
||||||
{
|
|
||||||
scalar dictValue = 0;
|
|
||||||
|
|
||||||
if (!hasDict_)
|
|
||||||
{
|
|
||||||
FatalErrorIn
|
|
||||||
(
|
|
||||||
"calcEntry::getDictEntry() const"
|
|
||||||
) << "No dictionary attached!"
|
|
||||||
<< exit(FatalError);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* chars = coco_string_create_char
|
|
||||||
(
|
|
||||||
t->val,
|
|
||||||
1,
|
|
||||||
(coco_string_length(t->val) - 1)
|
|
||||||
);
|
|
||||||
word keyword(chars);
|
|
||||||
coco_string_delete(chars);
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<<"lookup: " << keyword << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar Result() const
|
|
||||||
{
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//! Construct for the specified scanner
|
|
||||||
/**
|
|
||||||
* Use the default error handling, or optionally provide an error
|
|
||||||
* handler, which will not be deleted upon destruction.
|
|
||||||
*/
|
|
||||||
Parser(Scanner* scan, Errors* err = 0);
|
|
||||||
~Parser(); //!< Destructor - cleanup errors and dummyToken
|
|
||||||
void SemErr(const wchar_t* msg); //!< Handle semantic error
|
|
||||||
|
|
||||||
void calcEntry();
|
|
||||||
void Expr(scalar& val);
|
|
||||||
void Term(scalar& val);
|
|
||||||
void Factor(scalar& val);
|
|
||||||
|
|
||||||
void Parse(); //!< Execute the parse operation
|
|
||||||
|
|
||||||
}; // end Parser
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
|
|
||||||
#endif // COCO_calcEntryPARSER_H__
|
|
||||||
|
|
||||||
@ -1,932 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "calcEntryScanner.h"
|
|
||||||
|
|
||||||
// values for the file stream buffering
|
|
||||||
#define MIN_BUFFER_LENGTH 1024 // 1KB
|
|
||||||
#define MAX_BUFFER_LENGTH (64*MIN_BUFFER_LENGTH) // 64KB
|
|
||||||
// value for the heap management
|
|
||||||
#define HEAP_BLOCK_SIZE (64*1024) // 64KB
|
|
||||||
|
|
||||||
|
|
||||||
namespace Foam {
|
|
||||||
namespace functionEntries {
|
|
||||||
namespace calcEntryInternal {
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * Wide Character String Routines * * * * * * * * * * * //
|
|
||||||
|
|
||||||
// string handling, wide character
|
|
||||||
|
|
||||||
wchar_t* coco_string_create(const wchar_t* str) {
|
|
||||||
int len = coco_string_length(str);
|
|
||||||
wchar_t* dest = new wchar_t[len + 1];
|
|
||||||
if (len) {
|
|
||||||
wcsncpy(dest, str, len);
|
|
||||||
}
|
|
||||||
dest[len] = 0;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t* coco_string_create(const wchar_t* str, int index, int length) {
|
|
||||||
int len = coco_string_length(str);
|
|
||||||
if (len) {
|
|
||||||
len = length;
|
|
||||||
}
|
|
||||||
wchar_t* dest = new wchar_t[len + 1];
|
|
||||||
if (len) {
|
|
||||||
wcsncpy(dest, &(str[index]), len);
|
|
||||||
}
|
|
||||||
dest[len] = 0;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wchar_t* coco_string_create_lower(const wchar_t* str) {
|
|
||||||
if (!str) { return NULL; }
|
|
||||||
return coco_string_create_lower(str, 0, wcslen(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wchar_t* coco_string_create_lower(const wchar_t* str, int index, int len) {
|
|
||||||
if (!str) { return NULL; }
|
|
||||||
wchar_t* dest = new wchar_t[len + 1];
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
const wchar_t ch = str[index + i];
|
|
||||||
if ((L'A' <= ch) && (ch <= L'Z')) {
|
|
||||||
dest[i] = ch - (L'A' - L'a');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dest[i] = ch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dest[len] = L'\0';
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2) {
|
|
||||||
int str1Len = coco_string_length(str1);
|
|
||||||
int str2Len = coco_string_length(str2);
|
|
||||||
|
|
||||||
wchar_t* dest = new wchar_t[str1Len + str2Len + 1];
|
|
||||||
|
|
||||||
if (str1Len) { wcscpy(dest, str1); }
|
|
||||||
if (str2Len) { wcscpy(dest + str1Len, str2); }
|
|
||||||
|
|
||||||
dest[str1Len + str2Len] = 0;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t ch) {
|
|
||||||
int len = coco_string_length(str1);
|
|
||||||
wchar_t* dest = new wchar_t[len + 2];
|
|
||||||
wcsncpy(dest, str1, len); // or use if (len) { wcscpy(dest, str1); }
|
|
||||||
dest[len] = ch;
|
|
||||||
dest[len + 1] = 0;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
void coco_string_delete(wchar_t* &str) {
|
|
||||||
delete [] str;
|
|
||||||
str = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int coco_string_length(const wchar_t* str) {
|
|
||||||
return str ? wcslen(str) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool coco_string_endswith(const wchar_t* str, const wchar_t* endstr) {
|
|
||||||
int strLen = wcslen(str);
|
|
||||||
int endLen = wcslen(endstr);
|
|
||||||
return (endLen <= strLen) && (wcscmp(str + strLen - endLen, endstr) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int coco_string_indexof(const wchar_t* str, const wchar_t ch) {
|
|
||||||
const wchar_t* fnd = wcschr(str, ch);
|
|
||||||
return fnd ? (fnd - str) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int coco_string_lastindexof(const wchar_t* str, const wchar_t ch) {
|
|
||||||
const wchar_t* fnd = wcsrchr(str, ch);
|
|
||||||
return fnd ? (fnd - str) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void coco_string_merge(wchar_t* &dest, const wchar_t* str) {
|
|
||||||
if (!str) { return; }
|
|
||||||
wchar_t* newstr = coco_string_create_append(dest, str);
|
|
||||||
delete [] dest;
|
|
||||||
dest = newstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool coco_string_equal(const wchar_t* str1, const wchar_t* str2) {
|
|
||||||
return wcscmp(str1, str2) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int coco_string_compareto(const wchar_t* str1, const wchar_t* str2) {
|
|
||||||
return wcscmp(str1, str2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int coco_string_hash(const wchar_t* str) {
|
|
||||||
int h = 0;
|
|
||||||
if (!str) { return 0; }
|
|
||||||
while (*str != 0) {
|
|
||||||
h = (h * 7) ^ *str;
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
if (h < 0) { h = -h; }
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
double coco_string_toDouble(const wchar_t* str)
|
|
||||||
{
|
|
||||||
return str ? wcstod(str, NULL) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float coco_string_toFloat(const wchar_t* str)
|
|
||||||
{
|
|
||||||
return str ? wcstof(str, NULL) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// string handling, byte character
|
|
||||||
//
|
|
||||||
|
|
||||||
wchar_t* coco_string_create(const char* str) {
|
|
||||||
int len = str ? strlen(str) : 0;
|
|
||||||
wchar_t* dest = new wchar_t[len + 1];
|
|
||||||
for (int i = 0; i < len; ++i) {
|
|
||||||
dest[i] = wchar_t(str[i]);
|
|
||||||
}
|
|
||||||
dest[len] = 0;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t* coco_string_create(const char* str, int index, int length) {
|
|
||||||
int len = str ? length : 0;
|
|
||||||
wchar_t* dest = new wchar_t[len + 1];
|
|
||||||
for (int i = 0; i < len; ++i) {
|
|
||||||
dest[i] = wchar_t(str[index + i]);
|
|
||||||
}
|
|
||||||
dest[len] = 0;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char* coco_string_create_char(const wchar_t* str) {
|
|
||||||
int len = coco_string_length(str);
|
|
||||||
char *dest = new char[len + 1];
|
|
||||||
for (int i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
dest[i] = char(str[i]);
|
|
||||||
}
|
|
||||||
dest[len] = 0;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* coco_string_create_char(const wchar_t* str, int index, int length) {
|
|
||||||
int len = coco_string_length(str);
|
|
||||||
if (len) {
|
|
||||||
len = length;
|
|
||||||
}
|
|
||||||
char *dest = new char[len + 1];
|
|
||||||
for (int i = 0; i < len; ++i) {
|
|
||||||
dest[i] = char(str[index + i]);
|
|
||||||
}
|
|
||||||
dest[len] = 0;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void coco_string_delete(char* &str) {
|
|
||||||
delete [] str;
|
|
||||||
str = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
double coco_string_toDouble(const char* str)
|
|
||||||
{
|
|
||||||
return str ? strtod(str, NULL) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float coco_string_toFloat(const char* str)
|
|
||||||
{
|
|
||||||
return str ? strtof(str, NULL) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
Token::Token()
|
|
||||||
:
|
|
||||||
kind(0),
|
|
||||||
pos(0),
|
|
||||||
col(0),
|
|
||||||
line(0),
|
|
||||||
val(NULL),
|
|
||||||
next(NULL)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// Note: this delete may not be correct if the token was actually
|
|
||||||
// allocated by the internal heap mechanism
|
|
||||||
Token::~Token() {
|
|
||||||
coco_string_delete(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Buffer Implementation
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Buffer::Buffer(Buffer* b)
|
|
||||||
:
|
|
||||||
buf(b->buf),
|
|
||||||
bufCapacity(b->bufCapacity),
|
|
||||||
bufLen(b->bufLen),
|
|
||||||
bufPos(b->bufPos),
|
|
||||||
bufStart(b->bufStart),
|
|
||||||
fileLen(b->fileLen),
|
|
||||||
cStream(b->cStream),
|
|
||||||
stdStream(b->stdStream),
|
|
||||||
isUserStream_(b->isUserStream_)
|
|
||||||
{
|
|
||||||
// avoid accidental deletion on any of these members
|
|
||||||
b->buf = NULL;
|
|
||||||
b->cStream = NULL;
|
|
||||||
b->stdStream = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Buffer::Buffer(FILE* istr, bool isUserStream)
|
|
||||||
:
|
|
||||||
buf(NULL),
|
|
||||||
bufCapacity(0),
|
|
||||||
bufLen(0),
|
|
||||||
bufPos(0),
|
|
||||||
bufStart(0),
|
|
||||||
fileLen(0),
|
|
||||||
cStream(istr),
|
|
||||||
stdStream(NULL),
|
|
||||||
isUserStream_(isUserStream)
|
|
||||||
{
|
|
||||||
// ensure binary read on windows
|
|
||||||
#if _MSC_VER >= 1300
|
|
||||||
_setmode(_fileno(cStream), _O_BINARY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (CanSeek()) {
|
|
||||||
fseek(cStream, 0, SEEK_END);
|
|
||||||
fileLen = ftell(cStream);
|
|
||||||
fseek(cStream, 0, SEEK_SET);
|
|
||||||
bufLen = (fileLen < MAX_BUFFER_LENGTH) ? fileLen : MAX_BUFFER_LENGTH;
|
|
||||||
bufStart = INT_MAX; // nothing in the buffer so far
|
|
||||||
}
|
|
||||||
|
|
||||||
bufCapacity = (bufLen > 0) ? bufLen : MIN_BUFFER_LENGTH;
|
|
||||||
buf = new unsigned char[bufCapacity];
|
|
||||||
if (fileLen > 0) SetPos(0); // setup buffer to position 0 (start)
|
|
||||||
else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
|
|
||||||
if (bufLen == fileLen && CanSeek()) Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Buffer::Buffer(std::istream* istr, bool isUserStream)
|
|
||||||
:
|
|
||||||
buf(NULL),
|
|
||||||
bufCapacity(0),
|
|
||||||
bufLen(0),
|
|
||||||
bufPos(0),
|
|
||||||
bufStart(0),
|
|
||||||
fileLen(0),
|
|
||||||
cStream(NULL),
|
|
||||||
stdStream(istr),
|
|
||||||
isUserStream_(isUserStream)
|
|
||||||
{
|
|
||||||
// ensure binary read on windows
|
|
||||||
#if _MSC_VER >= 1300
|
|
||||||
// TODO
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Buffer::Buffer(std::string& str)
|
|
||||||
:
|
|
||||||
buf(NULL),
|
|
||||||
bufCapacity(0),
|
|
||||||
bufLen(0),
|
|
||||||
bufPos(0),
|
|
||||||
bufStart(0),
|
|
||||||
fileLen(0),
|
|
||||||
cStream(NULL),
|
|
||||||
stdStream(new std::istringstream(str)),
|
|
||||||
isUserStream_(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
Buffer::Buffer(const unsigned char* chars, int len)
|
|
||||||
:
|
|
||||||
buf(new unsigned char[len]),
|
|
||||||
bufCapacity(len),
|
|
||||||
bufLen(len),
|
|
||||||
bufPos(0),
|
|
||||||
bufStart(0),
|
|
||||||
fileLen(len),
|
|
||||||
cStream(NULL),
|
|
||||||
stdStream(NULL),
|
|
||||||
isUserStream_(false)
|
|
||||||
{
|
|
||||||
memcpy(this->buf, chars, len*sizeof(char));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Buffer::Buffer(const char* chars, int len)
|
|
||||||
:
|
|
||||||
buf(new unsigned char[len]),
|
|
||||||
bufCapacity(len),
|
|
||||||
bufLen(len),
|
|
||||||
bufPos(0),
|
|
||||||
bufStart(0),
|
|
||||||
fileLen(len),
|
|
||||||
cStream(NULL),
|
|
||||||
stdStream(NULL),
|
|
||||||
isUserStream_(false)
|
|
||||||
{
|
|
||||||
memcpy(this->buf, chars, len*sizeof(char));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Buffer::~Buffer() {
|
|
||||||
Close();
|
|
||||||
if (buf) {
|
|
||||||
delete [] buf;
|
|
||||||
buf = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Buffer::Close() {
|
|
||||||
if (!isUserStream_) {
|
|
||||||
if (cStream) {
|
|
||||||
fclose(cStream);
|
|
||||||
cStream = NULL;
|
|
||||||
}
|
|
||||||
else if (stdStream) {
|
|
||||||
delete stdStream;
|
|
||||||
stdStream = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Buffer::Read() {
|
|
||||||
if (stdStream)
|
|
||||||
{
|
|
||||||
int ch = stdStream->get();
|
|
||||||
if (stdStream->eof())
|
|
||||||
{
|
|
||||||
return EoF;
|
|
||||||
}
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bufPos < bufLen) {
|
|
||||||
return buf[bufPos++];
|
|
||||||
} else if (GetPos() < fileLen) {
|
|
||||||
SetPos(GetPos()); // shift buffer start to Pos
|
|
||||||
return buf[bufPos++];
|
|
||||||
} else if (cStream && !CanSeek() && (ReadNextStreamChunk() > 0)) {
|
|
||||||
return buf[bufPos++];
|
|
||||||
} else {
|
|
||||||
return EoF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int UTF8Buffer::Read() {
|
|
||||||
int ch;
|
|
||||||
do {
|
|
||||||
ch = Buffer::Read();
|
|
||||||
// until we find a utf8 start (0xxxxxxx or 11xxxxxx)
|
|
||||||
} while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EoF));
|
|
||||||
if (ch < 128 || ch == EoF) {
|
|
||||||
// nothing to do, first 127 chars are the same in ascii and utf8
|
|
||||||
// 0xxxxxxx or end of file character
|
|
||||||
} else if ((ch & 0xF0) == 0xF0) {
|
|
||||||
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
||||||
int c1 = ch & 0x07; ch = Buffer::Read();
|
|
||||||
int c2 = ch & 0x3F; ch = Buffer::Read();
|
|
||||||
int c3 = ch & 0x3F; ch = Buffer::Read();
|
|
||||||
int c4 = ch & 0x3F;
|
|
||||||
ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
|
|
||||||
} else if ((ch & 0xE0) == 0xE0) {
|
|
||||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
|
||||||
int c1 = ch & 0x0F; ch = Buffer::Read();
|
|
||||||
int c2 = ch & 0x3F; ch = Buffer::Read();
|
|
||||||
int c3 = ch & 0x3F;
|
|
||||||
ch = (((c1 << 6) | c2) << 6) | c3;
|
|
||||||
} else if ((ch & 0xC0) == 0xC0) {
|
|
||||||
// 110xxxxx 10xxxxxx
|
|
||||||
int c1 = ch & 0x1F; ch = Buffer::Read();
|
|
||||||
int c2 = ch & 0x3F;
|
|
||||||
ch = (c1 << 6) | c2;
|
|
||||||
}
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Buffer::Peek() {
|
|
||||||
int curPos = GetPos();
|
|
||||||
int ch = Read();
|
|
||||||
SetPos(curPos);
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Buffer::GetPos() const {
|
|
||||||
if (stdStream)
|
|
||||||
{
|
|
||||||
return stdStream->tellg();
|
|
||||||
}
|
|
||||||
|
|
||||||
return bufPos + bufStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Buffer::SetPos(int value) {
|
|
||||||
if (stdStream)
|
|
||||||
{
|
|
||||||
stdStream->seekg(value, std::ios::beg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((value >= fileLen) && cStream && !CanSeek()) {
|
|
||||||
// Wanted position is after buffer and the stream
|
|
||||||
// is not seek-able e.g. network or console,
|
|
||||||
// thus we have to read the stream manually till
|
|
||||||
// the wanted position is in sight.
|
|
||||||
while ((value >= fileLen) && (ReadNextStreamChunk() > 0))
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((value < 0) || (value > fileLen)) {
|
|
||||||
wprintf(L"--- buffer out of bounds access, position: %d\n", value);
|
|
||||||
::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((value >= bufStart) && (value < (bufStart + bufLen))) { // already in buffer
|
|
||||||
bufPos = value - bufStart;
|
|
||||||
} else if (cStream) { // must be swapped in
|
|
||||||
fseek(cStream, value, SEEK_SET);
|
|
||||||
bufLen = fread(buf, sizeof(char), bufCapacity, cStream);
|
|
||||||
bufStart = value; bufPos = 0;
|
|
||||||
} else {
|
|
||||||
bufPos = fileLen - bufStart; // make Pos return fileLen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Read the next chunk of bytes from the stream, increases the buffer
|
|
||||||
// if needed and updates the fields fileLen and bufLen.
|
|
||||||
// Returns the number of bytes read.
|
|
||||||
int Buffer::ReadNextStreamChunk() {
|
|
||||||
int freeLen = bufCapacity - bufLen;
|
|
||||||
if (freeLen == 0) {
|
|
||||||
// in the case of a growing input stream
|
|
||||||
// we can neither seek in the stream, nor can we
|
|
||||||
// foresee the maximum length, thus we must adapt
|
|
||||||
// the buffer size on demand.
|
|
||||||
bufCapacity = bufLen * 2;
|
|
||||||
unsigned char *newBuf = new unsigned char[bufCapacity];
|
|
||||||
memcpy(newBuf, buf, bufLen*sizeof(char));
|
|
||||||
delete [] buf;
|
|
||||||
buf = newBuf;
|
|
||||||
freeLen = bufLen;
|
|
||||||
}
|
|
||||||
int read = fread(buf + bufLen, sizeof(char), freeLen, cStream);
|
|
||||||
if (read > 0) {
|
|
||||||
fileLen = bufLen = (bufLen + read);
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
// end of stream reached
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Buffer::CanSeek() const {
|
|
||||||
return cStream && (ftell(cStream) != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Scanner Implementation
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Scanner::Scanner(FILE* istr)
|
|
||||||
:
|
|
||||||
buffer(new Buffer(istr, true))
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Scanner::Scanner(std::istream& istr)
|
|
||||||
:
|
|
||||||
buffer(new Buffer(&istr, true))
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Scanner::Scanner(const wchar_t* fileName) {
|
|
||||||
char *chFileName = coco_string_create_char(fileName);
|
|
||||||
FILE* istr;
|
|
||||||
if ((istr = fopen(chFileName, "rb")) == NULL) {
|
|
||||||
wprintf(L"--- Cannot open file %ls\n", fileName);
|
|
||||||
::exit(1);
|
|
||||||
}
|
|
||||||
coco_string_delete(chFileName);
|
|
||||||
buffer = new Buffer(istr, false);
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Scanner::Scanner(const unsigned char* buf, int len)
|
|
||||||
:
|
|
||||||
buffer(new Buffer(buf, len))
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Scanner::Scanner(const char* buf, int len)
|
|
||||||
:
|
|
||||||
buffer(new Buffer(buf, len))
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Scanner::~Scanner() {
|
|
||||||
char* cur = reinterpret_cast<char*>(firstHeap);
|
|
||||||
|
|
||||||
while (cur) {
|
|
||||||
cur = *(reinterpret_cast<char**>(cur + HEAP_BLOCK_SIZE));
|
|
||||||
free(firstHeap);
|
|
||||||
firstHeap = cur;
|
|
||||||
}
|
|
||||||
delete [] tval;
|
|
||||||
delete buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Scanner::Init() {
|
|
||||||
for (int i = 65; i <= 90; ++i) start.set(i, 1);
|
|
||||||
for (int i = 97; i <= 122; ++i) start.set(i, 1);
|
|
||||||
for (int i = 36; i <= 36; ++i) start.set(i, 5);
|
|
||||||
start.set(45, 20);
|
|
||||||
for (int i = 48; i <= 57; ++i) start.set(i, 9);
|
|
||||||
start.set(34, 2);
|
|
||||||
start.set(46, 7);
|
|
||||||
start.set(123, 14);
|
|
||||||
start.set(125, 15);
|
|
||||||
start.set(43, 21);
|
|
||||||
start.set(42, 16);
|
|
||||||
start.set(47, 17);
|
|
||||||
start.set(40, 18);
|
|
||||||
start.set(41, 19);
|
|
||||||
start.set(Buffer::EoF, -1);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tvalLength = 128;
|
|
||||||
tval = new wchar_t[tvalLength]; // text of current token
|
|
||||||
|
|
||||||
// HEAP_BLOCK_SIZE byte heap + pointer to next heap block
|
|
||||||
heap = malloc(HEAP_BLOCK_SIZE + sizeof(void*));
|
|
||||||
firstHeap = heap;
|
|
||||||
heapEnd =
|
|
||||||
reinterpret_cast<void**>
|
|
||||||
(reinterpret_cast<char*>(heap) + HEAP_BLOCK_SIZE);
|
|
||||||
*heapEnd = 0;
|
|
||||||
heapTop = heap;
|
|
||||||
if (sizeof(Token) > HEAP_BLOCK_SIZE) {
|
|
||||||
wprintf(L"--- Too small HEAP_BLOCK_SIZE\n");
|
|
||||||
::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = -1; line = 1; col = 0;
|
|
||||||
oldEols = 0;
|
|
||||||
NextCh();
|
|
||||||
if (ch == 0xEF) { // check optional byte order mark for UTF-8
|
|
||||||
NextCh(); int ch1 = ch;
|
|
||||||
NextCh(); int ch2 = ch;
|
|
||||||
if (ch1 != 0xBB || ch2 != 0xBF) {
|
|
||||||
wprintf(L"Illegal byte order mark at start of file");
|
|
||||||
::exit(1);
|
|
||||||
}
|
|
||||||
Buffer *oldBuf = buffer;
|
|
||||||
buffer = new UTF8Buffer(buffer); col = 0;
|
|
||||||
delete oldBuf; oldBuf = NULL;
|
|
||||||
NextCh();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pt = tokens = CreateToken(); // first token is a dummy
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Scanner::NextCh() {
|
|
||||||
if (oldEols > 0) {
|
|
||||||
ch = EOL;
|
|
||||||
oldEols--;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pos = buffer->GetPos();
|
|
||||||
ch = buffer->Read(); col++;
|
|
||||||
// replace isolated '\r' by '\n' in order to make
|
|
||||||
// eol handling uniform across Windows, Unix and Mac
|
|
||||||
if (ch == L'\r' && buffer->Peek() != L'\n') ch = EOL;
|
|
||||||
if (ch == EOL) { line++; col = 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Scanner::AddCh() {
|
|
||||||
if (tlen >= tvalLength) {
|
|
||||||
tvalLength *= 2;
|
|
||||||
wchar_t *newBuf = new wchar_t[tvalLength];
|
|
||||||
memcpy(newBuf, tval, tlen*sizeof(wchar_t));
|
|
||||||
delete [] tval;
|
|
||||||
tval = newBuf;
|
|
||||||
}
|
|
||||||
if (ch != Buffer::EoF) {
|
|
||||||
tval[tlen++] = ch;
|
|
||||||
NextCh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Scanner::Comment0() {
|
|
||||||
int level = 1, pos0 = pos, line0 = line, col0 = col;
|
|
||||||
NextCh();
|
|
||||||
if (ch == L'/') {
|
|
||||||
NextCh();
|
|
||||||
for(;;) {
|
|
||||||
if (ch == 10) {
|
|
||||||
level--;
|
|
||||||
if (level == 0) { oldEols = line - line0; NextCh(); return true; }
|
|
||||||
NextCh();
|
|
||||||
} else if (ch == buffer->EoF) return false;
|
|
||||||
else NextCh();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buffer->SetPos(pos0); NextCh(); line = line0; col = col0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scanner::Comment1() {
|
|
||||||
int level = 1, pos0 = pos, line0 = line, col0 = col;
|
|
||||||
NextCh();
|
|
||||||
if (ch == L'*') {
|
|
||||||
NextCh();
|
|
||||||
for(;;) {
|
|
||||||
if (ch == L'*') {
|
|
||||||
NextCh();
|
|
||||||
if (ch == L'/') {
|
|
||||||
level--;
|
|
||||||
if (level == 0) { oldEols = line - line0; NextCh(); return true; }
|
|
||||||
NextCh();
|
|
||||||
}
|
|
||||||
} else if (ch == L'/') {
|
|
||||||
NextCh();
|
|
||||||
if (ch == L'*') {
|
|
||||||
level++; NextCh();
|
|
||||||
}
|
|
||||||
} else if (ch == buffer->EoF) return false;
|
|
||||||
else NextCh();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buffer->SetPos(pos0); NextCh(); line = line0; col = col0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Scanner::CreateHeapBlock() {
|
|
||||||
char* cur = reinterpret_cast<char*>(firstHeap);
|
|
||||||
|
|
||||||
// release unused blocks
|
|
||||||
while
|
|
||||||
(
|
|
||||||
(reinterpret_cast<char*>(tokens) < cur)
|
|
||||||
|| (reinterpret_cast<char*>(tokens) > (cur + HEAP_BLOCK_SIZE))
|
|
||||||
) {
|
|
||||||
cur = *(reinterpret_cast<char**>(cur + HEAP_BLOCK_SIZE));
|
|
||||||
free(firstHeap);
|
|
||||||
firstHeap = cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HEAP_BLOCK_SIZE byte heap + pointer to next heap block
|
|
||||||
void* newHeap = malloc(HEAP_BLOCK_SIZE + sizeof(void*));
|
|
||||||
*heapEnd = newHeap;
|
|
||||||
heapEnd =
|
|
||||||
reinterpret_cast<void**>
|
|
||||||
(reinterpret_cast<char*>(newHeap) + HEAP_BLOCK_SIZE);
|
|
||||||
*heapEnd = 0;
|
|
||||||
heap = newHeap;
|
|
||||||
heapTop = heap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Token* Scanner::CreateToken() {
|
|
||||||
const int reqMem = sizeof(Token);
|
|
||||||
if
|
|
||||||
(
|
|
||||||
(reinterpret_cast<char*>(heapTop) + reqMem)
|
|
||||||
>= reinterpret_cast<char*>(heapEnd)
|
|
||||||
) {
|
|
||||||
CreateHeapBlock();
|
|
||||||
}
|
|
||||||
// token 'occupies' heap starting at heapTop
|
|
||||||
Token* tok = reinterpret_cast<Token*>(heapTop);
|
|
||||||
// increment past this part of the heap, which is now used
|
|
||||||
heapTop =
|
|
||||||
reinterpret_cast<void*>
|
|
||||||
(reinterpret_cast<char*>(heapTop) + reqMem);
|
|
||||||
tok->val = NULL;
|
|
||||||
tok->next = NULL;
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Scanner::AppendVal(Token* tok) {
|
|
||||||
const int reqMem = (tlen + 1) * sizeof(wchar_t);
|
|
||||||
if
|
|
||||||
(
|
|
||||||
(reinterpret_cast<char*>(heapTop) + reqMem)
|
|
||||||
>= reinterpret_cast<char*>(heapEnd)
|
|
||||||
) {
|
|
||||||
if (reqMem > HEAP_BLOCK_SIZE) {
|
|
||||||
wprintf(L"--- Too long token value\n");
|
|
||||||
::exit(1);
|
|
||||||
}
|
|
||||||
CreateHeapBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// add text value from heap
|
|
||||||
tok->val = reinterpret_cast<wchar_t*>(heapTop);
|
|
||||||
|
|
||||||
// increment past this part of the heap, which is now used
|
|
||||||
heapTop =
|
|
||||||
reinterpret_cast<void*>
|
|
||||||
(reinterpret_cast<char*>(heapTop) + reqMem);
|
|
||||||
|
|
||||||
// copy the currently parsed tval into the token
|
|
||||||
wcsncpy(tok->val, tval, tlen);
|
|
||||||
tok->val[tlen] = L'\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Token* Scanner::NextToken() {
|
|
||||||
while (ch == ' ' ||
|
|
||||||
(ch >= 9 && ch <= 10) || ch == 13
|
|
||||||
) NextCh();
|
|
||||||
if ((ch == L'/' && Comment0()) || (ch == L'/' && Comment1())) return NextToken();
|
|
||||||
t = CreateToken();
|
|
||||||
t->pos = pos; t->col = col; t->line = line;
|
|
||||||
int state = start.state(ch);
|
|
||||||
tlen = 0; AddCh();
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case -1: { t->kind = eofSym; break; } // NextCh already done
|
|
||||||
case 0: { t->kind = noSym; break; } // NextCh already done
|
|
||||||
case 1:
|
|
||||||
case_1:
|
|
||||||
if ((ch >= L'0' && ch <= L':') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_1;}
|
|
||||||
else {t->kind = 1; break;}
|
|
||||||
case 2:
|
|
||||||
case_2:
|
|
||||||
if (ch <= 9 || (ch >= 11 && ch <= 12) || (ch >= 14 && ch <= L'!') || (ch >= L'#' && ch <= L'[') || (ch >= L']' && ch <= 65535)) {AddCh(); goto case_2;}
|
|
||||||
else if (ch == L'"') {AddCh(); goto case_4;}
|
|
||||||
else if (ch == 92) {AddCh(); goto case_3;}
|
|
||||||
else {t->kind = noSym; break;}
|
|
||||||
case 3:
|
|
||||||
case_3:
|
|
||||||
if ((ch >= L' ' && ch <= L'~')) {AddCh(); goto case_2;}
|
|
||||||
else {t->kind = noSym; break;}
|
|
||||||
case 4:
|
|
||||||
case_4:
|
|
||||||
{t->kind = 2; break;}
|
|
||||||
case 5:
|
|
||||||
if ((ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;}
|
|
||||||
else {t->kind = noSym; break;}
|
|
||||||
case 6:
|
|
||||||
case_6:
|
|
||||||
if ((ch >= L'0' && ch <= L':') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;}
|
|
||||||
else {t->kind = 3; break;}
|
|
||||||
case 7:
|
|
||||||
case_7:
|
|
||||||
if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_8;}
|
|
||||||
else {t->kind = noSym; break;}
|
|
||||||
case 8:
|
|
||||||
case_8:
|
|
||||||
if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_8;}
|
|
||||||
else {t->kind = 4; break;}
|
|
||||||
case 9:
|
|
||||||
case_9:
|
|
||||||
if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_9;}
|
|
||||||
else if (ch == L'E' || ch == L'e') {AddCh(); goto case_10;}
|
|
||||||
else if (ch == L'.') {AddCh(); goto case_13;}
|
|
||||||
else {t->kind = 4; break;}
|
|
||||||
case 10:
|
|
||||||
case_10:
|
|
||||||
if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;}
|
|
||||||
else if (ch == L'+' || ch == L'-') {AddCh(); goto case_11;}
|
|
||||||
else {t->kind = noSym; break;}
|
|
||||||
case 11:
|
|
||||||
case_11:
|
|
||||||
if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;}
|
|
||||||
else {t->kind = noSym; break;}
|
|
||||||
case 12:
|
|
||||||
case_12:
|
|
||||||
if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;}
|
|
||||||
else {t->kind = 4; break;}
|
|
||||||
case 13:
|
|
||||||
case_13:
|
|
||||||
if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_13;}
|
|
||||||
else if (ch == L'E' || ch == L'e') {AddCh(); goto case_10;}
|
|
||||||
else {t->kind = 4; break;}
|
|
||||||
case 14:
|
|
||||||
{t->kind = 5; break;}
|
|
||||||
case 15:
|
|
||||||
{t->kind = 6; break;}
|
|
||||||
case 16:
|
|
||||||
{t->kind = 9; break;}
|
|
||||||
case 17:
|
|
||||||
{t->kind = 10; break;}
|
|
||||||
case 18:
|
|
||||||
{t->kind = 11; break;}
|
|
||||||
case 19:
|
|
||||||
{t->kind = 12; break;}
|
|
||||||
case 20:
|
|
||||||
if (ch == L'.') {AddCh(); goto case_7;}
|
|
||||||
else {t->kind = 8; break;}
|
|
||||||
case 21:
|
|
||||||
if (ch == L'.') {AddCh(); goto case_7;}
|
|
||||||
else {t->kind = 7; break;}
|
|
||||||
|
|
||||||
}
|
|
||||||
AppendVal(t);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// get the next token (possibly a token already seen during peeking)
|
|
||||||
Token* Scanner::Scan() {
|
|
||||||
if (tokens->next == NULL) {
|
|
||||||
return pt = tokens = NextToken();
|
|
||||||
} else {
|
|
||||||
pt = tokens = tokens->next;
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// peek for the next token, ignore pragmas
|
|
||||||
Token* Scanner::Peek() {
|
|
||||||
do {
|
|
||||||
if (pt->next == NULL) {
|
|
||||||
pt->next = NextToken();
|
|
||||||
}
|
|
||||||
pt = pt->next;
|
|
||||||
} while (pt->kind > maxT); // skip pragmas
|
|
||||||
|
|
||||||
return pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// make sure that peeking starts at the current scan position
|
|
||||||
void Scanner::ResetPeek() {
|
|
||||||
pt = tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,398 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef COCO_calcEntrySCANNER_H__
|
|
||||||
#define COCO_calcEntrySCANNER_H__
|
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cwchar>
|
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// io.h and fcntl are used to ensure binary read from streams on windows
|
|
||||||
#if _MSC_VER >= 1300
|
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1400
|
|
||||||
#define coco_swprintf swprintf_s
|
|
||||||
#elif _MSC_VER >= 1300
|
|
||||||
#define coco_swprintf _snwprintf
|
|
||||||
#else
|
|
||||||
// assume every other compiler knows swprintf
|
|
||||||
#define coco_swprintf swprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define COCO_WCHAR_MAX 65535
|
|
||||||
|
|
||||||
|
|
||||||
namespace Foam {
|
|
||||||
namespace functionEntries {
|
|
||||||
namespace calcEntryInternal {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * Wide Character String Routines * * * * * * * * * * * //
|
|
||||||
|
|
||||||
//
|
|
||||||
// string handling, wide character
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
//! Create by copying str
|
|
||||||
wchar_t* coco_string_create(const wchar_t* str);
|
|
||||||
|
|
||||||
//! Create a substring of str starting at index and length characters long
|
|
||||||
wchar_t* coco_string_create(const wchar_t* str, int index, int length);
|
|
||||||
|
|
||||||
//! Create a lowercase string from str
|
|
||||||
wchar_t* coco_string_create_lower(const wchar_t* str);
|
|
||||||
|
|
||||||
//! Create a lowercase substring from str starting at index and length characters long
|
|
||||||
wchar_t* coco_string_create_lower(const wchar_t* str, int index, int length);
|
|
||||||
|
|
||||||
//! Create a string by concatenating str1 and str2
|
|
||||||
wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2);
|
|
||||||
|
|
||||||
//! Create a string by concatenating a character to the end of str
|
|
||||||
wchar_t* coco_string_create_append(const wchar_t* str, const wchar_t ch);
|
|
||||||
|
|
||||||
//! Free storage and nullify the argument
|
|
||||||
void coco_string_delete(wchar_t* &str);
|
|
||||||
|
|
||||||
//! The length of the str, or 0 if the str is NULL
|
|
||||||
int coco_string_length(const wchar_t* str);
|
|
||||||
|
|
||||||
//! Return true if the str ends with the endstr
|
|
||||||
bool coco_string_endswith(const wchar_t* str, const wchar_t* endstr);
|
|
||||||
|
|
||||||
//! Return the index of the first occurrence of ch.
|
|
||||||
// Return -1 if nothing is found.
|
|
||||||
int coco_string_indexof(const wchar_t* str, const wchar_t ch);
|
|
||||||
|
|
||||||
//! Return the index of the last occurrence of ch.
|
|
||||||
// Return -1 if nothing is found.
|
|
||||||
int coco_string_lastindexof(const wchar_t* str, const wchar_t ch);
|
|
||||||
|
|
||||||
//! Append str to dest
|
|
||||||
void coco_string_merge(wchar_t* &dest, const wchar_t* str);
|
|
||||||
|
|
||||||
//! Compare strings, return true if they are equal
|
|
||||||
bool coco_string_equal(const wchar_t* str1, const wchar_t* str2);
|
|
||||||
|
|
||||||
//! Compare strings, return 0 if they are equal
|
|
||||||
int coco_string_compareto(const wchar_t* str1, const wchar_t* str2);
|
|
||||||
|
|
||||||
//! Simple string hashing function
|
|
||||||
int coco_string_hash(const wchar_t* str);
|
|
||||||
|
|
||||||
//
|
|
||||||
// String conversions
|
|
||||||
// ~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
//! Convert wide string to double
|
|
||||||
double coco_string_toDouble(const wchar_t* str);
|
|
||||||
|
|
||||||
//! Convert wide string to float
|
|
||||||
float coco_string_toFloat(const wchar_t* str);
|
|
||||||
|
|
||||||
//
|
|
||||||
// String handling, byte character
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
//! Create by copying byte str
|
|
||||||
wchar_t* coco_string_create(const char* str);
|
|
||||||
|
|
||||||
//! Create a substring of byte str starting at index and length characters long
|
|
||||||
wchar_t* coco_string_create(const char* str, int index, int length);
|
|
||||||
|
|
||||||
//! Create a byte string by copying str
|
|
||||||
char* coco_string_create_char(const wchar_t* str);
|
|
||||||
|
|
||||||
//! Create a byte substring of str starting at index and length characters long
|
|
||||||
char* coco_string_create_char(const wchar_t* str, int index, int length);
|
|
||||||
|
|
||||||
//! Free storage and nullify the argument
|
|
||||||
void coco_string_delete(char* &str);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// String conversions, byte character
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
//! Convert byte string to double
|
|
||||||
double coco_string_toDouble(const char* str);
|
|
||||||
|
|
||||||
//! Convert byte string to float
|
|
||||||
float coco_string_toFloat(const char* str);
|
|
||||||
|
|
||||||
// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * //
|
|
||||||
|
|
||||||
|
|
||||||
//! Scanner Token
|
|
||||||
class Token
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int kind; //!< token kind
|
|
||||||
int pos; //!< token position in the source text (starting at 0)
|
|
||||||
int col; //!< token column (starting at 1)
|
|
||||||
int line; //!< token line (starting at 1)
|
|
||||||
wchar_t* val; //!< token value
|
|
||||||
Token *next; //!< Peek tokens are kept in linked list
|
|
||||||
|
|
||||||
Token(); //!< Construct null
|
|
||||||
~Token(); //!< Destructor - cleanup allocated val??
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//! Scanner Buffer
|
|
||||||
//
|
|
||||||
//! This Buffer supports the following cases:
|
|
||||||
//! -# seekable stream (file)
|
|
||||||
//! -# whole stream in buffer
|
|
||||||
//! -# part of stream in buffer
|
|
||||||
//! -# non seekable stream (network, console)
|
|
||||||
class Buffer {
|
|
||||||
private:
|
|
||||||
unsigned char *buf; //!< input buffer
|
|
||||||
int bufCapacity; //!< capacity of buf
|
|
||||||
int bufLen; //!< length of buffer
|
|
||||||
int bufPos; //!< current position in buffer
|
|
||||||
int bufStart; //!< position of first byte in buffer relative to input stream
|
|
||||||
int fileLen; //!< length of input stream (may change if the stream is no file)
|
|
||||||
FILE* cStream; //!< input stdio stream (normally seekable)
|
|
||||||
std::istream* stdStream; //!< STL std stream (seekable)
|
|
||||||
bool isUserStream_; //!< was the stream opened by the user?
|
|
||||||
|
|
||||||
int ReadNextStreamChunk();
|
|
||||||
bool CanSeek() const; //!< true if stream can be seeked otherwise false
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Buffer(Buffer*); //!< for the UTF8Buffer
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const int EoF = COCO_WCHAR_MAX + 1;
|
|
||||||
|
|
||||||
//! Attach buffer to a stdio stream.
|
|
||||||
//! User streams are not closed in the destructor
|
|
||||||
Buffer(FILE*, bool isUserStream = true);
|
|
||||||
|
|
||||||
//! Attach buffer to an STL std stream
|
|
||||||
//! User streams are not closed in the destructor
|
|
||||||
explicit Buffer(std::istream*, bool isUserStream = true);
|
|
||||||
|
|
||||||
//! Copy buffer contents from constant string
|
|
||||||
//! Handled internally as an istringstream
|
|
||||||
explicit Buffer(std::string&);
|
|
||||||
|
|
||||||
//! Copy buffer contents from constant character string
|
|
||||||
Buffer(const unsigned char* chars, int len);
|
|
||||||
//! Copy buffer contents from constant character string
|
|
||||||
Buffer(const char* chars, int len);
|
|
||||||
|
|
||||||
//! Close stream (but not user streams) and free buf (if any)
|
|
||||||
virtual ~Buffer();
|
|
||||||
|
|
||||||
virtual void Close(); //!< Close stream (but not user streams)
|
|
||||||
virtual int Read(); //!< Get character from stream or buffer
|
|
||||||
virtual int Peek(); //!< Peek character from stream or buffer
|
|
||||||
|
|
||||||
virtual int GetPos() const;
|
|
||||||
virtual void SetPos(int value);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//! A Scanner buffer that handles UTF-8 characters
|
|
||||||
class UTF8Buffer : public Buffer {
|
|
||||||
public:
|
|
||||||
UTF8Buffer(Buffer* b) : Buffer(b) {}
|
|
||||||
virtual int Read();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// StartStates
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
//! maps characters (integers) to start states of tokens
|
|
||||||
class StartStates {
|
|
||||||
private:
|
|
||||||
class Elem {
|
|
||||||
public:
|
|
||||||
int key, val;
|
|
||||||
Elem *next;
|
|
||||||
Elem(int k, int v) :
|
|
||||||
key(k), val(v), next(0)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
Elem **tab;
|
|
||||||
|
|
||||||
public:
|
|
||||||
StartStates() :
|
|
||||||
tab(new Elem*[128])
|
|
||||||
{
|
|
||||||
memset(tab, 0, 128 * sizeof(Elem*));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~StartStates() {
|
|
||||||
for (int i = 0; i < 128; ++i) {
|
|
||||||
Elem *e = tab[i];
|
|
||||||
while (e) {
|
|
||||||
Elem *next = e->next;
|
|
||||||
delete e;
|
|
||||||
e = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete [] tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(int key, int val) {
|
|
||||||
Elem *e = new Elem(key, val);
|
|
||||||
int k = unsigned(key) % 128;
|
|
||||||
e->next = tab[k];
|
|
||||||
tab[k] = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
int state(int key) {
|
|
||||||
Elem *e = tab[unsigned(key) % 128];
|
|
||||||
while (e && e->key != key) e = e->next;
|
|
||||||
return e ? e->val : 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// KeywordMap
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
//! maps strings to integers (identifiers to keyword kinds)
|
|
||||||
class KeywordMap {
|
|
||||||
private:
|
|
||||||
class Elem {
|
|
||||||
public:
|
|
||||||
wchar_t *key;
|
|
||||||
int val;
|
|
||||||
Elem *next;
|
|
||||||
Elem(const wchar_t *k, int v) :
|
|
||||||
key(coco_string_create(k)), val(v), next(0)
|
|
||||||
{}
|
|
||||||
virtual ~Elem() {
|
|
||||||
coco_string_delete(key);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Elem **tab;
|
|
||||||
|
|
||||||
public:
|
|
||||||
KeywordMap() :
|
|
||||||
tab(new Elem*[128])
|
|
||||||
{
|
|
||||||
memset(tab, 0, 128 * sizeof(Elem*));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~KeywordMap() {
|
|
||||||
for (int i = 0; i < 128; ++i) {
|
|
||||||
Elem *e = tab[i];
|
|
||||||
while (e) {
|
|
||||||
Elem *next = e->next;
|
|
||||||
delete e;
|
|
||||||
e = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete [] tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(const wchar_t *key, int val) {
|
|
||||||
Elem *e = new Elem(key, val);
|
|
||||||
const int k = coco_string_hash(key) % 128;
|
|
||||||
e->next = tab[k];
|
|
||||||
tab[k] = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get(const wchar_t *key, int defaultVal) {
|
|
||||||
Elem *e = tab[coco_string_hash(key) % 128];
|
|
||||||
while (e && !coco_string_equal(e->key, key)) e = e->next;
|
|
||||||
return e ? e->val : defaultVal;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//! A Coco/R Scanner
|
|
||||||
class Scanner {
|
|
||||||
private:
|
|
||||||
static const int maxT = 13;
|
|
||||||
static const int noSym = 13;
|
|
||||||
|
|
||||||
static const int eofSym = 0; //!< end-of-file token id
|
|
||||||
static const char EOL = '\n'; //!< end-of-line character
|
|
||||||
|
|
||||||
void *firstHeap; //!< the start of the heap management
|
|
||||||
void *heap; //!< the currently active block
|
|
||||||
void *heapTop; //!< the top of the heap
|
|
||||||
void **heapEnd; //!< the end of the last heap block
|
|
||||||
|
|
||||||
StartStates start; //!< A map of start states for particular characters
|
|
||||||
KeywordMap keywords; //!< A hash of keyword literals to token kind
|
|
||||||
|
|
||||||
Token *t; //!< current token
|
|
||||||
wchar_t *tval; //!< text of current token
|
|
||||||
int tvalLength; //!< maximum capacity (length) for tval
|
|
||||||
int tlen; //!< length of tval
|
|
||||||
|
|
||||||
Token *tokens; //!< list of tokens already peeked (first token is a dummy)
|
|
||||||
Token *pt; //!< current peek token
|
|
||||||
|
|
||||||
int ch; //!< current input character
|
|
||||||
|
|
||||||
int pos; //!< byte position of current character
|
|
||||||
int line; //!< line number of current character
|
|
||||||
int col; //!< column number of current character
|
|
||||||
int oldEols; //!< the number of EOLs that appeared in a comment
|
|
||||||
|
|
||||||
void CreateHeapBlock(); //!< add a heap block, freeing unused ones
|
|
||||||
Token* CreateToken(); //!< fit token on the heap
|
|
||||||
void AppendVal(Token* tok); //!< adjust tok->val to point to the heap and copy tval into it
|
|
||||||
|
|
||||||
void Init(); //!< complete the initialization for the constructors
|
|
||||||
void NextCh(); //!< get the next input character into ch
|
|
||||||
void AddCh(); //!< append the character ch to tval
|
|
||||||
bool Comment0();
|
|
||||||
bool Comment1();
|
|
||||||
|
|
||||||
Token* NextToken(); //!< get the next token
|
|
||||||
|
|
||||||
public:
|
|
||||||
//! The scanner buffer
|
|
||||||
Buffer *buffer;
|
|
||||||
|
|
||||||
//! Using an existing open file handle for the scanner
|
|
||||||
Scanner(FILE*);
|
|
||||||
|
|
||||||
//! Using an existing open STL std stream
|
|
||||||
explicit Scanner(std::istream&);
|
|
||||||
|
|
||||||
//! Open a file for reading and attach scanner
|
|
||||||
explicit Scanner(const wchar_t* fileName);
|
|
||||||
|
|
||||||
//! Attach scanner to an existing character buffer
|
|
||||||
Scanner(const unsigned char* chars, int len);
|
|
||||||
//! Attach scanner to an existing character buffer
|
|
||||||
Scanner(const char* chars, int len);
|
|
||||||
|
|
||||||
~Scanner(); //!< free heap and allocated memory
|
|
||||||
Token* Scan(); //!< get the next token (possibly a token already seen during peeking)
|
|
||||||
Token* Peek(); //!< peek for the next token, ignore pragmas
|
|
||||||
void ResetPeek(); //!< ensure that peeking starts at the current scan position
|
|
||||||
|
|
||||||
}; // end Scanner
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
|
|
||||||
#endif // COCO_calcEntrySCANNER_H__
|
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ FoamFile
|
|||||||
version 2.0;
|
version 2.0;
|
||||||
format ascii;
|
format ascii;
|
||||||
class dictionary;
|
class dictionary;
|
||||||
object testDictTest;
|
object testDictCalc;
|
||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -19,28 +19,13 @@ flowRatePerHour 720;
|
|||||||
x 10;
|
x 10;
|
||||||
y 20;
|
y 20;
|
||||||
z t s v;
|
z t s v;
|
||||||
// z #test{ // this
|
p #calc{ 1 + 2 + 10 * 15 + $x - $y };
|
||||||
// 123 - 456
|
|
||||||
// // comments // are
|
|
||||||
// /* stripped
|
|
||||||
// * 10
|
|
||||||
// * {}
|
|
||||||
// */
|
|
||||||
// + 1 /*100 */ 10
|
|
||||||
// };
|
|
||||||
|
|
||||||
p this calculation #calc{
|
// this calculation is in-place, but does not work inside a string:
|
||||||
1 + 2 + 10 * 15 +
|
flowRate "The flow rate " #calc{ $flowRatePerHour / 3600 } "kg/s";
|
||||||
$x - $y
|
|
||||||
// $x + $y
|
|
||||||
}
|
|
||||||
is done inplace;
|
|
||||||
|
|
||||||
|
// this is also okay
|
||||||
|
x #calc{ $x * 1E-3 };
|
||||||
|
|
||||||
flowRate #calc{ $flowRatePerHour / 3600};
|
|
||||||
|
|
||||||
xxx yyy;
|
|
||||||
foo 30;
|
|
||||||
bar 15;
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|||||||
46
applications/test/dictionary/testDictCalcError
Normal file
46
applications/test/dictionary/testDictCalcError
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*--------------------------------*- C++ -*----------------------------------*\
|
||||||
|
| ========= | |
|
||||||
|
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||||
|
| \\ / O peration | Version: Any |
|
||||||
|
| \\ / A nd | Web: www.OpenFOAM.org |
|
||||||
|
| \\/ M anipulation | |
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
FoamFile
|
||||||
|
{
|
||||||
|
version 2.0;
|
||||||
|
format ascii;
|
||||||
|
class dictionary;
|
||||||
|
object testDictCalcError;
|
||||||
|
}
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
flowRatePerHour 720;
|
||||||
|
|
||||||
|
x 10;
|
||||||
|
y 20;
|
||||||
|
z t s v;
|
||||||
|
// z #test{ // this
|
||||||
|
// 123 - 456
|
||||||
|
// // comments // are
|
||||||
|
// /* stripped
|
||||||
|
// * 10
|
||||||
|
// * {}
|
||||||
|
// */
|
||||||
|
// + 1 /*100 */ 10
|
||||||
|
// };
|
||||||
|
|
||||||
|
p this calculation #calc{
|
||||||
|
1xxx1 + 2 + 10 * 15 +
|
||||||
|
$x - $y
|
||||||
|
// $x + $y
|
||||||
|
}
|
||||||
|
is done inplace;
|
||||||
|
|
||||||
|
|
||||||
|
flowRate #calc{ $flowRatePerHour / 3600};
|
||||||
|
|
||||||
|
xxx yyy;
|
||||||
|
foo 30;
|
||||||
|
bar 15;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -142,6 +142,12 @@ $(functionEntries)/includeIfPresentEntry/includeIfPresentEntry.C
|
|||||||
$(functionEntries)/inputModeEntry/inputModeEntry.C
|
$(functionEntries)/inputModeEntry/inputModeEntry.C
|
||||||
$(functionEntries)/removeEntry/removeEntry.C
|
$(functionEntries)/removeEntry/removeEntry.C
|
||||||
|
|
||||||
|
calcEntry = $(functionEntries)/calcEntry
|
||||||
|
$(calcEntry)/calcEntryParser.atg
|
||||||
|
$(calcEntry)/calcEntryInternal.C
|
||||||
|
$(calcEntry)/calcEntry.C
|
||||||
|
|
||||||
|
|
||||||
IOdictionary = db/IOobjects/IOdictionary
|
IOdictionary = db/IOobjects/IOdictionary
|
||||||
$(IOdictionary)/IOdictionary.C
|
$(IOdictionary)/IOdictionary.C
|
||||||
$(IOdictionary)/IOdictionaryIO.C
|
$(IOdictionary)/IOdictionaryIO.C
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
EXE_INC =
|
EXE_INC = -I$(OBJECTS_DIR)
|
||||||
|
|
||||||
LIB_LIBS = \
|
LIB_LIBS = \
|
||||||
$(FOAM_LIBBIN)/libOSspecific.o \
|
$(FOAM_LIBBIN)/libOSspecific.o \
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd.
|
\\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd.
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -68,17 +68,23 @@ bool Foam::functionEntries::calcEntry::execute
|
|||||||
myErrorHandler("calcEntryInternal::Parser");
|
myErrorHandler("calcEntryInternal::Parser");
|
||||||
|
|
||||||
calcEntryInternal::Scanner scanner(iss);
|
calcEntryInternal::Scanner scanner(iss);
|
||||||
|
|
||||||
|
// set the starting line
|
||||||
|
scanner.Line(is.lineNumber());
|
||||||
|
|
||||||
calcEntryInternal::Parser parser(&scanner, &myErrorHandler);
|
calcEntryInternal::Parser parser(&scanner, &myErrorHandler);
|
||||||
|
|
||||||
// Attach dictionary context
|
// Attach dictionary context
|
||||||
parser.dict(parentDict);
|
parser.dict(parentDict);
|
||||||
|
|
||||||
// Attach scalar functions
|
|
||||||
// parser.functions(parentDict);
|
|
||||||
|
|
||||||
parser.Parse();
|
parser.Parse();
|
||||||
|
|
||||||
// make a small input list to contain the answer
|
// mostly have an extra newline in the lookahead token
|
||||||
|
// so subtract 1 to keep things vaguely in sync
|
||||||
|
// (this is still far from perfect)
|
||||||
|
is.lineNumber() = scanner.Line() - 1;
|
||||||
|
|
||||||
|
// a small input list to contain the answer
|
||||||
tokenList tokens(2);
|
tokenList tokens(2);
|
||||||
tokens[0] = parser.Result();
|
tokens[0] = parser.Result();
|
||||||
tokens[1] = token::END_STATEMENT;
|
tokens[1] = token::END_STATEMENT;
|
||||||
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd.
|
\\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd.
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -0,0 +1,129 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / 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
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "calcEntryInternal.H"
|
||||||
|
#include "addToGlobalFunctionSelectionTable.H"
|
||||||
|
#include "unitConversion.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace functionEntries
|
||||||
|
{
|
||||||
|
namespace calcEntryInternal
|
||||||
|
{
|
||||||
|
|
||||||
|
defineGlobalFunctionSelectionTable(dispatch,ParamList);
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#define globalConstant0(Name, Constant)\
|
||||||
|
scalar Name##_0(const UList<scalar>& param) \
|
||||||
|
{ \
|
||||||
|
return Constant; \
|
||||||
|
} \
|
||||||
|
addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_0,&Name##_0)
|
||||||
|
|
||||||
|
|
||||||
|
#define globalFunction0(Name, Function)\
|
||||||
|
scalar Name##_0(const UList<scalar>& param) \
|
||||||
|
{ \
|
||||||
|
return Function(); \
|
||||||
|
} \
|
||||||
|
addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_0,&Name##_0)
|
||||||
|
|
||||||
|
|
||||||
|
#define globalFunction1(Name, Function)\
|
||||||
|
scalar Name##_1(const UList<scalar>& param) \
|
||||||
|
{ \
|
||||||
|
return Function(param[0]); \
|
||||||
|
} \
|
||||||
|
addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_1,&Name##_1)
|
||||||
|
|
||||||
|
|
||||||
|
#define globalFunction2(Name, Function)\
|
||||||
|
scalar Name##_2(const UList<scalar>& param) \
|
||||||
|
{ \
|
||||||
|
return Function(param[0], param[1]); \
|
||||||
|
} \
|
||||||
|
addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_2,&Name##_2)
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
globalConstant0(pi, constant::mathematical::pi);
|
||||||
|
|
||||||
|
globalFunction1(degToRad, degToRad);
|
||||||
|
globalFunction1(radToDeg, radToDeg);
|
||||||
|
globalFunction1(asin, Foam::asin);
|
||||||
|
globalFunction1(acos, Foam::acos);
|
||||||
|
globalFunction1(atan, Foam::atan);
|
||||||
|
globalFunction1(sin, Foam::sin);
|
||||||
|
globalFunction1(cos, Foam::cos);
|
||||||
|
globalFunction1(tan, Foam::tan);
|
||||||
|
globalFunction1(log, Foam::log);
|
||||||
|
globalFunction1(log10, Foam::log10);
|
||||||
|
globalFunction1(mag, Foam::mag);
|
||||||
|
|
||||||
|
globalFunction2(atan2, Foam::atan2);
|
||||||
|
globalFunction2(pow, Foam::pow);
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
scalar dispatch(const word& name, const UList<scalar>& param)
|
||||||
|
{
|
||||||
|
// create lookup name with parameter count
|
||||||
|
const word lookupName = name + '_' + Foam::name(param.size());
|
||||||
|
|
||||||
|
dispatchParamListMemberFunctionTable::iterator mfIter =
|
||||||
|
dispatchParamListMemberFunctionTablePtr_->find(lookupName);
|
||||||
|
|
||||||
|
if (mfIter == dispatchParamListMemberFunctionTablePtr_->end())
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"calcEntryInternal::scalarFunctions::dispatch"
|
||||||
|
"(const word&, const UList<scalar>&) : "
|
||||||
|
) << "Unknown function " << name << nl << nl
|
||||||
|
<< "Valid types are :" << endl
|
||||||
|
<< dispatchParamListMemberFunctionTablePtr_->sortedToc()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mfIter()(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace calcEntryInternal
|
||||||
|
} // End namespace functionEntries
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / 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
|
||||||
|
|
||||||
|
Namespace
|
||||||
|
Foam::functionEntries::calcEntryInternal
|
||||||
|
|
||||||
|
Description
|
||||||
|
Contains global functions and classes for the calcEntry.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
calcEntryInternal.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef calcEntryInternal_H
|
||||||
|
#define calcEntryInternal_H
|
||||||
|
|
||||||
|
#include "error.H"
|
||||||
|
#include "scalar.H"
|
||||||
|
#include "DynamicList.H"
|
||||||
|
#include "globalFunctionSelectionTables.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace functionEntries
|
||||||
|
{
|
||||||
|
namespace calcEntryInternal
|
||||||
|
{
|
||||||
|
|
||||||
|
// Global Function Selectors
|
||||||
|
|
||||||
|
declareGlobalFunctionSelectionTable
|
||||||
|
(
|
||||||
|
scalar,
|
||||||
|
dispatch,
|
||||||
|
ParamList,
|
||||||
|
(
|
||||||
|
const UList<scalar>& param
|
||||||
|
),
|
||||||
|
(param)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Dispatch calculation to the named function
|
||||||
|
scalar dispatch(const word&, const UList<scalar>&);
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace calcEntryInternal
|
||||||
|
} // End namespace functionEntries
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,258 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Attributed Grammar for Coco/R (-*- C++ -*- version)
|
||||||
|
compile with:
|
||||||
|
coco-cpp calcEntryParser.atg
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
[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]
|
||||||
|
#include "dictionary.H"
|
||||||
|
#include "wchar.H"
|
||||||
|
#include "calcEntryInternal.H"
|
||||||
|
|
||||||
|
|
||||||
|
COMPILER calcEntry
|
||||||
|
// grammar pragmas:
|
||||||
|
$prefix=calcEntry
|
||||||
|
$namespace=Foam::functionEntries::calcEntryInternal
|
||||||
|
$define=EXPLICIT_EOF // grammar handles eof itself
|
||||||
|
$define=STREAMS_ONLY // only use STL streams
|
||||||
|
$define=NO_UTF8 // disable UTF8 on input
|
||||||
|
|
||||||
|
private:
|
||||||
|
//- The parent dictionary
|
||||||
|
dictionary* dict_;
|
||||||
|
|
||||||
|
//- The calculation result
|
||||||
|
scalar val;
|
||||||
|
|
||||||
|
//- lookup dictionary entry
|
||||||
|
scalar getDictLookup(const word&) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- attach a dictionary
|
||||||
|
void dict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
dict_ = const_cast<dictionary*>(&dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return the calculated result
|
||||||
|
scalar Result() const
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
[initialize] // add to Parser constructor
|
||||||
|
dict_ = 0;
|
||||||
|
val = 0;
|
||||||
|
[/initialize]
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
[code]
|
||||||
|
Foam::scalar Parser::getDictLookup(const word& keyword) const
|
||||||
|
{
|
||||||
|
if (!dict_)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"calcEntry::getDictEntry(const word&) const"
|
||||||
|
) << "No dictionary attached!"
|
||||||
|
<< exit(FatalError);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar dictValue = 0;
|
||||||
|
|
||||||
|
entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false);
|
||||||
|
if (entryPtr && !entryPtr->isDict())
|
||||||
|
{
|
||||||
|
if (entryPtr->stream().size() != 1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"calcEntry::getDictEntry(const word&) const"
|
||||||
|
) << "keyword " << keyword << " has "
|
||||||
|
<< entryPtr->stream().size() << " values in dictionary "
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
entryPtr->stream() >> dictValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"calcEntry::getDictEntry(const word&) const"
|
||||||
|
) << "keyword " << keyword << " is undefined in dictionary "
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dictValue;
|
||||||
|
}
|
||||||
|
[/code]
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
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 (.
|
||||||
|
// skip leading '$' for the keyword
|
||||||
|
val = getDictLookup(t->toString(1, t->length()-1));
|
||||||
|
.)
|
||||||
|
| number (. val = coco_string_toDouble(t->val); .)
|
||||||
|
) (. if (negative) { val = -val; } .)
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// functions like sin(x) or pow(x, y) etc.
|
||||||
|
Func<scalar& val>
|
||||||
|
=
|
||||||
|
ident (.
|
||||||
|
word funcName(t->toString());
|
||||||
|
DynamicList<scalar> stack(4);
|
||||||
|
.)
|
||||||
|
'('
|
||||||
|
[ (. scalar x; .)
|
||||||
|
Expr<x> (. stack.append(x); .)
|
||||||
|
{ ',' Expr<x> (. stack.append(x); .)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
')' (. val = dispatch(funcName, stack); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
END calcEntry.
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd.
|
\\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd.
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -45,7 +45,7 @@ namespace Foam
|
|||||||
Class CocoParserErrors Declaration
|
Class CocoParserErrors Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
template<class BaseClass>
|
template<class BaseClass, class StringClass=std::wstring>
|
||||||
class CocoParserErrors
|
class CocoParserErrors
|
||||||
:
|
:
|
||||||
public BaseClass
|
public BaseClass
|
||||||
@ -90,14 +90,14 @@ public:
|
|||||||
// Error Handling
|
// Error Handling
|
||||||
|
|
||||||
//- Handle a general warning 'msg'
|
//- Handle a general warning 'msg'
|
||||||
virtual void Warning(const wchar_t* msg)
|
virtual void Warning(const StringClass& msg)
|
||||||
{
|
{
|
||||||
WarningIn(name_)
|
WarningIn(name_)
|
||||||
<< msg << endl;
|
<< msg << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Handle a general warning 'msg'
|
//- Handle a general warning 'msg'
|
||||||
virtual void Warning(int line, int col, const wchar_t* msg)
|
virtual void Warning(int line, int col, const StringClass& msg)
|
||||||
{
|
{
|
||||||
WarningIn(name_)
|
WarningIn(name_)
|
||||||
<<"line " << line << " col " << col << ": "
|
<<"line " << line << " col " << col << ": "
|
||||||
@ -105,7 +105,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- Handle general error 'msg' (eg, a semantic error)
|
//- Handle general error 'msg' (eg, a semantic error)
|
||||||
virtual void Error(int line, int col, const wchar_t* msg)
|
virtual void Error(int line, int col, const StringClass& msg)
|
||||||
{
|
{
|
||||||
FatalErrorIn(name_)
|
FatalErrorIn(name_)
|
||||||
<< "line " << line << " col " << col <<": " << msg << endl
|
<< "line " << line << " col " << col <<": " << msg << endl
|
||||||
@ -113,7 +113,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- Handle general error 'msg' (eg, a semantic error)
|
//- Handle general error 'msg' (eg, a semantic error)
|
||||||
virtual void Error(const wchar_t* msg)
|
virtual void Error(const StringClass& msg)
|
||||||
{
|
{
|
||||||
FatalErrorIn(name_)
|
FatalErrorIn(name_)
|
||||||
<< msg << endl
|
<< msg << endl
|
||||||
@ -121,7 +121,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- Handle a general exception 'msg'
|
//- Handle a general exception 'msg'
|
||||||
virtual void Exception(const wchar_t* msg)
|
virtual void Exception(const StringClass& msg)
|
||||||
{
|
{
|
||||||
this->Error(msg);
|
this->Error(msg);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,53 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / 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 Foam::addToGlobalFunctionSelectionTable
|
||||||
|
|
||||||
|
Description
|
||||||
|
Macros for easy insertion into global function selection tables
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef addToGlobalFunctionSelectionTable_H
|
||||||
|
#define addToGlobalFunctionSelectionTable_H
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
// add to hash-table of functions with 'lookup' as the key
|
||||||
|
#define addNamedToGlobalFunctionSelectionTable\
|
||||||
|
(memberFunction,argNames,lookup,functionPtr) \
|
||||||
|
\
|
||||||
|
/* Add to the table, find by lookup name */ \
|
||||||
|
add##memberFunction##argNames##GlobalMemberFunctionToTable \
|
||||||
|
add_##lookup##_##memberFunction##argNames##GlobalMemberFunctionTo##Table_\
|
||||||
|
(#lookup, functionPtr)
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,145 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / 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 Foam::globalFunctionSelectionTables
|
||||||
|
|
||||||
|
Description
|
||||||
|
Macros to enable the easy declaration of global function selection tables.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef globalMemberFunctionSelectionTables_H
|
||||||
|
#define globalMemberFunctionSelectionTables_H
|
||||||
|
|
||||||
|
#include "memberFunctionSelectionTables.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
// external use:
|
||||||
|
// ~~~~~~~~~~~~~
|
||||||
|
// declare a run-time selection:
|
||||||
|
#define declareGlobalFunctionSelectionTable\
|
||||||
|
(returnType,memberFunction,argNames,argList,parList) \
|
||||||
|
\
|
||||||
|
/* Construct from argList function pointer type */ \
|
||||||
|
typedef returnType (*memberFunction##argNames##MemberFunctionPtr)argList; \
|
||||||
|
\
|
||||||
|
/* Construct from argList function table type */ \
|
||||||
|
typedef HashTable \
|
||||||
|
<memberFunction##argNames##MemberFunctionPtr, word, string::hash> \
|
||||||
|
memberFunction##argNames##MemberFunctionTable; \
|
||||||
|
\
|
||||||
|
/* Construct from argList function pointer table pointer */ \
|
||||||
|
extern memberFunction##argNames##MemberFunctionTable* \
|
||||||
|
memberFunction##argNames##MemberFunctionTablePtr_; \
|
||||||
|
\
|
||||||
|
/* Table memberFunction called from the table add function */ \
|
||||||
|
void construct##memberFunction##argNames##MemberFunctionTables(); \
|
||||||
|
\
|
||||||
|
/* Table destructor called from the table add function destructor */ \
|
||||||
|
void destroy##memberFunction##argNames##MemberFunctionTables(); \
|
||||||
|
\
|
||||||
|
/* Class to add constructor from argList to table */ \
|
||||||
|
class add##memberFunction##argNames##GlobalMemberFunctionToTable \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
\
|
||||||
|
add##memberFunction##argNames##GlobalMemberFunctionToTable \
|
||||||
|
( \
|
||||||
|
const word& lookup, \
|
||||||
|
memberFunction##argNames##MemberFunctionPtr function \
|
||||||
|
) \
|
||||||
|
{ \
|
||||||
|
construct##memberFunction##argNames##MemberFunctionTables(); \
|
||||||
|
memberFunction##argNames##MemberFunctionTablePtr_->insert \
|
||||||
|
( \
|
||||||
|
lookup, \
|
||||||
|
function \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
~add##memberFunction##argNames##GlobalMemberFunctionToTable() \
|
||||||
|
{ \
|
||||||
|
destroy##memberFunction##argNames##MemberFunctionTables(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal use:
|
||||||
|
// constructor/destructor aid
|
||||||
|
#define defineGlobalFunctionSelectionTableConstructDestruct\
|
||||||
|
(memberFunction,argNames) \
|
||||||
|
\
|
||||||
|
/* Table constructor called from the table add function */ \
|
||||||
|
void construct##memberFunction##argNames##MemberFunctionTables()\
|
||||||
|
{ \
|
||||||
|
static bool constructed = false; \
|
||||||
|
if (!constructed) \
|
||||||
|
{ \
|
||||||
|
constructed = true; \
|
||||||
|
memberFunction##argNames##MemberFunctionTablePtr_ \
|
||||||
|
= new memberFunction##argNames##MemberFunctionTable; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* Table destructor called from the table add function destructor */ \
|
||||||
|
void destroy##memberFunction##argNames##MemberFunctionTables()\
|
||||||
|
{ \
|
||||||
|
if (memberFunction##argNames##MemberFunctionTablePtr_) \
|
||||||
|
{ \
|
||||||
|
delete memberFunction##argNames##MemberFunctionTablePtr_; \
|
||||||
|
memberFunction##argNames##MemberFunctionTablePtr_ = NULL; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal use:
|
||||||
|
// create pointer to hash-table of functions
|
||||||
|
#define defineGlobalFunctionSelectionTablePtr\
|
||||||
|
(memberFunction,argNames) \
|
||||||
|
\
|
||||||
|
/* Define the memberFunction table */ \
|
||||||
|
memberFunction##argNames##MemberFunctionTable* \
|
||||||
|
memberFunction##argNames##MemberFunctionTablePtr_ = NULL
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// external use:
|
||||||
|
// ~~~~~~~~~~~~~
|
||||||
|
// define run-time selection table
|
||||||
|
#define defineGlobalFunctionSelectionTable\
|
||||||
|
(memberFunction,argNames) \
|
||||||
|
\
|
||||||
|
defineGlobalFunctionSelectionTablePtr \
|
||||||
|
(memberFunction,argNames); \
|
||||||
|
defineGlobalFunctionSelectionTableConstructDestruct \
|
||||||
|
(memberFunction,argNames)
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / 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 Foam::addToStaticMemberFunctionSelectionTable
|
||||||
|
|
||||||
|
Description
|
||||||
|
Macros for easy insertion into member function selection tables
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef addToStaticMemberFunctionSelectionTable_H
|
||||||
|
#define addToStaticMemberFunctionSelectionTable_H
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
// add to hash-table of functions with 'lookup' as the key
|
||||||
|
#define addNamedToStaticMemberFunctionSelectionTable\
|
||||||
|
(baseType,thisType,memberFunction,argNames,lookup,functionPtr) \
|
||||||
|
\
|
||||||
|
/* Add the thisType memberFunction to the table, find by lookup name */ \
|
||||||
|
baseType::add##memberFunction##argNames##StaticMemberFunctionToTable<thisType> \
|
||||||
|
add_##lookup##_##thisType##memberFunction##argNames##StaticMemberFunctionTo##baseType##Table_\
|
||||||
|
(#lookup, functionPtr)
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / 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 Foam::staticMemberFunctionSelectionTables
|
||||||
|
|
||||||
|
Description
|
||||||
|
Macros to enable the easy declaration of member function selection tables.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef staticMemberFunctionSelectionTables_H
|
||||||
|
#define staticMemberFunctionSelectionTables_H
|
||||||
|
|
||||||
|
#include "memberFunctionSelectionTables.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
// external use:
|
||||||
|
// ~~~~~~~~~~~~~
|
||||||
|
// declare a run-time selection:
|
||||||
|
#define declareStaticMemberFunctionSelectionTable\
|
||||||
|
(returnType,baseType,memberFunction,argNames,argList,parList) \
|
||||||
|
\
|
||||||
|
/* Construct from argList function pointer type */ \
|
||||||
|
typedef returnType (*memberFunction##argNames##MemberFunctionPtr)argList; \
|
||||||
|
\
|
||||||
|
/* Construct from argList function table type */ \
|
||||||
|
typedef HashTable \
|
||||||
|
<memberFunction##argNames##MemberFunctionPtr, word, string::hash> \
|
||||||
|
memberFunction##argNames##MemberFunctionTable; \
|
||||||
|
\
|
||||||
|
/* Construct from argList function pointer table pointer */ \
|
||||||
|
static memberFunction##argNames##MemberFunctionTable* \
|
||||||
|
memberFunction##argNames##MemberFunctionTablePtr_; \
|
||||||
|
\
|
||||||
|
/* Table memberFunction called from the table add function */ \
|
||||||
|
static void construct##memberFunction##argNames##MemberFunctionTables(); \
|
||||||
|
\
|
||||||
|
/* Table destructor called from the table add function destructor */ \
|
||||||
|
static void destroy##memberFunction##argNames##MemberFunctionTables(); \
|
||||||
|
\
|
||||||
|
/* Class to add constructor from argList to table */ \
|
||||||
|
template<class baseType##Type> \
|
||||||
|
class add##memberFunction##argNames##StaticMemberFunctionToTable \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
\
|
||||||
|
add##memberFunction##argNames##StaticMemberFunctionToTable \
|
||||||
|
( \
|
||||||
|
const word& lookup, \
|
||||||
|
memberFunction##argNames##MemberFunctionPtr function \
|
||||||
|
) \
|
||||||
|
{ \
|
||||||
|
construct##memberFunction##argNames##MemberFunctionTables(); \
|
||||||
|
memberFunction##argNames##MemberFunctionTablePtr_->insert \
|
||||||
|
( \
|
||||||
|
lookup, \
|
||||||
|
function \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
~add##memberFunction##argNames##StaticMemberFunctionToTable() \
|
||||||
|
{ \
|
||||||
|
destroy##memberFunction##argNames##MemberFunctionTables(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal use:
|
||||||
|
// constructor/destructor aid
|
||||||
|
#define defineStaticMemberFunctionSelectionTableConstructDestruct\
|
||||||
|
(baseType,memberFunction,argNames) \
|
||||||
|
\
|
||||||
|
/* Table constructor called from the table add function constructor */ \
|
||||||
|
void baseType::construct##memberFunction##argNames##MemberFunctionTables()\
|
||||||
|
{ \
|
||||||
|
static bool constructed = false; \
|
||||||
|
if (!constructed) \
|
||||||
|
{ \
|
||||||
|
constructed = true; \
|
||||||
|
baseType::memberFunction##argNames##MemberFunctionTablePtr_ \
|
||||||
|
= new baseType::memberFunction##argNames##MemberFunctionTable;\
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
/* Table destructor called from the table add function destructor */ \
|
||||||
|
void baseType::destroy##memberFunction##argNames##MemberFunctionTables() \
|
||||||
|
{ \
|
||||||
|
if (baseType::memberFunction##argNames##MemberFunctionTablePtr_) \
|
||||||
|
{ \
|
||||||
|
delete baseType::memberFunction##argNames##MemberFunctionTablePtr_;\
|
||||||
|
baseType::memberFunction##argNames##MemberFunctionTablePtr_ = NULL;\
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal use:
|
||||||
|
// create pointer to hash-table of functions
|
||||||
|
#define defineStaticMemberFunctionSelectionTablePtr\
|
||||||
|
(baseType,memberFunction,argNames) \
|
||||||
|
\
|
||||||
|
/* Define the memberFunction table */ \
|
||||||
|
baseType::memberFunction##argNames##MemberFunctionTable* \
|
||||||
|
baseType::memberFunction##argNames##MemberFunctionTablePtr_ = NULL
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// external use:
|
||||||
|
// ~~~~~~~~~~~~~
|
||||||
|
// define run-time selection table
|
||||||
|
#define defineStaticMemberFunctionSelectionTable\
|
||||||
|
(baseType,memberFunction,argNames) \
|
||||||
|
\
|
||||||
|
defineStaticMemberFunctionSelectionTablePtr \
|
||||||
|
(baseType,memberFunction,argNames); \
|
||||||
|
defineStaticMemberFunctionSelectionTableConstructDestruct \
|
||||||
|
(baseType,memberFunction,argNames) \
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -41,6 +41,7 @@ SeeAlso
|
|||||||
#define wchar_H
|
#define wchar_H
|
||||||
|
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -58,6 +59,9 @@ Ostream& operator<<(Ostream&, const wchar_t);
|
|||||||
//- Output wide character (Unicode) string as UTF-8
|
//- Output wide character (Unicode) string as UTF-8
|
||||||
Ostream& operator<<(Ostream&, const wchar_t*);
|
Ostream& operator<<(Ostream&, const wchar_t*);
|
||||||
|
|
||||||
|
//- Output wide character (Unicode) string as UTF-8
|
||||||
|
Ostream& operator<<(Ostream&, const std::wstring&);
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|||||||
@ -101,13 +101,13 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t wc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* ws)
|
Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* wstr)
|
||||||
{
|
{
|
||||||
if (ws)
|
if (wstr)
|
||||||
{
|
{
|
||||||
for (const wchar_t* p = ws; *p; ++p)
|
for (const wchar_t* iter = wstr; *iter; ++iter)
|
||||||
{
|
{
|
||||||
os << *p;
|
os << *iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,4 +115,20 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* ws)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::Ostream& Foam::operator<<(Ostream& os, const std::wstring& wstr)
|
||||||
|
{
|
||||||
|
for
|
||||||
|
(
|
||||||
|
std::wstring::const_iterator iter = wstr.begin();
|
||||||
|
iter != wstr.end();
|
||||||
|
++iter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
os << *iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -33,13 +33,13 @@ boundaryField
|
|||||||
{
|
{
|
||||||
type flowRateInletVelocity;
|
type flowRateInletVelocity;
|
||||||
flowRate 0.00379;
|
flowRate 0.00379;
|
||||||
value uniform (-0 10.82857143 -0);
|
value uniform (0 10.82857143 0);
|
||||||
}
|
}
|
||||||
inletSides
|
inletSides
|
||||||
{
|
{
|
||||||
type flowRateInletVelocity;
|
type flowRateInletVelocity;
|
||||||
flowRate 0.00832;
|
flowRate 0.00832;
|
||||||
value uniform (-0 11.88571429 -0);
|
value uniform (0 11.88571429 0);
|
||||||
}
|
}
|
||||||
outlet
|
outlet
|
||||||
{
|
{
|
||||||
|
|||||||
13
wmake/rules/General/coco
Normal file
13
wmake/rules/General/coco
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# handie Coco/R attributed grammars
|
||||||
|
|
||||||
|
.SUFFIXES: .atg
|
||||||
|
|
||||||
|
atgtoo = \
|
||||||
|
$(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/$(WM_ARCH)$(WM_COMPILER)/bin/coco-cpp \
|
||||||
|
-single \
|
||||||
|
-frames $(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/share/coco-cpp \
|
||||||
|
$$SOURCE -o $(OBJECTS_DIR) && \
|
||||||
|
$(CC) $(c++FLAGS) -c $*.cpp -o $@
|
||||||
|
|
||||||
|
.atg.dep:
|
||||||
|
$(MAKE_DEP)
|
||||||
@ -4,6 +4,7 @@ include $(GENERAL_RULES)/sourceToDep
|
|||||||
|
|
||||||
include $(GENERAL_RULES)/flex
|
include $(GENERAL_RULES)/flex
|
||||||
include $(GENERAL_RULES)/flex++
|
include $(GENERAL_RULES)/flex++
|
||||||
|
include $(GENERAL_RULES)/coco
|
||||||
## include $(GENERAL_RULES)/byacc
|
## include $(GENERAL_RULES)/byacc
|
||||||
## include $(GENERAL_RULES)/btyacc++
|
## include $(GENERAL_RULES)/btyacc++
|
||||||
include $(GENERAL_RULES)/bison
|
include $(GENERAL_RULES)/bison
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
# ========= |
|
# ========= |
|
||||||
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
# \\ / O peration |
|
# \\ / O peration |
|
||||||
# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
|
# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
|
||||||
# \\/ M anipulation |
|
# \\/ M anipulation |
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# License
|
# License
|
||||||
@ -60,16 +60,17 @@ include $(RULES)/$(WM_LINK_LANGUAGE)
|
|||||||
# targets
|
# targets
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
all: $(BIN)/dirToString $(BIN)/wmkdep
|
all: $(BIN)/dirToString $(BIN)/wmkdep $(BIN)/wmkdepend
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(BIN)/dirToString $(BIN)/wmkdep 2>/dev/null
|
rm -f $(BIN)/dirToString $(BIN)/wmkdep $(BIN)/wmkdepend 2>/dev/null
|
||||||
|
|
||||||
|
|
||||||
$(BIN)/dirToString: dirToString.c
|
$(BIN)/dirToString: dirToString.c
|
||||||
@mkdir -p $(BIN)
|
@mkdir -p $(BIN)
|
||||||
$(cc) $(cFLAGS) dirToString.c -o $(BIN)/dirToString
|
$(cc) $(cFLAGS) dirToString.c -o $(BIN)/dirToString
|
||||||
|
|
||||||
|
|
||||||
$(BIN)/wmkdep: wmkdep.l
|
$(BIN)/wmkdep: wmkdep.l
|
||||||
@mkdir -p $(BIN)
|
@mkdir -p $(BIN)
|
||||||
flex wmkdep.l
|
flex wmkdep.l
|
||||||
@ -77,4 +78,13 @@ $(BIN)/wmkdep: wmkdep.l
|
|||||||
@rm -f lex.yy.c 2>/dev/null
|
@rm -f lex.yy.c 2>/dev/null
|
||||||
|
|
||||||
|
|
||||||
|
# for bootstrapping - use generated files directly (instead of from .atg file)
|
||||||
|
$(BIN)/wmkdepend: wmkdepend.cpp \
|
||||||
|
wmkdependParser.cpp wmkdependScanner.cpp \
|
||||||
|
wmkdependParser.h wmkdependScanner.h
|
||||||
|
@mkdir -p $(BIN)
|
||||||
|
$(CC) $(c++FLAGS) \
|
||||||
|
wmkdepend.cpp wmkdependParser.cpp wmkdependScanner.cpp \
|
||||||
|
-o $(BIN)/wmkdepend
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|||||||
164
wmake/src/wmkdepend.cpp
Normal file
164
wmake/src/wmkdepend.cpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / 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
|
||||||
|
|
||||||
|
Application
|
||||||
|
wmkdepend
|
||||||
|
|
||||||
|
Description
|
||||||
|
A fast dependency list generator that emulates the behaviour and
|
||||||
|
output of cpp -M. However, the output contains no duplications and
|
||||||
|
is ~40% faster than cpp.
|
||||||
|
|
||||||
|
The algorithm uses flex to scan for includes and searches the files
|
||||||
|
found. Each file is entered into a hash table so that files are scanned
|
||||||
|
only once. This is why this program is faster than cpp.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
wmkdep [ -Idirectory ... -Idirectory ] filename
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "wmkdependParser.h"
|
||||||
|
|
||||||
|
// Note: since we use the Coco/R default error messages, we must use
|
||||||
|
// wide streams for stderr.
|
||||||
|
|
||||||
|
void printUsage(const char* message = NULL)
|
||||||
|
{
|
||||||
|
if (message)
|
||||||
|
{
|
||||||
|
fwprintf(stderr, L"\nError: %s\n\n", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwprintf
|
||||||
|
(
|
||||||
|
stderr,
|
||||||
|
L"Usage: wmkdepend [ -Idirectory ... -Idirectory ] filename\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
|
printUsage("Error: input file not supplied");
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (strncmp(argv[i], "-I", 2) == 0 && strlen(argv[i]) > 2)
|
||||||
|
{
|
||||||
|
std::string dirName(argv[i] + 2);
|
||||||
|
|
||||||
|
// add trailing slash if required
|
||||||
|
if (dirName.rfind('/') != dirName.size()-1)
|
||||||
|
{
|
||||||
|
dirName += '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
wmake::Parser::includeDirs.push_back(dirName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sourceFile(argv[argc-1]);
|
||||||
|
|
||||||
|
fwprintf
|
||||||
|
(
|
||||||
|
stderr,
|
||||||
|
L"Making dependency list for source file %s\n",
|
||||||
|
sourceFile.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string::size_type basePos = sourceFile.rfind('/');
|
||||||
|
if (basePos == std::string::npos)
|
||||||
|
{
|
||||||
|
basePos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
basePos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string::size_type dotPos = sourceFile.rfind('.');
|
||||||
|
if
|
||||||
|
(
|
||||||
|
dotPos == std::string::npos
|
||||||
|
|| dotPos == sourceFile.size()-1
|
||||||
|
|| dotPos <= basePos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
fwprintf
|
||||||
|
(
|
||||||
|
stderr,
|
||||||
|
L"Cannot find extension in source file name %s\n",
|
||||||
|
sourceFile.c_str()
|
||||||
|
);
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string depFile = sourceFile.substr(0, dotPos);
|
||||||
|
depFile += ".dep";
|
||||||
|
|
||||||
|
const std::string sourceExt = sourceFile.substr(dotPos);
|
||||||
|
if (sourceExt == ".java")
|
||||||
|
{
|
||||||
|
// import directories to ignore
|
||||||
|
wmake::Parser::ignoreDir("java.*");
|
||||||
|
wmake::Parser::ignoreDir("org.*");
|
||||||
|
wmake::Parser::ignoreDir("com.*");
|
||||||
|
wmake::Parser::ignoreDir("sunw.*");
|
||||||
|
wmake::Parser::ignoreDir("sun.*");
|
||||||
|
wmake::Parser::ignoreDir("launcher.*");
|
||||||
|
|
||||||
|
std::cout
|
||||||
|
<< "$(CLASSES_DIR)/"
|
||||||
|
<< sourceFile.substr(basePos, dotPos - basePos) << ".class: "
|
||||||
|
<< depFile << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout
|
||||||
|
<< "$(OBJECTS_DIR)/"
|
||||||
|
<< sourceFile.substr(basePos, dotPos - basePos) << ".o: "
|
||||||
|
<< depFile << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wmake::Parser::sourceFile = sourceFile;
|
||||||
|
wmake::Parser::depFile = depFile;
|
||||||
|
|
||||||
|
wmake::Parser::includeFile(sourceFile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
497
wmake/src/wmkdependParser.atg
Normal file
497
wmake/src/wmkdependParser.atg
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Attributed Grammar for Coco/R (-*- C++ -*- version)
|
||||||
|
compile with:
|
||||||
|
coco-cpp wmkdependParser.atg
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
[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 wmkdependParser.atg
|
||||||
|
|
||||||
|
Description
|
||||||
|
An attributed Coco/R grammar to parse C/C++, Fortran and Java files
|
||||||
|
for include and import statements.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
generated
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
[/copy]
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
//! @brief A simple HashTable implementation
|
||||||
|
/**
|
||||||
|
* @note This hash table is only vaguely STL-like. In accordance with
|
||||||
|
* its present purpose, this hash table only supports a constIterator
|
||||||
|
* and no deletions. For simplicity, the constIterator increment is
|
||||||
|
* simply via a next() method. Instead of comparing to an end value,
|
||||||
|
* the constIterator valid() method is used.
|
||||||
|
* For example,
|
||||||
|
* @code
|
||||||
|
* for
|
||||||
|
* (
|
||||||
|
* HashTable<foo>::constIterator iter = myHash.begin();
|
||||||
|
* iter.valid();
|
||||||
|
* iter.next()
|
||||||
|
* )
|
||||||
|
* {
|
||||||
|
* std::cerr<< "key: " << iter.key() << "\n";
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class StringHashSet
|
||||||
|
{
|
||||||
|
//! An entry within the HashTable
|
||||||
|
struct hashedEntry
|
||||||
|
{
|
||||||
|
const std::string key_; //<! The lookup key
|
||||||
|
hashedEntry *next_; //<! Pointer to next hashedEntry in sub-list
|
||||||
|
|
||||||
|
hashedEntry(const std::string& key, hashedEntry *next=0)
|
||||||
|
:
|
||||||
|
key_(key), next_(next)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
const int size_; //<! fixed HashTable size
|
||||||
|
hashedEntry** table_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Construct with a default size
|
||||||
|
StringHashSet(int size = 500)
|
||||||
|
:
|
||||||
|
size_(size),
|
||||||
|
table_(new hashedEntry*[size_])
|
||||||
|
{
|
||||||
|
memset(table_, 0, size_ * sizeof(hashedEntry*));
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Destructor
|
||||||
|
~StringHashSet()
|
||||||
|
{
|
||||||
|
for (int hashIdx = 0; hashIdx < size_; ++hashIdx)
|
||||||
|
{
|
||||||
|
hashedEntry* ep = table_[hashIdx];
|
||||||
|
while (ep)
|
||||||
|
{
|
||||||
|
hashedEntry* del = ep;
|
||||||
|
ep = ep->next_;
|
||||||
|
delete del;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] table_;
|
||||||
|
table_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Return hash index for lookup name in hash table
|
||||||
|
bool hashKeyIndex(const std::string& name) const
|
||||||
|
{
|
||||||
|
int hashIdx = 0;
|
||||||
|
|
||||||
|
// calculate hash index
|
||||||
|
for
|
||||||
|
(
|
||||||
|
std::string::const_iterator iter = name.begin();
|
||||||
|
iter != name.end();
|
||||||
|
++iter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
hashIdx = hashIdx << 1 ^ *iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashIdx < 0)
|
||||||
|
{
|
||||||
|
hashIdx = -hashIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashIdx % size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Return true if name is found in hash table
|
||||||
|
bool found(const std::string& name) const
|
||||||
|
{
|
||||||
|
const int hashIdx = hashKeyIndex(name);
|
||||||
|
|
||||||
|
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||||
|
{
|
||||||
|
if (name == ep->key_)
|
||||||
|
{
|
||||||
|
// found
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry not found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Return true if name is found in hash table, insert if not found
|
||||||
|
bool foundOrInsert(const std::string& name)
|
||||||
|
{
|
||||||
|
const int hashIdx = hashKeyIndex(name);
|
||||||
|
|
||||||
|
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||||
|
{
|
||||||
|
if (name == ep->key_)
|
||||||
|
{
|
||||||
|
// found - return true
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not found - insert it
|
||||||
|
table_[hashIdx] = new hashedEntry(name, table_[hashIdx]);
|
||||||
|
|
||||||
|
// entry not found (but was added) - return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
COMPILER wmkdepend
|
||||||
|
// grammar pragmas:
|
||||||
|
$namespace=wmake
|
||||||
|
$prefix=wmkdepend
|
||||||
|
$define=FORCE_UTF8
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
private:
|
||||||
|
|
||||||
|
//! Hash of files already visited
|
||||||
|
static StringHashSet visitedFiles_;
|
||||||
|
|
||||||
|
//! Hash of (java) directories already visited
|
||||||
|
static StringHashSet visitedDirs_;
|
||||||
|
|
||||||
|
//! Replace all '.' with '/'
|
||||||
|
static void dotToSlash(std::string& name);
|
||||||
|
|
||||||
|
//! Import (java) directories
|
||||||
|
static void importDir(const std::string& dirName);
|
||||||
|
|
||||||
|
//! Import (java) file
|
||||||
|
static void importFile(const std::string& name);
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! Include directories to search
|
||||||
|
static std::list<std::string> includeDirs;
|
||||||
|
|
||||||
|
//! The name of the top-level source file
|
||||||
|
static std::string sourceFile;
|
||||||
|
|
||||||
|
//! The name of the top-level dep file
|
||||||
|
static std::string depFile;
|
||||||
|
|
||||||
|
//! Add directory to list of visited dirs, thus effectively ignoring it
|
||||||
|
static void ignoreDir(const std::string& name);
|
||||||
|
|
||||||
|
//! Include file
|
||||||
|
static void includeFile(const std::string& name);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
[code]
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
StringHashSet Parser::visitedFiles_;
|
||||||
|
StringHashSet Parser::visitedDirs_;
|
||||||
|
|
||||||
|
std::list<std::string> Parser::includeDirs;
|
||||||
|
std::string Parser::sourceFile;
|
||||||
|
std::string Parser::depFile;
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::dotToSlash(std::string& name)
|
||||||
|
{
|
||||||
|
std::string::size_type start = 0;
|
||||||
|
|
||||||
|
while ((start = name.find('.', start)) != std::string::npos)
|
||||||
|
{
|
||||||
|
name.replace(start, 1, 1, '/');
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::ignoreDir(const std::string& name)
|
||||||
|
{
|
||||||
|
visitedDirs_.foundOrInsert(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::includeFile(const std::string& name)
|
||||||
|
{
|
||||||
|
if (visitedFiles_.foundOrInsert(name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use stdio and buffering within Coco/R -- (faster)
|
||||||
|
FILE *fh = fopen(name.c_str(), "r");
|
||||||
|
if (fh)
|
||||||
|
{
|
||||||
|
std::cout << depFile << ": " << name << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for
|
||||||
|
(
|
||||||
|
std::list<std::string>::const_iterator iter = includeDirs.begin();
|
||||||
|
iter != includeDirs.end();
|
||||||
|
++iter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const std::string pathName = *iter + name;
|
||||||
|
|
||||||
|
fh = fopen(pathName.c_str(), "r");
|
||||||
|
if (fh)
|
||||||
|
{
|
||||||
|
std::cout << depFile << ": " << pathName << "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fh)
|
||||||
|
{
|
||||||
|
Scanner scanner(fh);
|
||||||
|
Parser parser(&scanner);
|
||||||
|
|
||||||
|
parser.Parse();
|
||||||
|
fclose(fh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fwprintf
|
||||||
|
(
|
||||||
|
stderr,
|
||||||
|
L"could not open file %s for source file %s\n",
|
||||||
|
name.c_str(), sourceFile.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::importFile(const std::string& name)
|
||||||
|
{
|
||||||
|
// check if a globbed form was already visited
|
||||||
|
std::string::size_type dotPos = name.find('.');
|
||||||
|
if (dotPos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string dirGlob = name.substr(0, dotPos);
|
||||||
|
dirGlob += ".*";
|
||||||
|
|
||||||
|
if (visitedDirs_.found(dirGlob))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string javaFileName = name;
|
||||||
|
|
||||||
|
dotToSlash(javaFileName);
|
||||||
|
javaFileName += ".java";
|
||||||
|
|
||||||
|
includeFile(javaFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::importDir(const std::string& name)
|
||||||
|
{
|
||||||
|
if (visitedDirs_.foundOrInsert(name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dirName = name;
|
||||||
|
dotToSlash(dirName);
|
||||||
|
|
||||||
|
DIR *source = opendir(dirName.c_str());
|
||||||
|
|
||||||
|
if (source)
|
||||||
|
{
|
||||||
|
struct dirent *list;
|
||||||
|
|
||||||
|
// Read and parse all the entries in the directory
|
||||||
|
while ((list = readdir(source)) != NULL)
|
||||||
|
{
|
||||||
|
const char* ext = strstr(list->d_name, ".java");
|
||||||
|
|
||||||
|
// avoid matching on something like '.java~'
|
||||||
|
if (ext && strlen(ext) == 5)
|
||||||
|
{
|
||||||
|
std::string pathName = dirName + list->d_name;
|
||||||
|
includeFile(pathName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fwprintf
|
||||||
|
(
|
||||||
|
stderr,
|
||||||
|
L"could not open directory %s\n",
|
||||||
|
dirName.c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[/code]
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
CHARACTERS
|
||||||
|
letter = 'A'..'Z' + 'a'..'z' + '_'.
|
||||||
|
digit = "0123456789".
|
||||||
|
cr = '\r'.
|
||||||
|
lf = '\n'.
|
||||||
|
tab = '\t'.
|
||||||
|
stringCh = ANY - '"' - '\\' - cr - lf.
|
||||||
|
printable = '\u0020' .. '\u007e'.
|
||||||
|
java_letter = letter + '$'.
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * TOKENS * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
TOKENS
|
||||||
|
|
||||||
|
// string
|
||||||
|
string =
|
||||||
|
'"' { stringCh | '\\' printable } '"'.
|
||||||
|
|
||||||
|
// single-quoted string (eg, Fortran)
|
||||||
|
sqstring =
|
||||||
|
'\'' { stringCh | '\\' printable } '\''.
|
||||||
|
|
||||||
|
// for java import
|
||||||
|
package_name =
|
||||||
|
java_letter { java_letter | digit }
|
||||||
|
{ '.' java_letter { java_letter | digit } } .
|
||||||
|
|
||||||
|
// for java import
|
||||||
|
package_dir =
|
||||||
|
java_letter { java_letter | digit }
|
||||||
|
{ '.' java_letter { java_letter | digit } } ".*" .
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * PRAGMAS / COMMENTS / IGNORE * * * * * * * * * * * //
|
||||||
|
|
||||||
|
COMMENTS FROM "/*" TO "*/" NESTED
|
||||||
|
COMMENTS FROM "//" TO lf
|
||||||
|
|
||||||
|
IGNORE tab
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * PRODUCTIONS * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
PRODUCTIONS
|
||||||
|
|
||||||
|
wmkdepend
|
||||||
|
=
|
||||||
|
{
|
||||||
|
// C/C++-style includes
|
||||||
|
'#'
|
||||||
|
[
|
||||||
|
"include"
|
||||||
|
[
|
||||||
|
string (.
|
||||||
|
if (isUTF8())
|
||||||
|
{
|
||||||
|
includeFile(t->toStringUTF8(1, t->length()-2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
includeFile(t->toString(1, t->length()-2));
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[ ANY { ANY } ] '\n' // skip trailing junk
|
||||||
|
|
||||||
|
// Fortran-style includes
|
||||||
|
| "include"
|
||||||
|
[
|
||||||
|
sqstring (.
|
||||||
|
if (isUTF8())
|
||||||
|
{
|
||||||
|
includeFile(t->toStringUTF8(1, t->length()-2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
includeFile(t->toString(1, t->length()-2));
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
]
|
||||||
|
[ ANY { ANY } ] '\n' // skip trailing junk
|
||||||
|
|
||||||
|
// Java imports
|
||||||
|
| "import"
|
||||||
|
(
|
||||||
|
package_dir (.
|
||||||
|
if (isUTF8())
|
||||||
|
{
|
||||||
|
importDir(t->toStringUTF8());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
importDir(t->toString());
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
| package_name (.
|
||||||
|
if (isUTF8())
|
||||||
|
{
|
||||||
|
importFile(t->toStringUTF8());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
importFile(t->toString());
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
)
|
||||||
|
';'
|
||||||
|
[ ANY { ANY } ] '\n' // skip trailing junk
|
||||||
|
|
||||||
|
| [ ANY { ANY } ] '\n' // skip any other lines
|
||||||
|
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
END wmkdepend.
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
575
wmake/src/wmkdependParser.cpp
Normal file
575
wmake/src/wmkdependParser.cpp
Normal file
@ -0,0 +1,575 @@
|
|||||||
|
/*---------------------------------*- 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 wmkdependParser.atg
|
||||||
|
|
||||||
|
Description
|
||||||
|
An attributed Coco/R grammar to parse C/C++, Fortran and Java files
|
||||||
|
for include and import statements.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
generated
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
// This file was generated with Coco/R C++ (7 Feb 2010)
|
||||||
|
// http://www.ssw.uni-linz.ac.at/coco/
|
||||||
|
// with these defines:
|
||||||
|
// - FORCE_UTF8
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cwchar>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "wmkdependParser.h"
|
||||||
|
|
||||||
|
namespace wmake {
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
StringHashSet Parser::visitedFiles_;
|
||||||
|
StringHashSet Parser::visitedDirs_;
|
||||||
|
|
||||||
|
std::list<std::string> Parser::includeDirs;
|
||||||
|
std::string Parser::sourceFile;
|
||||||
|
std::string Parser::depFile;
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::dotToSlash(std::string& name)
|
||||||
|
{
|
||||||
|
std::string::size_type start = 0;
|
||||||
|
|
||||||
|
while ((start = name.find('.', start)) != std::string::npos)
|
||||||
|
{
|
||||||
|
name.replace(start, 1, 1, '/');
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::ignoreDir(const std::string& name)
|
||||||
|
{
|
||||||
|
visitedDirs_.foundOrInsert(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::includeFile(const std::string& name)
|
||||||
|
{
|
||||||
|
if (visitedFiles_.foundOrInsert(name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use stdio and buffering within Coco/R -- (faster)
|
||||||
|
FILE *fh = fopen(name.c_str(), "r");
|
||||||
|
if (fh)
|
||||||
|
{
|
||||||
|
std::cout << depFile << ": " << name << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for
|
||||||
|
(
|
||||||
|
std::list<std::string>::const_iterator iter = includeDirs.begin();
|
||||||
|
iter != includeDirs.end();
|
||||||
|
++iter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const std::string pathName = *iter + name;
|
||||||
|
|
||||||
|
fh = fopen(pathName.c_str(), "r");
|
||||||
|
if (fh)
|
||||||
|
{
|
||||||
|
std::cout << depFile << ": " << pathName << "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fh)
|
||||||
|
{
|
||||||
|
Scanner scanner(fh);
|
||||||
|
Parser parser(&scanner);
|
||||||
|
|
||||||
|
parser.Parse();
|
||||||
|
fclose(fh);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fwprintf
|
||||||
|
(
|
||||||
|
stderr,
|
||||||
|
L"could not open file %s for source file %s\n",
|
||||||
|
name.c_str(), sourceFile.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::importFile(const std::string& name)
|
||||||
|
{
|
||||||
|
// check if a globbed form was already visited
|
||||||
|
std::string::size_type dotPos = name.find('.');
|
||||||
|
if (dotPos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string dirGlob = name.substr(0, dotPos);
|
||||||
|
dirGlob += ".*";
|
||||||
|
|
||||||
|
if (visitedDirs_.found(dirGlob))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string javaFileName = name;
|
||||||
|
|
||||||
|
dotToSlash(javaFileName);
|
||||||
|
javaFileName += ".java";
|
||||||
|
|
||||||
|
includeFile(javaFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::importDir(const std::string& name)
|
||||||
|
{
|
||||||
|
if (visitedDirs_.foundOrInsert(name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dirName = name;
|
||||||
|
dotToSlash(dirName);
|
||||||
|
|
||||||
|
DIR *source = opendir(dirName.c_str());
|
||||||
|
|
||||||
|
if (source)
|
||||||
|
{
|
||||||
|
struct dirent *list;
|
||||||
|
|
||||||
|
// Read and parse all the entries in the directory
|
||||||
|
while ((list = readdir(source)) != NULL)
|
||||||
|
{
|
||||||
|
const char* ext = strstr(list->d_name, ".java");
|
||||||
|
|
||||||
|
// avoid matching on something like '.java~'
|
||||||
|
if (ext && strlen(ext) == 5)
|
||||||
|
{
|
||||||
|
std::string pathName = dirName + list->d_name;
|
||||||
|
includeFile(pathName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fwprintf
|
||||||
|
(
|
||||||
|
stderr,
|
||||||
|
L"could not open directory %s\n",
|
||||||
|
dirName.c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//! @cond fileScope
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create by copying str - only used locally
|
||||||
|
inline static wchar_t* coco_string_create(const wchar_t* str)
|
||||||
|
{
|
||||||
|
const int len = wcslen(str);
|
||||||
|
wchar_t* dst = new wchar_t[len + 1];
|
||||||
|
wcsncpy(dst, str, len);
|
||||||
|
dst[len] = 0;
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Free storage and nullify the argument
|
||||||
|
inline static void coco_string_delete(wchar_t* &str)
|
||||||
|
{
|
||||||
|
delete[] str;
|
||||||
|
str = NULL;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//! @endcond fileScope
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Parser Implementation
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Parser::SynErr(int n)
|
||||||
|
{
|
||||||
|
if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::SemErr(const std::wstring& msg)
|
||||||
|
{
|
||||||
|
if (errDist >= minErrDist) errors->Error(t->line, t->col, msg);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Parser::isUTF8() const
|
||||||
|
{
|
||||||
|
return scanner && scanner->buffer && scanner->buffer->isUTF8();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::Get()
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
t = la;
|
||||||
|
la = scanner->Scan();
|
||||||
|
if (la->kind <= maxT)
|
||||||
|
{
|
||||||
|
++errDist;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dummyToken != t)
|
||||||
|
{
|
||||||
|
dummyToken->kind = t->kind;
|
||||||
|
dummyToken->pos = t->pos;
|
||||||
|
dummyToken->col = t->col;
|
||||||
|
dummyToken->line = t->line;
|
||||||
|
dummyToken->next = NULL;
|
||||||
|
coco_string_delete(dummyToken->val);
|
||||||
|
dummyToken->val = coco_string_create(t->val);
|
||||||
|
t = dummyToken;
|
||||||
|
}
|
||||||
|
la = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::Expect(int n)
|
||||||
|
{
|
||||||
|
if (la->kind == n)
|
||||||
|
{
|
||||||
|
Get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SynErr(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::ExpectWeak(int n, int follow)
|
||||||
|
{
|
||||||
|
if (la->kind == n)
|
||||||
|
{
|
||||||
|
Get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SynErr(n);
|
||||||
|
while (!StartOf(follow))
|
||||||
|
{
|
||||||
|
Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Parser::WeakSeparator(int n, int syFol, int repFol)
|
||||||
|
{
|
||||||
|
if (la->kind == n)
|
||||||
|
{
|
||||||
|
Get();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (StartOf(repFol))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SynErr(n);
|
||||||
|
while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0)))
|
||||||
|
{
|
||||||
|
Get();
|
||||||
|
}
|
||||||
|
return StartOf(syFol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::wmkdepend()
|
||||||
|
{
|
||||||
|
while (StartOf(1)) {
|
||||||
|
if (la->kind == 5) {
|
||||||
|
Get();
|
||||||
|
if (la->kind == 6) {
|
||||||
|
Get();
|
||||||
|
if (la->kind == 1) {
|
||||||
|
Get();
|
||||||
|
if (isUTF8())
|
||||||
|
{
|
||||||
|
includeFile(t->toStringUTF8(1, t->length()-2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
includeFile(t->toString(1, t->length()-2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StartOf(2)) {
|
||||||
|
Get();
|
||||||
|
while (StartOf(3)) {
|
||||||
|
Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(7);
|
||||||
|
} else if (la->kind == 6) {
|
||||||
|
Get();
|
||||||
|
if (la->kind == 2) {
|
||||||
|
Get();
|
||||||
|
if (isUTF8())
|
||||||
|
{
|
||||||
|
includeFile(t->toStringUTF8(1, t->length()-2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
includeFile(t->toString(1, t->length()-2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (StartOf(4)) {
|
||||||
|
Get();
|
||||||
|
while (StartOf(3)) {
|
||||||
|
Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(7);
|
||||||
|
} else if (la->kind == 8) {
|
||||||
|
Get();
|
||||||
|
if (la->kind == 4) {
|
||||||
|
Get();
|
||||||
|
if (isUTF8())
|
||||||
|
{
|
||||||
|
importDir(t->toStringUTF8());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
importDir(t->toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (la->kind == 3) {
|
||||||
|
Get();
|
||||||
|
if (isUTF8())
|
||||||
|
{
|
||||||
|
importFile(t->toStringUTF8());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
importFile(t->toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else SynErr(11);
|
||||||
|
Expect(9);
|
||||||
|
if (StartOf(3)) {
|
||||||
|
Get();
|
||||||
|
while (StartOf(3)) {
|
||||||
|
Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(7);
|
||||||
|
} else {
|
||||||
|
if (StartOf(5)) {
|
||||||
|
Get();
|
||||||
|
while (StartOf(3)) {
|
||||||
|
Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Parser::Parse()
|
||||||
|
{
|
||||||
|
t = NULL;
|
||||||
|
// might call Parse() twice
|
||||||
|
if (dummyToken) {
|
||||||
|
coco_string_delete(dummyToken->val);
|
||||||
|
delete dummyToken;
|
||||||
|
}
|
||||||
|
dummyToken = new Token(coco_string_create(L"Dummy Token"));
|
||||||
|
la = dummyToken;
|
||||||
|
Get();
|
||||||
|
wmkdepend();
|
||||||
|
Expect(0); // expect end-of-file automatically added
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Parser::Parser(Scanner* scan, Errors* err)
|
||||||
|
:
|
||||||
|
dummyToken(NULL),
|
||||||
|
deleteErrorsDestruct_(!err),
|
||||||
|
errDist(minErrDist),
|
||||||
|
scanner(scan),
|
||||||
|
errors(err),
|
||||||
|
t(NULL),
|
||||||
|
la(NULL)
|
||||||
|
{
|
||||||
|
if (!errors) // add in default error handling
|
||||||
|
{
|
||||||
|
errors = new Errors();
|
||||||
|
}
|
||||||
|
// user-defined initializations:
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Parser::StartOf(int s)
|
||||||
|
{
|
||||||
|
const bool T = true;
|
||||||
|
const bool x = false;
|
||||||
|
|
||||||
|
static const bool set[6][12] =
|
||||||
|
{
|
||||||
|
{T,x,x,x, x,x,x,x, x,x,x,x},
|
||||||
|
{x,T,T,T, T,T,T,T, T,T,T,x},
|
||||||
|
{x,x,T,T, T,T,x,x, T,T,T,x},
|
||||||
|
{x,T,T,T, T,T,T,x, T,T,T,x},
|
||||||
|
{x,T,x,T, T,T,T,x, T,T,T,x},
|
||||||
|
{x,T,T,T, T,x,x,x, x,T,T,x}
|
||||||
|
};
|
||||||
|
|
||||||
|
return set[s][la->kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Parser::~Parser()
|
||||||
|
{
|
||||||
|
if (deleteErrorsDestruct_) { delete errors; } // delete default error handling
|
||||||
|
if (dummyToken) {
|
||||||
|
coco_string_delete(dummyToken->val);
|
||||||
|
delete dummyToken;
|
||||||
|
}
|
||||||
|
// user-defined destruction:
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Errors Implementation
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Errors::Errors()
|
||||||
|
:
|
||||||
|
count(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Errors::~Errors()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Errors::clear()
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::wstring Errors::strerror(int n)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 0: return L"EOF expected"; break;
|
||||||
|
case 1: return L"string expected"; break;
|
||||||
|
case 2: return L"sqstring expected"; break;
|
||||||
|
case 3: return L"package_name expected"; break;
|
||||||
|
case 4: return L"package_dir expected"; break;
|
||||||
|
case 5: return L"\"#\" expected"; break;
|
||||||
|
case 6: return L"\"include\" expected"; break;
|
||||||
|
case 7: return L"\"\\n\" expected"; break;
|
||||||
|
case 8: return L"\"import\" expected"; break;
|
||||||
|
case 9: return L"\";\" expected"; break;
|
||||||
|
case 10: return L"??? expected"; break;
|
||||||
|
case 11: return L"invalid wmkdepend"; break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// std::wostringstream buf; (this typedef might be missing)
|
||||||
|
std::basic_ostringstream<wchar_t> buf;
|
||||||
|
buf << "error " << n;
|
||||||
|
return buf.str();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Errors::Warning(const std::wstring& msg)
|
||||||
|
{
|
||||||
|
fwprintf(stderr, L"%ls\n", msg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Errors::Warning(int line, int col, const std::wstring& msg)
|
||||||
|
{
|
||||||
|
fwprintf(stderr, L"-- line %d col %d: %ls\n", line, col, msg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Errors::Error(int line, int col, const std::wstring& msg)
|
||||||
|
{
|
||||||
|
fwprintf(stderr, L"-- line %d col %d: %ls\n", line, col, msg.c_str());
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Errors::SynErr(int line, int col, int n)
|
||||||
|
{
|
||||||
|
this->Error(line, col, this->strerror(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Errors::Exception(const std::wstring& msg)
|
||||||
|
{
|
||||||
|
fwprintf(stderr, L"%ls", msg.c_str());
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
310
wmake/src/wmkdependParser.h
Normal file
310
wmake/src/wmkdependParser.h
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
/*---------------------------------*- 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 wmkdependParser.atg
|
||||||
|
|
||||||
|
Description
|
||||||
|
An attributed Coco/R grammar to parse C/C++, Fortran and Java files
|
||||||
|
for include and import statements.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
generated
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
// This file was generated with Coco/R C++ (7 Feb 2010)
|
||||||
|
// http://www.ssw.uni-linz.ac.at/coco/
|
||||||
|
// with these defines:
|
||||||
|
// - FORCE_UTF8
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef COCO_wmkdependPARSER_H__
|
||||||
|
#define COCO_wmkdependPARSER_H__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
//! @brief A simple HashTable implementation
|
||||||
|
/**
|
||||||
|
* @note This hash table is only vaguely STL-like. In accordance with
|
||||||
|
* its present purpose, this hash table only supports a constIterator
|
||||||
|
* and no deletions. For simplicity, the constIterator increment is
|
||||||
|
* simply via a next() method. Instead of comparing to an end value,
|
||||||
|
* the constIterator valid() method is used.
|
||||||
|
* For example,
|
||||||
|
* @code
|
||||||
|
* for
|
||||||
|
* (
|
||||||
|
* HashTable<foo>::constIterator iter = myHash.begin();
|
||||||
|
* iter.valid();
|
||||||
|
* iter.next()
|
||||||
|
* )
|
||||||
|
* {
|
||||||
|
* std::cerr<< "key: " << iter.key() << "\n";
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class StringHashSet
|
||||||
|
{
|
||||||
|
//! An entry within the HashTable
|
||||||
|
struct hashedEntry
|
||||||
|
{
|
||||||
|
const std::string key_; //<! The lookup key
|
||||||
|
hashedEntry *next_; //<! Pointer to next hashedEntry in sub-list
|
||||||
|
|
||||||
|
hashedEntry(const std::string& key, hashedEntry *next=0)
|
||||||
|
:
|
||||||
|
key_(key), next_(next)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
const int size_; //<! fixed HashTable size
|
||||||
|
hashedEntry** table_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Construct with a default size
|
||||||
|
StringHashSet(int size = 500)
|
||||||
|
:
|
||||||
|
size_(size),
|
||||||
|
table_(new hashedEntry*[size_])
|
||||||
|
{
|
||||||
|
memset(table_, 0, size_ * sizeof(hashedEntry*));
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Destructor
|
||||||
|
~StringHashSet()
|
||||||
|
{
|
||||||
|
for (int hashIdx = 0; hashIdx < size_; ++hashIdx)
|
||||||
|
{
|
||||||
|
hashedEntry* ep = table_[hashIdx];
|
||||||
|
while (ep)
|
||||||
|
{
|
||||||
|
hashedEntry* del = ep;
|
||||||
|
ep = ep->next_;
|
||||||
|
delete del;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] table_;
|
||||||
|
table_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Return hash index for lookup name in hash table
|
||||||
|
bool hashKeyIndex(const std::string& name) const
|
||||||
|
{
|
||||||
|
int hashIdx = 0;
|
||||||
|
|
||||||
|
// calculate hash index
|
||||||
|
for
|
||||||
|
(
|
||||||
|
std::string::const_iterator iter = name.begin();
|
||||||
|
iter != name.end();
|
||||||
|
++iter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
hashIdx = hashIdx << 1 ^ *iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashIdx < 0)
|
||||||
|
{
|
||||||
|
hashIdx = -hashIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashIdx % size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Return true if name is found in hash table
|
||||||
|
bool found(const std::string& name) const
|
||||||
|
{
|
||||||
|
const int hashIdx = hashKeyIndex(name);
|
||||||
|
|
||||||
|
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||||
|
{
|
||||||
|
if (name == ep->key_)
|
||||||
|
{
|
||||||
|
// found
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry not found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Return true if name is found in hash table, insert if not found
|
||||||
|
bool foundOrInsert(const std::string& name)
|
||||||
|
{
|
||||||
|
const int hashIdx = hashKeyIndex(name);
|
||||||
|
|
||||||
|
for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
|
||||||
|
{
|
||||||
|
if (name == ep->key_)
|
||||||
|
{
|
||||||
|
// found - return true
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not found - insert it
|
||||||
|
table_[hashIdx] = new hashedEntry(name, table_[hashIdx]);
|
||||||
|
|
||||||
|
// entry not found (but was added) - return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "wmkdependScanner.h"
|
||||||
|
|
||||||
|
namespace wmake {
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class Errors Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
//! Parser error handing
|
||||||
|
class Errors
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int count; //!< The number of errors detected
|
||||||
|
|
||||||
|
//! Return a string describing the given error code.
|
||||||
|
static std::wstring strerror(int n);
|
||||||
|
|
||||||
|
Errors(); //!< Construct null - start with no errors
|
||||||
|
virtual ~Errors(); //!< Destructor
|
||||||
|
virtual void clear(); //!< Clear the error count
|
||||||
|
|
||||||
|
//! Handle a general warning 'msg'
|
||||||
|
virtual void Warning(const std::wstring& msg);
|
||||||
|
//! Handle a general warning 'msg'
|
||||||
|
virtual void Warning(int line, int col, const std::wstring& msg);
|
||||||
|
//! Handle general error 'msg' (eg, a semantic error)
|
||||||
|
virtual void Error(int line, int col, const std::wstring& msg);
|
||||||
|
//! Handle syntax error 'n', uses strerror for the message, calls Error()
|
||||||
|
virtual void SynErr(int line, int col, int n);
|
||||||
|
//! Handle a general exception 'msg'
|
||||||
|
virtual void Exception(const std::wstring& msg);
|
||||||
|
|
||||||
|
}; // Errors
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class Parser Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
//! A Coco/R Parser
|
||||||
|
class Parser
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
_EOF=0,
|
||||||
|
_string=1,
|
||||||
|
_sqstring=2,
|
||||||
|
_package_name=3,
|
||||||
|
_package_dir=4,
|
||||||
|
maxT = 10 //<! max term (w/o pragmas)
|
||||||
|
};
|
||||||
|
static const int minErrDist = 2; //!< min. distance before reporting errors
|
||||||
|
|
||||||
|
Token *dummyToken;
|
||||||
|
bool deleteErrorsDestruct_; //!< delete the 'errors' member in destructor
|
||||||
|
int errDist;
|
||||||
|
|
||||||
|
void SynErr(int n); //!< Handle syntax error 'n'
|
||||||
|
void Get();
|
||||||
|
void Expect(int n);
|
||||||
|
bool StartOf(int s);
|
||||||
|
void ExpectWeak(int n, int follow);
|
||||||
|
bool WeakSeparator(int n, int syFol, int repFol);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Scanner *scanner;
|
||||||
|
Errors *errors;
|
||||||
|
|
||||||
|
Token *t; //!< last recognized token
|
||||||
|
Token *la; //!< lookahead token
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//! Hash of files already visited
|
||||||
|
static StringHashSet visitedFiles_;
|
||||||
|
|
||||||
|
//! Hash of (java) directories already visited
|
||||||
|
static StringHashSet visitedDirs_;
|
||||||
|
|
||||||
|
//! Replace all '.' with '/'
|
||||||
|
static void dotToSlash(std::string& name);
|
||||||
|
|
||||||
|
//! Import (java) directories
|
||||||
|
static void importDir(const std::string& dirName);
|
||||||
|
|
||||||
|
//! Import (java) file
|
||||||
|
static void importFile(const std::string& name);
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! Include directories to search
|
||||||
|
static std::list<std::string> includeDirs;
|
||||||
|
|
||||||
|
//! The name of the top-level source file
|
||||||
|
static std::string sourceFile;
|
||||||
|
|
||||||
|
//! The name of the top-level dep file
|
||||||
|
static std::string depFile;
|
||||||
|
|
||||||
|
//! Add directory to list of visited dirs, thus effectively ignoring it
|
||||||
|
static void ignoreDir(const std::string& name);
|
||||||
|
|
||||||
|
//! Include file
|
||||||
|
static void includeFile(const std::string& name);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//! Construct for the specified scanner
|
||||||
|
/*!
|
||||||
|
* Use the default error handling, or optionally provide an error
|
||||||
|
* handler, which will not be deleted upon destruction.
|
||||||
|
*/
|
||||||
|
Parser(Scanner* scan, Errors* err = 0);
|
||||||
|
~Parser();
|
||||||
|
void Parse(); //!< Execute the parse operation
|
||||||
|
void SemErr(const std::wstring& msg); //!< Handle semantic error
|
||||||
|
bool isUTF8() const; //!< Return true if scanner buffer is UTF8
|
||||||
|
|
||||||
|
void wmkdepend();
|
||||||
|
|
||||||
|
}; // end Parser
|
||||||
|
|
||||||
|
} // End namespace
|
||||||
|
|
||||||
|
#endif // COCO_wmkdependPARSER_H__
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
1022
wmake/src/wmkdependScanner.cpp
Normal file
1022
wmake/src/wmkdependScanner.cpp
Normal file
File diff suppressed because it is too large
Load Diff
477
wmake/src/wmkdependScanner.h
Normal file
477
wmake/src/wmkdependScanner.h
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
/*---------------------------------*- 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 wmkdependParser.atg
|
||||||
|
|
||||||
|
Description
|
||||||
|
An attributed Coco/R grammar to parse C/C++, Fortran and Java files
|
||||||
|
for include and import statements.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
generated
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
// This file was generated with Coco/R C++ (7 Feb 2010)
|
||||||
|
// http://www.ssw.uni-linz.ac.at/coco/
|
||||||
|
// with these defines:
|
||||||
|
// - FORCE_UTF8
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef COCO_wmkdependSCANNER_H__
|
||||||
|
#define COCO_wmkdependSCANNER_H__
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cwchar>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace wmake {
|
||||||
|
|
||||||
|
// * * * * * * * * * * * Miscellaneous String Routines * * * * * * * * * * * //
|
||||||
|
|
||||||
|
//! Simple lower-case string transformation
|
||||||
|
template<class StringT>
|
||||||
|
inline void coco_string_toLower(StringT& str)
|
||||||
|
{
|
||||||
|
for
|
||||||
|
(
|
||||||
|
typename StringT::iterator iter = str.begin();
|
||||||
|
iter != str.end();
|
||||||
|
++iter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (*iter >= 'A' && *iter <= 'Z')
|
||||||
|
{
|
||||||
|
*iter += ('a' - 'A'); // lower-case
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Simple string hashing function
|
||||||
|
template<class StringT>
|
||||||
|
inline int coco_string_hash(const StringT& str)
|
||||||
|
{
|
||||||
|
int h = 0;
|
||||||
|
for
|
||||||
|
(
|
||||||
|
typename StringT::const_iterator iter = str.begin();
|
||||||
|
iter != str.end();
|
||||||
|
++iter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
h = (h * 7) ^ *iter;
|
||||||
|
}
|
||||||
|
return h < 0 ? -h : h;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// String conversions
|
||||||
|
// ~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
//! Convert wide string to double
|
||||||
|
inline double coco_string_toDouble(const wchar_t* str)
|
||||||
|
{
|
||||||
|
return str ? wcstod(str, NULL) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Convert wide string to long
|
||||||
|
inline long coco_string_toLong(const wchar_t* str)
|
||||||
|
{
|
||||||
|
return str ? wcstol(str, NULL, 10) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! A byte string (restricted to 8bit values) by copying str
|
||||||
|
std::string coco_stdString(const wchar_t* str);
|
||||||
|
|
||||||
|
//! A byte string (restricted to 8bit values) by copying str,
|
||||||
|
//! up to length characters long
|
||||||
|
std::string coco_stdString(const wchar_t* str, unsigned length);
|
||||||
|
|
||||||
|
//! A byte substring (restricted to 8bit values) of str,
|
||||||
|
//! starting at index and length characters long
|
||||||
|
std::string coco_stdString(const wchar_t* str, unsigned index, unsigned length);
|
||||||
|
|
||||||
|
//! A UTF8 byte string by copying str
|
||||||
|
std::string coco_stdStringUTF8(const wchar_t* str);
|
||||||
|
|
||||||
|
//! A UTF8 byte string by copying str, up to length characters long
|
||||||
|
std::string coco_stdStringUTF8(const wchar_t* str, unsigned length);
|
||||||
|
|
||||||
|
//! A UTF8 byte substring, starting at index and length characters long
|
||||||
|
std::string coco_stdStringUTF8(const wchar_t* str, unsigned index, unsigned length);
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * End of String Routines * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class Token Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
/*!
|
||||||
|
* @brief Scanner Token
|
||||||
|
*
|
||||||
|
* @note since each Token is allocated by the internal heap mechanism,
|
||||||
|
* the destructor does not clean up the val member.
|
||||||
|
*/
|
||||||
|
class Token
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int kind; //!< token kind
|
||||||
|
int pos; //!< token position in the source text (starting at 0)
|
||||||
|
int col; //!< token column (starting at 1)
|
||||||
|
int line; //!< token line (starting at 1)
|
||||||
|
wchar_t* val; //!< token value (normally allocated from the internal heap)
|
||||||
|
Token *next; //!< Peek tokens are kept in linked list
|
||||||
|
|
||||||
|
int length() const; //!< The length of val, or 0 if val is NULL
|
||||||
|
|
||||||
|
//! Construct null Token, optionally with pointer to a string value
|
||||||
|
Token(wchar_t* value = 0);
|
||||||
|
~Token(); //!< Destructor - does not cleanup val member
|
||||||
|
|
||||||
|
//! Token val as byte string (restricted to 8bit values)
|
||||||
|
inline std::string toString() const
|
||||||
|
{
|
||||||
|
return coco_stdString(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Token val as byte string (restricted to 8bit values), up to length characters long
|
||||||
|
inline std::string toString(unsigned length) const
|
||||||
|
{
|
||||||
|
return coco_stdString(val, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Token val as byte string (restricted to 8bit values), starting at index and length characters long
|
||||||
|
inline std::string toString(unsigned index, unsigned length) const
|
||||||
|
{
|
||||||
|
return coco_stdString(val, index, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Token val as UTF8 byte string
|
||||||
|
inline std::string toStringUTF8() const
|
||||||
|
{
|
||||||
|
return coco_stdStringUTF8(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Token val as UTF8 byte string, up to length characters long
|
||||||
|
inline std::string toStringUTF8(unsigned length) const
|
||||||
|
{
|
||||||
|
return coco_stdStringUTF8(val, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Token val as UTF8 byte substring, starting at index and length characters long
|
||||||
|
inline std::string toStringUTF8(unsigned index, unsigned length) const
|
||||||
|
{
|
||||||
|
return coco_stdStringUTF8(this->val, index, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class Buffer Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
/*!
|
||||||
|
* @brief Scanner Buffer Token
|
||||||
|
*
|
||||||
|
* This Buffer supports the following cases:
|
||||||
|
* -# seekable stream (file)
|
||||||
|
* -# whole stream in buffer
|
||||||
|
* -# part of stream in buffer
|
||||||
|
* -# non seekable stream (network, console)
|
||||||
|
*/
|
||||||
|
class Buffer
|
||||||
|
{
|
||||||
|
unsigned char *buf; //!< input buffer
|
||||||
|
int bufCapacity; //!< capacity of buf
|
||||||
|
int bufLen; //!< length of buffer
|
||||||
|
int bufPos; //!< current position in buffer
|
||||||
|
int bufStart; //!< position of first byte in buffer relative to input stream
|
||||||
|
int fileLen; //!< length of input stream (may change if the stream is no file)
|
||||||
|
FILE* cStream; //!< input stdio stream (normally seekable)
|
||||||
|
std::istream* stdStream; //!< STL std stream (seekable)
|
||||||
|
bool isUserStream_; //!< was the stream opened by the user?
|
||||||
|
|
||||||
|
int ReadNextStreamChunk();
|
||||||
|
bool CanSeek() const; //!< true if stream can be seeked otherwise false
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Buffer(Buffer*); //!< for the UTF8Buffer
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! max unicode characters is 0xFFFF (16bit storage)
|
||||||
|
static const int MaxChar = 65535;
|
||||||
|
static const int EoF = MaxChar + 1;
|
||||||
|
|
||||||
|
//! Copy buffer contents from constant character string
|
||||||
|
Buffer(const char* chars, int len);
|
||||||
|
|
||||||
|
//! Copy buffer contents from constant character string
|
||||||
|
Buffer(const unsigned char* chars, int len);
|
||||||
|
|
||||||
|
//! @brief Attach buffer to a stdio stream.
|
||||||
|
//! User streams are not closed in the destructor
|
||||||
|
Buffer(FILE*, bool isUserStream = true);
|
||||||
|
|
||||||
|
//! @brief Attach buffer to an STL standard stream
|
||||||
|
//! User streams are not closed in the destructor
|
||||||
|
explicit Buffer(std::istream*, bool isUserStream = true);
|
||||||
|
|
||||||
|
//! Close stream (but not user streams) and free buf (if any)
|
||||||
|
virtual ~Buffer();
|
||||||
|
|
||||||
|
virtual void Close(); //!< Close stream (but not user streams)
|
||||||
|
virtual int Read(); //!< Get character from stream or buffer
|
||||||
|
virtual int Peek(); //!< Peek character from stream or buffer
|
||||||
|
|
||||||
|
virtual int GetPos() const;
|
||||||
|
virtual void SetPos(int value);
|
||||||
|
virtual bool isUTF8() const; //!< Return false - buffer is not UTF8
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class UTF8Buffer Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
//! A Scanner Buffer variant that decodes UTF-8 characters into 16bit unicode
|
||||||
|
class UTF8Buffer : public Buffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UTF8Buffer(Buffer* b) : Buffer(b) {}
|
||||||
|
virtual int Read();
|
||||||
|
virtual bool isUTF8() const; //!< Return true - buffer is UTF8
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class StartStates Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
//! maps characters (integers) to start states of tokens as a HashTable
|
||||||
|
class StartStates
|
||||||
|
{
|
||||||
|
//! HashTable entry
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
int key; //<! The lookup key
|
||||||
|
int val; //<! The data
|
||||||
|
Entry *next; //<! Pointer next Entry in sub-list
|
||||||
|
|
||||||
|
Entry(int k, int v, Entry *n=0)
|
||||||
|
:
|
||||||
|
key(k), val(v), next(n)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int size_ = 128; //<! fixed HashTable size
|
||||||
|
Entry **table_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StartStates()
|
||||||
|
:
|
||||||
|
table_(new Entry*[size_])
|
||||||
|
{
|
||||||
|
memset(table_, 0, size_*sizeof(Entry*));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~StartStates()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size_; ++i)
|
||||||
|
{
|
||||||
|
Entry *e = table_[i];
|
||||||
|
while (e)
|
||||||
|
{
|
||||||
|
Entry *next = e->next;
|
||||||
|
delete e;
|
||||||
|
e = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] table_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(int key, int val)
|
||||||
|
{
|
||||||
|
const int hashIndex = unsigned(key) % size_;
|
||||||
|
table_[hashIndex] = new Entry(key, val, table_[hashIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int state(int key)
|
||||||
|
{
|
||||||
|
Entry *e = table_[unsigned(key) % size_];
|
||||||
|
while (e && e->key != key) e = e->next;
|
||||||
|
return e ? e->val : 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class KeywordMap Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
//! maps strings to integers (identifiers to keyword kinds) as a HashTable
|
||||||
|
class KeywordMap
|
||||||
|
{
|
||||||
|
//! HashTable entry
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
const std::wstring key; //<! The lookup key
|
||||||
|
int val; //<! The data
|
||||||
|
Entry *next; //<! Pointer next Entry in sub-list
|
||||||
|
|
||||||
|
Entry(const std::wstring& k, int v, Entry *n=0)
|
||||||
|
:
|
||||||
|
key(k), val(v), next(n)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int size_ = 128; //<! fixed HashTable size
|
||||||
|
Entry **table_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
KeywordMap()
|
||||||
|
:
|
||||||
|
table_(new Entry*[size_])
|
||||||
|
{
|
||||||
|
memset(table_, 0, size_*sizeof(Entry*));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~KeywordMap()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size_; ++i)
|
||||||
|
{
|
||||||
|
Entry *e = table_[i];
|
||||||
|
while (e)
|
||||||
|
{
|
||||||
|
Entry *next = e->next;
|
||||||
|
delete e;
|
||||||
|
e = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] table_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const std::wstring& key, int val)
|
||||||
|
{
|
||||||
|
const int hashIndex = coco_string_hash(key) % size_;
|
||||||
|
table_[hashIndex] = new Entry(key, val, table_[hashIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get(const std::wstring& key, int defaultVal)
|
||||||
|
{
|
||||||
|
Entry *e = table_[coco_string_hash(key) % size_];
|
||||||
|
while (e && e->key != key) e = e->next;
|
||||||
|
return e ? e->val : defaultVal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class Scanner Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
//! A Coco/R Scanner
|
||||||
|
class Scanner
|
||||||
|
{
|
||||||
|
static const int maxT = 10;
|
||||||
|
static const int noSym = 10;
|
||||||
|
static const int eofSym = 0; //!< end-of-file token id
|
||||||
|
static const char EOL = '\n'; //!< end-of-line character
|
||||||
|
|
||||||
|
void *firstHeap; //!< the start of the heap management
|
||||||
|
void *heap; //!< the currently active block
|
||||||
|
void *heapTop; //!< the top of the heap
|
||||||
|
void **heapEnd; //!< the end of the last heap block
|
||||||
|
|
||||||
|
StartStates start; //!< A map of start states for particular characters
|
||||||
|
KeywordMap keywords; //!< A hash of keyword literals to token kind
|
||||||
|
|
||||||
|
Token *t; //!< current token
|
||||||
|
wchar_t *tval; //!< text of current token
|
||||||
|
int tvalLength; //!< maximum capacity (length) for tval
|
||||||
|
int tlen; //!< length of tval
|
||||||
|
|
||||||
|
Token *tokens; //!< list of tokens already peeked (first token is a dummy)
|
||||||
|
Token *pt; //!< current peek token
|
||||||
|
|
||||||
|
int ch; //!< current input character
|
||||||
|
int pos; //!< byte position of current character
|
||||||
|
int line; //!< line number of current character
|
||||||
|
int col; //!< column number of current character
|
||||||
|
int oldEols; //!< the number of EOLs that appeared in a comment
|
||||||
|
|
||||||
|
void CreateHeapBlock(); //!< add a heap block, freeing unused ones
|
||||||
|
Token* CreateToken(); //!< fit token on the heap
|
||||||
|
void AppendVal(Token* tok); //!< adjust tok->val to point to the heap and copy tval into it
|
||||||
|
void SetScannerBehindT();
|
||||||
|
|
||||||
|
void Init(); //!< complete the initialization for the constructors
|
||||||
|
void NextCh(); //!< get the next input character into ch
|
||||||
|
void AddCh(); //!< append the character ch to tval
|
||||||
|
bool Comment0();
|
||||||
|
bool Comment1();
|
||||||
|
Token* NextToken(); //!< get the next token
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! The scanner buffer
|
||||||
|
Buffer *buffer;
|
||||||
|
|
||||||
|
//! Attach scanner to an existing character buffer
|
||||||
|
Scanner(const char* chars, int len);
|
||||||
|
|
||||||
|
//! Attach scanner to an existing character buffer
|
||||||
|
Scanner(const unsigned char* chars, int len);
|
||||||
|
|
||||||
|
//! Attach scanner to an existing open file handle
|
||||||
|
Scanner(FILE*);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
//! Open a file for reading and attach scanner - Windows only
|
||||||
|
explicit Scanner(const std::wstring& fileName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! Open a file for reading and attach scanner
|
||||||
|
explicit Scanner(const std::string& fileName);
|
||||||
|
|
||||||
|
//! Attach scanner to an existing open STL standard stream
|
||||||
|
explicit Scanner(std::istream&);
|
||||||
|
|
||||||
|
~Scanner(); //!< free heap and allocated memory
|
||||||
|
Token* Scan(); //!< get the next token (possibly a token already seen during peeking)
|
||||||
|
Token* Peek(); //!< peek for the next token, ignore pragmas
|
||||||
|
void ResetPeek(); //!< ensure that peeking starts at the current scan position
|
||||||
|
|
||||||
|
int Line() const; //!< Return the current line
|
||||||
|
void Line(int lineNo); //!< Define the starting line for reporting errors
|
||||||
|
|
||||||
|
}; // end Scanner
|
||||||
|
|
||||||
|
} // End namespace
|
||||||
|
|
||||||
|
#endif // COCO_wmkdependSCANNER_H__
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Reference in New Issue
Block a user