2011-01-25 80 views
3

我希望能夠解析如下的字符串:「123456abcd9876az45678」。該BNF是這樣的:沒有分隔符的掃描器

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

然而,類java.util.Scanner中不允許我做到以下幾點:

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()); 
} 

理想情況下,應該產生:

-123456 
abcd 
987 
az 
45678 

我真的希望java.util.Scanner能幫助我,但看起來我必須創建自己的掃描器。 Java API中是否有任何東西可以幫助我?


這個問題想念太多的信息。因此,所有的答案都是有效的問題,但不是我的問題。

+0

我不知道這是什麼代碼是應該做的,但我想你應該有[AZ],而不是* [AZ] – 2011-01-25 21:17:09

+0

好吧,完整常見的情況是下面的「4D8 - 1D4 + 20」被解析爲兩個骰子+常量。可能會有更多的骰子滾動,可能沒有,可能有空格或沒有空格。底線是我想在沒有任何分隔符的情況下即時更換標記。我也不想被重定向到SO裏的通常的Dice符號線程,因爲它不能幫助我使用所有這些eval函數。我想建立骰子表達式的樹。 – 2011-01-25 21:44:36

回答

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)); 
} 
1

您可以使用PatternMatcher類來實現此目的。請參閱this示例。

+0

不正則正則表達式不會這樣做。在這個問題下看到我的評論。 – 2011-01-25 21:45:11

1

要使用掃描儀作爲標記生成器,使用與findWithinHorizon\G只有組開始(=當前位置)進行掃描。

實例支持空格(如在意見中的要求):

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");