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; |
16 | set_lexer_state(const std::string &a):state(a){} |
17 | template <class Iterator,class Context> |
18 | 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 | #ifdef _MSC_VER |
27 | # pragma warning(push) |
28 | # pragma warning(disable: 4512) // assignment operator could not be generated. |
29 | #endif |
30 | struct store_double |
31 | { |
32 | std::vector<double> &out; |
33 | store_double(std::vector<double> &a):out(a){} |
34 | template <class Iterator,class LexerContext> |
35 | void operator () (Iterator const& start, Iterator const& end |
36 | , BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&, std::size_t |
37 | , LexerContext &) const |
38 | { |
39 | std::string work(start, end); |
40 | out.push_back(x: std::atof(nptr: work.c_str())); |
41 | } |
42 | }; |
43 | |
44 | struct add_row |
45 | { |
46 | std::vector<std::vector<double> > &matrix; |
47 | std::vector<double> &row; |
48 | |
49 | add_row(std::vector<std::vector<double> > &a,std::vector<double> &b) |
50 | :matrix(a),row(b) {} |
51 | template <class Iterator,class Context> |
52 | void operator () (Iterator const&, Iterator const& |
53 | , BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&, std::size_t |
54 | , Context &ctx) const |
55 | { |
56 | matrix.push_back(x: std::vector<double>()); |
57 | matrix.back().swap(x&: row); |
58 | ctx.set_state_name("A" ); |
59 | } |
60 | }; |
61 | |
62 | template <class Lexer> |
63 | struct matlib_tokens : boost::spirit::lex::lexer<Lexer> |
64 | { |
65 | matlib_tokens(std::vector<std::vector<double> > &a) |
66 | : matrix(a) |
67 | { |
68 | typedef boost::spirit::lex::token_def<> token_def_; |
69 | |
70 | this->self.add_pattern("REAL1" , "[0-9]+(\\.[0-9]*)?" ); |
71 | this->self.add_pattern("REAL2" , "\\.[0-9]+" ); |
72 | |
73 | number = "[-+]?({REAL1}|{REAL2})([eE][-+]?[0-9]+)?" ; |
74 | |
75 | this->self |
76 | = token_def_('[') [set_lexer_state("A" )] |
77 | ; |
78 | |
79 | this->self("A" ) |
80 | = token_def_('[') [set_lexer_state("B" )] |
81 | | ',' |
82 | | token_def_(']') [set_lexer_state("INITIAL" )] |
83 | ; |
84 | |
85 | this->self("B" ) |
86 | = number [store_double(row)] |
87 | | ',' |
88 | | token_def_(']') [add_row(matrix,row)] |
89 | ; |
90 | } |
91 | |
92 | boost::spirit::lex::token_def<> number; |
93 | std::vector<std::vector<double> > &matrix; |
94 | std::vector<double> row; |
95 | }; |
96 | #ifdef _MSC_VER |
97 | # pragma warning(pop) |
98 | #endif |
99 | |
100 | #endif |
101 | |
102 | |