2011-01-25 4 views
3

"123456abcd9876az45678"のような文字列を解析できるようにしたいと考えています。 BNFはこのようなものです:、これは得られるはず理想的デリミタなしのスキャナ

Scanner s = new Scanner("-123456abcd9876az45678"); 
System.out.println(s.nextInt()); 
while (s.hasNext("[a-z]+")) { 
    System.out.println(s.next("[a-z]+")); 
    System.out.println(s.nextInt()); 
} 

number: ? definition of an int ? 
word: letter { , letter } 
expression: number { , word , number } 

しかしクラスjava.util.scannerは私が次の操作を行うことはできません

-123456 
abcd 
987 
az 
45678 

私は本当にjava.util.Scannerが私を助けてくれることを望んでいましたが、自分のスキャナを作成する必要があるように見えます。 Java APIに既に存在するものはありますか?


質問が多すぎます。したがって、すべての回答は質問には有効ですが、私の問題には有効ではありません。

+0

私はこのコードが行うことになっているのか分からないが、私はあなたが[AZ] *の代わりに持っている必要があります想像[AZ]は –

+0

大丈夫、完全な一般的なケースは以下の通りです「4D8 - 1D4 + 20」 2つのダイスロール+定数として解析されます。より多くのサイコロがあるかもしれませんが、スペースがないかもしれません。要するに、デリミタなしでオンザフライでトークンを変更したいのです。私はまた、すべてのこれらの評価関数を使用して私を助けていないので、通常のダイス表記スレッドにリダイレクトされることは望ましくありません。私はサイコロの表現の木を作りたいと思っています。 –

答えて

3

残念ながら、ScannerクラスAFAIKではデリミタを使用できません。デリミタを無視する場合は、findInLine()またはfindWithinHorizon()などの方法を使用する必要があります。あなたの場合、findWithinHorizion()が適切でしょう。

Scanner s = new Scanner("-123456abcd9876az45678"); 
Pattern num = Pattern.compile("[+-]?\\d+"); 
Pattern letters = Pattern.compile("[A-Za-z]+"); 
System.out.println(s.findWithinHorizon(num, 0)); 
String str; 
while ((str = s.findWithinHorizon(letters, 0)) != null) { 
    System.out.println(str); 
    System.out.println(s.findWithinHorizon(num, 0)); 
} 
+0

いいアイデアですが、これで言語を構築することはできません。つまり、を検索するとの場合は、をスキップして番号を検索します。私はこれについて私自身のスキャナを作らなければならないと思う。 –

+0

@Frór:あなたの仕様に合っていることを除いて、あなたが私たちに与えた例とあまり変わりません。もちろん、あなたが必要としていないその他の細部は除いています。 –

+0

はい、私は他の要件があると思います。私は今、この全体の質問を削除し、問題の完全な概要を持つ新しい質問を再作成することを考えています。 –

1

PatternおよびMatcherクラスを使用してこれを達成できます。例:thisを参照してください。

+0

Nope regexはそれをしません。質問の下に私のコメントを参照してください。 –

+2

あなたのコメントは、パターン/マッチャーのイディオムが不十分な理由を私にはっきりさせません。 –

+0

申し訳ありませんが、完全であるために、私は、正規表現よりも優れた何か、より良いものが欲しいです。正規表現は、私の場合、私が期待する柔軟性を完全に過剰なものにしてしまいます。とにかくありがとうございました ! –

1

のみグループ開始(=現在の位置)からスキャンする\GfindWithinHorizonを使用し、トークナイザとしてスキャナを使用します。 (コメントで要求されるように)空白を支える

例:

Scanner scanner = new Scanner(input); 
while (true) { 
    String letters = scanner.findWithinHorizon("\\G\\s*\\[a-zA-Z]+", 0); 
    if (letters != null) { 
    System.out.println("letters: " + letters.trim()); 
    } else { 
    String number = scanner.findWithinHorizon("\\G\\s[+-]?[0-9]+", 0); 
    if (number != null) { 
     System.out.println("number: " + number.trim()); 
    } else if (scanner.findWithinHorizon("\\G\\s*\\Z", 0) != null) { 
     System.out.println("end"); 
     break; 
    } else { 
     System.out.println("unrecognized input"); 
     break; 
    } 
    } 
} 

実際のアプリケーションでは、おそらく先行パターンをコンパイルする必要があります。

-1

区切り文字は、任意のものと一致できないパターンに設定できます。

Scanner s = ... 
s.useDelimiter("(?!=a)a"); 
関連する問題