3

我正在研究一个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);

我得到了这个结果;

[不正确]/html查询?[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);

输出将是;[正确]/html查询?

第一个版本(错误的)似乎解析消耗'/htmlquery'(“rule_wo_question”)然后它发现它不能消耗'?这使这条规则失效。那么这个规则就不能转到替代规则 ("rule_w_question") 。最后程序返回“[不正确]”

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


==================================================== ============ 我的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
4

4 回答 4

3

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

于 2011-09-18T20:30:41.567 回答
1

你有什么理由不这样做吗?

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

编辑:实际上这将匹配/后跟空(“0-9”0次)并且不会费心寻找“az”,更改*+.

于 2011-09-18T07:52:51.920 回答
0
qi::rule<string_iterator> some_rule(
    (char_('/') >> *char_("0-9")) >> qi::eol /*first rule accept  /123..*/
  | (char_('/') >> *char_("a-z")) >> qi::eol /*second rule accept /abc..*/
);

而不是eol你可以使用','或其他一些终止符。问题是char_('/') >> *char_("0-9"))匹配 '/' 后跟 0 个或多个数字。所以“/abcd”匹配“/”然后停止解析。K-ballo 的解决方案是我处理这种情况的方式,但这个解决方案是作为替代方案提供的,以防(由于某种原因)他的方案不可接受。

于 2011-09-20T14:50:12.857 回答
0

这是因为你的第一条规则有一个匹配,而Spirit是贪婪的。

(char_('/') >> *char_("0-9"))

将“/abcd”输入此规则将导致以下逻辑:

  • "/abcd" -> '/' 是下一个字符吗?是的。子规则匹配。-> "abcd" 仍然存在。
  • "abcd" -> 有 0 个或多个数字吗?是的。有0位数。子规则匹配。-> "abcd" 仍然存在。
  • 替代 ('|') 语句的第一个子句匹配;跳过剩余的替代条款。-> "abcd" 仍然存在。
  • 剩余“abcd”的规则匹配。这可能不会解析并导致您的失败。

您可以考虑将表示“0 或更多”的“*”更改为表示“1 或更多”的“+”。

于 2013-07-22T07:27:41.553 回答