抽象構文木を取り、その逆ではなくコードを生成するパーサーの背後にある例と理論について知っている人はいますか?数学的には、少なくとも直感的には、コード-> ASTの機能は可逆的であると思いますが、ドラゴンブックなどの通常のリソースに加えて、この作業/例を見つけようとしています。何か案は?
11 に答える
そのようなものはビジターと呼ばれます。ツリーをトラバースし、コードの最適化や生成など、実行する必要のあるすべてのことを実行します。
当社のDMS Software Reengineering Toolkitは、任意の言語の機械的処理 (分析/変換) に対する「ポーカーアンテ」として、パーサーとパーサーインバース (「prettyprinters」と呼ばれる) を主張しています。これらは、完全なラウンドトリップを提供します: 取得された位置情報 (ファイル/行/列) とコメントを含む AST へのソース テキストと、元のトークン位置の再生成 (「忠実な印刷」) またはきれいにフォーマットされた (「きれいな印刷」) を含む正当なソース テキストへの AST。 ) コメントの再生成を含むオプション。
パーサーは、多くの場合、文法とトークンの字句定義の組み合わせによって指定されます。これらの表記は通常、効率的な解析エンジンにコンパイルされます。DMS は、ご想像のとおり、「パーサー」側でそれを行います。ここにいる他の人々は、「ビジター」はプリティプリンティングを行う方法であり、アセンブリコードのように、抽象化の最低レベルでプリティプリンティングを実装する正しい方法であると示唆しています。ただし、DMS prettyprintersは、テキスト ボックス構築言語の観点から指定されています。ラテックスのような文法用語を使用して、さまざまな言語要素の水平方向、垂直方向、埋め込み、間隔、連結、積層などの配置を制御できます。DMS は、これらを実装する効率的な低レベルのビジターにコンパイルします (他の回答が示唆するように)。ボックス世代。しかし、パーサー ジェネレーターと同様に、醜い詳細をすべて見ることはできません。
DMS には、C++、C、Java、C#、COBOL などから HTML、XML、一部のマシンのアセンブリ言語、一時的なプロパティの仕様、仕様に至るまで、さまざまなプログラミング言語と正式な表記法に対応するこれらの言語フロント エンドのセットが 30 以上あります。構成可能な抽象代数など
私はlewapの反応が好きです:
ビジターを表現する数学的方法を見つけ、パーサーとの双対を持っている
しかし、あなたはサンプルを求めたので、サイズを確認するためにこれを試してください。Visual Studio には、優れた対称性を備えた UML エディターが含まれています。それとエディターの両方が実装される方法は、すべてモデルのビューを構成し、いずれかを編集するとモデルが変更され、結果としてすべてが同期されたままになります。
Haskell での可逆解析の理論、実用的な実装、および例があります。ライブラリは Paweł Nowak によるものです。 出発点としてhttps://hackage.haskell.org/package/syntaxを参照して ください。次の URL で例を見つけることができます。
実際、少なくとも数学的な意味では、解析ツリーからコードを生成することは、コードを解析することよりもはるかに簡単です。あいまいな文法がたくさんあります。つまり、それらを解析する独自の方法はありませんが、解析ツリーは常に独自の方法 (モジュロ空白) で文字列に変換できます。
ドラゴンの本は、パーサーの理論をよく説明しています。
これは、ターゲット言語がソース言語と同じである非最適化コンパイラのバックエンドによく似ています。
1つの質問は、「解析されていない」コードが元のコードと同一である必要があるのか、それとも機能的に同等である必要があるのかということです。
たとえば、出力で元のインデントスタイルとは異なるインデントスタイルを使用しても問題ありませんか?その情報は意味的に重要ではないため、通常はASTに保存されません。
注目すべきことの1つは、自動コードリファクタリングツールです。
「ビジターパターン」のアイデアは良いです。ただし、「Visitor」パターンを線形リストパターン、または一般的なパターンと見なし、リスト、マトリックス、ツリーなどのより具体的なケースのパターンを追加する必要があります。
Webで「階層型ビジターパターン」または「ツリービジターパターン」を探します。
ツリーデータ構造(「コレクション」)があり、ツリーからアイテムを「訪問」、「反復」、または「読み取る」たびに、データを処理したいと考えています。
あなたの場合、いくつかのソースコードをスキャン/解析した結果を表すツリーデータ構造があります。次に、各アイテムのデータを読み取り、それを宛先コードに変換します。
理論についてどこで見つければよいかわかりませんが、boost::spirit 2.0には qi (パーサー) とkarma (ジェネレーター) の両方があり、同じ基本的な構造と文法を共有しているため、概念の実用的な実装です。
ジェネレーター側のドキュメントはまだかなり薄いです (spirit2 は Boost 1.38 で新しく、まだベータ版です)、いくつかのカルマ サンプル コードがあり、ライブラリは動作状態にあり、少なくともいくつかあります。利用可能な例。
私はこれらをずっとやっていて、「DeParse」と呼んでいます。
空白とコメントも再キャプチャしたい場合にのみ、注意が必要です。出力時に再生成できるように、それらを解析ツリーに入れる必要があります。
「Visitor」に加えて、「unparser」も Web 検索に適したキーワードです。