处理堆栈上的对象破坏

时间:2012-11-21 23:08:33

标签: c++ stack allocation bnf destruction

我目前正在编写关于该主题的个人教育的编译器前端,并且我遇到了一个问题,即我通过运算符重载在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);
}

ChainRule,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子类的构造函数中使用pass by值,因为这不允许我定义递归语法。

所以我没有选择按值传递对象,也没有通过指针传递对象的选项。任何人都可以指出一个解决方案,不会强迫我像这样定义我的语法吗?

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,但我的目标是编写自己的解析器。

2 个答案:

答案 0 :(得分:1)

您可以在堆上分配返回对象(通过工厂)并将它们作为引用返回。工厂可以跟踪它们,这样你就不会泄漏。就语法而言,它将与按值返回时相同。

答案 1 :(得分:1)

您可以通过使用包装器对象替换Rule*(具有不能为其重载运算符的问题)来解决此问题。即ChainRule将包含RuleRef next而不是Rule * next等,并且将为RuleRef定义所有运算符。 RuleRef只会包含Rule*,并且可以从Rule*构建。为了使内存处理更容易,您可以从智能指针类继承。