C++ Boost 和表达公式的思考

// testspri.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
//#define  BOOST_SPIRIT_NO_REGEX_LIB
//
//#include "D:/boost/boost_1_40_0/boost/regex.h"
//#include "D:/boost/boost_1_40_0/boost/spirit.hpp"
//#include "D:/boost/boost_1_40_0/boost/spirit/actor.hpp"
//using namespace boost::spirit;
#include <string>
#include <iostream>
using namespace std;
//const string input = "This Hello World program using Spirit counts the number of  Hello World occurrences in the input";
//
//int main ()
//  {
//  int count = 0;
//  parse (input.c_str(),
//         *(str_p("Hello World") [ increment_a(count) ]
//           |
//           anychar_p)
//        );
//  cout << count <<endl;
// 
//  return 0;
//  }
//#define  BOOST_SPIRIT_NO_REGEX_LIB
//
//#include "D:/boost/boost_1_40_0/boost/regex.h"
//#include "D:/boost/boost_1_40_0/boost/spirit.hpp"
//#include "D:/boost/boost_1_40_0/boost/spirit/actor/assign_actor.hpp"
//
//using namespace std;
//using namespace boost::spirit;
//
//const string input = "Alex 8 9.2 Jim 91 5.6";
//
//typedef struct {
//  string name;
//  int    idcode;
//  float  rating;
//} Employee;
//
//int main ()
//  {
//  string name;
//  int idcode;
//  float rating;
//
//  int status = parse (input.c_str(),
//                      *((+alpha_p) [assign_a(name)] >> ' ' >>
//                        int_p[assign_a(idcode)] >> ' ' >>
//                        real_p[assign_a(rating)] >>  !blank_p)
//        ).full;
//  cout << status << endl;
//  return 0;
//  }
//#define  BOOST_SPIRIT_NO_REGEX_LIB
//
//#include "boost/regex.h"
//#include "boost/spirit.hpp"
//#include "boost/spirit/actor/assign_actor.hpp"
//
//using namespace std;
//using namespace boost::spirit;
//
//struct my_enum : public grammar<my_enum>
//    {
//    template <typename ScannerT>
//      struct definition
//        {
//        definition(my_enum const& self)
//          {
//          enum_specifier = enum_p >> '{' >> enum_list >> '}';
//          enum_p = str_p("enum");
//          enum_list = +id_p >> *(',' >> +id_p);
//          id_p = range_p('a','z');
//          }
//
//          rule<ScannerT> enum_specifier, enum_p, enum_list, id_p;
//          rule<ScannerT> const& start() const { return enum_specifier; }
//        };
//    };
//
//string input = "enum { ah, bk  }";
//
//int main ()
//  {
//  my_enum e;
//  int status = parse(input.c_str(), e, space_p).hit;
//  cout << status << endl;
//  return 0;
//  }
#include <iostream>
#include <vector>
#include <boost/spirit.hpp>
#include <boost/spirit/phoenix.hpp>
using namespace std;
using namespace boost::spirit;
using namespace phoenix;
//int main()
//{
////为rule准备一个val变量,类型为double
////准确地说:是一个phoenix类(这里的member1),它和其它phoenix类组成lambda表达式,在lambda中可以把它看成是一个double。
//struct calc_closure : boost::spirit::closure<calc_closure, double>
//{
//member1 val;
//};
////定义ContextT策略为calc_closure::context_t
//rule<phrase_scanner_t, calc_closure::context_t> factor, term, exp;
////直接使用phoenix的lambda表达式作为Actor
//factor = real_p[factor.val = arg1] | ('(' >> exp[factor.val = arg1] >> ')');
//term   = factor[term.val = arg1] >> *(('*' >> factor[term.val *= arg1]) | ('/' >> factor[term.val /= arg1]));
//exp    = term[exp.val = arg1] >> *(('+' >> term[exp.val += arg1]) | ('-' >> term[exp.val -= arg1]));
//const char *szExp = "-1 + (2 * (3 / (4 + 5)))";
//double result;
//parse_info<> r = parse( szExp , exp[assign_a(result)], space_p);
//cout << szExp;
//if(r.full)
//{
////成功,得到结果
//cout << " = " << result << endl;
//}
//else
//{
////失败,显示错误位置
//cout << endl << string(r.stop - szExp, ' ') << '^' << endl;
//}
//return 0;
//}

#include <stack>
#include <string>
#include <cassert>
#include <iostream>
#include <functional>
#include <boost/bind.hpp>
#include <boost/spirit.hpp>

template <typename op>
void CalStack(std::stack<double>& values) {
    assert(values.size() >= 2);

    double op2 = values.top();
    values.pop();
    double op1 = values.top();
    values.pop();

    values.push(op()(op1, op2));
}

void eval(const char* expr) {
    using boost::spirit::rule;
    using boost::spirit::ch_p;
    using boost::spirit::real_p;
    using boost::spirit::space_p;

    using boost::bind;
    using boost::ref;

    using std::stack;

    typedef double Type;

    stack<Type> sValueStack;

    // E ::= T ( (+T) | (-T) )*
    // T ::= F ( (*F) | (/F) )*
    // F ::= ('(' E ')') | 浮点数

    rule<> E, F, T;
    E = (T >> *(
            (ch_p('+') >> T)[bind(&CalStack<std::plus<Type> >, ref(sValueStack))] |
            (ch_p('-') >> T)[bind(&CalStack<std::minus<Type> >, ref(sValueStack))]
        ));
    T = (F >> *(
            (ch_p('*') >> F)[bind(&CalStack<std::multiplies<Type> >, ref(sValueStack))] |
            (ch_p('/') >> F)[bind(&CalStack<std::divides<Type> >, ref(sValueStack))]
        ));
    F = (ch_p('(') >> E >> ch_p(')')) |
        (*space_p >> real_p[bind(&stack<Type>::push, ref(sValueStack), _1)] >> *space_p);

    if (parse(expr, E).full) {
        assert(sValueStack.size() == 1);
        std::cout << sValueStack.top() << std::endl;
    } else {
        std::cout << "计算过程中遇到错误" << std::endl;
    }
}

int main() {
    std::string input;
    while( std::getline(std::cin, input) ) {
        eval(input.c_str());
    }
}

你可能感兴趣的:(C++,String,struct,input,regex,lambda)