Boost Spirit符号表中的错误处理

Error handling in Boost Spirit symbol table

本文关键字:错误 处理 Spirit 符号 Boost      更新时间:2023-10-16

假设我有一个这样的符号表:

struct jass_types : qi::symbols<char, jass_type> {

现在我想用它的父类型填充自定义的类型:

identifier %= 
    char_("a-zA-Z") >> -(*char_("a-zA-Z_0-9") >> char_("a-zA-Z0-9"))
    ;
type %=
    lit("type") >> identifier >>
    lit("extends") >> identifier[type_symbols.find(_1)]

结构如下:

BOOST_FUSION_ADAPT_STRUCT(
wc3lib::jass::jass_type,
(std::string, identifier)
(wc3lib::jass::jass_type*, parent)
)

我如何写我的代码,它存储0到属性"父",如果"扩展"之后的标识符在符号表中找不到,我如何正确地对缺失的符号作出反应?

我的想法是这样的:

boost::variant<wc3lib::jass::jass_type*,std::string> parent

并根据类型是否在符号表中找到的事实填充指针或标识符,但我必须在之后检测父类的类型信息。另一种选择是如上所述为parent存储0,并创建一个带有标识符信息的错误对象等。如果没有找到符号,Boost可能已经做了同样的事情??

编辑:

首先犯了使用_2而不是_1的错误,但它仍然不能工作,因为它显然需要一个char*值而不是std::string,所以我添加了一个自定义函数:

inline jass_type* get_type_symbol(jass_types &types, const std::string &value) {
    return types.find(value.c_str());
}

和一个语义动作:

type =
    lit("type") >> identifier >>
    lit("extends") >> identifier[phoenix::bind(&get_type_symbol, ref(type_symbols), _1)]
    ;

,但它似乎仍然是过于复杂的这种方式,我无法解决正确的错误检测/存储标识符的问题,如果符号没有找到!

你可以这样做:

// simplified identifier rule exposes a `std::strirng`:
qi::rule<It, std::string()> identifier = char_("a-zA-Z") >> *char_("a-zA-Z_0-9");
struct jass_types : qi::symbols<char, jass_type*> {
        // ...
};
typedef boost::variant<jass_type*, std::string> jass_typeref;
jass_types type_symbols;

注意,我让symbols<>解析器只直接返回指向jass_type的指针。现在,规则可以像这样简单:

qi::rule<It, jass_typeref()> typeref_ = type_symbols | identifier;

例如:as

type %= "type" >> identifier >> "extends" >> typeref_;

要提供默认值,您可以执行

type %= "type" >> identifier >> 
        ("extends" >> typeref_ | qi::attr(std::string("::object")));

(假设所有类型最终扩展::object)