c++ - Boost Spirit Grammar 检测登录失败

标签 c++ parsing boost boost-spirit boost-spirit-qi

我编写了以下简单语法来检测服务器返回的字符串是否为登录失败。我在 phrase_parse 函数中内联使用它,但由于代码被定期调用,我想创建语法的静态实例。我用的是这个:

bool loginFailed() 
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    // current data is an re2 stringpiece. so .data returns char*
    const char* front = currentData.data();
    const char* back = currentData.end();

    return qi::phrase_parse(front, back, -qi::int_ >> (ascii::no_case[qi::lit("no")] | ascii::no_case[qi::lit("bad")]), qi::space);
}

哪个有效。但是,当我将其翻译成以下内容时,语法似乎总是失败。我想做的是在我的 cpp 文件中:

namespace {
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    struct FailedGrammar : qi::grammar<const char*>
    {
        FailedGrammar() : 
            FailedGrammar::base_type(m_start),
            m_start()
        {
            m_start = -qi::int_ >> (ascii::no_case[qi::lit("no")] | ascii::no_case[qi::lit("bad")]);
        }
        qi::rule<const char*> m_start;
    };

    const FailedGrammar s_failedInstance;
}

然后像这样调用:

bool loginFailed() 
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    // current data is an re2 stringpiece. so .data returns char*
    const char* front = currentData.data();
    const char* back = currentData.end();

    return qi::phrase_parse(front, back, s_failedInstance, qi::space);
}

我要识别的字符串是这样的:

0002 NO FAILED LOGIN

其中数字是可选的。我知道使用 re2 执行此操作的其他方法,但是,我正在寻找一种 spirit 实现。

有没有人有任何指示或失败的潜在原因?

编辑: 我在调试器中发现了很多语法问题。首先,我意识到要解析像 0002 这样的数字我应该写成 *(qi::int_)。此外,我摆脱了 ascii::space 以支持 ascii::blank

最佳答案

您的第一个版本使用 skipper 。

你的第二个没有¹。您可以修复它:

struct FailedGrammar : qi::grammar<const char*, qi::space_type>
{
    FailedGrammar() : FailedGrammar::base_type(m_start), m_start()
    {
        m_start = -qi::int_ >> (ascii::no_case[qi::lit("no")] | ascii::no_case[qi::lit("bad")]);
    }
    qi::rule<const char*, qi::space_type> m_start;
};

注意:使用 qi::space/qi::lit 和 ascii::no_case 是不一致的。您可以大大简化。

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/utility/string_ref.hpp>

namespace login_detection {
    using namespace boost::spirit::qi;
    static const rule<const char*> s_failed = skip(space) [ no_case [ -int_ >> lit("no") | "bad" ] ];
}

bool loginFailed2(boost::string_ref response) {
    return parse(response.begin(), response.end(), login_detection::s_failed);
}

int main() {
    return loginFailed2("0002 NO FAILED LOGIN")? 1 : 2;
}

事实上,很少或根本没有理由在命名空间范围内制定规则:

bool loginFailed2(boost::string_ref response) {
    using namespace boost::spirit::qi;
    static const rule<const char*> s_failed = skip(space) [ no_case [ -int_ >> lit("no") | "bad" ] ];
    return parse(response.begin(), response.end(), s_failed);
}

不过,我建议比较生成的程序集,因为我认为我将与

相同
bool loginFailed2(boost::string_ref response) {
    using namespace boost::spirit::qi;
    return phrase_parse(response.begin(), response.end(), no_case [ -int_ >> lit("no") | "bad" ], space);
}

¹ Boost spirit skipper issues

关于c++ - Boost Spirit Grammar 检测登录失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40554513/

相关文章:

c++ - 在 int 或 long long int 的指数运算期间捕获溢出

parsing - Rascal:解析具有多个 "_"s 的字符串

java - 如何在一种方法中获取从 java 中的 CSV 文件读取的值并在另一种方法中使用它们?

java - 在未排序的 xml 文件中查找特定值

c++ - 我无法编译 boost - 找不到 *.o 文件

c++ - 为什么调用已删除的对象成员后没有错误?

c++ - 类(class)成员重新排序

c++ - BOOST_MESSAGE 未定义

c++ - 我对C++ boost::asio和std::async有疑问

c++ - 在 C++ 中列出 WMI 类的所有属性