使用C ++,AST的Bison / Flex教程,并重新包含词法分析器和解析器

时间:2012-05-24 07:22:27

标签: c++ parsing bison flex-lexer abstract-syntax-tree

我正在学习解析,野牛和...法。我正在寻找一个明确的&完整的教程/示例演示了以下所有内容:

  1. C ++(不是C)抽象语法树。
  2. 重入词人。
  3. 重入解析器。
  4. 从字符串中读取(与文件相比)也很好。
  5. 我找到了多个示例和教程,但每个示例和教程通常只满足上述要求中的一小部分。到目前为止,我最好的教程是来自John Levine的Oreilly一书中的第3-2章 - 它有AST;所有C虽然只满足上面的Re_1。我欢迎推荐好的示例/教程,现实生活中的开源项目。例如,我看到MySql .yy文件 - 看起来很好,但对于像我这样的初学者来说太大/太复杂。

2 个答案:

答案 0 :(得分:4)

最后,我结合了几个例子来得到我想要的东西。前两个例子来自John Levine的关于bison& flex(第2版)的书,ISBN-10:0596155972。另一个来自phpcompiler网站,不幸的是,从2017年经常不再存在。我将链接保留在此处,以防网站存档:www.phpcompiler.org/articles/reentrantparser.html

感谢Adrien,这是一个存档版本(2017-03-02工作):

http://web.archive.org/web/20120520150851/http://www.phpcompiler.org/articles/reentrantparser.html

答案 1 :(得分:1)

首先,我想说C ++语法对于Lex / Bison来说过于复杂。这里的问题主要在于语法冲突。编写没有它们的C ++语法是不可能的。 C ++标准明确说明了这一点,并包含了一些如何解决它们的指南。

没有解决语法冲突的通用解决方案。特别是语法冲突,C ++的解析需要有关已定义标识符的详细知识。这意味着您需要拥有更大的C ++前端部分。只有语法是不够的。

然而,建立AST是可能的。看一个小样本程序。

class HashEntry
{
private:

      int key;
      int value;

public:

      HashEntry(int key, int value)
      {
            this->key = key;
            this->value = value;
      }

      int getKey() { return key; }

      int getValue() { return value; }
};

const int TABLE_SIZE = 128;

class HashMap
{
private:

      HashEntry **table;

public:

      HashMap()
      {
            table = new HashEntry*[TABLE_SIZE];

            for (int i = 0; i < TABLE_SIZE; i++)
                  table[i] = NULL;
      }

      int get(int key)
      {
            int hash = (key % TABLE_SIZE);

            while (table[hash] != NULL && table[hash]->getKey() != key)
                  hash = (hash + 1) % TABLE_SIZE;

            if (table[hash] == NULL)
                  return -1;
            else
                  return table[hash]->getValue();
      }

      void put(int key, int value)
      {
            int hash = (key % TABLE_SIZE);

            while (table[hash] != NULL && table[hash]->getKey() != key)
                  hash = (hash + 1) % TABLE_SIZE;

            if (table[hash] != NULL)
                  delete table[hash];

            table[hash] = new HashEntry(key, value);
      }     

      ~HashMap()
      {
            for (int i = 0; i < TABLE_SIZE; i++)
                  if (table[i] != NULL)
                        delete table[i];

            delete[] table;
      }
};

这是这个程序的AST: enter image description here

此树严重缩小。叶子上的黄色圆圈(非常小)是终端符号,中间的绿色圆圈是非终端。中心的粉色圆圈是TranslationUnit。这棵树有2009个节点。