単純なバージョンは、元の文法の各ルールを変更します。
LHS = RHS1 RHS2 ... RHSN ;
することが:
LHS = RHS1 COMMENTS RHS2 COMMENTS ... COMMENTS RHSN ;
これは抽象的には機能しますが、LL または LALR ベースの場合、パーサー ジェネレーターが台無しになる可能性があります。そのため、GLR などのより強力なパーサー ジェネレーターに切り替える必要があります。
よりスマートなバージョンは、すべての終端T を非終端記号に (and のみ) 置き換えます。
T = COMMENTS t ;
T の代わりに t を自明に発行するように元の字句解析器を変更します。まだ先読みの問題があります。
しかし、これは本当の解決策の基礎を与えてくれます。
これのより洗練されたバージョンは、レクサーがトークンの前に表示されたコメントを収集し、それが発行する次のトークンにそれらを添付することです。本質的には、文法の最終規則の変更をレクサーで実装しています。
これで、パーサー (テクノロジを切り替える必要はありません) は、最初に見たトークンだけを見るようになりました。トークンはコメントを注釈として保持します。コメントを前のトークンに添付するコメントと次のトークンに添付するコメントに分けると便利ですが、決定する実際的な方法がないため、これをヒューリスティックよりも優れたものにすることはできません。コメントが実際に属しているトークン。
トークンとコメントの位置情報を取得して、元のテキスト (「コメントを適切な場所に配置」) を再生成できるようにする方法を理解するのは楽しいことです。言語の構文規則に違反しない方法で、適切な基数値、文字列エスケープなどを使用して実際にテキストを再生成すると、より楽しくなります。
これは、一般的な言語処理ツールを使用して行いますが、かなりうまく機能します。変換タスクに集中できるように、すべてをまっすぐにするのは驚くべきことです。人々はこれを過小評価しています。