我进行了很多搜索,但似乎找不到关于如何使用%union的清晰示例。我想例如将以下标记保存在名为classID的结构中:
[a-zA-Z][a-zA-Z0-9]* { yylval=new IDClass(yytext); return ID; }
这是我在.hpp
文件夹中包含的结构:
class Node {
public:
Node(){}
};
class IDClass : public Node {
public:
string name;
IDClass(string name):
Node(),name(name)
{}
};
&然后在我的.ypp
文件中,我想将其用于某些检查:
Define: Type ID { if(doesIDexists(***$2->name***)){errorDef(yylineno, ID_ptr->name);exit(1);}}
但是很明显,$ 2->名称不会返回它。 %union在结构中的正确用法是什么?如何正确获取名称的值?
谢谢你。
没有“在结构中正确使用%union
”,因为%union
用于声明union
。 (当然,您可以声明只有一个成员的union
,但这几乎没有意义。)
声明不是union
的语义类型的正确方法是:
%define api.value.type { Node* }
但是那不会让您想要,因为您想要的既不是union
也不是固定类型,而是隐式动态类型转换或类似内容。那不在野牛的选项菜单上。 (很容易理解为什么不这样做。动态类型转换不是左值,因此Bison必须知道何时应用它,何时不应用它。)
所以您可以使用上面的%define api.value.type
,然后写出语法操作:
Define: Type ID { if (doesIDexist(dynamic_cast<IDClass>($2)->name)) {
errorDef(@2.first_line,
dynamic_cast<IDClass>($2)->name);
exit(1);
}
}
如果生成的是C ++解析器而不是C ++解析器,而C解析器恰好在C ++中工作,那么您还有其他选择,对于您的应用程序而言,这可能是更好的解决方案,也可能不是。 C解析器的选项在Bison手册的Language Semantics章中进行了说明,C ++选项的名称为their own chapter,尽管如果您要使用C ++接口,则需要阅读整个C ++部分。
注意:我将yylineno
更改为@2.first_line
,因为yylineno
通常不准确; yylineno
通常是与超前标记关联的行号,通常与错误不在同一行。但是你不能仅仅做出改变。您还必须确保词法分析器正确填写yylloc
。请参阅《 Bison手册》中的Tracking Locations章节。