2017-02-20 71 views
0

试图学习Boost :: Spirit并想要解决c样式标识符的一个简单示例。下面的语法不会声称'incompatible_start_rule'。目标是让这个语法返回一个字符串,而不是一个字符串向量,因为默认属性传播规则会。Boost Spirit语法自定义属性

template <typename IT> 
struct cppIdentifier : qi::grammar<IT, std::string, space_type()> 
{ 

    cppIdentifier() : cppIdentifier::base_type(start) 
    { 
     start = char_("a-zA-Z_")[boost::phoenix::push_back(_val, _1)] 
       >> *(char_("a-zA-Z0-9_")[boost::phoenix::push_back(_val, _1)]); 
    } 

    qi::rule<IT, std::string, space_type> start; 
}; 

要做到这一点我需要做些什么?

另外请注意,我很清楚这个特定问题可能有很多替代方案,但是我对学习如何操作自定义语法的属性类型感兴趣,所以请保留这些在评论中而不是答案中。

由于提前,

回答

2

首先,你需要使用函数签名式的模板参数指定规则的输出属性类型(和继承的属性类型,如果有的话)。而不是qi::grammar<IT, std::string, space_type()>,请尝试qi::grammar<IT, std::string(), space_type>

其次,你并不真的需要在这里语​​义动作 - 但如果你打算使用语法分析器,你需要lexeme[]指令:

template <typename IT> 
struct cppIdentifier : qi::grammar<IT, std::string(), qi::space_type> 
{ 
    cppIdentifier() : cppIdentifier::base_type(start) 
    { 
     start = qi::lexeme[char_("a-zA-Z_") >> *(char_("a-zA-Z0-9_"))]; 
    } 

    qi::rule<IT, std::string(), qi::space_type> start; 
}; 

最后,确保你传递一个兼容skipper对象到phrase_parse:

std::string s = "HELLO 123"; 

cppIdentifier < std::string::const_iterator> id; 

std::string ident; 

qi::phrase_parse(s.cbegin(), s.cend(), id, qi::space_type(), ident); 

// without lexeme[], ident becomes "HELLO123", not "HELLO" 
+1

欢迎,[标签:boost-spirit]的[SO]标签中的新贡献者。非常感谢您的帮助! – sehe

+1

非常感谢!我从网站学到了很多东西,包括你的答案,所以如果我能以小的方式提供帮助,我会尝试。我也发现我从写自己的答案中学到很多东西。 –

+0

是的!这很有用,谢谢。显然,我需要深入研究规则和语法模板参数。 –