Découpeur de chaîne (Parseur)

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Shadow
Messages : 1413
Inscription : mer. 04/nov./2015 17:39

Découpeur de chaîne (Parseur)

Message par Shadow »

Salut,

J'ai fait faire un code à L'IA pour pouvoir découper une chaine pour identifier les parties.
Ceci peut servir pour un traitement dans le parsing d'un code.
Dites moi se que vous en pensez.

Code : Tout sélectionner

; Module de parsing créér par ChatGPT le 14/12/2024.
DeclareModule Parseur
  Declare Init()
  Declare ParseAndIdentify(Code.s)
EndDeclareModule

Module Parseur
  Global RegexBloc.i

  Procedure Init()
    ; Liste des caractères autorisés pour former un mot :
    ; Lettres minuscules standard : a-z
    ; Lettres majuscules standard : A-Z
    ; Lettres accentuées et spéciales (minuscules) : àáâãäåæçèéêëìíîïðñòóôõöøùúûüµýÿþß
    ; Lettres accentuées et spéciales (majuscules) : ÀÁÂÃÄÅÆÇÐÈÉÊËÌÍÎÏÑÒÓÔÕÖØÞÙÚÛÜÝ
    ; On ajoute également l’underscore et les chiffres (0-9) pour autoriser des noms du type var2
    ;
    ; Le motif pour un mot devient donc :
    ; [ ... toutes les lettres, l'underscore ... ] [ ... lettres, chiffres, underscore ... ]*(\.[ ... ]+)*
    ;
    ; On conserve la logique de l'expression régulière précédente, mais on étend la classe de caractères.
    ;
    ; On n’oublie pas : Le reste (opérateurs, symboles, etc.) est capturé par [^a-zA-Z0-9_... \s]+
    ;
    Define RegexPattern.s
    RegexPattern = "[a-zA-Z0-9_àáâãäåæçèéêëìíîïðñòóôõöøùúûüµýÿþßÀÁÂÃÄÅÆÇÐÈÉÊËÌÍÎÏÑÒÓÔÕÖØÞÙÚÛÜÝŸ]" + 
                   "[a-zA-Z0-9_àáâãäåæçèéêëìíîïðñòóôõöøùúûüµýÿþßÀÁÂÃÄÅÆÇÐÈÉÊËÌÍÎÏÑÒÓÔÕÖØÞÙÚÛÜÝŸ0-9_]*" + 
                   "(\.[a-zA-Z0-9_àáâãäåæçèéêëìíîïðñòóôõöøùúûüµýÿþßÀÁÂÃÄÅÆÇÐÈÉÊËÌÍÎÏÑÒÓÔÕÖØÞÙÚÛÜÝŸ0-9_]+)*" +
                   "|[0-9]+(\.[0-9]+)*|=|[^a-zA-Z0-9_àáâãäåæçèéêëìíîïðñòóôõöøùúûüµýÿþßÀÁÂÃÄÅÆÇÐÈÉÊËÌÍÎÏÑÒÓÔÕÖØÞÙÚÛÜÝŸ\s]+"

    RegexBloc = CreateRegularExpression(#PB_Any, RegexPattern)
    If RegexBloc = 0
      Debug "Erreur lors de la création de l'expression régulière"
      End
    EndIf

    Debug "Parseur initialisé"
  EndProcedure

  ; Fonction pour tester si un token est un "Mot"
  ; Ici, on considère qu'un mot commence par une lettre (accentuée ou non) ou un underscore.
  Procedure.i IsWordStart(Token.s)
    If Token = ""
      ProcedureReturn #False
    EndIf
    
    ; Premier caractère du token
    Define FirstChar.s = Mid(Token, 1, 1)
    
    ; Liste des caractères considérés comme lettre ou underscore pour le début d'un mot
    Define AllowedFirstChars.s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZàáâãäåæçèéêëìíîïðñòóôõöøùúûüµýÿþßÀÁÂÃÄÅÆÇÐÈÉÊËÌÍÎÏÑÒÓÔÕÖØÞÙÚÛÜÝŸ_"
    
    If FindString(AllowedFirstChars, FirstChar, 1) > 0
      ProcedureReturn #True
    EndIf
    
    ProcedureReturn #False
  EndProcedure

  Procedure ParseAndIdentify(Code.s)
    Protected Position.i, Partie.s, Longueur.i, ElementType.s
    Protected Dim Results.s(0) ; Tableau pour stocker les résultats détaillés
    Protected ResultsCount.i = 0 ; Compteur pour gérer les indices du tableau
    Protected Buffer.s = "" ; Permet de regrouper les parties complexes
    Protected BufferPosition.i = -1 ; Position de début du buffer

    If ExamineRegularExpression(RegexBloc, Code)
      While NextRegularExpressionMatch(RegexBloc)
        Partie = RegularExpressionMatchString(RegexBloc)
        Position = RegularExpressionMatchPosition(RegexBloc)
        Longueur = Len(Partie)

        ; Test si c'est l'opérateur "="
        If Partie = "="
          If Buffer <> ""
            ReDim Results(ResultsCount)
            Results(ResultsCount) = "Type: Expression, Valeur: '" + Buffer + "', Position: " + Str(BufferPosition) + ", Longueur: " + Str(Len(Buffer))
            ResultsCount + 1
            Buffer = ""
          EndIf
          ElementType = "Opérateur"
          ReDim Results(ResultsCount)
          Results(ResultsCount) = "Type: " + ElementType + ", Valeur: '" + Partie + "', Position: " + Str(Position) + ", Longueur: " + Str(Longueur)
          ResultsCount + 1

        ElseIf IsWordStart(Partie)
          ; C'est un mot
          If Buffer <> ""
            ; On vide d'abord le buffer si non vide (on le considère comme expression)
            ReDim Results(ResultsCount)
            Results(ResultsCount) = "Type: Expression, Valeur: '" + Buffer + "', Position: " + Str(BufferPosition) + ", Longueur: " + Str(Len(Buffer))
            ResultsCount + 1
            Buffer = ""
          EndIf

          ElementType = "Mot"
          ReDim Results(ResultsCount)
          Results(ResultsCount) = "Type: " + ElementType + ", Valeur: '" + Partie + "', Position: " + Str(Position) + ", Longueur: " + Str(Longueur)
          ResultsCount + 1

        Else
          ; Sinon, c'est un fragment d'expression (nombres, symboles, etc.)
          If Buffer = ""
            BufferPosition = Position
          EndIf
          Buffer + Partie
        EndIf
      Wend

      ; Ajouter le dernier buffer restant comme un bloc logique
      If Buffer <> ""
        ReDim Results(ResultsCount)
        Results(ResultsCount) = "Type: Expression, Valeur: '" + Buffer + "', Position: " + Str(BufferPosition) + ", Longueur: " + Str(Len(Buffer))
        ResultsCount + 1
      EndIf
    EndIf

    ; Afficher les résultats
    For i = 0 To ResultsCount - 1
      Debug Results(i)
    Next
  EndProcedure
EndModule

; Exemple d'utilisation avec caractères accentués
Parseur::Init()
Parseur::ParseAndIdentify("variable = é * / á5 + )(mônd3.1258 * 2 . ) / françàis - voi.türe.phâre . / ((45 / 0 * 5.01.254) ) * 56) + 36.0215 - / * . et autre_variable")
Debug "---"
Parseur::ParseAndIdentify(" if  variable  =  =  +  =  -  *  /  ef.  *  /  5  +  )  àáâ  ãäåæç ¢£¤¥ èéêëìí  îïðñòóôõ  être  leçon  éléphant  öøùúûüýÿÀÁ  ÂÃÄÅÆÇÈÉ  dû  ÊËÌÍÎÏÐÑÒÓ  ÔÕÖØÙÚÛÜÝŸ(3.1258 * 2 . ) / 15.369 - voi.tu = re.phare . / ((45 / 0 * 5.01.254) ) * 56) + 36.0215 - / * . et autre_variable")
Debug "---"
Parseur::ParseAndIdentify("àáâãäåæçèéêëìíîïðñòóôõöøùúûüµýÿþÀÁÂÃÄÅÆßÇÐÈÉÊËÌÍÎÏÑÒÓÔÕÖØÞÙÚÛÜÝŸ!?%&*+-/<=>^|~(){}[],.:;#$'@\_¡¢£¤¥¦§¨©ª«¬­®¯°±²³´¶·¸¹º»¼½¾¿×÷" + Chr(34))
Debug "---"
Parseur::ParseAndIdentify(" àáâãäåæçèé êëìíîïðñòóôõöø ùúûüµýÿþÀÁÂÃÄÅÆ ßÇÐÈÉÊËÌÍÎÏÑÒÓÔÕ ÖØÞÙÚÛÜÝŸ!?%& *+-/<=>^|~(){ }[],.:;#$'@\_ ¡¢£¤¥¦§¨©ª«¬­®¯°±² ³´¶·¸¹º»¼½¾¿×÷ " + Chr(34))
Debug "---"
Parseur::ParseAndIdentify("If éléphant = 24.258 + ( (85.231 * 2.5 - 63.147 / -45 + 34 - -65) / 25 + 69 -91 / 25.4956541 ) - ( -56 / 8 * 51.1735 -36 + 954 ) & éléphant " + Chr(34))
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: Découpeur de chaîne (Parseur)

Message par Micoute »

Bravo Shadow, il est bien pratique ton petit programme. J'aime bien.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Répondre