2014-07-25 5 views
0

Je suis en train de tokenizer entrée à un programme avec quelque chose comme ce qui suit:La meilleure façon de tokenize entrée

create table users schema {firstName: string, lastName: string, age:number, address: string} 
insert on users values {firstName: foo, lastName: bar, age:1, address: 32 foobar street} 

Je veux que les jetons à venir comme les suivantes:

Token 1: insert 
Token 2: on 
Token 3: users 
Token 4: values 
Token 5: {firstName: foo, lastName: bar, age:1, address: 32 foobar street} 

Il est une syntaxe de type SQL que j'essaie d'utiliser. Est-ce que regex est le meilleur moyen ou existe-t-il autre chose?

+0

Dès le départ pour moi, je suggère regex. Bien que je n'en connaisse qu'un peu en Java, il se peut qu'il y ait quelque chose de mieux. – user3003304

+0

Pourquoi le jeton 5 '{firstName: foo, lastName: bar, age: 1, adresse: 32 foobar street}'? Cela ne ressemblerait-il pas plus à 'Token 5: '{', Token 6: firstName, Token 7: ':', ...'? – Jashaszun

+0

Qu'est-il arrivé à la ligne 'create table'? Pourquoi n'est-il pas inclus dans les jetons? – Jashaszun

Répondre

0

Cette regex

^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\{.*\}).*$ 

vos œuvres pour deux entrées données, mais presque certainement échouer pour les entrées dont la syntaxe (non déclarées en question) est valable.

Si vous seriez prêt à accepter une légère modification de la syntaxe d'entrée, vous voudrez peut-être envisager d'utiliser JSON (et utiliser l'analyseur de java pour elle, jackson: https://github.com/FasterXML/jackson)

1

Je pense que la meilleure façon de gérer ce problème particulier utilise une regex dans une boucle.

Pattern pat = Pattern.compile("\\{.*?\\}|[^ \\{]+"); 
Matcher m = pat.matcher(source); 
while (m.find()) { 
    String token = m.group(0); 
    // add to an ArrayList or whatever 
} 

Le modèle cherche soit:

  • accolade gauche, suivi de quoi que ce soit, suivi d'une accolade droite. (Une barre oblique inverse doit être inséré avant les accolades car sinon ils ont une signification particulière. .*? signifie correspondance zéro ou plusieurs caractères, avec le sens ? aussi peu que possible dans le cas où il existe plusieurs } dans l'entrée.

  • Toute séquence de caractères qui n'est pas vide ou {

la boucle trouvera chaque jeton à son tour,.. m.group(0) retourne la chaîne qui a été adapté

l'utilisation d'un regex, il est difficile de revenir av nombre ariable de jetons. L'utilisation de split est souvent un bon moyen de diviser une chaîne en un nombre variable de jetons, mais ce cas est un peu trop compliqué pour déterminer le délimiteur correct. (Je suis sûr que c'est faisable mais rendrait votre code plus difficile à comprendre.)

J'ai testé cela sur les deux échantillons d'entrée que vous fournissez, et je pense qu'il fournit les résultats que vous voulez.

Questions connexes