C++ 用boost::spirit简单表达
我需要解析C++ 用boost::spirit简单表达,c++,parsing,boost-spirit,boost-phoenix,C++,Parsing,Boost Spirit,Boost Phoenix,我需要解析简单表达式::=限制整数(天|小时|分钟)。我写了语法代码 struct Parser: grammar<std::string::const_iterator, boost::spirit::ascii::space_type> { public: Parser(ConditionTree& a_lTree): Parser::base_type(limit_expression), m_lTree(a_lTree) { using
简单表达式::=限制整数(天|小时|分钟)
。我写了语法代码
struct Parser: grammar<std::string::const_iterator, boost::spirit::ascii::space_type>
{
public:
Parser(ConditionTree& a_lTree):
Parser::base_type(limit_expression),
m_lTree(a_lTree)
{
using boost::spirit::qi::uint_;
using boost::spirit::qi::_1;
using boost::spirit::qi::_2;
limit_expression = limit_days_operator | limit_hours_operator | limit_minutes_operator ;
limit_days_operator = ( string("limit") > uint_ > string("days") )[ phoenix::bind( &ConditionTree::AddDaysLimitOperator, m_lTree, _2) ] ;
limit_hours_operator = ( string("limit") > uint_ > string("hours") )[ phoenix::bind( &ConditionTree::AddHoursLimitOperator, m_lTree, _2) ] ;
limit_minutes_operator = ( string("limit") > uint_ > string("minutes") )[ phoenix::bind( &ConditionTree::AddMinutesLimitOperator, m_lTree, _2) ] ;
BOOST_SPIRIT_DEBUG_NODE(limit_expression);
BOOST_SPIRIT_DEBUG_NODE(limit_days_operator);
BOOST_SPIRIT_DEBUG_NODE(limit_hours_operator);
BOOST_SPIRIT_DEBUG_NODE(limit_minutes_operator);
}
rule<std::string::const_iterator, boost::spirit::ascii::space_type> limit_expression;
rule<std::string::const_iterator, boost::spirit::ascii::space_type> limit_days_operator;
rule<std::string::const_iterator, boost::spirit::ascii::space_type> limit_hours_operator;
rule<std::string::const_iterator, boost::spirit::ascii::space_type> limit_minutes_operator;
ConditionTree& m_lTree;
}
void main()
{
ConditionTree oTree;
Parser parser(oTree);
std::string strTest("limit5minutes");
std::string::const_iterator it_begin(strTest.begin());
std::string::const_iterator it_end(strTest.end());
bool result = phrase_parse(it_begin, it_end, parser, space);
}
然后解析器正确地读取了
limit5days
,但没有正确地读取limit5minutes
,因为,正如我所看到的,它与limit5hours
没有区别,这里发生了很多事情。然而,当我整理好一些小东西试图阅读并完成它(SSCCE)时,它也编译了:
我在此简要说明了一些要点:
- 语义操作中的绑定表达式按值复制
,这样您就不能对成员进行变异<此处需要代码>phx::refm_lTree
- 期望点使得除了“天数”限制之外,无法成功解析任何内容
- 使用
,除非您确实希望将字符串的值用作属性。更好的是,只需编写lit
,因为重载会完成其余的工作“limit”>>uint\u>>“days”
会导致连接和紧耦合MULTree
限制
结构:
qi::rule<Iterator, ConditionTree::Limit(), Skipper> limit_expression;
limit_expression = "limit" >> qi::uint_ >> unit_;
因为现在语法只解析Limit
对象,所以可以在解析后原子地进行计算:
ConditionTree::Limit limit;
if (phrase_parse(iter, end, parser, ascii::space, limit))
{
AddLimit(oTree, limit);
}
将解析与求值分离使您能够添加以下内容
- 重复计算同一表达式(无重复解析)
- 在求值之前简化表达式树
- 评估前验证
- 调试
- 更有趣的是,它允许您以函数式风格编写
,而不改变对象:ApplyLimit
ConditionTree ApplyLimit(ConditionTree const& ct, Limit limit) { return ct + limit; // do something here }
- 但最重要的是:它极大地简化了语法,为你节省了本该花在其他方面的时间
void AddLimit(ConditionTree&, ConditionTree::Limit): 5 minutes
表册
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
结构条件树{
结构极限{
无符号值;
枚举单位{天、小时、分钟}单位;
};
好友无效添加限制(条件树和ct,限制){
std::coutvoid main()
,真的吗?(你必须使用上世纪90年代的编译器来编译此文件)@cv_和_他感谢你注意到编辑,这已经是值得的:)
ConditionTree ApplyLimit(ConditionTree const& ct, Limit limit) {
return ct + limit; // do something here
}
void AddLimit(ConditionTree&, ConditionTree::Limit): 5 minutes
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
struct ConditionTree {
struct Limit {
unsigned value;
enum unit_t { days, hours, minutes } unit;
};
friend void AddLimit(ConditionTree& ct, Limit limit) {
std::cout << "AddLimit: " << limit.value;
switch (limit.unit) {
case Limit::days: std::cout << " days\n"; break;
case Limit::hours: std::cout << " hours\n"; break;
case Limit::minutes: std::cout << " minutes\n"; break;
}
}
};
BOOST_FUSION_ADAPT_STRUCT(ConditionTree::Limit, (unsigned,value)(ConditionTree::Limit::unit_t,unit))
template <typename Iterator = std::string::const_iterator, typename Skipper = ascii::space_type>
struct Parser: qi::grammar<Iterator, ConditionTree::Limit(), ascii::space_type>
{
public:
Parser() : Parser::base_type(limit_expression)
{
unit_.add("days", ConditionTree::Limit::days)
("hours", ConditionTree::Limit::hours)
("minutes", ConditionTree::Limit::minutes);
limit_expression = "limit" >> qi::uint_ >> unit_;
}
qi::symbols<char, ConditionTree::Limit::unit_t> unit_;
qi::rule<Iterator, ConditionTree::Limit(), Skipper> limit_expression;
};
int main()
{
ConditionTree oTree;
Parser<> parser;
std::string strTest("limit5minutes");
std::string::const_iterator iter(strTest.begin()), end(strTest.end());
ConditionTree::Limit limit;
if (phrase_parse(iter, end, parser, ascii::space, limit))
{
AddLimit(oTree, limit);
}
}