忽略所有字符直到给定的单词 [英] Ignore all characters up to a given word

查看:50
本文介绍了忽略所有字符直到给定的单词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个示例代码,可以正确解析字符串str. 如果字符串前后有多余的字符,我该如何工作?例如,如果我did str = std::string("AAA") + str + std::string("AAA")

I have this example code, which parses the string str correctly. How to I make it work if there any extra characters before and/or after the string? For example if I did str = std::string("AAA") + str + std::string("AAA")

frame.h

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

#include <boost/fusion/adapted/std_pair.hpp>

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

struct frame
{
  std::string addr;
  std::string func;
  std::string file;
  std::string fullname;
  std::string line;

  std::map<std::string, std::string> kv;
};

template <typename Iterator>
struct argsArray : qi::grammar<Iterator, std::map<std::string, std::string>()>
{
  argsArray() : argsArray::base_type(query)
  {
    query =
        qi::lit("args=[") >> pair >> *(qi::lit(',') >> pair) >> qi::lit(']');
    pair = qi::lit("{name=") >> quoted_string >> qi::lit(",value=") >>
           quoted_string >> qi::lit("}");
    key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
    quoted_string %= boost::spirit::lexeme['"' >> +(qi::char_ - '"') >> '"'];
  }
  qi::rule<Iterator, std::map<std::string, std::string>()> query;
  qi::rule<Iterator, std::pair<std::string, std::string>()> pair;
  qi::rule<Iterator, std::string()> key;
  qi::rule<Iterator, std::string()> quoted_string;
};

template <typename Iterator>
struct frameParser : qi::grammar<Iterator, frame(), ascii::space_type>
{
  frameParser() : frameParser::base_type(frame_rule)
  {
    static const auto _addr = phx::bind(&frame::addr, qi::_r1);
    static const auto _func = phx::bind(&frame::func, qi::_r1);
    static const auto _file = phx::bind(&frame::file, qi::_r1);
    static const auto _fullname = phx::bind(&frame::fullname, qi::_r1);
    static const auto _line = phx::bind(&frame::line, qi::_r1);
    static const auto _kv = phx::bind(&frame::kv, qi::_r1);

    func = qi::lit("func=") >> quoted_string;
    addr = qi::lit("addr=") >> quoted_string;
    file = qi::lit("file=") >> quoted_string;
    fullname = qi::lit("fullname=") >> quoted_string;
    line = qi::lit("line=") >> quoted_string;
    func_rule = func[_func = qi::_1];
    addr_rule = addr[_addr = qi::_1];
    file_rule = file[_file = qi::_1];
    fullname_rule = fullname[_fullname = qi::_1];
    line_rule = line[_line = qi::_1];

    kv_rule = arrTest[_kv = qi::_1];
    quoted_string %= boost::spirit::lexeme['"' >> +(qi::char_ - '"') >> '"'];

    frame_rule = qi::lit("frame={") >>
                 (addr_rule(qi::_val) ^ qi::lit(',') ^ func_rule(qi::_val) ^
                  qi::lit(',') ^ file_rule(qi::_val) ^ qi::lit(',') ^
                  fullname_rule(qi::_val) ^ qi::lit(',') ^ line_rule(qi::_val) ^
                  qi::lit(',') ^ kv_rule(qi::_val)) >>
                 qi::lit('}');

    BOOST_SPIRIT_DEBUG_NODES(
        (frame_rule)(func_rule)(addr_rule)(fullname_rule)(line_rule))
  }

  qi::rule<Iterator, void(frame&), ascii::space_type> func_rule, addr_rule,
      file_rule, fullname_rule, line_rule, kv_rule;
  qi::rule<Iterator, frame(), ascii::space_type> frame_rule;
  qi::rule<Iterator, std::string()> addr, func, file, fullname, line;
  qi::rule<Iterator, std::string()> quoted_string;
  argsArray<Iterator> arrTest;
};

test.cc

#include <iostream>
#include "gtest/gtest.h"
#include "parser/frame.h"

TEST(ParseFrameString, Test1)
{
  std::string str = R"(frame={addr="0x0000000000414008",)"
                    R"(func="main",)"
                    R"(args=[{name="argc",value="1"},)"
                    R"({name="argv",value="0x7fffffffe1a8"}],)"
                    R"(file="/home/stiopa/development/gdbFront/main.cc",)"
                    R"(fullname="/home/stiopa/development/gdbFront/main.cc",)"
                    R"(line="90"}")";

  typedef std::string::const_iterator It;
  const frameParser<It> g;
  It iter(str.begin()), end(str.end());
  frame frame;
  bool r = phrase_parse(iter, end, g, boost::spirit::ascii::space, frame);

  EXPECT_EQ(r, true);
  EXPECT_EQ(frame.addr, "0x0000000000414008");
  EXPECT_EQ(frame.func, "main");

  std::map<std::string, std::string> kv{{"argc", "1"},
                                        {"argv", "0x7fffffffe1a8"}};
  EXPECT_EQ(frame.kv, kv);

  EXPECT_EQ(frame.file, "/home/stiopa/development/gdbFront/main.cc");
  EXPECT_EQ(frame.fullname, "/home/stiopa/development/gdbFront/main.cc");
  EXPECT_EQ(frame.line, "90");
}

推荐答案

简单,低技术含量的解决方案是使用存储库中的qi::seek:

The simple, low-tech solution would be to use qi::seek from the repository:

#include <boost/spirit/repository/include/qi_seek.hpp>
namespace qir = boost::spirit::repository::qi;

然后:

bool r = phrase_parse(iter, end, qir::seek[g], boost::spirit::ascii::space, frame);

演示

在Coliru上直播

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

#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/repository/include/qi_seek.hpp>

namespace qi = boost::spirit::qi;
namespace qir = boost::spirit::repository::qi;
namespace phx = boost::phoenix;
namespace ascii = boost::spirit::ascii;

struct frame
{
    std::string addr;
    std::string func;
    std::string file;
    std::string fullname;
    std::string line;

    std::map<std::string, std::string> kv;
};

template <typename Iterator>
struct argsArray : qi::grammar<Iterator, std::map<std::string, std::string>()>
{
    argsArray() : argsArray::base_type(query)
    {
        query =
            qi::lit("args=[") >> pair >> *(qi::lit(',') >> pair) >> qi::lit(']');
        pair = qi::lit("{name=") >> quoted_string >> qi::lit(",value=") >>
            quoted_string >> qi::lit("}");
        key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
        quoted_string %= boost::spirit::lexeme['"' >> +(qi::char_ - '"') >> '"'];
    }
    qi::rule<Iterator, std::map<std::string, std::string>()> query;
    qi::rule<Iterator, std::pair<std::string, std::string>()> pair;
    qi::rule<Iterator, std::string()> key;
    qi::rule<Iterator, std::string()> quoted_string;
};

template <typename Iterator>
struct frameParser : qi::grammar<Iterator, frame(), ascii::space_type>
{
    frameParser() : frameParser::base_type(frame_rule)
    {
        static const auto _addr = phx::bind(&frame::addr, qi::_r1);
        static const auto _func = phx::bind(&frame::func, qi::_r1);
        static const auto _file = phx::bind(&frame::file, qi::_r1);
        static const auto _fullname = phx::bind(&frame::fullname, qi::_r1);
        static const auto _line = phx::bind(&frame::line, qi::_r1);
        static const auto _kv = phx::bind(&frame::kv, qi::_r1);

        func = qi::lit("func=") >> quoted_string;
        addr = qi::lit("addr=") >> quoted_string;
        file = qi::lit("file=") >> quoted_string;
        fullname = qi::lit("fullname=") >> quoted_string;
        line = qi::lit("line=") >> quoted_string;
        func_rule = func[_func = qi::_1];
        addr_rule = addr[_addr = qi::_1];
        file_rule = file[_file = qi::_1];
        fullname_rule = fullname[_fullname = qi::_1];
        line_rule = line[_line = qi::_1];

        kv_rule = arrTest[_kv = qi::_1];
        quoted_string %= boost::spirit::lexeme['"' >> +(qi::char_ - '"') >> '"'];

        frame_rule = qi::lit("frame={") >>
            (addr_rule(qi::_val) ^ qi::lit(',') ^ func_rule(qi::_val) ^
             qi::lit(',') ^ file_rule(qi::_val) ^ qi::lit(',') ^
             fullname_rule(qi::_val) ^ qi::lit(',') ^ line_rule(qi::_val) ^
             qi::lit(',') ^ kv_rule(qi::_val)) >>
            qi::lit('}');

        BOOST_SPIRIT_DEBUG_NODES(
                (frame_rule)(func_rule)(addr_rule)(fullname_rule)(line_rule))
    }

    qi::rule<Iterator, void(frame&), ascii::space_type> func_rule, addr_rule,
        file_rule, fullname_rule, line_rule, kv_rule;
    qi::rule<Iterator, frame(), ascii::space_type> frame_rule;
    qi::rule<Iterator, std::string()> addr, func, file, fullname, line;
    qi::rule<Iterator, std::string()> quoted_string;
    argsArray<Iterator> arrTest;
};


#include <iostream>
//#include "parser/frame.h"

int main()
{
    std::string str = R"(frame={addr="0x0000000000414008",)"
        R"(func="main",)"
        R"(args=[{name="argc",value="1"},)"
        R"({name="argv",value="0x7fffffffe1a8"}],)"
        R"(file="/home/stiopa/development/gdbFront/main.cc",)"
        R"(fullname="/home/stiopa/development/gdbFront/main.cc",)"
        R"(line="90"}")";
    str = "AAA" + str + "AAA";

    typedef std::string::const_iterator It;
    const frameParser<It> g;
    It iter(str.begin()), end(str.end());
    frame frame;
    bool r = phrase_parse(iter, end, qir::seek[g], boost::spirit::ascii::space, frame);

    assert(r == true);
    assert(frame.addr == "0x0000000000414008");
    assert(frame.func == "main");

    std::map<std::string, std::string> kv{{"argc", "1"},
        {"argv", "0x7fffffffe1a8"}};

    assert(frame.kv == kv);

    assert(frame.file == "/home/stiopa/development/gdbFront/main.cc");
    assert(frame.fullname == "/home/stiopa/development/gdbFront/main.cc");
    assert(frame.line == "90");
}

测试仍然通过.

这篇关于忽略所有字符直到给定的单词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆