10

オフサイド言語とは

...その言語の宣言 (ブロック) の範囲は、インデントによって表されます。

そのような言語の例としては、Python、Boo、Nemerle、YAML などがあります。

だから私の質問はこれです:これらを実際に解析するにはどうすればよいですか? タブとスペースの問題を解決するにはどうすればよいですか (2 つのタブまたは 8 つのスペースは同等かどうか)? ここでパーサージェネレーターは役に立ちますか、それともレクサー/パーサーを自分でハンドコーディングする必要がありますか?

4

6 に答える 6

9

Python には、中かっこ ("{", "}") と同等のIndentおよびDedentトークンを生成するレクサーがあります。そのようなレクサーの単純な実装を使用して、Stack Overflow にも例があります。

タブとスペースの場合、Python にはコーディング規則しかありません。インデント レベルごとに 4 つのスペースを使用します。ただし、タブは正当な構文です。

于 2010-08-10T23:13:37.837 に答える
5

タブ対スペースの問題を解決する最も簡単な方法は、スペースとタブの組み合わせを禁止することです (これは、たとえば F# で行われていることです)。最新のエディターでは、タブをいくつかのスペースに変換できます。

パーサージェネレーターを放棄する必要があるかどうかについては、おそらくそうではありませんが、どこかでオフサイドの識別をハックする必要があります。これには、あなたの側で少し創造性が必要になる場合があります。F# のソースを閲覧したところ、レクシング後の手順を使用して、オフサイド言語要素を表す追加のトークンを作成しているようです。

于 2010-02-12T15:56:00.943 に答える
4

タブとスペースの問題を解決するにはどうすればよいですか (2 つのタブまたは 8 つのスペースは同等かどうか)?

2 つのタブが 8 つのスペースに等しいかどうかは、エディターの設定によって異なります。

オリジネーターによって表現されたオフサイド ルールは、空白の絶対数ではなく、連続する 2 行のコードの相対的な配置に言及しています。理解を深めるのに役立つ読み物(およびいくつかの引用)を次に示します。

「空白は Python ソース コードで重要です。」

いいえ、一般的ではありません。ステートメントのインデント レベルのみが重要です (つまり、ステートメントの一番左にある空白)。それ以外の場所では、空白は重要ではなく、他の言語と同じように好きなように使用できます。何も含まない (または任意の空白のみを含む) 空行をどこにでも挿入することもできます。

また、インデントの正確な量はまったく問題ではなく、ネストされたブロックの相対的なインデント (相互に相対的) のみが重要です。[...]

于 2010-02-01T17:02:14.587 に答える
2

価値があるのは、Haskell もインデントベースであり、オプションで { foo; バー; etc } 空白が不便な場合。私は単純なインデントベースのパーサーParsecで書きました。これは Lisp のように読むように意図されていますが、インデントは演算子の適用を示しています。括弧は 1 行でのみ使用できます。

(aaa bb) cc
         e fffff (ggg hhh) iii
                 jjj kkk
         ddd

aaaに適用されますbb。結果は三項関数です。引数cce適用される 、1 つの引数に適用される、およびddd. アプリケーションが X スペースではなく、列の配置に基づいていることを確認してください。

パーサーもおそらくもっと単純になるでしょう。

于 2010-10-05T08:50:55.337 に答える
1

タブとスペースに関していくつかのオプションがあります。タブとスペースの混在を禁止するか、スペースに対するタブの比率を固定と仮定するか、プログラマーがプロジェクトごとまたはソース ファイルごとに決定できるようにします (ある種の "#pragma tab (4)" タブを許可したり、タブが表すスペースの数を変更したりするためのスタイル ディレクティブ)。

ANTLR 3 などのパーサー ジェネレーターは、これに簡単に対処できます。私は自分自身で例をいじり、その C# ターゲットにコンパイルしました。DirkGently's answerのリンクは、コードに直接変換される Python アルゴリズムを説明しています。私のアプローチは、空白と改行に個別のトークンを定義し、レクサーが追加のインデント/デデントトークンをその場で挿入するために使用する「トークンの発行」関数をオーバーライドすることでした。これは、「最後のトークンを取得」機能をオーバーライドする、私が見た他のアプローチよりも実装が簡単であることが判明しましたが、どちらもかなりうまく機能します。

于 2010-03-18T21:32:24.627 に答える
0

私は自分で 1 つの解決策を得ました。これは、ネスト ツリーのブロックと同じようにコードを分析します。括弧の部分については、通常の方法を使用しました。

これがそのパーサーです: https://github.com/jiyinyiyong/cirru-parser

于 2013-12-10T12:29:54.627 に答える