Boost Spirit语法自定义属性

时间:2017-02-20 04:52:20

标签: boost boost-spirit-qi

尝试学习Boost :: Spirit并希望解决c风格标识符的简单示例。下面的语法没有编译声明“incompatible_start_rule”#。目标是这个语法返回一个字符串而不是一个字符串向量,就像默认的属性传播规则一样。

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

我需要做些什么来实现这个目标?

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

1 个答案:

答案 0 :(得分:2)

首先,您需要使用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;
};

最后,确保将兼容的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"