Line data Source code
1 : #ifndef MATHEVAL_IMPLEMENTATION
2 : #error "Do not include parser.hpp directly!"
3 : #endif
4 :
5 : #pragma once
6 :
7 : #include "ast.hpp"
8 :
9 : #define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
10 : #include <boost/spirit/include/qi.hpp>
11 :
12 : #include <iostream>
13 :
14 : namespace matheval {
15 :
16 : namespace qi = boost::spirit::qi;
17 : namespace ascii = boost::spirit::ascii;
18 :
19 : namespace parser {
20 :
21 : struct expectation_handler {
22 : template <typename>
23 : struct result {
24 : typedef void type;
25 : };
26 :
27 : template <typename Iterator>
28 2 : void operator()(Iterator first, Iterator last,
29 : boost::spirit::info const &info) const {
30 4 : std::stringstream msg;
31 : msg << "Expected " << info << " at \"" << std::string(first, last)
32 2 : << "\"";
33 :
34 2 : throw std::runtime_error(msg.str()); // NOLINT
35 : }
36 : };
37 :
38 : template <typename Iterator>
39 : struct grammar : qi::grammar<Iterator, ast::expression(), ascii::space_type> {
40 : expectation_handler err_handler;
41 : qi::rule<Iterator, ast::expression(), ascii::space_type> expression,
42 : logical, equality, relational, additive, multiplicative, factor;
43 : qi::rule<Iterator, ast::operand(), ascii::space_type> primary;
44 : qi::rule<Iterator, ast::unary_op(), ascii::space_type> unary;
45 : qi::rule<Iterator, ast::binary_op(), ascii::space_type> binary;
46 : qi::rule<Iterator, ast::ternary_op(), ascii::space_type> ternary;
47 : qi::rule<Iterator, std::string()> variable;
48 :
49 : qi::symbols<typename std::iterator_traits<Iterator>::value_type, double>
50 : constant;
51 : qi::symbols<typename std::iterator_traits<Iterator>::value_type,
52 : double (*)(double)>
53 : ufunc, unary_op;
54 : qi::symbols<typename std::iterator_traits<Iterator>::value_type,
55 : double (*)(double, double)>
56 : bfunc, additive_op, multiplicative_op, logical_op, relational_op, equality_op, power;
57 : qi::symbols<typename std::iterator_traits<Iterator>::value_type,
58 : double (*)(double, double, double)>
59 : tfunc;
60 :
61 : grammar();
62 : };
63 :
64 : } // namespace parser
65 :
66 : typedef parser::grammar<std::string::const_iterator> grammar;
67 :
68 : } // namespace matheval
|