解析器的上下文无关语法的表示有多好?

时间:2009-10-08 15:08:23

标签: c++ parsing

我已经共享了包含解析器的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

3 个答案:

答案 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行,我认为将多个类放在同一个标​​题中是正确的。