metaparse/example/grammar_calculator/main.cpp
2017-04-20 16:35:06 +02:00

161 lines
4.2 KiB
C++

// Copyright Abel Sinkovics (abel@sinkovics.hu) 2011.
// 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)
#include <boost/config.hpp>
#if BOOST_METAPARSE_STD < 2011
#include <iostream>
int main()
{
std::cout << "Please use a compiler that supports constexpr" << std::endl;
}
#else
#define BOOST_MPL_LIMIT_STRING_SIZE 64
#define BOOST_METAPARSE_LIMIT_STRING_SIZE BOOST_MPL_LIMIT_STRING_SIZE
#include <boost/metaparse/grammar.hpp>
#include <boost/metaparse/entire_input.hpp>
#include <boost/metaparse/build_parser.hpp>
#include <boost/metaparse/token.hpp>
#include <boost/metaparse/string.hpp>
#include <boost/metaparse/util/digit_to_int.hpp>
#include <boost/mpl/apply_wrap.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/times.hpp>
#include <boost/mpl/divides.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/char.hpp>
#include <boost/mpl/int.hpp>
using boost::metaparse::build_parser;
using boost::metaparse::entire_input;
using boost::metaparse::token;
using boost::metaparse::grammar;
using boost::metaparse::util::digit_to_int;
using boost::mpl::apply_wrap1;
using boost::mpl::fold;
using boost::mpl::front;
using boost::mpl::back;
using boost::mpl::plus;
using boost::mpl::minus;
using boost::mpl::times;
using boost::mpl::divides;
using boost::mpl::eval_if;
using boost::mpl::equal_to;
using boost::mpl::_1;
using boost::mpl::_2;
using boost::mpl::char_;
using boost::mpl::lambda;
using boost::mpl::int_;
#ifdef _STR
#error _STR already defined
#endif
#define _STR BOOST_METAPARSE_STRING
template <class A, class B>
struct lazy_plus : plus<typename A::type, typename B::type> {};
template <class A, class B>
struct lazy_minus : minus<typename A::type, typename B::type> {};
template <class A, class B>
struct lazy_times : times<typename A::type, typename B::type> {};
template <class A, class B>
struct lazy_divides : divides<typename A::type, typename B::type> {};
template <class C, class T, class F>
struct lazy_eval_if : eval_if<typename C::type, T, F> {};
template <class A, class B>
struct lazy_equal_to : equal_to<typename A::type, typename B::type> {};
template <class Sequence, class State, class ForwardOp>
struct lazy_fold :
fold<typename Sequence::type, typename State::type, typename ForwardOp::type>
{};
typedef
lazy_fold<
back<_1>,
front<_1>,
lambda<
lazy_eval_if<
lazy_equal_to<front<_2>, char_<'*'>>,
lazy_times<_1, back<_2>>,
lazy_divides<_1, back<_2>>
>
>::type
>
prod_action;
typedef
lazy_fold<
back<_1>,
front<_1>,
lambda<
lazy_eval_if<
lazy_equal_to<front<_2>, char_<'+'>>,
lazy_plus<_1, back<_2>>,
lazy_minus<_1, back<_2>>
>
>::type
>
plus_action;
typedef
lambda<
lazy_fold<
_1,
int_<0>,
lambda<
lazy_plus<lazy_times<_1, int_<10>>, apply_wrap1<digit_to_int<>, _2>>
>::type
>
>::type
int_action;
typedef
grammar<_STR("plus_exp")>
::rule<_STR("int ::= ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9')+"), int_action>::type
::rule<_STR("ws ::= (' ' | '\n' | '\r' | '\t')*")>::type
::rule<_STR("int_token ::= int ws"), front<_1>>::type
::rule<_STR("plus_token ::= '+' ws"), front<_1>>::type
::rule<_STR("minus_token ::= '-' ws"), front<_1>>::type
::rule<_STR("mult_token ::= '*' ws"), front<_1>>::type
::rule<_STR("div_token ::= '/' ws"), front<_1>>::type
::rule<_STR("plus_token ::= '+' ws")>::type
::rule<_STR("plus_exp ::= prod_exp ((plus_token | minus_token) prod_exp)*"), plus_action>::type
::rule<_STR("prod_exp ::= int_token ((mult_token | div_token) int_token)*"), prod_action>::type
expression;
typedef build_parser<entire_input<expression>> calculator_parser;
int main()
{
using std::cout;
using std::endl;
cout
<< apply_wrap1<calculator_parser, _STR("13")>::type::value << endl
<< apply_wrap1<calculator_parser, _STR("1+ 2*4-6/2")>::type::value << endl
;
}
#endif