web-dev-qa-db-ja.com

ソースコードの代わりに構文ツリーを保存しないのはなぜですか?

プログラミング言語はたくさんあります。すべての言語が解析され、コードに変換される前に構文チェックが行われるため、抽象構文ツリー(AST)が構築されます。

この抽象構文ツリーがあります。なぜ、ソースコードの代わりに(またはソースコードの横に)この構文ツリーを格納しないのですか?

ASTを使用します。チーム内のすべてのプログラマは、このツリーを必要な言語にシリアル化し(適切な文脈自由文法で)、ASTそれらが終了すると、コーディングスタイルの質問({と}を配置する場所、空白、インデントなどを配置する場所)に関する議論がなくなります。

このアプローチの長所と短所は何ですか?

115
Calmarius

ソースコードの代わりにこの構文ツリーを保存しないのはなぜですか?チーム内のすべてのプログラマーは、このツリーを任意の言語にシリアル化できます。終了したら、ASTにパースします。

確かに、それは合理的な考えです。 Microsoftには ほぼ正確にそれを行うための1990年代の研究プロジェクト がありました。

いくつかのシナリオが思い浮かびます。

1つ目はかなり簡単です。あなたが言うように、ASTは、スペースなどのさまざまなプログラマーの好みに応じて異なるビューにレンダリングすることができます。しかし、ASTそのシナリオではやり過ぎです。自分でプリティプリンターを作成してください。ファイルをエディターに読み込んだら、プリティプリンターを実行してファイルを適切な形式にし、保存時に元の形式に戻します。

二つ目はもっと面白いです。抽象構文ツリーを保存できる場合、変更のコード差分はテキストではなく構文になります。コードが移動されるリファクタリングは、はるかに理解しやすくなります。もちろん欠点は、tree-diffアルゴリズムの記述が厳密なものではなく、言語ごとに実行する必要があることです。テキストの差分は、ほとんどすべての言語で機能します。

3つ目は、シモニーが意図的なプログラミングのために構想したものに似ています。プログラミング言語に共通する基本的な概念はシリアライズされたものであり、それらの概念のさまざまなビューがさまざまな言語でレンダリングされます。美しいアイデアですが、醜い事実は、言語の細部が十分に異なっているため、最小公分母アプローチが実際に機能しないことです。

要するに、それは素敵なアイデアですが、それは比較的小さな利益のために膨大な量の余分な作業です。だからこそ誰もそれをしません。

48
Eric Lippert

これがまさに.NETのバイトコードと同じであると主張できます。 Infact redgateのリフレクタープログラムは、バイトコードをさまざまな.NETプログラミング言語に変換します。

しかし、問題があります。構文は、他の言語では表現できない1つの言語で表現できるものと同じくらい、言語固有です。これは.NETで発生し、C++は7つのアクセスレベルすべてにアクセスできる唯一の.NET言語です。

.NET環境以外では、かなり扱いにくくなります。各言語は、独自の関連ライブラリのセットを持ち始めます。 CとJavaの両方で一般的な構文を反映することは不可能です。これらは、非常に異なる方法で模擬問題を解決するため、同じ命令の実行を反映しています。

20
Michael Shaw

最も顕著な点は次のとおりだと思います。

  • メリットはありません。誰もがペットの言語を使用できることを意味するとおっしゃっていました。 しかし、それは真実ではありません–構文ツリー表現を使用すると、構文上の違いのみが除外され、意味上の違いは除外されません。これは、VBおよびC#、またはJavaおよびScalaなど)のような非常に類似した言語である程度機能します。しかし、完全に機能するわけではありません。

  • 問題があります。言語の自由を手に入れましたが、ツールの自由を失いました。テキストエディターでコードを読んだり編集したりすることはできなくなります。また、IDE – youdependon a ASTコードの読み取りと編集の両方を表す特定のツール。ここでは何も得られません。

    この最後のポイントを説明するために、強力なBASIC方言の独自の実装であるRealBasicを見てみましょう。しばらくの間、言語は離陸できるように見えましたが、完全にベンダーに依存していたため、コードはIDE独自の非テキスト形式Big間違い。

14
Konrad Rudolph

私はあなたの考えの一部に似ていますが、言語を言語に翻訳するのがいかに簡単であるかをかなり過大評価しています。それが簡単なら、ASTを保存する必要すらありません。言語Xを常にASTに解析して、ASTから言語Y.

ただし、コンパイラの仕様で、いくつかのASTをある種のAPIを介して公開することについてもう少し考えてほしいと思います。アスペクト指向プログラミング、リファクタリング、静的プログラム分析などは、そのようなAPI。これらの機能の実装者がコンパイラライターによってすでに実装されている作業の多くをやり直す必要はありません。

プログラムを表現するためのプログラマーのデータ構造が文字列を含むファイルの束としてどれほど頻繁にあるかは奇妙です。

13
psr

テキストとASTの両方を保存する場合、テキストは既に1つの言語で存在し、ASTはテキスト。

一方、ASTのみを保存すると、コメントなど、復元できないものは失われます。

6
Tesserex

このアイデアを中心に構築されたシステムがあります:JetBrains [〜#〜] mps [〜#〜] 。エディターは少し変わっているか、またはまったく異なりますが、一般的にはそれほど大きな問題ではありません。最大の問題は、それがテキストではなくなったことです。そのため、通常のテキストベースのツール(他のエディター、grepsed、マージ、および差分ツールなど.

5
SK-logic

実際には、ASTを格納し、エディターにASTの特定の言語への「射影」を提示する、一般に「言語ワークベンチ」と呼ばれるいくつかの製品があります。@ sk-logicとしてJetBrainsのMPSはそのようなシステムの1つであり、もう1つはIntentional SoftwareのIntentional Workbenchだと述べた。

ドメイン固有のプロジェクションを作成できるため、特にドメイン固有の言語の領域では、言語ワークベンチの可能性が非常に高いようです。たとえば、Intentionalは、回路図として投影される電気に関連するDSLをデモします。ドメインの専門家にとって、テキストベースのプログラミング言語で記述された回路よりもはるかに簡単かつ正確に議論および批判できます。

実際、言語のワークベンチは、DSLの作業を除いて、開発者はおそらく使い慣れた一般的なプログラミング言語で作業することを好むため、追い付くのに時間がかかりました。テキストエディタやプログラミングIDEと直接比較すると、言語ワークベンチには膨大なオーバーヘッドがあり、その利点はそれほど明確ではありません。私が見たどの言語ワークベンチも、自分のIDEを簡単に拡張できるところまでブートストラップしていません。つまり、言語ワークベンチが生産性に優れている場合、言語ワークベンチツールが改善されないのはなぜですか。 -そしてより速い速度でより良いですか?

5
Larry OBrien

アイデアは理論上は興味深いと思いますが、プログラミング言語が異なればサポートする構成も異なるため、他の言語には同等のものがないため、実用的ではありません。

たとえば、X ++には 'while select'ステートメントがあり、C#では多くの追加コード(追加のクラス、追加のロジックなど)なしでは記述できませんでした。 http://msdn.Microsoft.com/en-us/library/aa558063.aspx

ここで私が言っていることは、多くの言語には、同じ言語のコードの大きなブロック、または他の言語にはまったく存在しない要素にさえ翻訳される構文糖があります。 AST=アプローチが機能しない理由は次のとおりです。

言語XのキーワードKは、AST= 4ステートメント:S1、S2、S3、およびS4で翻訳されています。ASTは、言語Yに翻訳されています。プログラマーがS2を変更すると、Xに変換するとどうなりますか?コードは、単一のキーワードではなく4つのステートメントとして変換されます...

AST=アプローチに対する最後の引数はプラットフォーム関数です:関数がプラットフォームに埋め込まれるとどうなりますか?.NETのEnvironment.GetEnvironmentVariableのように、それをどのように変換しますか?

4

あなたは私の心を読んでいます。

数年前にコンパイラコースを受講したときに、ASTを取得し、通常のインフィックス表記の代わりにプレフィックス表記でシリアル化し、括弧を使用してステートメント全体を区切る場合、 、あなたはLISPを取得します。私は学部の研究でScheme(LISPの方言)について学びましたが、実際にそれを理解することはできませんでした。コース。

あなたが提案するものの問題:

  1. ASTをグラフィカル環境で作成するのは難しい/遅いです。結局のところ、私たちのほとんどは、マウスを動かすよりも速くタイプできます。それでも、新たに出てくる質問は、ハードウェアキーボードを備えたキーボード/ラップトップと比較すると、タブレットでのプログラムコードは遅い/扱いにくいです。パレットからコンポーネントをドラッグアンドドロップしてASTを作成できる場合タブレット上の大きなタッチスクリーンデバイスプログラミング上のキャンバスに実際のことになる可能性があります。

  2. これをサポートする既存のツールはほとんどありません。複雑さを増すIDEとインテリジェント化するエディターの作成に数十年の開発が集中しています。テキストの再フォーマット、テキストの比較、テキストの検索のためのこれらすべてのツールがあります。ツリー全体で正規表現検索に相当するツールはどこにありますか?または2本の木の差分?これらすべてはテキストで簡単に行えます。しかし、彼らは言葉だけを比較することができます。変数名を変更します。単語は異なりますが、意味の意味は同じであり、それらのdiffツールは問題が発生します。テキストではなくASTを操作するために開発されたこのようなツールを使用すると、セマンティックな意味の比較に近づくことができます。それは良いことでしょう。

  3. プログラムのソースコードをASTは比較的よく理解されていますが(コンパイラとインタープリタがありますね))、ASTをプログラムに変えますコードはあまりよく理解されていません。2つの素数を乗算して大きな合成数を取得することは比較的簡単ですが、大きな合成数を素数に戻すことははるかに困難です。そのため、ASTの解析と逆コンパイルを行います。言語間の違いが問題になる場所。特定の言語内でも、ASTを逆コンパイルする方法は複数あります。たとえば、オブジェクトのコレクションを繰り返し処理して、ある種の結果を取得します。forループを使用して、配列を繰り返し処理しますか?それはコンパクトで高速ですが、制限があります。コレクションで動作するある種のイテレータを使用しますか?そのコレクションは可変サイズである可能性があり、速度を犠牲にして(可能な場合)柔軟性を追加します。Map/Reduce?より複雑、しかし暗黙的に並列化可能です。それは好みに応じてJava。

やがて、開発努力が費やされ、タッチスクリーンとASTを使用して開発が行われます。タイピングはそれほど必要ではなくなります。今日のコンピュータの使い方を見ると、現在の位置からの論理的な進展として、今日、それが#1を解決するでしょう。

すでに木を使っています。 LISPは単にシリアル化されたASTです。 XML(および拡張機能によるHTML)は、単にシリアライズされたツリーです。検索を行うために、XPathとCSS(それぞれXMLとHTML)のプロトタイプがいくつかあります。 CSSスタイルのセレクターと修飾子を作成できるグラフィカルツールが作成されると、#2の一部が解決されます。これらのセレクターを拡張して正規表現をサポートできるようになれば、さらに近づくでしょう。 2つのXMLまたはHTMLドキュメントを比較するための優れたグラフィカルdiffツールを探しています。人々がそれらのツールを開発するにつれて、#2は解決できるでしょう。人々はすでにそのようなことに取り組んでいます。彼らはまだそこにいません。

これらのASTをプログラミング言語のテキストに逆コンパイルできる唯一の方法は、目標を追求することです。既存のコードを変更している場合、変更されたコードを可能な限り開始コード(最小限のテキスト差分)に類似させるアルゴリズムによって目標が達成される可能性があります。私がコードを最初から作成している場合、目標は最小で最もタイトなコード(forループのようです)になる可能性があります。または、可能な限り効率的に並列化するコードである可能性があります(マップ/リデュースまたはCSPに関連するものなど)。したがって、同じASTは、同じ言語であっても、目標の設定方法に基づいて、大幅に異なるコードになる可能性があります。このようなシステムを開発すると、#3が解決されます。計算が複雑になります。つまり、ハンドヘルドタブレットが大量の負荷のかかる作業をクラウドベースのサーバーにオフロードできるように、おそらくクライアントサーバーの配置が必要になるでしょう。

4
Meower68

抽象構文ツリーのコーディングに関連して注目すべき他の2つの興味深いプロジェクトは Tree-Sitter で、これはAtomテキストエディターとGithubの一部です。コードを解析します。リアルタイムでASTにアクセスできます。これにより、作成者が「選択範囲の拡張」と呼ぶものなど、非常に興味深いことを行うことができます。この場合、1つの単語をクリックし続けると、より高いレベルのテキストに関連するテキストが強調表示されます。 ASTはその構造を理解しているためです。:

enter image description here

テキストファイルにソースコードを保存しない nison プログラミング言語もあります。代わりに、テキストファイルを解析し、すべての詳細を取り除いて、高度に抽象化されたバージョンのコードを残し、それをハッシュします。その「コード」は、ファイル名ではなくハッシュを使用してアクセスされます。これにより、ビルドや依存関係の競合がなくなり、コードベースを変更せずに変数/関数などの名前を簡単に変更できるなど、多くの興味深いメリットがもたらされます。

これらのプロジェクトはどちらも、生のテキストから少し離れた、ASTに近い抽象化レベルでコーディングできます。

2

ソースコードの代わりにASTを読んで変更するのは難しいです。

ただし、一部のコンパイラ関連ツールでは、ASTを使用できます。 Javaバイトコードと.NET中間コードは、ASTと同様に機能します。

1
umlcat

書式設定スタイルに関する議論をなくすことを意図している場合は、ソースファイルを読み込み、表示と編集のために個人の好みに合わせて書式設定しますが、保存すると、チームが選択したスタイルに再書式設定します。使用します。

Emacsのようなエディタを使用すると、非常に簡単です。ファイル全体のフォーマットスタイルの変更は、3つのコマンドからなるジョブです。

ロード時にファイルを自動的に独自のスタイルに変換し、保存時にチームスタイルに変換するフックを構築することもできます。

1
Gustav Bertram

それはいい考えです。しかし、各言語のASTは他のすべての言語とは異なります。

私が知っている唯一の例外はVB.NETとC#で、Microsoftはそれらが「構文が異なるまったく同じ言語」であると主張しています。他の.NET言語(IronPython、F#など)でも、ASTレベルで異なります。

JVM言語でも同じことが言えます。それらはすべて同じバイトコードをターゲットにしますが、言語の構成が異なるため、異なる言語と異なるASTになります。

CoffeScriptやXtendのような「薄層」言語でさえ、基礎となる言語(それぞれJavaScriptとJava)の理論の多くを共有しています。ただし、ASTレベルで保持される(または保持する必要がある)より高いレベルの概念を導入します。

xtendがJava ASTから再構築できた場合、既存のJavaコードですよね。

0
Javier