5

別のトークンと誤って一致させることなく、JavaCC を使用して文字列を解析する良い方法を考えようとしています。これらの文字列には、スペース、文字、数字を含めることができます。

私の識別子と番号トークンは次のとおりです。

<IDENTIFIER: (["a"-"z", "A"-"Z"])+>
<NUMBER: (["0"-"9"])+>

私の現在の文字列トークンは次のとおりです。

<STRING: "\"" (<IDENTIFIER> | <NUMBERS> | " ")+ "\"">

理想的には、引用符の中にあるものだけを保存したいと思います。変数と値を実際に保存する別のファイルがあります。そこの引用符を削除する必要がありますか?

私はもともとパーサーファイルに次のようなメソッドを持っていました:

variable=<INDENTIFIER> <ASSIGN> <QUOTE> message=<IDENTIFIER> <QUOTE>
{File.saveVariable(variable.image, message.image);}

しかし、ご想像のとおり、これにはスペースや数字を使用できませんでした。変数名などの識別子については、文字のみを許可したいと考えています。

そのため、文字列リテラルをキャプチャする方法についてアドバイスをお願いしたいと思います。特に、次のような文字列を作成したいと思います。

" hello", "hello ", " hello " and "\nhello", "hello\n", "\nhello\n"

私の構文で有効です。

4

1 に答える 1

11

最初のパーサーを渡すと、"パーサーは STRING STATE に入り、次の (ボーナス: 引用なし) にそれを残します"

お気に入り:

TOKEN:
{
  <QUOTE:"\""> : STRING_STATE
}

<STRING_STATE> MORE:
{
  "\\" : ESC_STATE
}

<STRING_STATE> TOKEN:
{
  <ENDQUOTE:<QUOTE>> : DEFAULT
| <CHAR:~["\"","\\"]>
}

<ESC_STATE> TOKEN:
{
  <CNTRL_ESC:["\"","\\","/","b","f","n","r","t"]> : STRING_STATE
}

これは次のように使用できます。

/**
 * Match a quoted string.
 */
String string() :
{
  StringBuilder builder = new StringBuilder();
}
{
  <QUOTE> ( getChar(builder) )* <ENDQUOTE>
  {
    return builder.toString();
  }
}

/**
 * Match char inside quoted string.
 */
void getChar(StringBuilder builder):
{
  Token t;
}
{
  ( t = <CHAR> | t = <CNTRL_ESC> )
  {
    if (t.image.length() < 2)
    {
      // CHAR
      builder.append(t.image.charAt(0));
    }
    else if (t.image.length() < 6)
    {
      // ESC
      char c = t.image.charAt(1);
      switch (c)
      {
        case 'b': builder.append((char) 8); break;
        case 'f': builder.append((char) 12); break;
        case 'n': builder.append((char) 10); break;
        case 'r': builder.append((char) 13); break;
        case 't': builder.append((char) 9); break;
        default: builder.append(c);
      }
    }
  }
}

HTH。

于 2012-08-17T18:35:15.997 に答える