2014-08-31 78 views
1

我在解析项目时遇到了麻烦。至少我找到了问题出现的最小代码示例。所以现在试图解析字符串boost :: spirit :: qi matches [] trouble

“bool func1; const bool func2;”

这里最小的示例代码:

namespace qi = boost::spirit::qi; 
using qi::lexeme; 
using qi::string; 
typedef boost::spirit::ascii::space_type TSkipper; 

struct MyField 
{ 
    bool isConst; 
    std::string mtype; 
    std::string name; 
}; 

BOOST_FUSION_ADAPT_STRUCT 
    (
    MyField, 
    (bool, isConst) 
    (std::string, mtype) 
    (std::string, name) 
    ) 

void SpiritTestSimple() 
{ 
    qi::rule<std::string::const_iterator, std::string(), TSkipper> valid_symbols; 
    qi::rule<std::string::const_iterator, MyField(), TSkipper> field; 

    valid_symbols %= lexeme[*qi::char_("a-zA-Z")]; 

    field %= qi::matches[string("const")] >> valid_symbols >> valid_symbols; 

    std::string data = "aaa aaaa; const bbb bbbb;"; 

    //----------------------------------------------------------------- 
    std::string::const_iterator first = data.begin(), last = data.end(); 
    std::list<MyField> parsed_vals; 
    bool is_parsed; 
    try 
    { 
     is_parsed = qi::phrase_parse( first, last, 
             +(field > ';'), 
             boost::spirit::ascii::space, parsed_vals); 
    } 
    catch(const qi::expectation_failure<std::string::const_iterator>& e) 
    { 
     std::string frag(e.first, e.last); 
     std::cout << e.what() << "'" << frag << "'" << std::endl; 
    } 

    BOOST_ASSERT(is_parsed && "the example not parsed"); 
} 

我,因为在我的项目这一块可以没有写

+(field > ';') 

。每个函数声明都必须以';'结尾。当上面的代码示例运行我看到引发的异常并在控制台中出现的记录:

boost::spirit::qi::expectation_failure'' 

按照我的理解正确的 - 最后的分号后的解析器尝试解析下一个域规则,在解析“匹配”(因为它在任何情况下都会返回值),但valid_symbols的下一个分析失败,因为在最后一个分号后没有数据。所以解析失败。

如何避免在我的情况下解析失败?

回答

2

最大的问题是

valid_symbols = qi::lexeme[*qi::char_("a-zA-Z")]; 

这里的问题是,它可以匹配空字符串。所以“字段”的整个生产可以是一个空字符串。如果您将其更改为(使用qi::alpha作为简写):

valid_symbols = qi::lexeme[+qi::alpha]; 

你会发现它正确地解析输入。

其它注意事项:

  • 当你说

    “我,因为在我的项目中写道+(field > ';')此块可以是不存在的”似乎矛盾的我。如果你想使整个街区可选,你会写

    *(field > ';') 
    

    ,或者如果你想重复;;我期望

    *(-field > ';') 
    

    (或者+(-field > ';'))。

  • 你将要学习使用BOOST_SPIRIT_DEBUG要找准你自己

您的问题,请参阅如何使用精神内置调试功能演示完整的工作示例:Live On Coliru

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

namespace qi = boost::spirit::qi; 
typedef boost::spirit::ascii::space_type TSkipper; 

struct MyField 
{ 
    bool isConst; 
    std::string mtype; 
    std::string name; 
}; 

BOOST_FUSION_ADAPT_STRUCT 
    (
    MyField, 
    (bool, isConst) 
    (std::string, mtype) 
    (std::string, name) 
    ) 

template <typename It, typename TSkipper = boost::spirit::ascii::space_type> 
struct MyGrammar : qi::grammar<It, std::list<MyField>(), TSkipper> 
{ 
    MyGrammar() : MyGrammar::base_type(start) { 
     valid_symbols = qi::lexeme[+qi::alpha]; 
     field   = qi::matches[qi::string("const")] >> valid_symbols >> valid_symbols; 
     start   = +(field > ";"); 

     BOOST_SPIRIT_DEBUG_NODES((valid_symbols)(field)(start)) 
    } 
    private: 
    qi::rule<std::string::const_iterator, std::string(),  TSkipper> valid_symbols; 
    qi::rule<std::string::const_iterator, MyField(),   TSkipper> field; 
    qi::rule<std::string::const_iterator, std::list<MyField>(), TSkipper> start; 
}; 

int main() 
{ 
    std::string const data = "aaa aaaa; const bbb bbbb;"; 

    //----------------------------------------------------------------- 
    std::string::const_iterator first = data.begin(), last = data.end(); 
    std::list<MyField> parsed_vals; 

    bool is_parsed = false; 

    try 
    { 
     MyGrammar<std::string::const_iterator> grammar; 

     is_parsed = qi::phrase_parse( first, last, 
             grammar, 
             boost::spirit::ascii::space, 
             parsed_vals); 
    } 
    catch(const qi::expectation_failure<std::string::const_iterator>& e) 
    { 
     std::string frag(e.first, e.last); 
     std::cout << "Expectation failure: " << e.what() << " at '" << frag << "'" << std::endl; 
    } 

    BOOST_ASSERT(is_parsed && "the example not parsed"); 
} 

哪打印:

<start> 
<try>aaa aaaa; const bbb </try> 
<field> 
    <try>aaa aaaa; const bbb </try> 
    <valid_symbols> 
    <try>aaa aaaa; const bbb </try> 
    <success> aaaa; const bbb bbb</success> 
    <attributes>[[a, a, a]]</attributes> 
    </valid_symbols> 
    <valid_symbols> 
    <try> aaaa; const bbb bbb</try> 
    <success>; const bbb bbbb;</success> 
    <attributes>[[a, a, a, a]]</attributes> 
    </valid_symbols> 
    <success>; const bbb bbbb;</success> 
    <attributes>[[0, [a, a, a], [a, a, a, a]]]</attributes> 
</field> 
<field> 
    <try> const bbb bbbb;</try> 
    <valid_symbols> 
    <try> bbb bbbb;</try> 
    <success> bbbb;</success> 
    <attributes>[[b, b, b]]</attributes> 
    </valid_symbols> 
    <valid_symbols> 
    <try> bbbb;</try> 
    <success>;</success> 
    <attributes>[[b, b, b, b]]</attributes> 
    </valid_symbols> 
    <success>;</success> 
    <attributes>[[1, [b, b, b], [b, b, b, b]]]</attributes> 
</field> 
<field> 
    <try></try> 
    <valid_symbols> 
    <try></try> 
    <fail/> 
    </valid_symbols> 
    <fail/> 
</field> 
<success></success> 
<attributes>[[[0, [a, a, a], [a, a, a, a]], [1, [b, b, b], [b, b, b, b]]]]</attributes> 
</start> 
+0

PS。你可以直接在那里编写'qi :: matches [“const”]'' – sehe 2014-08-31 21:52:03

相关问题