1
0
mirror of https://github.com/aportelli/LatAnalyze.git synced 2024-11-10 00:45:36 +00:00

first experimental IO that read matrices from a bison/flex parser

This commit is contained in:
Antonin Portelli 2013-05-21 18:02:42 +01:00
parent 30c8c2e205
commit 86d9607224
22 changed files with 763 additions and 55 deletions

4
.gitignore vendored
View File

@ -40,3 +40,7 @@ config.status
stamp-h1
myconfig.sh
# bison/flex generated sources
latan/IOASCIILexer.cpp
latan/IOASCIIParser.cpp
latan/IOASCIIParser.hpp

View File

@ -19,6 +19,8 @@ AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_LEX
AC_PROG_YACC
m4_ifdef([AM_PROG_AR],[AM_PROG_AR])
LT_INIT

View File

@ -1,9 +1,25 @@
#include <iostream>
#include <latan/Global.h>
#include <latan/IO.hpp>
using namespace std;
using namespace Latan;
int main(void)
{
ASCIIFile F;
DMat A,B;
F.Open("foo.boot",FileMode::Read);
A = F.Read<DMat>("bla");
B = F.Read<DMat>("bli");
cout << A << endl;
cout << B << endl;
cout << A*B << endl;
return EXIT_SUCCESS;
}
/*
int main(void)
{
DMat m(2,2);
@ -18,3 +34,4 @@ int main(void)
v(1) = v(0) - 1;
cout << "Here is the vector v:\n" << v << endl;
}
*/

29
latan/Exceptions.cpp Normal file
View File

@ -0,0 +1,29 @@
#include <latan/Exceptions.hpp>
#include <latan/includes.hpp>
#ifndef ERR_PREF
#define ERR_PREF "[" + Env::Name + " v" + Env::Version + "] "
#endif
#ifndef ERR_SUFF
#define ERR_SUFF " (" + loc + ")"
#endif
#define CONST_EXC(name,init) \
name::name(string msg, string loc)\
:init\
{}
using namespace std;
using namespace Latan;
using namespace Exceptions;
// logic errors
CONST_EXC(Logic,logic_error(ERR_PREF+msg+ERR_SUFF))
CONST_EXC(Implementation,Logic("implementation error: "+msg,loc))
CONST_EXC(Range,Logic("range error: "+msg,loc))
// runtime errors
CONST_EXC(Runtime,runtime_error(ERR_PREF+msg+ERR_SUFF))
CONST_EXC(IO,Runtime("IO error: "+msg,loc))
CONST_EXC(Parsing,Runtime(msg,loc))
CONST_EXC(Syntax,Runtime("syntax error: "+msg,loc))

37
latan/Exceptions.hpp Normal file
View File

@ -0,0 +1,37 @@
#ifndef LATAN_EXCEPTIONS_HPP_
#define LATAN_EXCEPTIONS_HPP_
#include <stdexcept>
#ifndef LATAN_GLOBAL_HPP_
#include <latan/Global.hpp>
#endif
#define SRC_LOC strfrom<const char*>(__FUNCTION__) + " at "\
+ strfrom<const char*>(__FILE__) + ":" + strfrom<int>(__LINE__)
#define LATAN_ERROR(exc,msg) throw(Exceptions::exc(msg,SRC_LOC))
#define DECL_EXC(name,base) \
class name: public base\
{\
public:\
explicit name(std::string msg, std::string loc);\
}
LATAN_BEGIN_CPPDECL
namespace Exceptions
{
// logic errors
DECL_EXC(Logic,std::logic_error);
DECL_EXC(Implementation,Logic);
DECL_EXC(Range,Logic);
// runtime errors
DECL_EXC(Runtime,std::runtime_error);
DECL_EXC(IO,Runtime);
DECL_EXC(Parsing,Runtime);
DECL_EXC(Syntax,Runtime);
}
LATAN_END_CPPDECL
#endif

View File

@ -1 +1,9 @@
#include <latan/Global.h>
#include <latan/Global.hpp>
#include <latan/includes.hpp>
using namespace std;
using namespace Latan;
const string Env::FullName = PACKAGE_STRING;
const string Env::Name = PACKAGE_NAME;
const string Env::Version = PACKAGE_VERSION;

View File

@ -1,19 +0,0 @@
#ifndef LATAN_GLOBAL_H_
#define LATAN_GLOBAL_H_
#include <latan/Eigen/Dense>
#define LATAN_NAMESPACE_NAME Latan
#define LATAN_BEGIN_CPPDECL namespace LATAN_NAMESPACE_NAME {
#define LATAN_END_CPPDECL }
LATAN_BEGIN_CPPDECL
typedef Eigen::MatrixXd DMat;
typedef Eigen::MatrixXcd CMat;
typedef Eigen::VectorXd DVec;
typedef Eigen::VectorXcd CVec;
LATAN_END_CPPDECL
#endif

53
latan/Global.hpp Normal file
View File

@ -0,0 +1,53 @@
#ifndef LATAN_GLOBAL_HPP_
#define LATAN_GLOBAL_HPP_
#include <string>
#include <latan/Eigen/Dense>
#define LATAN_BEGIN_CPPDECL namespace Latan {
#define LATAN_END_CPPDECL }
// attribute to switch off unused warnings with gcc
#ifdef __GNUC__
#define __dumb __attribute__((unused))
#else
#define __dumb
#endif
LATAN_BEGIN_CPPDECL
// Environment
namespace Env
{
extern const std::string FullName;
extern const std::string Name;
extern const std::string Version;
}
// string conversions
template <typename T>
static T ato(std::string str)
{
T buf;
std::istringstream stream(str);
stream >> buf;
return buf;
}
template <typename T>
static std::string strfrom(T x)
{
std::ostringstream stream;
stream << x;
return stream.str();
}
LATAN_END_CPPDECL
#include <latan/Exceptions.hpp>
#endif

View File

@ -1 +1,158 @@
#include <latan/IO.h>
#include <latan/IO.hpp>
#include <latan/includes.hpp>
using namespace std;
using namespace Latan;
// ASCII data format Bison/Flex parser declaration
int _IOASCII_parse(ASCIIParserState* state);
/******************************************************************************
* File implementation *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
File::File(void)
: name(""), mode(FileMode::Null), data()
{}
File::File(const string init_name, const FileMode::Type init_mode)
: name(init_name), mode(init_mode), data()
{}
// destructor //////////////////////////////////////////////////////////////////
File::~File(void)
{}
// access //////////////////////////////////////////////////////////////////////
string File::Name(void) const
{
return name;
}
FileMode::Type File::Mode(void) const
{
return mode;
}
// Internal functions //////////////////////////////////////////////////////////
void File::DeleteData(void)
{
IODataTable::iterator i;
for (i=data.begin();i!=data.end();++i)
{
delete i->second;
}
data.clear();
}
/******************************************************************************
* ASCIIParserState implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
ASCIIParserState::ASCIIParserState(istream* pt_istream, string* name,\
IODataTable* pt_data)
: data(pt_data), stream(pt_istream), stream_name(name)
{
init_scanner();
}
// destructor //////////////////////////////////////////////////////////////////
ASCIIParserState::~ASCIIParserState(void)
{
destroy_scanner();
}
/******************************************************************************
* ASCIIFile implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
ASCIIFile::ASCIIFile(void)
: File(), file_stream(), is_parsed(false), state(NULL)
{}
ASCIIFile::ASCIIFile(const string in_name, const FileMode::Type in_mode)
{
OpenASCII(in_name,in_mode);
}
// destructor //////////////////////////////////////////////////////////////////
ASCIIFile::~ASCIIFile(void)
{
Clear();
}
// tests ///////////////////////////////////////////////////////////////////////
bool ASCIIFile::IsOpen() const
{
return file_stream.is_open();
}
// IO //////////////////////////////////////////////////////////////////////////
void ASCIIFile::Close(void)
{
Clear();
}
void ASCIIFile::Open(const string new_name, const FileMode::Type new_mode)
{
if (IsOpen())
{
LATAN_ERROR(IO,"file already opened with name '"+name+"'");
}
OpenASCII(new_name,new_mode);
}
void ASCIIFile::Save(void)
{
LATAN_ERROR(Implementation,"saving ASCII files not implemented yet");
}
void ASCIIFile::SaveAs(const string new_name __dumb)
{
LATAN_ERROR(Implementation,"saving ASCII files not implemented yet");
}
// Internal functions //////////////////////////////////////////////////////////
void ASCIIFile::Clear()
{
DeleteData();
CloseASCII();
}
void ASCIIFile::OpenASCII(const string new_name, const FileMode::Type new_mode)
{
if (!IsOpen())
{
name = new_name;
mode = new_mode;
is_parsed = false;
file_stream.open(name.c_str());
if (mode & FileMode::Read)
{
state = new ASCIIParserState(&file_stream,&name,&data);
}
else
{
state = NULL;
}
}
}
void ASCIIFile::CloseASCII(void)
{
if (state)
{
delete state;
state = NULL;
}
if (IsOpen())
{
file_stream.close();
}
}
void ASCIIFile::Parse()
{
_IOASCII_parse(state);
}

View File

@ -1,12 +0,0 @@
#ifndef LATAN_IO_H_
#define LATAN_IO_H_
#include <latan/Global.h>
LATAN_BEGIN_CPPDECL
LATAN_END_CPPDECL
#endif

157
latan/IO.hpp Normal file
View File

@ -0,0 +1,157 @@
#ifndef LATAN_IO_HPP_
#define LATAN_IO_HPP_
#include <fstream>
#include <map>
#include <stack>
#include <sstream>
#include <string>
#include <H5Cpp.h>
#include <latan/Global.hpp>
#include <latan/IOObject.hpp>
#include <latan/Mat.hpp>
#include <latan/Sample.hpp>
LATAN_BEGIN_CPPDECL
/******************************************************************************
* Generic datafile class *
******************************************************************************/
typedef std::map<std::string,IOObject*> IODataTable;
namespace FileMode
{
typedef enum
{
Null = 0,
Write = 1 << 0,
Read = 1 << 1,
Append = 1 << 2
} Type;
}
class File
{
public:
// constructors
File(void);
File(const std::string in_name, const FileMode::Type in_mode);
// destructor
virtual ~File(void);
// access
std::string Name(void) const;
FileMode::Type Mode(void) const;
// tests
virtual bool IsOpen(void) const = 0;
// IO
virtual void Close(void) = 0;
virtual void Open(const std::string new_name, const FileMode::Type new_mode) = 0;
virtual void Save(void) = 0;
virtual void SaveAs(const std::string new_name) = 0;
protected:
// protected members
std::string name;
FileMode::Type mode;
IODataTable data;
// protected methods
void DeleteData(void);
template <typename IOObj> const IOObj& GetData(const std::string data_name);
};
// Template implementations
template <typename IOObj>
const IOObj& File::GetData(const std::string data_name)
{
try
{
return dynamic_cast<const IOObj&>(*(data.at(data_name)));
}
catch (std::out_of_range& e)
{
LATAN_ERROR(Range,"no data with name '"+data_name+"'");
}
}
/******************************************************************************
* ASCII datafile class *
******************************************************************************/
class ASCIIParserState
{
public:
// constructor
explicit ASCIIParserState(std::istream* pt_stream, std::string* name,\
IODataTable* pt_data);
// destructor
virtual ~ASCIIParserState(void);
// public members
IODataTable* data;
std::stack<DMat> dmat_buf;
std::stack<double> double_buf;
void* scanner;
std::istream* stream;
std::string* stream_name;
private:
// allocation/deallocation functions defined in IOASCIILexer.lpp
void init_scanner(void);
void destroy_scanner(void);
};
class ASCIIFile: public File
{
public:
// constructors
ASCIIFile(void);
ASCIIFile(const std::string in_name, const FileMode::Type in_mode);
// destructor
virtual ~ASCIIFile(void);
// access
template <typename IOObj> const IOObj& Read(const std::string name);
// tests
virtual bool IsOpen(void) const;
// IO
virtual void Close(void);
virtual void Open(const std::string new_name, const FileMode::Type new_mode);
virtual void Save(void);
virtual void SaveAs(const std::string new_name);
private:
// private members
std::fstream file_stream;
bool is_parsed;
ASCIIParserState* state;
// private methods
void Clear(void);
void OpenASCII(const std::string in_name, const FileMode::Type in_mode);
void CloseASCII(void);
void Parse(void);
};
// Template implementations
template <typename IOObj>
const IOObj& ASCIIFile::Read(const std::string data_name)
{
if ((mode & FileMode::Read)&&(IsOpen()))
{
if (!is_parsed)
{
Parse();
is_parsed = true;
}
return GetData<IOObj>(data_name);
}
else
{
if (IsOpen())
{
LATAN_ERROR(IO,"file '"+name+"' is not opened in read mode");
}
else
{
LATAN_ERROR(IO,"file not opened");
}
}
}
LATAN_END_CPPDECL
#endif

74
latan/IOASCIILexer.lpp Normal file
View File

@ -0,0 +1,74 @@
%option reentrant
%option prefix="_IOASCII_"
%option bison-bridge
%option bison-locations
%option noyywrap
%option yylineno
%{
#include <iostream>
#include <latan/IO.hpp>
#include <latan/IOASCIIParser.hpp>
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-parameter"
using namespace std;
using namespace Latan;
#define YY_EXTRA_TYPE ASCIIParserState*
#define YY_USER_ACTION \
yylloc->first_line = yylloc->last_line = yylineno;\
yylloc->first_column = yylloc->last_column + 1;\
yylloc->last_column = yylloc->first_column + yyleng - 1;
#define YY_INPUT(buf,result,max_size) \
{ \
(*yyextra->stream).read(buf,max_size);\
result = (*yyextra->stream).gcount();\
}
#define YY_DEBUG 0
#if (YY_DEBUG == 1)
#define RETTOK(tok) cout << #tok << "(" << yytext << ")" << endl; return tok
#else
#define RETTOK(tok) return tok
#endif
%}
DIGIT [0-9]
ALPHA [a-zA-Z_]
SIGN \+|-
EXP e|E
INT {SIGN}?{DIGIT}+
FLOAT {SIGN}?(({DIGIT}+\.{DIGIT}*)|({DIGIT}*\.{DIGIT}+))({EXP}{SIGN}?{INT}+)?
LMARK #L
BLANK [ \t]
%x MARK TYPE
%%
{LMARK} {BEGIN(MARK);}
{INT} {yylval->val_int = ato<int>(yytext); RETTOK(INT);}
{FLOAT} {yylval->val_double = ato<double>(yytext); RETTOK(FLOAT);}
({ALPHA}|{DIGIT})+ {strcpy(yylval->val_str,yytext); RETTOK(ID);}
<MARK>latan_begin {BEGIN(TYPE); RETTOK(OPEN);}
<MARK>latan_end {BEGIN(TYPE); RETTOK(CLOSE);}
<TYPE>mat {BEGIN(INITIAL); RETTOK(MAT);}
<*>\n {yylloc->last_column = 0;}
<*>[ \t]
<*>. {yylval->val_char = yytext[0]; RETTOK(ERR);}
%%
void ASCIIParserState::init_scanner()
{
yylex_init(&scanner);
yyset_extra(this, scanner);
}
void ASCIIParserState::destroy_scanner()
{
yylex_destroy(scanner);
}

83
latan/IOASCIIParser.ypp Normal file
View File

@ -0,0 +1,83 @@
%{
#include <iostream>
#include <sstream>
#include <cstring>
#include <latan/Global.hpp>
#include <latan/IO.hpp>
#include <latan/Sample.hpp>
using namespace std;
using namespace Latan;
%}
%pure-parser
%name-prefix="_IOASCII_"
%locations
%defines
%error-verbose
%parse-param { Latan::ASCIIParserState* state }
%initial-action {yylloc.last_column = 0;}
%lex-param { void* scanner }
%union
{
int val_int;
double val_double;
char val_char;
char val_str[256];
}
%token CLOSE
%token <val_char> ERR
%token <val_double> FLOAT
%token <val_int> INT
%token <val_str> ID
%token MAT
%token OPEN
%{
int _IOASCII_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
void _IOASCII_error(YYLTYPE* locp, ASCIIParserState* state, const char* err)
{
stringstream buf;
buf << *state->stream_name << ":" << locp->first_line << ":"\
<< locp->first_column << ": " << err;
LATAN_ERROR(Parsing,buf.str());
}
#define scanner state->scanner
%}
%%
datas:
/* empty string */
| datas mat
;
mat:
OPEN MAT ID INT floats CLOSE MAT
{
const int nrow = state->double_buf.size()/$INT, ncol = $INT;
(*state->data)[$ID] = new DMat(nrow,ncol);
DMat& M = dynamic_cast<DMat&>(*((*state->data)[$ID]));
int r,i,j;
r = 0;
while (!state->double_buf.empty())
{
j = r%ncol;
i = (r-j)/ncol;
M(i,j) = state->double_buf.top();
state->double_buf.pop();
++r;
}
}
;
floats:
FLOAT floats {state->double_buf.push($1);}
| FLOAT {state->double_buf.push($1);}
;

12
latan/IOObject.cpp Normal file
View File

@ -0,0 +1,12 @@
#include <latan/IOObject.hpp>
#include <latan/includes.hpp>
using namespace Latan;
IOObject::~IOObject(void)
{}
IOTypes::Type IOObject::IOType(void)
{
return IOTypes::NoType;
}

28
latan/IOObject.hpp Normal file
View File

@ -0,0 +1,28 @@
#ifndef LATAN_IOOBJECT_HPP_
#define LATAN_IOOBJECT_HPP_
#include <latan/Global.hpp>
LATAN_BEGIN_CPPDECL
namespace IOTypes
{
typedef enum
{
NoType = 0,
DMat = 1,
Sample = 2
} Type;
}
// Abstract base for IO objects
class IOObject
{
public:
virtual ~IOObject(void);
virtual IOTypes::Type IOType(void);
};
LATAN_END_CPPDECL
#endif

View File

@ -14,16 +14,31 @@ if CXX_INTEL
endif
endif
AM_LFLAGS = -olex.yy.c
AM_YFLAGS = -d
BUILT_SOURCES = IOASCIIParser.hpp
lib_LTLIBRARIES = liblatan.la
liblatan_la_SOURCES = \
Global.cpp \
Sample.cpp \
liblatan_la_SOURCES = \
Exceptions.cpp \
Global.cpp \
includes.hpp \
IO.cpp \
IOASCIIParser.ypp \
IOASCIILexer.lpp \
IOObject.cpp \
Mat.cpp \
Sample.cpp \
../config.h
liblatan_ladir = $(includedir)/latan
liblatan_la_HEADERS = \
Global.h \
Sample.h
Global.hpp \
IO.hpp \
IOObject.hpp \
Mat.hpp \
Sample.hpp
liblatan_la_CFLAGS = $(COM_CFLAGS)
liblatan_la_CXXFLAGS = $(COM_CXXFLAGS)

26
latan/Mat.cpp Normal file
View File

@ -0,0 +1,26 @@
#include <latan/Mat.hpp>
#include <latan/includes.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* DMat class *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
DMat::DMat(void)
: DMatBase()
{}
DMat::DMat(const DMat& M)
: DMatBase(M)
{}
DMat::DMat(unsigned int nrow, unsigned int ncol)
: DMatBase(nrow,ncol)
{}
IOTypes::Type DMat::IOType(void)
{
return IOTypes::DMat;
}

29
latan/Mat.hpp Normal file
View File

@ -0,0 +1,29 @@
#ifndef LATAN_MAT_HPP_
#define LATAN_MAT_HPP_
#include <latan/Eigen/Dense>
#include <latan/Global.hpp>
#include <latan/IOObject.hpp>
LATAN_BEGIN_CPPDECL
// Eigen aliases
typedef Eigen::MatrixXd DMatBase;
typedef Eigen::MatrixXcd CMatBase;
typedef Eigen::VectorXd DVecBase;
typedef Eigen::VectorXcd CVecBase;
class DMat: public DMatBase, public IOObject
{
public:
// constructors
DMat(void);
DMat(const DMat& M);
DMat(unsigned int nrow, unsigned int ncol);
// IO
virtual IOTypes::Type IOType(void);
};
LATAN_END_CPPDECL
#endif

View File

@ -1,16 +1,17 @@
#include <latan/Sample.h>
#include <latan/Sample.hpp>
#include <latan/includes.hpp>
using namespace LATAN_NAMESPACE_NAME;
using namespace Latan;
Sample::Sample(void)
: central(0,0), sample(0)
: central(0,0), sample(static_cast<ArrayType::Index>(0))
{}
Sample::Sample(const unsigned int init_nsample, const unsigned int init_nrow,\
const unsigned int init_ncol)
: central(init_nrow,init_ncol), sample(init_nsample)
{
for (int s=0;s<init_nsample;++s)
for (unsigned int s=0;s<init_nsample;++s)
{
sample(s).resize(init_nrow,init_ncol);
}

View File

@ -1,7 +1,8 @@
#ifndef LATAN_SAMPLE_H_
#define LATAN_SAMPLE_H_
#ifndef LATAN_SAMPLE_HPP_
#define LATAN_SAMPLE_HPP_
#include <latan/Global.h>
#include <latan/Global.hpp>
#include <latan/Mat.hpp>
LATAN_BEGIN_CPPDECL
@ -9,10 +10,13 @@ const int Central = -1;
class Sample
{
private:
// type alias for disambiguation
typedef Eigen::Array<DMat,Eigen::Dynamic,1> ArrayType;
public:
// Constructors/destructor
Sample(void);
Sample(Sample &S);
Sample(const unsigned int init_nsample, const unsigned int init_nrow,\
const unsigned int init_ncol);
~Sample(void);
@ -20,8 +24,9 @@ public:
DMat& operator()(const int s);
private:
DMat central;
Eigen::Array<DMat,Eigen::Dynamic,1> sample;
// type aliases
DMat central;
ArrayType sample;
};
LATAN_END_CPPDECL

View File

@ -1,6 +0,0 @@
#ifndef LATAN_INCLUDES_H_
#define LATAN_INCLUDES_H_
#include <iostream>
#endif

8
latan/includes.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef LATAN_INCLUDES_HPP_
#define LATAN_INCLUDES_HPP_
#include <fstream>
#include <iostream>
#include "../config.h"
#endif