mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
367 lines
9.1 KiB
C++
367 lines
9.1 KiB
C++
/*---------------------------------------------------------------------------*\
|
|
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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
@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>
|
|
#include <set>
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
COMPILER wmkdepend
|
|
// grammar pragmas:
|
|
$namespace=wmake
|
|
$prefix=wmkdepend
|
|
$define=FORCE_UTF8
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
private:
|
|
|
|
//! Set of (java) directories already visited
|
|
static std::set<std::string> 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:
|
|
//! Set of files already visited
|
|
static std::set<std::string> visitedFiles;
|
|
|
|
//! 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>
|
|
|
|
std::set<std::string> Parser::visitedDirs_;
|
|
|
|
std::set<std::string> Parser::visitedFiles;
|
|
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_.insert(name);
|
|
}
|
|
|
|
|
|
void Parser::includeFile(const std::string& name)
|
|
{
|
|
if (!visitedFiles.insert(name).second)
|
|
{
|
|
return; // already existed (did not insert)
|
|
}
|
|
|
|
// 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()
|
|
);
|
|
|
|
// only report the first occurance
|
|
visitedFiles.insert(name);
|
|
}
|
|
}
|
|
|
|
|
|
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_.find(dirGlob) != visitedDirs_.end())
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
std::string javaFileName = name;
|
|
|
|
dotToSlash(javaFileName);
|
|
javaFileName += ".java";
|
|
|
|
includeFile(javaFileName);
|
|
}
|
|
|
|
|
|
void Parser::importDir(const std::string& name)
|
|
{
|
|
if (!visitedDirs_.insert(name).second)
|
|
{
|
|
return; // already existed (did not insert)
|
|
}
|
|
|
|
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.
|
|
|
|
// ************************************************************************* //
|