1 //  Copyright (c) 2001-2009 Hartmut Kaiser
2 //  Copyright (c) 2009 Carl Barron
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
5 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef MATLIB_H_05102009
8 #define MATLIB_H_05102009
9 #include <boost/spirit/include/lex.hpp>
10 #include <vector>
11 #include <string>
12 
13 struct set_lexer_state
14 {
15     std::string state;
set_lexer_stateset_lexer_state16     set_lexer_state(const std::string &a):state(a){}
17     template <class Iterator,class Context>
operatorset_lexer_state18     void operator () (Iterator const&, Iterator const&
19       , BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&, std::size_t
20       , Context &ctx) const
21     {
22         ctx.set_state_name(state.c_str());
23     }
24 };
25 
26 struct store_double
27 {
28     std::vector<double> &out;
store_doublestore_double29     store_double(std::vector<double> &a):out(a){}
30     template <class Iterator,class LexerContext>
operatorstore_double31     void operator () (Iterator const& start, Iterator const& end
32       , BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&, std::size_t
33       , LexerContext &) const
34     {
35         std::string work(start, end);
36         out.push_back(std::atof(work.c_str()));
37     }
38 
39     // silence MSVC warning C4512: assignment operator could not be generated
40     BOOST_DELETED_FUNCTION(store_double& operator= (store_double const&));
41 };
42 
43 struct add_row
44 {
45     std::vector<std::vector<double> > &matrix;
46     std::vector<double> &row;
47 
add_rowadd_row48     add_row(std::vector<std::vector<double> > &a,std::vector<double> &b)
49         :matrix(a),row(b) {}
50     template <class Iterator,class Context>
operatoradd_row51     void operator () (Iterator const&, Iterator const&
52       , BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&, std::size_t
53       , Context &ctx) const
54     {
55         matrix.push_back(std::vector<double>());
56         matrix.back().swap(row);
57         ctx.set_state_name("A");
58     }
59 
60     // silence MSVC warning C4512: assignment operator could not be generated
61     BOOST_DELETED_FUNCTION(add_row& operator= (add_row const&));
62 };
63 
64 template <class Lexer>
65 struct matlib_tokens : boost::spirit::lex::lexer<Lexer>
66 {
matlib_tokensmatlib_tokens67     matlib_tokens(std::vector<std::vector<double> > &a)
68       : matrix(a)
69     {
70         typedef boost::spirit::lex::token_def<> token_def_;
71 
72         this->self.add_pattern("REAL1", "[0-9]+(\\.[0-9]*)?");
73         this->self.add_pattern("REAL2", "\\.[0-9]+");
74 
75         number = "[-+]?({REAL1}|{REAL2})([eE][-+]?[0-9]+)?";
76 
77         this->self
78             =   token_def_('[') [set_lexer_state("A")]
79             ;
80 
81         this->self("A")
82             =   token_def_('[') [set_lexer_state("B")]
83             |   ','
84             |   token_def_(']') [set_lexer_state("INITIAL")]
85             ;
86 
87         this->self("B")
88             =   number [store_double(row)]
89             |   ','
90             |   token_def_(']') [add_row(matrix,row)]
91             ;
92     }
93 
94     boost::spirit::lex::token_def<> number;
95     std::vector<std::vector<double> > &matrix;
96     std::vector<double> row;
97 };
98 
99 #endif
100 
101