IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Reconnaître un nom de champ sans guillemet [RegExp]


Sujet :

JavaScript

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2022
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2022
    Messages : 21
    Points : 28
    Points
    28
    Par défaut Reconnaître un nom de champ sans guillemet
    Bonjour tout le monde,

    J'écris un parser (mon premier parser!) pour reconnaître les chaînes de caractère de ce type : TERM : MATCH_TERM. J'écris ce parser en utilisant Chevrotain, mon code est en TypeScript mais l'erreur que j'ai ne provient pas de l'utilisation du TypeScript.

    J'avais initialement permis d'écrire la partie TERM uniquement entre guillemets simples ou doubles ('TERM' ou "TERM"). Je voudrais maintenant permettre d'écrire la partie TERM sans guillemets autour.

    Mes regex pour reconnaître la partie TERM entourée de guillemets fonctionnent bien et sont les suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const StringDoubleQuote = createToken({ name: "StringDoubleQuote", pattern: /"[^"\\]*(?:\\.[^"\\]*)*"/ });
    const StringSimpleQuote = createToken({ name: "StringSimpleQuote", pattern: /'[^'\\]*(?:\\.[^'\\]*)*'/ });
    Pour ces expressions régulières, je n'avais pas besoin de spécifier le caractère : comme marquant la fin du token, car le guillemet avait déjà cet usage.

    Pour rendre possible l'écriture de la partie TERM sans guillemets autour, j'ai utilisé l'expression régulière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const StringWithoutQuote = createToken({ name: "StringWithoutQuote", pattern: /[\w!@#\$%\^&.-]+/ });
    Pour définir la partie lexer du parser créé avec chevrotain j'ai écrit le code suivant qui définit les tokens possibles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    const StringWithoutQuote = createToken({ name: "StringWithoutQuote", pattern: /[\w!@#\$%\^&.-]+/ });
    const StringDoubleQuote = createToken({ name: "StringDoubleQuote", pattern: /"[^"\\]*(?:\\.[^"\\]*)*"/ });
    const StringSimpleQuote = createToken({ name: "StringSimpleQuote", pattern: /'[^'\\]*(?:\\.[^'\\]*)*'/ });
    const And = createToken({ name: "And", pattern: /(AND|and)/ });
    const Or = createToken({ name: "Or", pattern: /(OR|or)/ });
    const WhiteSpace = createToken({
        name: "WhiteSpace",
        pattern: /[ \t\n\r]+/,
        group: Lexer.SKIPPED
    });
    const Colon = createToken({ name: "Colon", pattern: /:/ });
    const Star = createToken({ name: "Star", pattern: /\*/ });
     
    //.... Many other token
     
    const allTokens = [
        WhiteSpace,
        Colon,
        Star,
        And,
        Or,
     
        //À ce niveau, j'ai également essayé de placer StringWithoutQuote après les chaînes de caractères avec guillemets dans le tableau allTokens.
     
        StringWithoutQuote,
        StringDoubleQuote,
        StringSimpleQuote
    ];
    Mon problème maintenant :
    Je vais prendre deux chaînes de caractère d'exemple :
    - aggregateType:*

    - orderInfo.orderDate:*

    Pour la première chaîne de caractère (aggregateType:*) quelle que soit la syntaxe utilisée (avec ou sans guillemets) le parser fonctionne bien et renvoie le résultat attendu.

    Mais pour la deuxième chaîne de caractère (orderInfo.orderDate:*), la syntaxe avec guillemets ('orderInfo.orderDate':* ou "orderInfo.orderDate":*) permet au parser de bien fonctionner et de me retourner le résultat attendu.

    Mais avec la syntaxe sans guillemets (orderInfo.orderDate:*), le parser me renvoie l'erreur suivante : Error : Failing to parse of string <orderInfo.orderDate:*>. Je ne suis pas sûr, mais j'ai vraiment l'impression que c'est l'ajout d'un point . dans la partie TERM qui cause l'erreur. Pourtant, dans ma regex (/[\w!@#\$%\^&.-]+/) j'ai bien mis que le point . fait partie de mes caractères spéciaux à prendre en compte dans le token créé.

    Quelqu'un voit-il ce que j'ai fait de mal et qui provoque ce comportement ?

    Merci d'avance si vous prenez le temps de m'aider.

  2. #2
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 235
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 235
    Points : 15 532
    Points
    15 532
    Par défaut
    quand j'essaye ce code, il trouve quelque chose. ce n'est pas ce que vous attendez mais ce n'est pas non plus le message d'erreur que vous citez donc je ne sais pas quelle est la différence avec votre code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    <script src="https://unpkg.com/chevrotain/lib/chevrotain.js"></script>
    <script>
     
    console.clear();
     
    const createToken = chevrotain.createToken;
    const Lexer = chevrotain.Lexer;
     
     
    const StringWithoutQuote = createToken({ name: "StringWithoutQuote", pattern: /[\w!@#\$%\^&.-]+/ });
    const StringDoubleQuote = createToken({ name: "StringDoubleQuote", pattern: /"[^"\\]*(?:\\.[^"\\]*)*"/ });
    const StringSimpleQuote = createToken({ name: "StringSimpleQuote", pattern: /'[^'\\]*(?:\\.[^'\\]*)*'/ });
    const And = createToken({ name: "And", pattern: /(AND|and)/ });
    const Or = createToken({ name: "Or", pattern: /(OR|or)/ });
    const WhiteSpace = createToken({
        name: "WhiteSpace",
        pattern: /[ \t\n\r]+/,
        group: Lexer.SKIPPED
    });
    const Colon = createToken({ name: "Colon", pattern: /:/ });
    const Star = createToken({ name: "Star", pattern: /\*/ });
     
    //.... Many other token
     
    const allTokens = [
        WhiteSpace,
        Colon,
        Star,
        And,
        Or,
     
        //À ce niveau, j'ai également essayé de placer StringWithoutQuote après les chaînes de caractères avec guillemets dans le tableau allTokens.
     
        StringWithoutQuote,
        StringDoubleQuote,
        StringSimpleQuote
    ];
     
    let SelectLexer = new Lexer(allTokens);
     
     
    let inputText = "orderInfo.orderDate:*";
    let lexingResult = SelectLexer.tokenize(inputText);
     
    console.log(lexingResult["tokens"]);
     
    </script>

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2022
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2022
    Messages : 21
    Points : 28
    Points
    28
    Par défaut
    Je vais continuer à regarder mais je pense avoir trouver le problème finalement.

    L'erreur se fait à cause de la définition du tableau allTokens je pense.

    J'ai un token and et un token or qui servent d'opérateur entre mes différentes expression. Comme le champs orderInfo.orderDate commence par or il doit essayer de construire un token or puis il n'arrive plus à parser la suite de ma chaîne de caractère car elle ne correspond plus alors à la syntaxe que j'ai défini dans mes règles de grammaire.

    Je vais donc essayer de placer mes tokens définissant mes termes avant mes tokens définissant les opérateurs or et and et je vous dit si ça marche bien.

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2022
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 23
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2022
    Messages : 21
    Points : 28
    Points
    28
    Par défaut
    Finalement la solution n'était pas de changer l'ordre des tokens dans le tableau de définition des tokens allTokens.

    Il fallait en fait définir un "pattern possible plus long" qui permet de dire à chaque fois que je check la présence de ce keyword (ici and ou or) je check aussi s'il ne s'agit pas d'un identifier moins spécifique (ici StringWithoutQuote).
    L'explication plus détaillée se trouve à la fin du paragraphe constructor de ce lien https://chevrotain.io/documentation/...ml#constructor

    La définition du lexer devient donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    const StringWithoutQuote = createToken({ name: "StringWithoutQuote", pattern: /[\w!@#\$%\^&.-]+/ });
    const StringDoubleQuote = createToken({ name: "StringDoubleQuote", pattern: /"[^"\\]*(?:\\.[^"\\]*)*"/ });
    const StringSimpleQuote = createToken({ name: "StringSimpleQuote", pattern: /'[^'\\]*(?:\\.[^'\\]*)*'/ });
    const And = createToken({ name: "And", pattern: /(AND|and)/, longer_alt: StringWithoutQuote });  //ajouter ici le longer_alt 
    const Or = createToken({ name: "Or", pattern: /(OR|or)/, longer_alt: StringWithoutQuote });  //ajouter ici le longer_alt 
    const WhiteSpace = createToken({
        name: "WhiteSpace",
        pattern: /[ \t\n\r]+/,
        group: Lexer.SKIPPED
    });
    const Colon = createToken({ name: "Colon", pattern: /:/ });
    const Star = createToken({ name: "Star", pattern: /\*/ });
     
    const allTokens = [
        WhiteSpace,
        Colon,
        Star,
        And,
        Or,
        StringWithoutQuote,
        StringDoubleQuote,
        StringSimpleQuote
    ];

  5. #5
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Tu pouvais aussi esquiver ce problème en imposant des word boundaries (ou des contraintes plus exigeantes) autour de ta pattern: /\b(or|OR)\b/
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Comment récupérer le nom du fichier sans l'extension ?
    Par altahir007 dans le forum Langage
    Réponses: 16
    Dernier message: 13/11/2009, 13h20
  2. [ODBC] Comment récupérer le nom des champs de table Access
    Par Alexlesilex dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 12/05/2006, 14h14
  3. Réponses: 3
    Dernier message: 30/01/2006, 16h24
  4. Comment récupérer le nom du fichier sans le chemin ?
    Par st0nky dans le forum Débuter
    Réponses: 3
    Dernier message: 08/12/2005, 11h01
  5. comment recuperer le nom des champs ?????
    Par e11137 dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 09/01/2004, 10h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo