Analyseur syntaxique en Java

Résolu
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 - 14 mars 2012 à 11:26
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 - 15 mars 2012 à 09:46
Salut,

Je cherche un code en JAVA qui me permet d'analyser une chaîne de caractère et indiquer s'il existe une erreur syntaxique Exemple : (a*b) "la chaîne à analyser" mon programme doit lever une exception si une erreur est détectée par exemple si je saisie "(a*b" il doit mentionner qu'une parenthèse manquante avec précision de l'endroit de l'erreur.

Donc mon programme doit fournir le même traitement que celui de la classe "PatternSyntaxeException" du paquatge Regex .

j'espère avoir des réponses le plus tôt possible.

Merci d'avance pour votre aide .

26 réponses

cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 12:06
Je te conseil de regarder cette source qui doit a peu près correspondre à ce que tu cherches à faire : http://www.javafr.com/codes/VERIFIER-TEXTE-JTEXTFIELD-AVEC-REGEX_54130.aspx

Les regex s'utilisent simplement en java. La difficulté sera peut être pour toi d'écrire l'expression régulière de contrôle (je ne sais pas si tu as de bonnes connaissances des regex). Si tu as un soucis sur ce sujet, je peux t'aider.
3
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 2
14 mars 2012 à 12:24
Merci Julien39 pour ta réponse :) mon programme doit principalement indiquer l'erreur exemple( "{" qui manque ou bien '(' qui n'est pas fermée ... et il doit mentionner l'emplacement de cette erreur..) et donc il doit pas analyser seulement la chaîne de caractère et dire si elle est valide ou pas (False/true) mais plutôt déterminer exactement les erreurs.
3
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 12:03
Bonjour,

je vais commencer par déplacer ton sujet vers le forum java (bien qu'il utilise également des regex).
1
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 20:03
Alors, dans ce cas là, ce n'est pas si complexe que ca : tu peux utiliser la récursivité habilement.

//Dans le cas ou il n'y a que deux parenthèses
public boolean testSimple(String invocation){
   return invocation.matches("[A-Za-z0-9]+\\.[A-Za-z0-9]+\\([A-Za-z0-9 ]*\\)");
}

//Ensuite, ca se complique, si il y a plusieurs méthodes appelées par exemple : m.afficher(f.calculer());

public boolean testCompose(String invocation){
   boolean res;
   //Si il y a plusieurs parentheses
   if(invocation.matches("[^\\(]*\\([^\\(]*\\("){
      res=testCompose(recupererSousGroupe(invocation)) && testSimple(supprimerSousGroupe(invocation));
   }
   else {
      res=testSimple(invocation);
   }
   return res;
}

public String recupererSousGroupe(String ligne){
    String res="";
    String patternStr = "[^\\(]*\\([^\\(]*\\((.*).*";
    Pattern pattern = Pattern.compile(patternStr);
    Matcher matcher = pattern.matcher(ligne);
    boolean matchFound = matcher.find();
    if (matchFound && matcher.groupCount()>=1) {
        res = matcher.group(1);
    }
    return res;
}
1

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 2
14 mars 2012 à 20:39
j'ai ces deux classe "Lexicale" et "Syntaxique"

package analyseur;
import java.util.List;
public class Lexicale {
    public String chaine="(a+b)";
    private int pos=0;
    public Lexicale(String chaine){this.chaine=chaine;}
    public boolean haveLexeme()
    {return(chaine.length()>pos);}

    public String getNextLexeme(){
    ignoreSpaceTabulationRetourLigne();
    while (haveLexeme())
    {
        switch(chaine.charAt(pos)){
        case '+':pos++; return("+");
        case '-':pos++; return("-");
        case '*':pos++; return("*");
        case '/':pos++; return("/");
        case '^':pos++; return("^");
        case '(':pos++; return("(");
        case ')':pos++; return(")");
        
        case'0': case'1': case'2': case'3':
        case'4':case'5':case'6':case'7':case'8':case'9':

         pos++; 

       while (haveLexeme()&& chaine.charAt(pos)<='9'&& chaine.charAt(pos)>='0')
       pos++;

       return("nb");
      
            case'a': case'b': case'c': case'd': case'e': case'f': case'g':
            case'h': case'i': case'j': case'k': case'l': case'm': case'n':
            case'o': case'p': case'q': case'r': case's': case't': case'u':
            case'v': case'w': case'x': case'y': case'z': case'A': case'B':
            case'C': case'D': case'E': case'F': case'G': case'H': case'I': case'J':
            case'K': case'L':case'M': case'N': case'O': case'P': case'Q': case'R':
            case'S':case'T': case'U': case'V': case'W': case'X': case'Y': case'Z': 
       {pos++;}
    while (haveLexeme()&& (chaine.charAt(pos)<='9')&&
     chaine.charAt(pos)>='0'||chaine.charAt(pos)>='a'&&
     chaine.charAt(pos)<='z'||chaine.charAt(pos)>='A'&& chaine.charAt(pos)<='Z')
    {pos++;} 
    return("id");

    case'\n':
    case'\t':
    case' ':
         ignoreSpaceTabulationRetourLigne();

         default: pos++;
         return (chaine.charAt(pos-1)+"n'est pas élément du langage");
    }
    }

    return ("EOF");
    }

    private void ignoreSpaceTabulationRetourLigne(){
    if (haveLexeme()&& ((chaine.charAt(pos))=='\n')||((chaine.charAt(pos))=='\t')||(chaine.charAt(pos))==' ')
    {pos++;
    while (haveLexeme()&& ((chaine.charAt(pos))=='\n')||
    ((chaine.charAt(pos))=='\t')||(chaine.charAt(pos))==' ') {pos++;}
    }
    }

    public int getPos(){return pos;}
    public void setPos(int pos){this.pos=pos;}


public void synchro(List <String>l)
{String lex="";
 if (haveLexeme())
     lex= getNextLexeme();
  while (haveLexeme()&& (!l.contains(lex)))
  {lex= getNextLexeme();}
 if (l.contains(lex))
 {int gh=getPos()-1;
 setPos(gh);
 }
}


  
}
1
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 2
14 mars 2012 à 20:42
Et voilà la classe Syntaxe

package analyseur;
import java.*;
import java.util.List;
import analyseur.Lexicale.*;



public class Syntaxe {
   
    private static String symbole;
    static List<String> L;
  static String chaine = null;
      static Lexicale x = new Lexicale(chaine);


      public grammaire (String chaine ){
          this.chaine= chaine;

      }
   static void E()
    {
    T();
    R1();
    }

 static void T()
   {
   F();
   R2();
   }

   static void R1()
   {   //int i=0; while (i< chaine.length())
       //symbole = chaine.charAt(0);
      if (symbole== "+")
    { accepter ("+");
      T();
      R1();
    }else if( symbole=="-"){
       accepter ("-");
      T();
      R1();}else
      {erreur(1);} // on ne met pas else erreur car on a epsilon
   }

   static void R2()
   { 
      if (symbole=="*")
    { accepter ("*");
      T();
      R1();
    }else if( symbole=="/"){
       accepter ("/");
      T();
      R1();}else{erreur(2);} // on ne met pas else erreur car on a epsilon
   }
   
  static void F()
   {
    H();
    R3();

   }
  
  static void R3()
   { if (symbole =="^")
     {accepter("^");
     F();}
     else
     {erreur(3);}
   }

    static void H(){
    if(symbole =="(")
    {
    accepter("(");
    E();
    }
    else if (symbole =="id")
    { 
       accepter ("id");
      }else{erreur(4);}
    }

   private static  void accepter(String cc) {

     if (symbole cc){symbole x.getNextLexeme();}
     
    }
public static void m(String xx){
  symbole = x.getNextLexeme();
  E();
  if (symbole=="§")
{ System.out.println("Succès");}
 else
{System.out.println("Echec");
}
}



    private static void erreur(int n){
        switch (n){
            case 1:{System.out.println("le symbole + ou - est manquant");
            L.add("§");
            L.add("(");
            L.add(")");
            L.add("id"); 
            L.add("nb");
            
            x.synchro(L);
            List L1 = null;// L1 contient les premiers de R1
           //List L2 = null;// contient les suivants de R1
            L1.add('+');
            L1.add('-');

           // L2.add(')');
            //L2.add('§');

            if (L1.contains(symbole))  {T();}
           /* else if
                    (L2.contains(symbole)){}*/
            }
            case 2:{System.out.println("le symbole * ou / est manquant");
            L.add("*");
            L.add("/");
            L.add("+");
            L.add("-");
            L.add("§");
            L.add(")");
            x.synchro(L);
            List L3 = null;
            L3.add("*");
             L3.add("/");//
            if ( L3.contains(symbole)){F();}}

            case 3:{System.out.println("le symbole ^ est manquant");  
            L.add("*");
            L.add("/");
            L.add("+");
            L.add("-");
            L.add("§");
            L.add( ")");
            L.add("^");
            x.synchro(L);
            List L4 = null;
            L4.add("^");
            if ( L4.contains(symbole)){F();}}

            case 4:{System.out.println("un id est manquant");}
            L.add("*");
            L.add("/");
            L.add("+");
            L.add("-");
            L.add("§");
            L.add(" )");L.add("(");L.add("^");
            L.add("nb");L.add("id");
            x.synchro(L);
            
            if (symbole == "("){ E();}
           
    
       }

   
    }
}

1
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 13:33
Alors le problème n'est pas uniquement lié à l'utilisation d'une expression régulière. Je n'ai pas vraiment d'idée très claire sur la façon de procéder.

Je pense qu'à ta place, je découperais la chaine pour l'analyser avec l'expression régulières suivante : [^\(].*(\([^\(]\)).* et j'essayerais d'analyser le contenu des parentèles de facon récursive jusqu'à ce que le capturing group ne contienne plus le sympbole ( ni )

Je pense que tu as un gros travail à effectuer pour créer l'algorithme qui va te permettre d'effectuer le contrôle. Les expression régulières ne résoudront pas tout mais pourront t'aider, c'est certain.
0
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 2
14 mars 2012 à 14:35
justement j'arrive pas à créer l'algorithme qui me permettra d'effectuer ce contrôle
si tu peux m'aider à trouver l'algorithme de la classe "PatternSyntaxeException" je te serais vraiment reconnaissante

Car cette classe est responsable de lever une exception si la syntaxe de l'expression n'est pas valide donc sûrement elle fait des analyses pour déterminer l'emplacement de l'erreur et sa nature,et pour cela j'ai besoin de connaitre comment la "PatternSyntaxeException" réalise son traitement car je pense que ça va m'aider .

merci infiniment
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 14:56
Désolé de te décevoir mais le code de la classe PatternSyntaxException est celui-ci :


public class PatternSyntaxeException extends Exception {

/**
 * 
 */
public PatternSyntaxeException() {
super();
// TODO Auto-generated constructor stub
}

/**
 * @param message
 * @param cause
 */
public PatternSyntaxeException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}

/**
 * @param message
 */
public PatternSyntaxeException(String message) {
super(message);
// TODO Auto-generated constructor stub
}

/**
 * @param cause
 */
public PatternSyntaxeException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}



}



Toutes les exceptions fonctionnent de la même façon : on considère que les données sont correctes et on fait le traitement : s'il y a une erreur, l'exception est levée. Il n'y a pas de contrôle d'effectué.
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 14:59
Mais bon, ce n'est pas si complexe que ca : pour vérifier que les parenthèses sont équilibrées par exemple :

String chaine="(3+2)*(4+5";
int nb=0;
for(int i=0; i<chaine.length; i++){
if(chaine.charAt(i)=="(".charAt(0)){
nb++;
}
else if(chaine.charAt(i)==")".charAt(0)){
nb--;
}
}
if(nb!=0){
System.out.println("Syntaxe incorrecte");
}
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 15:01
Mais par contre, on ne peut pas vraiment savoir d'où vient l'erreur sur cet exemple précis.

La chaine correcte peut être soit "(3+2)*(4)+5" soit "(3+2)*(4+5)" comment trancher ?

et pour les autres contrôles, ca doit se faire aussi...
0
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 2
14 mars 2012 à 15:25
Merci bien mais ce que je voulais savoir comment cette classe peut déterminer que l'expression n'est pas correcte par exemple elle produit une exception car une parenthèse ouvrante est présente sans la parenthèse fermante ...

Exemple :
Exception in thread "main" java.util.regex.PatternSyntaxException: Unmatched closing ')' near index 31 ^([01]?\d\d?|2[0-4]\d|25[0-5])\.)([01]?\d\d?|2[0-4]\d|25[0-5]\).([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$

Donc moi je veux réaliser un programme qui permet de détecter et mentionner les erreurs d'une expression.
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 15:58
C'est au moment de la compilation de d'expression régulière : le code analyse la chaine caractère par caractère : si le caractère i est une parenthèse alors il va chercher la parenthèse fermante de même niveau, en java, ca donnerait :

for(int i=0; i<regex.length; i++){
if(regex.charAt(i)=="(".charAt(0)){
determinerSousExpression(regex, i);
}
}

public void determinerSousExpression(String regex, int pos){
int niveau=0;
boolean match=false;
for(int i=pos; i<regex.length; i++){
if(regex.charAt(i)=="(".charAt(0)){
niveau++;
}
if(regex.charAt(i)==")".charAt(0)){
if(niveau==0){
System.out.prinln(regex.substring(pos, pos+i));
match=true;
}
niveau--;
}
}
if(!match){
// Et là, il font une petite mise en forme sur la sortie pour te montrer ton erreur
throw new PatternSyntaxException("Erreur en position "+pos);
}

}


Mais il n'y a pas d'analyse de la chaine à proprement parler, juste une compilation. Remarque, tu peux compiler le motif correspondant à ta chaine et récupérer l'exception si elle est levée et le tour est joué non ?
0
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 2
14 mars 2012 à 16:16
Vraiment merci pour ton aide mais j ai pas bien saisi ta dernière question ?
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 16:19
Non, à la réflexion, c'est une mauvaise idée, les utilisations détournées, c'est toujours un peu foireux.

Mais tu devrais pouvoir utiliser un mécanisme similaire pour vérifier ton expression : à quoi correspond ton expression et qu'en fais tu ? Quelles vérifications fait tu dessus ?
0
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 2
14 mars 2012 à 16:43
ah ok merci pour l'explication

Bon réellement je dois réaliser une application qui permet d'analyser une expression(syntaxiquement et sémantiquement) et indiquer les erreurs comme j'ai mentionné en haut ,ces expressions sont de type d'invocation de méthodes par exemple "m.afficher();" cette application sera réalisée dans le cadre de mon projet de fin d'études .

Mais vu que je suis un peu perdue j'ai voulu commencer par un petit exemple qui me permet de comprendre le mécanisme c'est pour cela que j'ai demandé de l'aide

je te remercie encore une fois pour ton aide
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 20:03
Reste à coder supprimerSousGroupe mais je n'ai pas eu le courage... Si tu as compris le reste, tu devrais t'en sortir.
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 20:05
Ha oui : je n'ai rien testé, j'ai tout écris directement dans la fenêtre du forum, il y a peut être une ou deux erreurs.

Si c'est vraiment trop moche, dis le moi et j'ouvrirai éclipse.

Je pense qu'il y a encore du travail à effectuer, là, tu ne peux pas détecter les structures du genre m.methodeA().methodeB(); mais tu peux déjà en faire pas mal.
0
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 371
14 mars 2012 à 20:06
Il y a quelques jours, j'ai déposé un tuto sur les expression régulières, ca peut te servir : http://www.javafr.com/tutoriaux/UTILISATION-EXPRESSIONS-REGULIERES_1286.aspx
0
VerInfo Messages postés 20 Date d'inscription mercredi 14 mars 2012 Statut Membre Dernière intervention 3 juillet 2012 2
14 mars 2012 à 20:32
je te remercie pour l'effort que t'as fournis

Mais je pense que ce programme ne permet pas de mentionner les erreurs, il indique seulement si l'expression valide ou non .
je pense que pour vérifier l'équilibrage des parenthèses je dois utiliser la pile ,et pour indiquer la position de l'erreur j'utilise la récursivité

Mais le problème c'est que j'arrive pas à combinais les deux et j'arrive pas à m'en sortir
0
Rejoignez-nous