Boost Spirit解析器使用三个字符串向量编译成一个结构,adapt not working 我是一名学生,需要用Boost库在C++中编写解析器。

Boost Spirit解析器使用三个字符串向量编译成一个结构,adapt not working 我是一名学生,需要用Boost库在C++中编写解析器。,c++,parsing,boost,struct,boost-fusion,C++,Parsing,Boost,Struct,Boost Fusion,所以我用QI写了一个语法,因为我需要解析成一个结构。到目前为止,一切顺利 我将给你一些示例代码。我认为这比把整个程序写下来容易 说明: 首先我们读取一个txt文件,然后解析器检查它,说“解析没问题!”然后解析到结构中。我们的输出是控制台中的结构 这很好,现在来看一些代码示例。在这里你可以看到助推精神气的语法: subject %= lexeme[lit("Fach: ") >> +(char_("a-zA-Z")) >> lit("\n")]; //works!

所以我用QI写了一个语法,因为我需要解析成一个结构。到目前为止,一切顺利

我将给你一些示例代码。我认为这比把整个程序写下来容易

说明: 首先我们读取一个txt文件,然后解析器检查它,说“解析没问题!”然后解析到结构中。我们的输出是控制台中的结构

这很好,现在来看一些代码示例。在这里你可以看到助推精神气的语法:

subject %= lexeme[lit("Fach: ") >> +(char_("a-zA-Z"))   >> lit("\n")]; //works!

        dozent %= lexeme[lit("Dozent: ") >> +(char_("a-zA-Z")) >> lit("\n")];

        date %= lexeme[lit("Datum: ") >> digit >> digit >> lit("-") >> digit >> digit >> lit("-") >> digit >> digit >> digit >> digit >> lit("\n")];

        count %= lexeme[lit("Anzahl: ") >> +digit >> lit("\n")];

        points %= lexeme[+digit >> lit("\t")];

        mark %= lexeme[digit >> lit("\n")];

        matnumber %= lexeme[(digit >> digit >> digit >> punct >> digit >> digit >> digit) >> lit("\t")];

        student %= matnumber >> points >> mark;

        start %=  subject >> dozent >> date >> count >> student;
这很好,学生规则带来了一个问题,我们有一个由三部分组成的元素。编号、点数和标记。你可以想象我的意思,这里是我们试图解析的TXT文件:

Subject: Physics
Dozent: Wayne
Datum: 20-10-2014
Anzahl: 20
729.888 33  5
185.363 35  5
最后两行是规则学生。在txt文件中,我们有两行以上的内容

我们可以把这些行作为“学生”,我们在结构中用typedef写了一个向量:

typedef boost::fusion::vector<string, string, string> student_t;
)

你看,下面有typedef

然后我们就有了语法规则

    qi::rule<Iterator, string(), ascii::space_type> subject;
    qi::rule<Iterator, string(), ascii::space_type> dozent;
    qi::rule<Iterator, string(), ascii::space_type> date;
    qi::rule<Iterator, string(), ascii::space_type> count;
    qi::rule<Iterator, string(), ascii::space_type> matnumber;
    qi::rule<Iterator, string(), ascii::space_type> points;
    qi::rule<Iterator, string(), ascii::space_type> mark;
    qi::rule<Iterator, boost::fusion::vector<boost::fusion::vector<std::string, std::string, std::string> >()> student; 
qi::规则主体;
qi::rule dozent;
qi::规则日期;
qi::规则计数;
qi::规则matnumber;
qi:规则点;
qi:规则标记;
齐:规则学生;
还有我们项目的最后一个问题

我们不知道qi:规则需要BOOST\u适应哪种数据类型。。。很好用。所有其他点都是字符串,但不知道如何实现我们创建的向量

所有其他规则都很好地工作,并在结构中,只是向量产生了问题

有人知道吗?如果你需要,我可以上传更多的文件和代码片段,但我仍然认为这可能只是一个我看不到的小问题。我环顾四周寻找了许多boost主题,但没有找到正确的内容

我必须补充的信息,我只是一个初学者,所以可能我没有解释所有的权利和。。。是 啊希望你能理解。而且我的英语不是最好的

提前感谢您的帮助


William

Spirit是一个解析器生成器。您似乎没有实际解析任何内容(您只是“提取”字符序列,这更像是标记化)

我会这样做:

  • 使用适当的数据类型
  • 使用
    空白
    跳过(不包括
    eol
  • eol
    期望值放在正确的位置
  • 把词素放在正确的位置
  • 制作
    date\t
    它自己的类型
  • 制作
    student\t
    它自己的类型
  • 修复使用
    std::vector()
    而不是~
    fusion::vector()
    的规则(这是一个错误)
  • 使用
    操作员eol]
    解析预期的学生行数
  • 使用
    qi::locals
    将预期的学生人数实际传递到
    repeat()

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <iostream>
#include <iomanip>

namespace qi = boost::spirit::qi;
namespace vec = boost::fusion;

struct student_t {
    std::string matr_nr;
    unsigned    points;
    int         mark;
};

struct date_t {
    unsigned dd, mm, yyyy;

    friend std::ostream& operator<<(std::ostream& os, date_t const& d) {
        std::ostream local(os.rdbuf());
        local << std::setw(2) << std::setfill('0') << d.dd <<
            "-" << std::setw(2) << std::setfill('0') << d.mm <<
            "-" << std::setw(4) << std::setfill('0') << d.yyyy;
        return os;
    }
};

BOOST_FUSION_ADAPT_STRUCT(student_t,
        (std::string,matr_nr)(unsigned,points)(int,mark))
BOOST_FUSION_ADAPT_STRUCT(date_t,
        (unsigned,dd)(unsigned,mm)(unsigned,yyyy))

struct klausur {
    std::string str_subject;
    std::string str_dozent;
    date_t date;

    unsigned count;
    std::vector<student_t>   students;

    friend std::ostream& operator<<(std::ostream& os, klausur const& k)
    {
        os << "Fach: "   << k.str_subject << '\n';
        os << "Dozent: " << k.str_dozent  << '\n';
        os << "Datum: "  << k.date        << '\n';
        os << "Anzahl: " << k.count       << '\n';
        for (auto& s : k.students) {
            os << "Mat_Nr: " << s.matr_nr << '\n';
            os << "Punkte: " << s.points  << '\n';
            os << "Note: "   << s.mark    << '\n';
        }
        return os;
    }
};

BOOST_FUSION_ADAPT_STRUCT(klausur,
        (std::string                     , str_subject)
        (std::string                     , str_dozent)
        (date_t                          , date)
        (unsigned                        , count)
        (std::vector<student_t>          , students)
    )

template <typename Iterator, typename Skipper = qi::ascii::blank_type>
struct grammar : qi::grammar<Iterator, klausur(), Skipper> {
    grammar() : grammar::base_type(start) {
        using namespace qi;
        subject   = "Fach:"   >> lexeme [ +~char_('\n') ] >> eol;
        dozent    = "Dozent:" >> lexeme [ +~char_('\n') ] >> eol;
        date      = "Datum:"  >> lexeme [uint_ >> '-' >> uint_ >> '-' >> uint_] >> eol;
        count     = "Anzahl:" >> uint_ >> eol;
        points    = uint_;
        mark      = int_parser<int, 10, 1, 1>(); // single base-10 digit

        // no clue about this format; what is it? Just a real number?
        matnumber = lexeme[digit >> digit >> digit >> punct >> digit >> digit >> digit];

        student   = matnumber >> points >> mark;

        _a_type expected;
        klausur_ %= subject
                 >> dozent
                 >> date
                 >> count            [ expected = _1 ]
                 >> repeat(expected) [ student >> (eol|eoi) ]
                 ;

        start     = klausur_;

        BOOST_SPIRIT_DEBUG_NODES((start)(klausur_)(student)(matnumber)(mark)(points)(count)(date)(dozent)(subject))
    }

  private:
    qi::rule<Iterator, klausur(), Skipper> start;
    qi::rule<Iterator, klausur(), Skipper, qi::locals<unsigned> > klausur_;

    qi::rule<Iterator, std::string()    , Skipper> subject;
    qi::rule<Iterator, std::string()    , Skipper> dozent;
    qi::rule<Iterator, date_t(),          Skipper> date;
    qi::rule<Iterator, unsigned()       , Skipper> count;
    qi::rule<Iterator, std::string()    , Skipper> matnumber;
    qi::rule<Iterator, unsigned()       , Skipper> points;
    qi::rule<Iterator, int()            , Skipper> mark;
    qi::rule<Iterator, student_t()      , Skipper> student;
};

int main() {
    using It = std::string::const_iterator;
    std::string const input =
R"(Fach: Physics
Dozent: Wayne
Datum: 20-10-2014
Anzahl: 2
729.888 33  5
185.363 35  5)";

    It f = input.begin(), l = input.end();

    grammar<It> g;
    klausur k;
    bool ok = qi::phrase_parse(f, l, g, qi::ascii::blank, k);

    if (ok) {
        std::cout << "Parse success\n";
        std::cout << k;
    } else {
        std::cout << "Parse failed\n";
    }

    if (f!=l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
以及72行调试输出:

<start>
  <try>Fach: Physics\nDozent</try>
  <klausur_>
    <try>Fach: Physics\nDozent</try>
    <subject>
      <try>Fach: Physics\nDozent</try>
      <success>Dozent: Wayne\nDatum:</success>
      <attributes>[[P, h, y, s, i, c, s]]</attributes>
    </subject>
    <dozent>
      <try>Dozent: Wayne\nDatum:</try>
      <success>Datum: 20-10-2014\nAn</success>
      <attributes>[[W, a, y, n, e]]</attributes>
    </dozent>
    <date>
      <try>Datum: 20-10-2014\nAn</try>
      <success>Anzahl: 2\n729.888 33</success>
      <attributes>[[20, 10, 2014]]</attributes>
    </date>
    <count>
      <try>Anzahl: 2\n729.888 33</try>
      <success>729.888 33  5\n185.36</success>
      <attributes>[2]</attributes>
    </count>
    <student>
      <try>729.888 33  5\n185.36</try>
      <matnumber>
        <try>729.888 33  5\n185.36</try>
        <success> 33  5\n185.363 35  5</success>
        <attributes>[[7, 2, 9, ., 8, 8, 8]]</attributes>
      </matnumber>
      <points>
        <try> 33  5\n185.363 35  5</try>
        <success>  5\n185.363 35  5</success>
        <attributes>[33]</attributes>
      </points>
      <mark>
        <try>  5\n185.363 35  5</try>
        <success>\n185.363 35  5</success>
        <attributes>[5]</attributes>
      </mark>
      <success>\n185.363 35  5</success>
      <attributes>[[[7, 2, 9, ., 8, 8, 8], 33, 5]]</attributes>
    </student>
    <student>
      <try>185.363 35  5</try>
      <matnumber>
        <try>185.363 35  5</try>
        <success> 35  5</success>
        <attributes>[[1, 8, 5, ., 3, 6, 3]]</attributes>
      </matnumber>
      <points>
        <try> 35  5</try>
        <success>  5</success>
        <attributes>[35]</attributes>
      </points>
      <mark>
        <try>  5</try>
        <success></success>
        <attributes>[5]</attributes>
      </mark>
      <success></success>
      <attributes>[[[1, 8, 5, ., 3, 6, 3], 35, 5]]</attributes>
    </student>
    <success></success>
    <attributes>[[[P, h, y, s, i, c, s], [W, a, y, n, e], [20, 10, 2014], 2, [[[7, 2, 9, ., 8, 8, 8], 33, 5], [[1, 8, 5, ., 3, 6, 3], 35, 5]]]]</attributes><locals>(2)</locals>
  </klausur_>
  <success></success>
  <attributes>[[[P, h, y, s, i, c, s], [W, a, y, n, e], [20, 10, 2014], 2, [[[7, 2, 9, ., 8, 8, 8], 33, 5], [[1, 8, 5, ., 3, 6, 3], 35, 5]]]]</attributes>
</start>

法赫:物理学
法赫:物理学
法赫:物理学
Dozent:Wayne\n数据:
[P,h,y,s,i,c,s]]
Dozent:Wayne\n数据:
数据:2014年10月20日\n
[W,a,y,n,e]]
数据:2014年10月20日\n
Anzahl:2\n729.888 33
[[20, 10, 2014]]
Anzahl:2\n729.888 33
729.888 33 5\n185.36
[2]
729.888 33 5\n185.36
729.888 33 5\n185.36
33 5\n185.363 35 5
[[7, 2, 9, ., 8, 8, 8]]
33 5\n185.363 35 5
5\n185.363 35 5
[33]
5\n185.363 35 5
\n185.363 35 5
[5]
\n185.363 35 5
[[[7, 2, 9, ., 8, 8, 8], 33, 5]]
一百八十五点三六三三五五
一百八十五点三六三三五五
35  5
[[1, 8, 5, ., 3, 6, 3]]
35  5
5.
[35]
5.
[5]
[[[1, 8, 5, ., 3, 6, 3], 35, 5]]
[P,h,y,s,i,c,s],[W,a,y,n,e],[20,102014],2,[7,2,9,8,8,8,8,33,5],[1,8,5,3,6,3,35,5].(2)
[P,h,y,s,i,c,s],[W,a,y,n,e],[20,102014],2,[[7,2,9,8,8,8,8,8,33,5],[1,8,5,3,6,3,35,5]]

为什么最后一条规则没有跳过者?你会犯什么错误?你试过这个规则吗?您确定student\u t不在命名空间客户端中吗?您在解析多个学生时遇到问题吗?您的开始规则仅包含一名学生。试试kleene star。嘿,有一个船长,但为了测试我删除了它。我总是得到这样一个错误:他无法解析更深层库函数中的运算符。我很确定student_t在名称空间客户端中,这有问题吗?当时只有一名学生参加考试。通常规则是<代码>+学生。提前感谢您的帮助。嘿,谢谢您的快速帮助和代码。我试着在我的VisualStudio2012中测试它,它总是说我不能将
it
作为使用指令。我将在我的程序中测试和实现的所有其他信息。我不是这方面的专家,所以我想这需要一些时间。感谢您
使用它=std::string::const\u迭代器是产生问题的部分。必须用typedef:)替换它,现在它可以工作了。谢谢:)
typedef std::string::const_迭代器剩下的唯一错误是visual studio不允许在多行中使用字符串,我尝试使用
\n
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <iostream>
#include <iomanip>

namespace qi = boost::spirit::qi;
namespace vec = boost::fusion;

struct student_t {
    std::string matr_nr;
    unsigned    points;
    int         mark;
};

struct date_t {
    unsigned dd, mm, yyyy;

    friend std::ostream& operator<<(std::ostream& os, date_t const& d) {
        std::ostream local(os.rdbuf());
        local << std::setw(2) << std::setfill('0') << d.dd <<
            "-" << std::setw(2) << std::setfill('0') << d.mm <<
            "-" << std::setw(4) << std::setfill('0') << d.yyyy;
        return os;
    }
};

BOOST_FUSION_ADAPT_STRUCT(student_t,
        (std::string,matr_nr)(unsigned,points)(int,mark))
BOOST_FUSION_ADAPT_STRUCT(date_t,
        (unsigned,dd)(unsigned,mm)(unsigned,yyyy))

struct klausur {
    std::string str_subject;
    std::string str_dozent;
    date_t date;

    unsigned count;
    std::vector<student_t>   students;

    friend std::ostream& operator<<(std::ostream& os, klausur const& k)
    {
        os << "Fach: "   << k.str_subject << '\n';
        os << "Dozent: " << k.str_dozent  << '\n';
        os << "Datum: "  << k.date        << '\n';
        os << "Anzahl: " << k.count       << '\n';
        for (auto& s : k.students) {
            os << "Mat_Nr: " << s.matr_nr << '\n';
            os << "Punkte: " << s.points  << '\n';
            os << "Note: "   << s.mark    << '\n';
        }
        return os;
    }
};

BOOST_FUSION_ADAPT_STRUCT(klausur,
        (std::string                     , str_subject)
        (std::string                     , str_dozent)
        (date_t                          , date)
        (unsigned                        , count)
        (std::vector<student_t>          , students)
    )

template <typename Iterator, typename Skipper = qi::ascii::blank_type>
struct grammar : qi::grammar<Iterator, klausur(), Skipper> {
    grammar() : grammar::base_type(start) {
        using namespace qi;
        subject   = "Fach:"   >> lexeme [ +~char_('\n') ] >> eol;
        dozent    = "Dozent:" >> lexeme [ +~char_('\n') ] >> eol;
        date      = "Datum:"  >> lexeme [uint_ >> '-' >> uint_ >> '-' >> uint_] >> eol;
        count     = "Anzahl:" >> uint_ >> eol;
        points    = uint_;
        mark      = int_parser<int, 10, 1, 1>(); // single base-10 digit

        // no clue about this format; what is it? Just a real number?
        matnumber = lexeme[digit >> digit >> digit >> punct >> digit >> digit >> digit];

        student   = matnumber >> points >> mark;

        _a_type expected;
        klausur_ %= subject
                 >> dozent
                 >> date
                 >> count            [ expected = _1 ]
                 >> repeat(expected) [ student >> (eol|eoi) ]
                 ;

        start     = klausur_;

        BOOST_SPIRIT_DEBUG_NODES((start)(klausur_)(student)(matnumber)(mark)(points)(count)(date)(dozent)(subject))
    }

  private:
    qi::rule<Iterator, klausur(), Skipper> start;
    qi::rule<Iterator, klausur(), Skipper, qi::locals<unsigned> > klausur_;

    qi::rule<Iterator, std::string()    , Skipper> subject;
    qi::rule<Iterator, std::string()    , Skipper> dozent;
    qi::rule<Iterator, date_t(),          Skipper> date;
    qi::rule<Iterator, unsigned()       , Skipper> count;
    qi::rule<Iterator, std::string()    , Skipper> matnumber;
    qi::rule<Iterator, unsigned()       , Skipper> points;
    qi::rule<Iterator, int()            , Skipper> mark;
    qi::rule<Iterator, student_t()      , Skipper> student;
};

int main() {
    using It = std::string::const_iterator;
    std::string const input =
R"(Fach: Physics
Dozent: Wayne
Datum: 20-10-2014
Anzahl: 2
729.888 33  5
185.363 35  5)";

    It f = input.begin(), l = input.end();

    grammar<It> g;
    klausur k;
    bool ok = qi::phrase_parse(f, l, g, qi::ascii::blank, k);

    if (ok) {
        std::cout << "Parse success\n";
        std::cout << k;
    } else {
        std::cout << "Parse failed\n";
    }

    if (f!=l) {
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
    }
}
Parse success
Fach: Physics
Dozent: Wayne
Datum: 20-10-2014
Anzahl: 2
Mat_Nr: 729.888
Punkte: 33
Note: 5
Mat_Nr: 185.363
Punkte: 35
Note: 5
<start>
  <try>Fach: Physics\nDozent</try>
  <klausur_>
    <try>Fach: Physics\nDozent</try>
    <subject>
      <try>Fach: Physics\nDozent</try>
      <success>Dozent: Wayne\nDatum:</success>
      <attributes>[[P, h, y, s, i, c, s]]</attributes>
    </subject>
    <dozent>
      <try>Dozent: Wayne\nDatum:</try>
      <success>Datum: 20-10-2014\nAn</success>
      <attributes>[[W, a, y, n, e]]</attributes>
    </dozent>
    <date>
      <try>Datum: 20-10-2014\nAn</try>
      <success>Anzahl: 2\n729.888 33</success>
      <attributes>[[20, 10, 2014]]</attributes>
    </date>
    <count>
      <try>Anzahl: 2\n729.888 33</try>
      <success>729.888 33  5\n185.36</success>
      <attributes>[2]</attributes>
    </count>
    <student>
      <try>729.888 33  5\n185.36</try>
      <matnumber>
        <try>729.888 33  5\n185.36</try>
        <success> 33  5\n185.363 35  5</success>
        <attributes>[[7, 2, 9, ., 8, 8, 8]]</attributes>
      </matnumber>
      <points>
        <try> 33  5\n185.363 35  5</try>
        <success>  5\n185.363 35  5</success>
        <attributes>[33]</attributes>
      </points>
      <mark>
        <try>  5\n185.363 35  5</try>
        <success>\n185.363 35  5</success>
        <attributes>[5]</attributes>
      </mark>
      <success>\n185.363 35  5</success>
      <attributes>[[[7, 2, 9, ., 8, 8, 8], 33, 5]]</attributes>
    </student>
    <student>
      <try>185.363 35  5</try>
      <matnumber>
        <try>185.363 35  5</try>
        <success> 35  5</success>
        <attributes>[[1, 8, 5, ., 3, 6, 3]]</attributes>
      </matnumber>
      <points>
        <try> 35  5</try>
        <success>  5</success>
        <attributes>[35]</attributes>
      </points>
      <mark>
        <try>  5</try>
        <success></success>
        <attributes>[5]</attributes>
      </mark>
      <success></success>
      <attributes>[[[1, 8, 5, ., 3, 6, 3], 35, 5]]</attributes>
    </student>
    <success></success>
    <attributes>[[[P, h, y, s, i, c, s], [W, a, y, n, e], [20, 10, 2014], 2, [[[7, 2, 9, ., 8, 8, 8], 33, 5], [[1, 8, 5, ., 3, 6, 3], 35, 5]]]]</attributes><locals>(2)</locals>
  </klausur_>
  <success></success>
  <attributes>[[[P, h, y, s, i, c, s], [W, a, y, n, e], [20, 10, 2014], 2, [[[7, 2, 9, ., 8, 8, 8], 33, 5], [[1, 8, 5, ., 3, 6, 3], 35, 5]]]]</attributes>
</start>