2009-12-25 5 views
1

Je voudrais analyser du texte à l'aide d'un analyseur descendant manuscrit. J'ai utilisé Scanner avec le délimiteur suivant: "\\s*". Malheureusement, le fait que ce motif corresponde à une chaîne vide semble rendre chaque hasNextFoo et nextFoo ne correspondant plus à rien.Java Scanner avec délimiteur vide

La documentation ne dit rien sur les délimiteurs éventuellement vides.

Répondre

1

Vous avez une objection au caractère '+'? Etes-vous sûr de vouloir utiliser une expression régulière, et pas seulement une instruction if testant des caractères d'espace? Vous dites "runtime". Est-ce que vos données sont dans une chaîne, ou viennent sur un flux, ou quoi?

+0

mignon. Je crois que @bmargulies essaye de dire que le caractère + correspondra "au moins un", "au lieu de none ou plus". Ce qui l'empêchera de correspondre à une chaîne vide. – GrayWizardx

+0

Oui, parce que je veux utiliser le scanner comme une lexer d'exécution. En bref, je veux être en mesure de demander 'scanner.next (pattern) ', qui renvoie la chaîne correspondante ou renvoie une exception sans consommer le flux. Les espaces devraient être ignorés. S'il y a une meilleure classe pour faire cela que scanner, je serais heureux de l'utiliser. –

+0

Blague à part, la réponse de @ trashgod est probablement ce que veulent. Vous ne nous avez vraiment pas donné assez de contexte pour continuer ici. – bmargulies

1

Oui, car je souhaite utiliser le scanner en tant que lexeur d'exécution. En bref, je veux être capable de demander à scanner.next (pattern), soit de retourner la chaîne correspondante, soit de retourner une exception sans consommer le flux. Les espaces devraient être ignorés. S'il y a une meilleure classe pour faire cela que scanner, je serais heureux de l'utiliser.

Je ne peux pas penser à une classe de bibliothèque sur étagère qui le fera pour vous. Le modèle normal d'un scanner/lexeur est que toute séquence de caractères invalide (c'est-à-dire qui entraîne une exception) sera consommée. Donc, je pense que vous devrez implémenter votre propre scanner à la main, en prenant soin de ne pas consommer les caractères de lecture anticipée. Vous pouvez le faire avec un lecteur "pushback" ou (si ce modèle n'est pas pratique) en tamponnant explicitement les caractères vous-même avec une sorte de modèle mark/reset. Si tout ce que vous faites est de diviser en jetons séparés par un ou plusieurs espaces, alors l'approche du lecteur de refoulement devrait être bonne.

0

Il est possible d'utiliser lookbehinds/lookaheads pour définir explicitement quels délimiteurs sont omis.

Par exemple ce scanner utilise comme séparateur des espaces blancs, mais n'a pas besoin d'eux entre les chiffres et les mots:

new Scanner("1A.23 4 BC-5") 
.useDelimiter("\\s+|(?<=\\d)(?=[A-Z])|(?<=[A-Z])(?=[-+.\\d])"); 

Il produit:

1 
A 
.23 
4 
BC 
-5 

Le regex se compose de trois alternances:

  • \s+ Les espaces blancs consécutifs sont un délimiteur.
  • (?<=\d)(?=[A-Z]) Une chaîne vide entre un chiffre et une lettre est un délimiteur.
  • une chaîne vide entre une lettre et '-', '+', '.' ou un chiffre est un délimiteur.

(Note: \w ne peut être utilisé ici comme il correspond à des chiffres.)

Questions connexes