web-dev-qa-db-ja.com

抽象構文木を構築する方法

ASTが何であるかについての一般的な考えがありますが、どのように構築するかを知りたいです。

文法と解析ツリーが与えられた場合、どのようにASTを構築しますか?

文法と表現が与えられたらどうしますか?

62
neuromancer

まず、最初に、文法を使用して式から解析ツリーを構築します。したがって、既に解析ツリーがある場合は、文法は必要ありません。

パーサーの処理量に応じて、式の解析から形成される結果のツリーは、すでに抽象構文ツリーである可能性があります。または、astを構築するために2回目のパスを必要とする単純な解析ツリーにすることもできます。

文法と式から構文解析ツリーを構築するには、最初に文法を作業コードに変換する必要があります。通常、作業は、式を表す入力ストリームをトークンのリストに分割するトークナイザーと、トークンのリストを取得し、そこから解析ツリーを作成するパーサーに分割します。

したがって、式1 + 2*(3+4)は、次のようなトークンのリストに分割される場合があります。

1 - int
+ - add_operator
2 - int
* - mul_operator
( - lparen
3 - int
+ - add_operator
4 - int
) - rparen

最初の列は実際のテキスト値です。 2番目はトークンタイプを表します。これらのトークンはパーサーに渡されます。パーサーは文法から構築され、トークンを認識して解析ツリーを構築します。

では、レキシカルトークナイザーと実際のパーサーをどのように書くのでしょうか?手で自分で転がすことができます。または、より一般的には、coco、antlr、Lex/yaccなどのパーサージェネレーターを使用します。これらのツールは、文法の説明を受け取り、tokenzierとパーサーのコードを生成します。 (コードジェネレーターは、ほとんどの一般的な言語といくつかの人気のない言語にも存在します。)

パーサーの構築方法は、使用する言語に大きく依存します。 Haskellでパーサーを記述する方法は、たとえばCで行う方法とはまったく異なります。

  • 独自の再帰降下パーサーを構築する の方法を示すチュートリアルを次に示します。

  • Coco は、さまざまな言語用のパーサージェネレーターであり、開始方法に関するドキュメントも付属しています。

  • Pythonがあなたのものなら、 pyparsing かもしれません。

42
HS.

レクサーやパーサーについては話さずに、一般的な観点からこれに答えます。

解析ツリーには、文脈自由文法の一部である非終端記号が含まれ、再帰の有無にかかわらず終端記号で構成される文字列を取得するために、プロダクションのチェーンを示します。したがって、構文解析ツリーがあれば、文法は必要ありません-構文解析ツリーから文法を導出できます。

ASTには非終端記号は含まれません。記号のみが含まれます。

例:

 E
 |
 E + T
 |   |
 T   M * M
 |   |   |
 M   a   b
 |
 a

a+a*bを表示する非常に簡単なバージョンです。抽象構文ツリーの解釈方法は、ツリーの優先順位、実行するトラバーサルのタイプ(インオーダー、プレオーダー、ポストオーダー)によって異なります。これは、検索ツリーにコーディングする一般的な関数になります。ただし、一般に、その解析ツリーのASTは次のようになります。

   +
 |   |
 a   * 
    | |
    a b
4
Dhruv Ghulati