2010-05-02 4 views
0

Désolé je ne pouvais pas penser à un meilleur titre, mais merci pour la lecture!Besoin de quelques idées sur la façon d'accomplir cela en Java (chaînes d'analyse)

Mon but ultime est de lire un fichier .java, de l'analyser et d'extraire tous les identifiants. Puis stockez-les tous dans une liste. Deux conditions préalables sont qu'il n'y a aucun commentaire dans le fichier, et tous les identifiants sont composés de lettres seulement.

En ce moment je peux lire le fichier, l'analyser par espaces, et tout stocker dans une liste. Si quelque chose dans la liste est un mot réservé java, il est supprimé. En outre, je supprime tous les symboles détachés qui ne sont attachés à rien (parenthèses et symboles arithmétiques).

Maintenant, je suis parti avec un tas de chaînes étranges, mais au moins, ils n'ont pas d'espaces en eux. Je sais que je vais devoir tout re-analyser avec un. delimiter afin de retirer des identifiants comme System.out.print, mais que sur les chaînes comme cet exemple:.

Logger.getLogger (MyHash.class.getName()) log (Level.SEVERE,

Après . re-analyse syntaxique par je serai parti avec plus de cordes folles comme:

getLogger (MyHash

getName())

log (niveau

SEVERE,

Comment vais-je pouvoir extraire tous les identifiants tout en omettant tous les déchets? Juste continuer à ré-analyser chaque symbole qui pourrait exister dans le code java? Cela semble plutôt boiteux et prend du temps. Je ne suis même pas sûr que cela fonctionnerait complètement. Alors, pouvez-vous suggérer une meilleure façon de faire cela?

+0

Qu'est-ce qu'un identifiant? Je vois votre note qu'ils sont composés de lettres seulement, et que les mots réservés de Java ne sont pas des identifiants, mais: Est-ce que toutes les autres séquences d'identificateurs de lettres sont? Si oui, pourquoi ne faites-vous pas simplement un String.split() en utilisant une regex qui se sépare par une non-lettre, et en mettant les résultats dans un ensemble? – CPerkins

Répondre

3

Il y a plusieurs solutions que vous pouvez utiliser, autres que le piratage analyseur soi-même:

  • Utilisez un analyseur existant, comme this one. Utilisez BCEL pour lire le bytecode, qui inclut tous les champs et variables.
  • Hack dans le compilateur ou l'exécution, en utilisant annotation processing ou mirrors - Je ne suis pas sûr que vous pouvez trouver tous les identificateurs de cette façon, mais les champs et les paramètres pour vous.
+0

Je pense que vous pouvez également utiliser, http://asm.ow2.org qui vient également avec un plugin eclipse. – phoenix24

0

Wow, ok. L'analyse est difficile - vraiment difficile - à faire correctement. Rouler votre propre analyseur Java va être incroyablement difficile à faire correctement. Vous constaterez qu'il y a beaucoup de cas de bord pour lesquels vous n'êtes pas préparé. Pour vraiment le faire correctement, et gérer tous les cas de bord, vous devrez écrire un analyseur réel.Un analyseur réel est composé d'un certain nombre de choses:

  1. Un analyseur lexical pour briser l'entrée en morceaux logiques
  2. Une grammaire pour déterminer comment interpréter les morceaux ci-dessus
  3. Le « analyseur » réelle qui est généré à partir de la grammaire à l'aide d'un outil comme ANTLR
  4. une table de symboles pour stocker des identifiants dans
  5. un arbre de syntaxe abstraite pour représenter le code que vous avez analysé

Une fois que vous avez tout cela, vous pouvez avoir un vrai parseur. Bien sûr, vous pouvez passer l'arbre de la syntaxe abstraite, mais vous avez besoin de pratiquement tout le reste. Cela vous laisse avec l'écriture d'environ 1/3 d'un compilateur. Si vous voulez vraiment terminer ce projet vous-même, vous devriez voir si vous pouvez trouver un exemple pour ANTLR qui contient une définition grammaticale java préexistante. Cela vous permettra d'avoir le plus de chemin possible, et vous devrez ensuite utiliser ANTLR pour remplir votre table de symboles.

Alternativement, vous pourriez aller avec les solutions astucieuses suggérées par Little Bobby Tables (nom génial, bww Bobby).

+0

"Wow, ok, l'analyse est difficile - vraiment difficile - à faire correctement" - Alors vous n'avez-vous pas offert "Compilers 302" à votre université? :-) –

+0

En termes de compilation, ce qu'il veut appartient en fait à la phase de lexing, pas à l'analyse. Et lexing n'est pas si difficile. – Oak

+0

Je suppose que vous avez raison.Dans un vrai compilateur, ce serait l'analyseur qui mettrait les choses dans la table des symboles, mais dans ce cas vous pouvez trouver des identifiants dans le lexeur, et c'est assez bon. – Benson

1

Je ne voudrais pas séparer le fichier entier en une fois en fonction des espaces. Au lieu de cela, je voudrais numériser le fichier lettre par lettre, en sauvegardant chaque caractère dans un tampon jusqu'à ce que je suis sûr qu'un identifiant a été atteint.

En pseudo-code:

clean buffer 
for each letter l in file: 
    if l is ' 
     toggle "character mode" 
    if l is " 
     toggle "string mode" 
    if l is a letter AND "character mode" is off AND "string mode" is off 
     add l to end of buffer 
    else 
     if buffer is NOT a keyword or a literal 
      add buffer to list of identifiers 
     clean buffer 

avis quelques lignes se cachent ici complexité encore - par exemple, pour vérifier si le tampon est un littéral, vous devez vérifier pour les deux vrai, faux, et nul. De plus, il y a plus de bogues dans le pseudo-code - il trouvera aussi des choses comme les parties e et L des littéraux (e dans les littéraux à virgule flottante, L dans les littéraux longs). Je suggère d'ajouter des «modes» supplémentaires pour prendre soin d'eux, mais c'est un peu délicat.

Il y a aussi quelques autres choses à faire si vous voulez vous assurer que c'est exact - par exemple, vous devez vous assurer de travailler avec unicode. Je recommande fortement d'enquêter sur le lexical structure de la langue, de sorte que vous ne manquerez de rien.

EDIT:

  • Cette solution peut facilement être étendue à traiter avec des identificateurs avec des numéros, ainsi que des commentaires.
  • Petit bug ci-dessus - vous devez gérer \ "différemment de", même avec \ 'et'.
Questions connexes