私は C++ で SQL 選択ステートメントの (手書きの) 再帰降下パーサーを作成しています。作成した解析ツリーが正しいかどうかを知る必要があります。確認したいのですが、SQL 解析ツリーの適切なソースがありませんでした。私のアプローチ方法は、プロダクションごとに関数を作成し、その関数で結果をルート ツリーに追加することです。誰でも私を助けることができますか?前もって感謝します。
3 に答える
私の会社は多くのパーサーを構築しており、あなたと同じ問題を抱えています。最近、ドラフト標準に基づく SQL 2011 パーサーを完成させました。
解析ツリーが正しいかどうかは、ほとんどの場合、多くのソース コード ケースについて手動で検査することによって判断します。これは、解析ツリーを簡単に検査できる形式で出力できることを前提としています。これは、解析ツリーの再帰的なツリー ウォークによって簡単に実現できます。[抽象構文木ノードがキャプチャしようとしているものを正しくモデル化していることをすでに信じている必要があります!]。ケースを慎重に選択して、文法のさまざまな部分を実行します (「文法の単体テスト」を考えてください)。SQL のようにリッチな言語にとって、これは大きな仕事です。
また、パーサーが一般的に機能することを検証する必要があります。これは、処理している SQL の特定の方言に多くの実際のコードを供給することによって行います。私は通常、100K-1M SLOC を見つけようとしますが、パーサーがそのすべてを処理できない場合は、まだやるべきことが残っています。そのレベルに到達すると、パーサーは問題ないと見なし、それ以上のエラーを「メンテナンスの問題」として扱います。
以下は直接的には役に立たないかもしれませんが、進むべき方向を示唆しているかもしれません。私は、非常に強力な解析機構を利用できることに基づいて、多少異なるアプローチを使用します。私たちのツールであるDMS Software Reengineering Toolkitは、指定された文法で AST を自動的に生成し、そのような解析ツリーを (XML として 1 つの形式で) 出力する組み込み機能を備えています。AST にはソース テキストを再生成 ("prettyprint") するのに十分な情報があり、DMS には組み込みの prettyprinter があります。したがって、さまざまなケースを手作業で検査した後、私が行うことは、大量のコード本体を取得し、ファイルごとに解析し (上記の作業により解析エラーは発生しません)、ソースをプリティプリントし、再解析します。ソース (エラーが発生しないことを期待)。これは、往復で何も失っていないことを示す強力なヒントです。
Smart Differencerという新しいツールが利用可能になりました。これは、2 つのプログラムのテキストを比較して、言語レイアウト規則を無視して「同じ」かどうかを確認します。基本的には、2 つのファイルを解析し、フォーマット (行/列/エスケープ/基数/コメント/空白) を無視して、それらの解析ツリーを比較することによって機能します。私たちが始めようとしているのは、ソース コードを解析してプリティプリントし、プリティプリントされた結果を元のファイルと比較してスマート比較することです。SmartDiff は「AST の違いはありません」と言うはずです。これは、私たちが何も失っていないことを示す、より強力なヒントです。印刷前と印刷後の解析ツリーを比較したい場合は、ほとんど同じことができます。
コードが正しいことを確認する方法はわかりませんが、SQL 文法の理解に不安がある場合は、SQLのさまざまな方言の BNF 文法を一覧表示している Web サイトを参照してください。これらのルールに従って、パーサーを構築できるはずです。