0

"{" は 1 行に 1 つである必要があります。したがって、それを認識するトークンを使用する必要があります。これは正しい例です:

program
{

また

program



{

そして、これは間違った例です:

program { 

また

program 
{ sentence;

次に、次のようなトークンがあります。

TOKEN: { < openKey: "{" >   {System.out.print(image +"\n");}}
SKIP: { < ( " " | "\r" | "\t" | "\n" )+ > }

しかし、記号「{」を1つ以上の「\n」の間に正確に入れる方法が思いつきません。そして、それを認識した後、正確に書く必要があります:

program
{

私が試してみると:

TOKEN: { < openKey: ( " " | "\r" | "\t" | "\n" )+ "{" ( " " | "\r" | "\t" | "\n" )+ >   {System.out.print(image +"\n");}}

これは実行されますが、入力にあったように非常に多くの「\n」が書き込まれます。

4

2 に答える 2

0

基本的な問題は、入力を解釈せずに出力していることです。言い換えれば、あなたが発見したように、入るものは出てくるものです.

読みやすくするために --- そして、何らかの点で語彙アナライザーにタスク全体を強制的に実行させて誤用しないようにするために --- print ステートメントをパーサーに移動することをお勧めします (たとえば、Start( ) 関数)。(実際には、再利用するつもりのない非常に小さなことをしていない限り、すべての出力をパーサーから完全に移動する傾向がありますが、それは別の質問です。)

次に、実際の問題に対処するために、一連の改行を 1 つの改行にするための解釈を行いました。これを行う最も簡単な方法は、基本的な replaceAll です。これが私の Start() 関数です。openKey は先ほどと同じように定義されており、WORD は単なる文字の連結です。

void Start() : 
{
  Token t;
}
{
    ( 
      t = <WORD>
      {System.out.print((t.image).replaceAll("(\n)+","\n"));}
    )*
    (
            t = <openKey>
            {System.out.print((t.image).replaceAll("(\n)+","\n"));}
            ( 
              t = <WORD>
              {System.out.print((t.image).replaceAll("(\n)+","\n"));}
            )*
    )*
    <EOF>

}

したがって、基本的に、これは 0 個以上の単語を取り、その後に 1 個以上の改行、左中括弧、1 個以上の改行、0 個以上の単語で構成されるユニットが続き、単語、中括弧、 1つ以上の改行セットごとに1つの改行のみ。

単語を要求する代わりに中括弧でファイルを開始できる場合、空の行、中括弧、および改行が出力されます。それがあなたが望むものかどうかはわかりませんが、空の行で出力を開始できるので、出力コードをいじって、目的の正確なフォーマットを取得する必要があります。さらに、ご覧のとおり関数に抽出できる非常に優れた繰り返しコードがいくつかあるので、それは読者の演習に残しておきます。

とにかく、この答えの基本的な前提は---そして、これは本当に時代の格言であり、コーディングだけでなく、人生のあらゆる分野での使用に適していると信じています---「出力する前に取り込むものを変更しない限りそれは、まさにあなたが取り入れたものになるでしょう!」

于 2012-07-04T09:37:46.783 に答える
0

私はそれを別の方法で行いました:

TOKEN: { < openKey: "\n" (" " | "\t")* "{" (" " | "\t")* ("\r" | "\n") >{System.out.print("{\r\n");}}   
SKIP: { " " | "\r" | "\t" | "\n" }

キャリッジ リターンに問題がありましたが、この方法でうまくいきます。

于 2012-07-24T14:19:42.240 に答える