最近的开发工作中有这样的需求:
在语法分析阶段建立好的语法树上作一些操作。
概括起来,大致有如下一些需求:
1. 将语法树对应的内容再打印出源码级表示,以协助调试,验证系统正确性。
2. 遍历语法树,对语法元素作语法正确性的检查。
3. 遍历语法树,转换生成后端所需的数据结构。
4. 。。。。。。
抽象来看,这些内容几乎都涉及到这样的要求: (1) 遍历 语法树 (2)对遍历到的每个元素执行相应的操作,
而这正好是Visitor模式的典型应用场景。
于是就抄起Design Patter复习了一下Visitor模式相关的内容。
在我的理解中,Visitor模式的核心思想是将对数据元素进行某种操作的代码集中到某个visitor类里头,从而避免将
诸多操作代码填塞到数据元素类中,保持了代码的清晰和干净,并利于扩展---基于Visitor模式,想对同一批数
据元素作不同的操作,只需要实现不同的Visitor类,在其中实现相应的操作动作即可,不需要对数据元素类作额外
的修改。
具体到 C++代码中,大致是这样的模样:
// Visitor的抽象基类
class abstractVisitor {
public:
virtual void visitIfStmt( ifStmt& stmt );
virtual void visitCaseStmt( caseStmt& stmt );
};
// 完成语法检查工作的Visitor
class grammarCheckVisitor : public abstractVisitor {
public:
virtual void visitIfStmt( ifStmt& stmt )
{
//执行具体的语法检查工作
}
virtual void visitCaseStmt( caseStmt& stmt)
{
.....
}
};
// 完成dump语法树工作的Visitor
class dumperVisitor : public abstractVisitor {
public:
virtual void visitIfStmt( ifStmt& stmt )
{
....
}
virtual void visitCaseStmt( caseStmt& stmt )
{
...
}
};
// 语法元素的抽象基类
class stmt {
public:
virtual void accept( abstractVisitor& v) = 0;
};
// If 语句对应的语法元素类
class ifStmt : public stmt {
public:
virtual void accept( abstractVisitor& v)
{
v.visitIfStmt( *this );
}
};
// Case语句对应的语法元素类
class caseStmt : public stmt {
public:
virtual void accept( abstractVisitor& v )
{
v.visitCaseStmt( *this );
}
}
调用端的代码大致如下:
int main()
{
。。。。。。
vector< stmt * > stmtVec;
。。。。。。
vector< stmt* >::iterator it = stmtVec.begin();
abstractVisitor * v = new dumpVisitor; // 创建Visitor ,执行不同的操作,创建不同的Visitor即可。
while ( it != stmtVec.end() ) {
(*it)->accept( v );
++it;
}
。。。。。。
}
概括起来,大致有如下一些需求:
1. 将语法树对应的内容再打印出源码级表示,以协助调试,验证系统正确性。
2. 遍历语法树,对语法元素作语法正确性的检查。
3. 遍历语法树,转换生成后端所需的数据结构。
4. 。。。。。。
抽象来看,这些内容几乎都涉及到这样的要求: (1) 遍历 语法树 (2)对遍历到的每个元素执行相应的操作,
而这正好是Visitor模式的典型应用场景。
于是就抄起Design Patter复习了一下Visitor模式相关的内容。
在我的理解中,Visitor模式的核心思想是将对数据元素进行某种操作的代码集中到某个visitor类里头,从而避免将
诸多操作代码填塞到数据元素类中,保持了代码的清晰和干净,并利于扩展---基于Visitor模式,想对同一批数
据元素作不同的操作,只需要实现不同的Visitor类,在其中实现相应的操作动作即可,不需要对数据元素类作额外
的修改。
具体到 C++代码中,大致是这样的模样:
// Visitor的抽象基类
class abstractVisitor {
public:
virtual void visitIfStmt( ifStmt& stmt );
virtual void visitCaseStmt( caseStmt& stmt );
};
// 完成语法检查工作的Visitor
class grammarCheckVisitor : public abstractVisitor {
public:
virtual void visitIfStmt( ifStmt& stmt )
{
//执行具体的语法检查工作
}
virtual void visitCaseStmt( caseStmt& stmt)
{
.....
}
};
// 完成dump语法树工作的Visitor
class dumperVisitor : public abstractVisitor {
public:
virtual void visitIfStmt( ifStmt& stmt )
{
....
}
virtual void visitCaseStmt( caseStmt& stmt )
{
...
}
};
// 语法元素的抽象基类
class stmt {
public:
virtual void accept( abstractVisitor& v) = 0;
};
// If 语句对应的语法元素类
class ifStmt : public stmt {
public:
virtual void accept( abstractVisitor& v)
{
v.visitIfStmt( *this );
}
};
// Case语句对应的语法元素类
class caseStmt : public stmt {
public:
virtual void accept( abstractVisitor& v )
{
v.visitCaseStmt( *this );
}
}
调用端的代码大致如下:
int main()
{
。。。。。。
vector< stmt * > stmtVec;
。。。。。。
vector< stmt* >::iterator it = stmtVec.begin();
abstractVisitor * v = new dumpVisitor; // 创建Visitor ,执行不同的操作,创建不同的Visitor即可。
while ( it != stmtVec.end() ) {
(*it)->accept( v );
++it;
}
。。。。。。
}