我目前正在为该主题编写个人教育的编译器前端,并且遇到了有关我通过运算符重载处理C++中的BNF定义的方式的问题。在堆栈上处理对象破坏
目前我的设置如下:
Rule.h:
class Rule
{
public:
ChainRule operator>>(Rule& right);
OrRule operator|(Rule& right);
KleeneRule operator*();
OptionalRule Rule::operator+();
virtual bool parse(TokenList::iterator& begin, TokenList::iterator end) = 0;
};
Rule.cpp:
ChainRule Rule::operator>>(Rule& right) {
return ChainRule(this, &right);
}
OrRule Rule::operator|(Rule& right) {
return OrRule(this, &right);
}
KleeneRule Rule::operator*() {
return KleeneRule(this);
}
OptionalRule Rule::operator+() {
return OptionalRule(this);
}
链式法则,OrRule,KleeneRule,OptionalRule和EmptyRule是平凡定义如下所以:
class ChainRule : public Rule
{
private:
Rule* next;
Rule* _this;
public:
ChainRule();
ChainRule(Rule* _this, Rule* right);
bool parse(TokenList::iterator& begin, TokenList::iterator end) override;
};
Rule的每个子类显然都定义了parse()的合理实现。使用这些类我可以定义我的语法如下:
OrRule assignment_exp = logical_or_exp
| unary_exp >> StringRule("=") >> assignment_exp
;
现在问题是这样的:每个重载操作符通过值返回一个新对象。这意味着每当我使用操作符>>或操作符|时从Rule类中,一旦我从调用操作符>>或操作符|返回,这些指针就会被垃圾回收因为堆栈已经被清理并且对象不见了。
既不能在我的Rule子类的构造函数中使用按值传递,因为这不允许我定义递归语法。
所以我没有选择通过值传递对象,也没有通过指针传递对象的选项。任何人都可以指出我的解决方案,不会强迫我像这样定义我的语法吗?
StringRule s = StringRule("=");
OrRule assignment_exp;
ChainRule temp1 = s >> assignment_exp;
ChainRule temp2 = unary_exp >> temp1;
assignment_exp = logical_or_exp | temp2;
P.S.我意识到各种解析器生成器和Boost.Spirit,但我的目标是编写我自己的解析器。