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