c++ - 用替代运算符提振 spirit '|' 失败!当有两个可能的规则时

标签 c++ boost boost-spirit-qi

我正在研究一个 HTTP 解析器。当我尝试使用替代运算符进行解析时,它发现了一个问题。我可以使用 hold[] 修复它们与属性中的值无关。当开头有两个相似的规则时,就会出现问题 规则。这里有一些简单的规则来证明我的问题;

qi::rule<string_iterator> some_rule(
        (char_('/') >> *char_("0-9")) /*first rule accept  /123..*/
      | (char_('/') >> *char_("a-z")) /*second rule accept /abc..*/
    );

然后我使用 qi::parse 解析这个规则,如果输入字符串喜欢,它将失败; “/abcd”

但是,当我在第一条规则之前切换第二条规则时。解析器将返回 true 我认为问题是因为当解析器使用第一条规则使用输入时 然后它发现第一个规则是失败的。它不会返回到第二条规则,即 第一条规则的替代方案。

我尝试将 hold[] 放在第一条规则中,但它仅有助于生成属性。它 没有解决这个问题。我不知道如何解决这个问题,因为 HTTP 有很多 他们有规则开头的规则与其他规则相同。


===========关于我的代码的更多信息============================
这是我解析字符串的函数

typedef std::string::const_iterator string_iterator;
typedef qi::rule<string_iterator, std::string()> rules_t;
void parse_to_string(const std::string& s, rules_t& r, std::string& result)
{
    using namespace rule;
    using qi::parse;

    std::string::const_iterator iter = s.begin();
    std::string::const_iterator end = s.end();

    bool err = parse(iter, end, r, result);

    if ( err && (iter==end) )
    {
           std::cout << "[correct]" << result << std::endl;
    }
    else
    {
          std::cout << "[incorrect]" << s << std::endl;
          std::cout << "[dead with]" << result << std::endl;
    }
}

主要是我有这段代码;

std::string result;
result = "";
str = "/htmlquery?";
qi::rule<string_iterator, std::string()> rule_wo_question( char_('/') >> *char_("a-z"));
qi::rule<string_iterator, std::string()> rule_w_question( char_('/') >> *char_("a-z") >> char_('?'));
qi::rule<string_iterator, std::string()> whatever_rule( rule_wo_question
                                                        | rule_w_question
                                                       );
parse_to_string(str, whatever_rule, result);

我得到了这个结果;

[不正确]/htmlquery? [dead with]/htmlquery <= 你可以看到它不能消耗'?'

但是当我这样切换规则时; (我把“rule_w_question”放在“rule_wo_question”之前)

std::string result;
    result = "";
    str = "/htmlquery?";
    qi::rule<string_iterator, std::string()> rule_wo_question( char_('/') >> *char_("a-z"));
    qi::rule<string_iterator, std::string()> rule_w_question( char_('/') >> *char_("a-z") >> char_('?'));
    qi::rule<string_iterator, std::string()> whatever_rule( rule_w_question
                                                            | rule_wo_question
                                                           );
    parse_to_string(str, whatever_rule, result);

输出将是; [正确]/htmlquery?

第一个版本(错误的)似乎解析使用了'/htmlquery'(“rule_wo_question”)然后它发现它不能使用'?'这使得这条规则失败了。 那么这个规则就不能转到另一个规则(“rule_w_question”)。最后程序返回“[incorrect]”

第二个版本我在“rule_wo_question”之前切换了“rule_w_question”。这就是解析器返回“[correct]”结果的原因。


============================================= =============== 我的整个代码与 boost 1.47 链接 pthread 和 boost_filesystem 这是我的主要 .c

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/network/protocol.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/bind.hpp>
#include <boost/spirit/include/qi_uint.hpp>

using namespace boost::spirit::qi;
namespace qi = boost::spirit::qi;

typedef std::string::const_iterator string_iterator;
typedef qi::rule<string_iterator, std::string()> rules_t;
void parse_to_string(const std::string& s, rules_t& r, std::string& result)
{
    using qi::parse;

    std::string::const_iterator iter = s.begin();
    std::string::const_iterator end = s.end();

    bool err = parse(iter, end, r, result);

    if ( err && (iter==end) )
    {
           std::cout << "[correct]" << result << std::endl;
    }
    else
    {
          std::cout << "[incorrect]" << s << std::endl;
          std::cout << "[dead with]" << result << std::endl;
    }
}





int main()
{
    std::string str, result;
    result = "";
    str = "/htmlquery?";
    qi::rule<string_iterator, std::string()> rule_wo_question( char_('/') >> *char_("a-z"));
    qi::rule<string_iterator, std::string()> rule_w_question( char_('/') >> *char_("a-z") >> char_('?'));
    qi::rule<string_iterator, std::string()> whatever_rule( rule_wo_question
                                                           | rule_w_question
                                                           );
    parse_to_string(str, whatever_rule, result);
    return 0;
}

结果是

[incorrect]/htmlquery?

[dead with]/htmlquery

最佳答案

Spirit 按照指定的顺序尝试给定的替代方案,并在与第一个匹配后停止解析。不执行详尽匹配。如果一个替代匹配它停止寻找。 IOW,备选方案的顺序很重要。您应该始终首先列出“最长”的备选方案。

关于c++ - 用替代运算符提振 spirit '|' 失败!当有两个可能的规则时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7459323/

相关文章:

java - JNI lib崩溃,更改了.c文件(未包含在Makefile中)

boost - 基于分布的弱学习器 : Decision stump

c++ - 串行端口奇偶校验在 boost asio 中失败

c++ - 无法编译 boost spirit word_count_lexer 示例

c++ - 在 WINPCAP 中如何知道哪些安装的设备有互联网连接?

c++ - 为什么 C++20 std::condition_variable 不支持 std::stop_token?

c++ - 将 boost 图拆分为连接的组件

c++ - 提升精神QI : Auto-rule deduction on a tuple with a sequence inside an alternative function

c++ - 如何使用 parse/phrase_parse 函数

c++ - 在 Carbon App 中将焦点设置到 Cocoa 窗口