構文解析過程は 2 つの部分から構成されています。
gram.y と scan.l で定義されているパーサは、Unix のツール yacc と lexを使って構成されています。
変換プロセスは、パーサから返されたデータ構造の変更や追加を行います。
パーサは、(平文 ASCII テキストとして渡される)問い合わせ文字列が正しい構文になっているかチェックしなければいけません。もし構文が正しい場合は 構文解析ツリーが作られて返されます。 正しくない場合はエラーが返されます。パーサと字句解析は Unix でよく知られたツールの lex と yacc を使用して実装されています。
字句解析はファイル scan.l で定義され、識別子や SQL キーワードなどの確認を担当します。 検出されたすべてのキーワードや識別子に対し トークンが生成されパーサに渡されます。
パーサはファイル gram.y の中で定義され、文法ルールとルールが実行されたときに実行されるアクションの組から構成されています。アクションのコード(実際は C 言語コードです)は構文解析ツリーを作るのに使われます。
ファイル scan.l はプログラム lex を使って C のソースファイル scan.cに変換されます。 そして gram.y は yacc を使って gram.c に書き換えられます。これらの書き換えが終わると、パーサを作るために通常の C コンパイラが使えるようになります。生成された C のファイルには絶対に変更を加えないでください。というのは次に lex もしくは yacc が呼ばれたときに上書きされる可能性があるからです。
注意: ここで言及した書き換えやコンパイルは通常 PostgreSQL のソースと一緒に配布される makefile を使って自動的に行われます。
yacc または gram.y で定義される文法ルールの詳しいことは本稿では説明しきれません。lex や yacc については本や資料がたくさん出ています。gram.y の文法の勉強を始める前に yacc の知識が必須となります。その知識なしではそこで何が起こっているのかを理解することは難しいでしょう。
構文解析過程では SQL の構文構造に関する固定ルールのみを使って構文解析ツリーを作成します。システムカタログの参照を行わないので要求されている操作の詳細な語義は理解しません。構文解析が終わった後に入力としてパーサから戻されたツリーを書き換えプロセスが引き受け、どのテーブル、関数、そして演算子が問い合わせによって参照されているのかの判断に必要な語義翻訳を行います。この情報を表すために作成されるデータ構造を問い合わせツリーと呼びます。
語義解釈と入力の構文解釈を切り分ける理由はシステムカタログの参照はトランザクション内でのみ行われ、問い合わせ文字列を受け取ってすぐにトランザクションを開始することは好ましくないと考えられるからです。入力に対する構文解析過程ではトランザクション管理コマンド(BEGIN、ROLLBACK、など)を特定するだけで充分であるとともに、それ以上の分析を行わなくても正しい処理が実行されます。実際の問い合わせ(例えば SELECT もしくは UPDATE)にかかわっていると言うことがわかっていて既にあるトランザクション内にいなければ新規トランザクションを開始することは問題ありません。これ以降に限り書き換えプロセスを起動することができます。
変換過程で作成された問い合わせツリーはほぼ到るところにおける行の構文解析ツリーに構造的には似ています。とは言っても詳細では多くの相違が存在します。例えば、構文解析ツリーの FuncCall ノードは構文的には関数呼び出しのようにみえます。参照された名前が通常の関数になるか集約関数となるかによって FuncExpr もしくは Aggref に書き換えられることがあります。さらに、列の実際のデータ型と表現結果に関する情報が問い合わせツリーに書き加えられます。