저는 방문자 패턴을 사용하여 C++에서 간단한 추상 구문 트리 (AST)를 구현하려고합니다. 일반적으로 방문자 패턴은 반환 값을 처리하지 않습니다. 하지만 내 AST에는 자식 노드의 반환 형식과 값을 염두에 둔 표현식 노드가 있습니다. 예를 들어, 내가 노드의이 같은 구조를 가지고 : CompareNode 및 SumNode 모두 이항 연산자이다이 경우반환 값이있는 방문자 패턴을 사용하여 AST를 구현하는 가장 좋은 방법은 무엇입니까?
class AstNode
{
public:
virtual void accept(AstNodeVisitor&) = 0;
void addChild(AstNode* child);
AstNode* left() { return m_left; }
AstNode* right() { return m_right; }
...
private:
AstNode* m_left;
AstNode* m_right;
};
class CompareNode : public AstNode
{
public:
virtual void accept(AstNodeVisitor& v)
{
v->visitCompareNode(this);
}
bool eval(bool lhs, bool rhs) const
{
return lhs && rhs;
}
};
class SumNode : public AstNode
{
public:
virtual void accept(AstNodeVisitor& v)
{
v->visitSumNode(this);
}
int eval(int lhs, int rhs) const
{
return lhs + rhs;
}
};
class AstNodeVisitor
{
public:
...
bool visitCompareNode(CompareNode& node)
{
// won't work, because accept return void!
bool lhs = node.left()->accept(*this);
bool rhs = node.right()->accept(*this);
return node.eval(lhs, rhs);
}
int visitSumNode(Node& node)
{
// won't work, because accept return void!
int lhs = node.left()->accept(*this);
int rhs = node.right()->accept(*this);
return node.eval(lhs, rhs);
}
};
을하지만 그들은 자녀의 방문의 반환 형식에 의존하고 있습니다.
지금까지 내가 단지 2 옵션이 있습니다, 그것을 작동하게 볼 수 있습니다 :
여전히 빈 반환 할 수 있습니다 동의, 컨텍스트 각각에 전달되는 객체에 동의하고 방문의 반환 값을 저장해 함수를 호출하고 방문 함수에서 사용합니다. 여기서 내가 사용할 형식을 알고 있습니다. 이것은 작동하지만 해킹처럼 느껴질 것입니다.
AstNode를 템플릿으로 만들고 함수를 가상으로 만들지는 않지만 반환 형식은 템플릿 매개 변수 T에 달려 있습니다. 이렇게하면 더 이상 일반적인 AstNode * 클래스가없고 AstNode *를 저장할 수 없습니다. 아이들 목록. 예를 들어
:
template <typename T`>
class AstNode
{
public:
T accept(AstNodeVisitor&);
...
};
그래서이 일을 더 우아한 방법이? 이것은 AST 보행을 구현하는 사람들에게는 상당히 일반적인 문제 여야하므로 가장 좋은 방법이 무엇인지 알고 싶습니다.
감사합니다.
반환 값의 형식은 무엇입니까? '문자열'? 'int'? '더블 '? –
@RSahu : OP는 반환 값이 공용체 또는 클래스라고 가정해야합니다. 그러면 그는 자신이 좋아하는 것을 반환 할 수 있습니다. –
@RSahu : 반환 값은 형식 및 사용자 정의 형식의 빌드 선택 일 수 있지만 컴파일 타임에 알려져 있습니다. 구체적으로 말하면 반환 값은 bool, void 또는 int, double 등 가능한 모든 숫자 유형을 나타내는 boost :: variant 유형이 될 수 있습니다. – swang