4

私は構文解析、バイソン、lexを学んでいます。私は、以下のすべてを示す明確で完全なチュートリアル/例を探しています。

  1. C ++(Cではない)抽象構文木。
  2. リエントラントレクサー。
  3. リエントラントパーサー。
  4. 文字列からの読み取り(ファイルからの読み取りと比較して)も同様に便利です。

複数の例とチュートリアルを見つけましたが、それぞれが通常、上記の要件のいくつかしか満たしていません。これまでのところ、私の最高のチュートリアルは、JohnLevineによるOreillyの本の第3-2章からのものです。ただし、すべてのCは、上記のRe_1のみを満たしています。素晴らしい例/チュートリアル、実際のオープンソースプロジェクトの推奨事項を歓迎します。たとえば、MySql .yyファイルを見ました-よく書かれているように見えますが、私のような初心者には大きすぎる/複雑すぎます。

4

2 に答える 2

4

結局、私はいくつかの例を組み合わせて、私が望むものを手に入れました。上位2つの例は、John Levineのbison&flexに関する本(第2版)、ISBN-10:0596155972からのものです。もう1つは、残念ながら2017-02-28の時点で存在しないphpcompilerWebサイトからのものです。サイトがどこかにアーカイブされている場合に備えて、ここにリンクを残します:www.phpcompiler.org/articles/reentrantparser.html

Adrienに感謝します、ここにアーカイブされたバージョンがあります(2017-03-02現在で動作します):

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

于 2012-06-14T00:30:27.110 に答える
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です。 ここに画像の説明を入力してください

このツリーは大幅にズームアウトされています。葉の黄色い円(非常に小さい)は終端記号であり、中央の緑色の円は非終端記号です。中央のピンクの円はTranslationUnitです。このツリーには2009ノードがあります。

于 2012-06-14T00:03:05.740 に答える