我已经共享了包含解析器的Context Free语法的类定义的头文件。你能评论一下设计吗? 这段代码是我的实验室作业。 也许我们可以从这段代码中获得一些好的编程技巧。类层次结构是好还是太复杂。
#ifndef CFG_H
#define CFG_H
#include <iostream>
#include <set>
#include <list>
using namespace std;
class Terminal;
class CfgSymbol
{
protected:
char ch;
set<Terminal*> first;
set<Terminal*> follow;
public:
CfgSymbol()
{
ch = '\0';
}
CfgSymbol(char c) : ch(c)
{
}
virtual void computeFirst() = 0;
};
class Terminal: public CfgSymbol
{
private:
public:
Terminal(): CfgSymbol()
{
}
Terminal(char c) : CfgSymbol(c)
{
computeFirst();
}
virtual void computeFirst()
{
first->insert(this);
}
};
class NonTerminal: public CfgSymbol
{
private:
public:
virtual void computeFirst();
virtual void computeFollow();
};
class SymbolString
{
public:
CfgProduction* prd;
list<CfgSymbol*> symstr;
void computeFirst();
void computeFollow();
};
class CfgProduction
{
private:
NonTerminal lhs;
SymbolString rhs;
public:
int add_terminal(char t);
int add_nonterminal(char n);
int set_lhs(char c);
};
class Cfg
{
public:
vector<CfgProduction*> prdList;
void addProduction(const CfgProduction& cfg);
void computeFirst();
void computeFollow();
void computeFirstFollow();
};
#endif
答案 0 :(得分:2)
没有评论,整个事情都毫无意义。
应该对如何使用对象实例及其使用的上下文进行一些冗长的描述。
另一方面,我通常从类定义之前的BNF语法定义开始(在注释中为leas)。然后围绕语法设计类。
答案 1 :(得分:2)
Spirit's documentation应该为grammar实施提供一个很好的介绍(使用模板)。不知道你的水平,也许这太简单了,但它非常有趣:
语法变得复杂,它 将零件分组是个好主意 逻辑模块。例如,何时 写一种语言,这可能是明智的 将表达式和语句放入 单独的语法胶囊。语法 利用封装 C ++类的属性。该 类的声明性使它成为现实 完美契合的定义 语法。既然语法什么都没有 我们可以做多个宣言 方便地在标题中发布它 文件。这个想法是一旦写完 并经过充分测试,语法可以 在许多情况下重复使用。我们现在有 语法库的概念。
答案 2 :(得分:1)
除模板外,您不应在标头中编写实现。标题必须只包含您的类和函数以及您的成员的签名。
惯例是每个文件只放一个类。编译更好:Multiple classes in a header file vs. a single header file per class。 但是,如果类的长度小于10行,我认为将多个类放在同一个标题中是正确的。