コメントは通常どのように解析されますか?


31

プログラミング言語とマークアップでは、コメントは一般にどのように扱われますか?私はいくつかのカスタムマークアップ言語のパーサーを書いており、最も驚きの少ない原則に従うことを望んでいるので、一般的な規則を決定しようとしています。

たとえば、トークン内に埋め込まれたコメントは、トークンと「干渉」する必要がありますか?一般的に、次のようなものです:

Sys/* comment */tem.out.println()

有効ですか?

また、言語が改行に敏感であり、コメントが改行にまたがっている場合、改行を考慮するかどうか

stuff stuff /* this is comment
this is still comment */more stuff 

として扱われる

stuff stuff more stuff

または

stuff stuff
more stuff

私はいくつかの特定の言語が何をするかを知っており、意見を求めていませんが、トークンと新しい行に関してマークアップによって一般的に期待される一般的なコンセンサスはありますか?


私の特定のコンテキストは、Wikiのようなマークアップです。


改行はコメント内にありますか?コメント内の他の文字とは異なる扱いになるのはなぜですか?

1
@Snowmanにはその視点がありますが、一方でトークン 'x'が行の最初のトークンであり、ソースを見ている人とパーサーは行ごとに読み取ります。ジレンマのようですので、質問をしました。
そり

4
しばらく前にこれを仕様どおりに行う必要があり、gccのドキュメントが優れたリソースであることがわかりました。あなたが考慮していないかもしれないいくつかの奇妙なコーナーケースがあります。
カールビーレフェルト

回答:


40

通常、コメントはトークン化プロセスの一部としてスキャンされます(そして破棄されます)が、解析前です。コメントは、周囲に空白がない場合でもトークンセパレータのように機能します。

ご指摘のとおり、C仕様では、コメントは単一のスペースに置き換えられることが明示的に規定されています。ただし、実際のパーサーは実際には何も置き換えず、空白文字をスキャンして破棄するのと同じ方法でコメントをスキャンして破棄するため、仕様の専門用語です。しかし、コメントがトークンをスペースと同じように分離することを簡単な方法で説明します。

コメントの内容は無視されるため、複数行コメント内の改行は効果がありません。改行に敏感な言語(PythonおよびVisual Basic)には通常、複数行のコメントはありませんが、JavaScriptは例外です。例えば:

return /*
       */ 17

と同等です

return 17

じゃない

return
17

単一行コメントは改行を保持します。つまり、

return // single line comment
    17

と同等です

return
17

じゃない

return 17

コメントはスキャンされますが、解析されないため、ネストされない傾向があります。そう

 /*  /* nested comment */ */

コメントは最初に開かれ、最初/*に閉じられるため、構文エラーです*/


3
ほとんどの言語では、インラインコメント(/* like this */)は単一の空白と見なされ、EOL終了コメント(// like this)は空白行と見なされます。
9000

@JacquesBですので、コメントをソースから全体がゼロ幅のスペースとして置き換えられるものとして扱うことを考えていますが、これはあなたが提案しているものと同等のようです。
そり

1
@artb通常のスペースは問題なく機能し、ASCIIコードページにあります。
ジョンドヴォルザーク

@JanDvorakスペースは、外観に影響を与え、理解を排除し、「コメントは実際には存在しない」というセマンティクスに近くなります。プライマリレンダリング出力はHTMLになるので、私の場合、ASCIIはブラウザがUnicodeをサポートするほど問題ではありません。そうは言っても、C標準では、コメントを1つのスペースに置き換えることが義務付けられていると思います。
そり

1
一部の言語、特にRacketには、複数行のコメントがネストされています:(define x #| this is #| a sub-comment |# the main comment |# 3) xyields 3
wchargin

9

質問に答えるには:

マークアップにより一般的に期待される一般的なコンセンサスはありますか?

トークン内に埋め込まれたコメントが正当であると期待する人はいないと思います。

一般的な経験則として、コメントは空白と同様に扱う必要があります。余分な空白を含むことが有効な場所には、コメントを埋め込むことも許可する必要があります。唯一の例外は文字列です。

trace("Hello /*world*/") // should print Hello /*world*/

文字列内のコメントをサポートするのは非常に奇妙で、それらをエスケープするのは面倒です!


2
文字列について考えたことがない、それは良いエッジケースです。私の現在の考えは、コメントの開始と終了の間に単純な正規表現を実行し、それを単一のスペースに置き換えることでした。それはあなたのケースをつまずいたでしょう。
そり

3
文字列をエスケープすることについてのそのビットのために+1。あなたの例ではHello /* world*/!、コメントの区切り文字を抑制するのではなく、一般に印刷することを期待しています。また、プログラマーへようこそ!
8ビットツリー

1
8bittreeに感謝します!そして、それが完全に私が意味したことです。Funnily十分な、私も....私の答えに**エスケープする必要がある
コナークラーク

2
@ArtBの一般的な「置換による解析」は、エッジケースや他の機能とのやり取りが非常に難しいため、最初から避けるのが最善です。
ホッブズ

7

空白を区別しない言語では、無視された文字(つまり、空白またはコメントの一部である文字)はトークンを区切ります。

たとえばSys tem、2つのトークンがありますSystemが、1つです。これの有用性は、あなたが比較しnew Foo()newFoo()そのうちの1つがFoo他の呼び出し中にのインスタンスを構築する場合により明確になるかもしれませんnewFoo

コメントは、空白の実行と同じ役割を果たします。たとえばnew/**/Foo()、と同じ働きをしnew Foo()ます。もちろん、これはもっと複雑になりますnew /**/ /**/ Foo()

技術的には、識別子内でコメントを許可することは可能ですが、特に実用的ではないと思います。

さて、空白に敏感な言語はどうでしょうか?

Pythonが思い浮かび、非常に単純な答えがあります:ブロックコメントはありません。でコメントを開始する#と、パーサーは、残りの行が存在せず、代わりに単なる改行であるかのように動作します。

それとは対照的に、jadeではブロックコメントが許可され、同じインデントレベルに戻るとブロックが終了します。例:

body
  //-
    As much text as you want
    can go here.
  p this is no longer part of the comment

ですから、この領域では、物事が通常どのように処理されるかと言うことはできません。共通点と思われるのは、コメントは常に行末で終わるということです。つまり、すべてのコメントは改行とまったく同じように機能します。


うーん、コメントにHTML \ XML構文を使用しているため、改行は複数行になるため、実際の問題です。
そり

3
@ArtB HTML / XML構文を使用している場合、単にその動作を使用するのが賢明かもしれません。
8ビットツリー

1
@ 8bittreeは理にかなっています。この方法はより便利なので、質問はそのままにします。
そり

3

過去に、字句解析の一部としてコメントを単一のトークンに変換しました。文字列についても同じことが言えます。そこから、人生は簡単です。

私が最後に構築したパーサーの特定のケースでは、エスケープルールがトップレベルの解析ルーチンに渡されます。エスケープルールは、コアグラマーとインラインのコメントトークンなどのトークンを処理するために使用されます。一般に、これらのトークンは破棄されました。

この方法で行うと、識別子の途中にコメントを付けて投稿した例では、識別子は単一の識別子ではありません。 。

文字列内のコメントのケースは、字句解析によって暗黙的に処理される必要があります。文字列を処理するルールはコメントに関心がないため、コメントは文字列の内容として扱われます。同じことがコメント内の文字列(または引用符で囲まれたリテラル)に適用されます-文字列はコメントの一部であり、これは明示的に単一のトークンです。コメントを処理するためのルールは、文字列には関心がありません。

それが理にかなって/助けになることを願っています。


ではconsole.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible")、コメントに引用符があり、文字列にコメント構文があるようなコードがある場合、レクサーはそれを正しくトークン化する方法をどのように知るでしょうか?それらのケースの一般的な説明を提供して、回答を編集してください。
chharvey

1

パーサーの目的によって異なります。コンパイル用の解析ツリーを構築するためにパーサーを作成する場合、コメントは潜在的にトークンを分離する以外にセマンティック値を持ちません(例:method / comment /(/ comment /))。この場合、スペースのように扱われます。

パーサーが、あるソース言語を別のソース言語に翻訳するトランスパイラーの一部である場合、またはパーサーがソース言語でコンパイル単位を取得し、それを解析、変更し、変更後のバージョンを同じソース言語で書き戻すプリプロセッサーである場合、コメント他のものと同様に非常に重要になります。

また、コメントにメタ情報があり、JavaDocのようにAPIドキュメントを生成するときのようにコメントを特に重視する場合、コメントは突然非常に重要です。

ここでは、多くの場合、コメントはトークン自体に添付されます。コメントが見つかった場合は、それをトークンのコメントとして添付します。トークンは、前後に複数のトークンを持つことができるため、これらのコメントの処理方法に再び依存します。

非コメントトークンにコメントを付けるという注釈の考え方は、文法からコメントを完全に削除することです。

解析ツリーを取得すると、ASTは独自のAST要素によって各トークンを表すコメントを展開し始めますが、通常の包含関係の横にある別のAST要素にアタッチされます。オープンソースIDEで利用可能なソース言語のすべてのパーサー/ AST実装を確認することをお勧めします。

非常に優れた実装の1つは、Java言語用のEclipseコンパイラインフラストラクチャです。私が覚えている限り、トークン化中にコメントを保持し、AST内のコメントを表します。また、このパーサー/ AST実装はフォーマットを保持します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.