blob: 85fa4868eed4427d75f3ecc5938aaf23a7f81290 [file] [log] [blame]
// Copyright (c) 2001-2009 Hartmut Kaiser
// Copyright (c) 2009 Carl Barron
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef MATLIB_H_05102009
#define MATLIB_H_05102009
#include <boost/spirit/include/lex.hpp>
#include <vector>
#include <string>
struct set_lexer_state
{
std::string state;
set_lexer_state(const std::string &a):state(a){}
template <class Iterator,class Context>
void operator () (Iterator const&, Iterator const&
, BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&, std::size_t
, Context &ctx) const
{
ctx.set_state_name(state.c_str());
}
};
struct store_double
{
std::vector<double> &out;
store_double(std::vector<double> &a):out(a){}
template <class Iterator,class LexerContext>
void operator () (Iterator const& start, Iterator const& end
, BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&, std::size_t
, LexerContext &) const
{
std::string work(start, end);
out.push_back(std::atof(work.c_str()));
}
private:
// silence MSVC warning C4512: assignment operator could not be generated
store_double& operator= (store_double const&);
};
struct add_row
{
std::vector<std::vector<double> > &matrix;
std::vector<double> &row;
add_row(std::vector<std::vector<double> > &a,std::vector<double> &b)
:matrix(a),row(b) {}
template <class Iterator,class Context>
void operator () (Iterator const&, Iterator const&
, BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&, std::size_t
, Context &ctx) const
{
matrix.push_back(std::vector<double>());
matrix.back().swap(row);
ctx.set_state_name("A");
}
private:
// silence MSVC warning C4512: assignment operator could not be generated
add_row& operator= (add_row const&);
};
template <class Lexer>
struct matlib_tokens : boost::spirit::lex::lexer<Lexer>
{
matlib_tokens(std::vector<std::vector<double> > &a)
: matrix(a)
{
typedef boost::spirit::lex::token_def<> token_def_;
this->self.add_pattern("REAL1", "[0-9]+(\\.[0-9]*)?");
this->self.add_pattern("REAL2", "\\.[0-9]+");
number = "[-+]?({REAL1}|{REAL2})([eE][-+]?[0-9]+)?";
this->self
= token_def_('[') [set_lexer_state("A")]
;
this->self("A")
= token_def_('[') [set_lexer_state("B")]
| ','
| token_def_(']') [set_lexer_state("INITIAL")]
;
this->self("B")
= number [store_double(row)]
| ','
| token_def_(']') [add_row(matrix,row)]
;
}
boost::spirit::lex::token_def<> number;
std::vector<std::vector<double> > &matrix;
std::vector<double> row;
};
#endif