加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – Boost.Spirit语法问题

发布时间:2020-12-16 09:52:43 所属栏目:百科 来源:网络整理
导读:我试图解析terminfo定义文本文件.我是Boost.Spirit的新手.我从简单的语法开始,只解析注释行,空行和终端定义.正如语法中的代码注释所示,取消注释[_val = _1]定义会中断编译.为什么?我可以修理吗? 如果我忽略实际的terminfo文件,我希望下面的代码解析这种文
我试图解析terminfo定义文本文件.我是Boost.Spirit的新手.我从简单的语法开始,只解析注释行,空行和终端定义.正如语法中的代码注释所示,取消注释[_val = _1]定义会中断编译.为什么?我可以修理吗?

如果我忽略实际的terminfo文件,我希望下面的代码解析这种文本:

# comment line

first definition line
  second 
  third line

# another comment line

码:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_eol.hpp>
#include <boost/spirit/include/qi_eoi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <vector>
#include <iostream>
#include <string>

namespace termcxx
{

namespace parser
{

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace px = boost::phoenix;

//using qi::double_;
using ascii::space;
//using px::ref;
using px::construct;

//using qi::eps;
//using qi::lit;
using qi::_val;
using qi::_1;
using ascii::char_;
using qi::eol;
using qi::eoi;


struct context
{
    int dummy;

    context () = default;
    context (context const &) = default;
    context (std::vector<char> a)
    { }
    context (std::vector<char> a,std::vector<char> b)
    { }
};

} }


BOOST_FUSION_ADAPT_STRUCT(
    termcxx::parser::context,(int,dummy))


namespace termcxx
{

namespace parser
{

template <typename Iterator>
struct parser
    : qi::grammar<Iterator,context()>
{
    qi::rule<Iterator,std::vector<char> > comment_line
    = (*space >> '#' >> *(char_ - eol) >> (eol | eoi))[_val = _1]
        ;

    qi::rule<Iterator,std::vector<char> > empty_line
    = (*space >> (eol | eoi))[_val = _1]
        ;

    qi::rule<Iterator,std::vector<char> > def_first_line
    = (+(char_ - eol) >> (eol | eoi))[_val = _1]
        ;

    qi::rule<Iterator,std::vector<char> > def_subsequent_line
    = (+space >> +(char_ - eol) >> (eol | eoi))[_val = _1]
        ;

    qi::rule<Iterator,std::vector<char> > definition
    = (def_first_line >> *def_subsequent_line)//[_val = _1] // Uncommenting the [_val = _1] breaks compilation. Why?
        ;

    qi::rule<Iterator,context()> start
    = (*(comment_line
            | empty_line
            | definition))[_val = construct<context> ()]
        ;

    parser()
        : parser::base_type(start)
    { }
};

template struct parser<std::string::iterator>;

} // namespace parser

} // namespace termcxx

解决方法

为什么你坚持指定[_val = _1]?这是多余的,因为默认属性传播就是这样做的.事实上它很疼,见下文

接下来,(def_first_line>> * def_subsequent_line)的属性类型(显然)与std :: vector< char>不兼容.也许你可以

>只使用默认属性传播(具有足够的智能来继续追加)
>使用raw []获得完整匹配的输入
>定义BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT(我不确定这是否得到很好的支持)

也,

>你可以替换std :: vector< char>当依赖于自动属性传播时,使用std :: string
>您可以检测解析器表达式的实际公开类型:Detecting the parameter types in a Spirit semantic action

更新

还有一些问题:

>您拼错了大多数规则的属性类型(missing()):

qi::rule<Iterator,std::string()> comment_line;
qi::rule<Iterator,std::string()> empty_line;
qi::rule<Iterator,std::string()> def_first_line;
qi::rule<Iterator,std::string()> def_subsequent_line;
qi::rule<Iterator,std::string()> definition;

>在eoi处匹配的empty_line在输入结束时导致无限循环
>使用char_也接受空格(使用图形代替:)

def_first_line      = graph >> +(char_ - eol)         >> (eol|eoi);

>使用qi :: space也会吃掉行尾!请改用qi :: blank
>青睐可靠性:

empty_line          = *blank >> eol;
    comment_line        = *blank >> '#' >> *(char_ - eol) >> (eol|eoi);
    def_first_line      = graph >> +(char_ - eol)         >> (eol|eoi);
    def_subsequent_line = +blank >> +(char_ - eol)        >> (eol|eoi);

    definition          = (def_first_line >> *def_subsequent_line);

    start               = (  
                            *(comment_line | empty_line | definition)
                          ) [ _val = px::construct<context>() ]
                          ;

在与Spirit合作时,这种简单的习惯将为您节省数小时的工作和理智.
>您可以在某种程度上简化包含

这是一个带有输出的固定版本Live On Coliru:

<start>
  <try># comment linennfirs</try>
  <comment_line>
    <try># comment linennfirs</try>
    <success>nfirst definition li</success>
    <attributes>[[,c,o,m,e,n,t,l,i,e]]</attributes>
  </comment_line>
  <comment_line>
    <try>nfirst definition li</try>
    <fail/>
  </comment_line>
  <empty_line>
    <try>nfirst definition li</try>
    <success>first definition lin</success>
    <attributes>[[]]</attributes>
  </empty_line>
  <comment_line>
    <try>first definition lin</try>
    <fail/>
  </comment_line>
  <empty_line>
    <try>first definition lin</try>
    <fail/>
  </empty_line>
  <definition>
    <try>first definition lin</try>
    <def_first_line>
      <try>first definition lin</try>
      <success>  second n  third li</success>
      <attributes>[[f,r,s,d,f,e]]</attributes>
    </def_first_line>
    <def_subsequent_line>
      <try>  second n  third li</try>
      <success>  third linenn# anot</success>
      <attributes>[[f,]]</attributes>
    </def_subsequent_line>
    <def_subsequent_line>
      <try>  third linenn# anot</try>
      <success>n# another comment l</success>
      <attributes>[[f,h,e]]</attributes>
    </def_subsequent_line>
    <def_subsequent_line>
      <try>n# another comment l</try>
      <fail/>
    </def_subsequent_line>
    <success>n# another comment l</success>
    <attributes>[[f,e]]</attributes>
  </definition>
  <comment_line>
    <try>n# another comment l</try>
    <fail/>
  </comment_line>
  <empty_line>
    <try>n# another comment l</try>
    <success># another comment li</success>
    <attributes>[[]]</attributes>
  </empty_line>
  <comment_line>
    <try># another comment li</try>
    <success></success>
    <attributes>[[,a,!]]</attributes>
  </comment_line>
  <comment_line>
    <try></try>
    <fail/>
  </comment_line>
  <empty_line>
    <try></try>
    <fail/>
  </empty_line>
  <definition>
    <try></try>
    <def_first_line>
      <try></try>
      <fail/>
    </def_first_line>
    <fail/>
  </definition>
  <success></success>
  <attributes>[]</attributes>
</start>
Success

完整代码供参考:

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <vector>
#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;

namespace termcxx { namespace parser {

    namespace ascii = boost::spirit::ascii;
    namespace px    = boost::phoenix;

    //using qi::double_;
    using ascii::blank;
    //using px::ref;
    using px::construct;

    //using qi::eps;
    //using qi::lit;
    using qi::_val;
    using qi::_1;
    using ascii::char_;
    using ascii::graph;
    using qi::eol;
    using qi::eoi;

    struct context
    {
        int dummy;

        context () = default;
        context (context const &) = default;
        context (std::vector<char> a) { }
        context (std::vector<char> a,std::vector<char> b) { }
    };

} }

BOOST_FUSION_ADAPT_STRUCT(termcxx::parser::context,dummy))

namespace termcxx { namespace parser {

    template <typename Iterator>
    struct parser : qi::grammar<Iterator,context()>
    {
        parser() : parser::base_type(start)
        { 
            empty_line          = *blank >> eol;
            comment_line        = *blank >> '#' >> *(char_ - eol) >> (eol|eoi);
            def_first_line      = graph >> +(char_ - eol)         >> (eol|eoi);
            def_subsequent_line = +blank >> +(char_ - eol)        >> (eol|eoi);

            definition          = (def_first_line >> *def_subsequent_line);

            start               = (  
                                    *(comment_line | empty_line | definition)
                                  ) [ _val = px::construct<context>() ]
                                  ;

            BOOST_SPIRIT_DEBUG_NODES((start)(def_first_line)(def_subsequent_line)(definition)(empty_line)(comment_line))
        }

      private:
        qi::rule<Iterator,context()> start;
        qi::rule<Iterator,std::string()> comment_line;
        qi::rule<Iterator,std::string()> empty_line;
        qi::rule<Iterator,std::string()> def_first_line;
        qi::rule<Iterator,std::string()> def_subsequent_line;
        qi::rule<Iterator,std::string()> definition;
    };

} }

int main()
{
    using It = boost::spirit::istream_iterator;
    termcxx::parser::parser<It> g;

    It f(std::cin >> std::noskipws),l;
    termcxx::parser::context data;
    if (qi::parse(f,g,data))
        std::cout << "Successn";
    else
        std::cout << "Failuren";

    if (f != l)
        std::cout << "Remaining input: '" << std::string(f,l) << "'n";
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读