Boost Spirit语法自定义属性

Boost Spirit grammar custom attribute

正在尝试学习 Boost::Spirit 并想处理一个 C 风格标识符的简单示例。下面的语法没有编译声明 'incompatible_start_rule'。此语法的目标是 return 字符串而不是字符串向量,正如默认属性传播规则那样。

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;
};

我需要做什么才能实现这一目标?

另请注意,我很清楚对于这个特定问题可能有许多更方便的选择,但我在学术上对如何操作自定义语法的属性类型很感兴趣,所以请离开那些在评论而不是答案中。

首先,您需要使用 function-signature-style 模板参数来指定规则的输出属性类型(以及继承的属性类型,如果有的话)。尝试 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;
};

最后,确保将兼容的船长对象传递给 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"