Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Les regex et grammaires de Perl 6
Une puissance expressive sans précédent, un tutoriel de Laurent Rosenfeld

Le , par Lolo78

0PARTAGES

6  0 
Bonsoir,

je viens de faire une mise à jour importante de l'article sur les Regex et les Grammaires de Perl 6, avec en particulier l'ajout d'une grammaire pour la mise en œuvre d'une calculette arithmétique (avec règles de précédence et parenthèses) ainsi que de quelques nouvelles pages relatives à des utilisations avancées des grammaires, notamment:



et une multitude d'améliorations de détail.

Si vous avez téléchargé la version antérieure, n'hésitez pas à revenir pour prendre connaissance de cette nouvelle version.

Au total, cette version représente environ une vingtaine de pages de plus que la version d'origine.

Bonne lecture à tous,

Laurent.

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de Pyramidev
Expert confirmé https://www.developpez.com
Le 03/11/2018 à 21:01
J'ai fini de lire le tutoriel.

Autre coquille dans la partie 2-10-2 :
Texte actuel : « Par exemple, pour rechercher la chaîne toto non immédiatement suivie de la chaîne titi, on peut utiliser la regex rx{ toto < !after titi>}. »
Je pense que tu voulais écrire : « Par exemple, pour rechercher la chaîne toto non immédiatement précédée de la chaîne titi, on peut utiliser la regex rx{ <!after titi> toto }. »

Si on pinaille pour les anglicisme, les mots anglais mutable et mutability se traduisent par muable et muabilité et non pas mutable et mutabilité. Je faisais cette faute aussi avant.

Si on pinaille encore plus, le caractère que tout le monde appelle le caractère dièse est en réalité le caractère croisillon (#). Le vrai caractère dièse est &#9839;.

À part ça, dans le tutoriel, on peut lire :
La Synopse (spécification d'origine) S05 semble indiquer que les variables ne sont en principe pas interpolées dans une regex, ou du moins pas de la façon où l'on entend ce terme en Perl 5. Dans la pratique, Perl 6 / Rakudo Star effectue actuellement (au moins dans la plupart des cas) l'interpolation des variables au sein des regex :
Code : Sélectionner tout
1
2
3
my $var = "ab";
say "Reconnu" if "abc" ~~ /$var c/;    # -> Reconnu
say ~$/;                               # -> abc
Par curiosité, j'ai creusé un peu.

Dans la page http://design.perl6.org/ , on peut lire :
« In the past the Synopses have often been referred to as "the formal Perl 6 specification" and "specs", but this usage is being deprecated in favor of treating tests from the "roast" test suite as official specifications. This is consistent with Synopsis 1, which says "Perl 6 is anything that passes the official test suite." »

Du coup, j'ai regardé un peu les tests unitaires et il y avait un fichier "roast/S05-interpolation/regex-in-variable.t".

Dans ce fichier, il y a plusieurs exemples d'interpolations de variables dans des regex, donc on peut considérer que cette fonctionnalité est officielle. Exemple :
Code : Sélectionner tout
1
2
3
4
my $foo = "a+b";
[...]
ok("a+b" ~~ m/$foo/, 'Simple scalar match 3');
La documentation officielle actuelle est pour l'instant muette sur ce point et le comportement exact reste (un peu) incertain et à préciser. Il semble qu'il faille comprendre que la variable n'est pas interpolée au moment de la construction du motif, mais seulement au moment de son utilisation lors de la reconnaissance proprement dite, ce qui permet d'utiliser une variable non encore initialisée dans la définition du motif :
Code : Sélectionner tout
1
2
3
4
5
my $var;
my $regex = rx/q.$var/; 
   # pas d'erreur bien que $var ne soit pas définie
$var = rx/abc/;
say "Vrai" if 'aaqdabchg' ~~ $regex;  # -> Vrai
Là, par contre, dans le fichier "regex-in-variable.t", je n'ai pas trouvé de test qui couvre vraiment ce cas. J'ai trouvé celui-ci :
Code : Sélectionner tout
1
2
3
    my $u;
    ok 'a' !~~ /$u/, 'undefined variable does not match';
Mais ce cas n'est pas vraiment pareil.

En tout cas, Perl 6 m'a l'air intéressant. Il est dans ma to-do-list des langages à apprendre.
2  0 
Avatar de CosmoKnacki
Expert confirmé https://www.developpez.com
Le 01/11/2018 à 3:18
Merci pour ces tutoriels qui, entre autres, m'ont poussé à mettre à jour ma distribution.

En ce qui concerne ce volet particulier, la nouvelle syntaxe est très déconcertante, et à première lecture je l'ai trouvée plutôt incongrue (Je m'attendais plutôt à l'introduction de nouvelles fonctionnalités sur la base de la syntaxe de perl 5). Mais au final il y a des choses intéressantes, notamment les opérations sur les classes de caractères, les alternatives les plus longues, les conjonctions. À noter aussi que le lookbehind n'a plus l'obligation de taille fixe comme en perl 5.
Je pense qu'une des idées générales est de déporter une partie des problèmes que l'on a pour habitude de résoudre avec une regex perl 5 vers la grammaire perl 6. Je dis ça parce que certaines fonctionnalités ne se retrouvent pas en perl 6 (même avec l'adverbe 5) comme par exemple les séquences d'échappement \G \K, la section (?(DEFINE)...) ou bien les verbes de contrôle du bactracking. Un peu comme si l'utilisation d'une de ces facilités devenait le signe de plutôt en passer par la définition d'une grammaire pour ensuite parser. Pourquoi pas, mais ne perd-on pas en légèreté?

À propos du fait qu'il faille échapper tout ce qui bouge, bien que ce soit contraignant, je pense que l'intention qu'il y a derrière est de pouvoir rendre disponible un maximum de caractères de la table ascii pour des fonctionnalités à venir. Certes on a plus à se demander si tel ou tel caractère doit être échappé (cela dit, c'est déjà le cas en perl 5 puisque les échappements inutiles sont ignorés), mais d'un autre coté ça peut alourdir certaines patterns.

Pour conclure, je dirai que c'est très prometteur mais qu'il s'agit encore, trois ans après sa sortie, d'un travail en cours (notamment du fait que toutes les fonctionnalités perl 5 ne soient pas disponibles avec l'adverbe 5).




Coquilles relevées dans le tutoriel:
2-2. Littéraux:
Code : Sélectionner tout
1
2
3
4
my $chaîne = "Esperluette est le nom parfois donné au signe &";
if $chaîne ~~ m/ perl / {
    say "$chaîne contient 'perl'"; # -> esperluette contient 'perl'
}
Je me suis demandé si c'était la sortie qui était en commentaire et je me suis dit que lorsque la pattern était un littéral, alors le résultat renvoyé était le premier champ (délimité par des caractères blancs) qui correspondait à la pattern. Eh! Pas folle la guêpe!

2-10-2. Assertions arrière: say "tititoto" ~~ rx{ toto <?after titi>}; # -> toto: L'assertion devrait-être placée à la position du premier t: say "tititoto" ~~ rx{ <?after titi> toto }; # -> toto.
1  0 
Avatar de Lolo78
Rédacteur/Modérateur https://www.developpez.com
Le 02/11/2018 à 11:08
Citation Envoyé par CosmoKnacki Voir le message

Je pense qu'une des idées générales est de déporter une partie des problèmes que l'on a pour habitude de résoudre avec une regex perl 5 vers la grammaire perl 6.
Certes, certaines choses peuvent être mieux faites avec des grammaires, et ce n'est pas forcément plus lourd, mais je pense que toutes les fonctionnalités des expressions régulières de Perl 5 sont présentes, mais avec une syntaxe souvent nettement plus claires. Mon article est un tutoriel, pas une documentation de référence, si bien que certaines fonctionnalités un peu obscures ou peu utilisées ne sont peut-être pas couvertes. Cela dit, je vais peut-être compléter certains aspects des regex que j'avais laissés de côté, pour essayer d'être complet.

Citation Envoyé par CosmoKnacki Voir le message

Je dis ça parce que certaines fonctionnalités ne se retrouvent pas en perl 6 (même avec l'adverbe 5)
Le but de l'adverbe 5 est de faciliter d'éventuelles migrations, pas forcément d'offrir l'intégralité des fonctionnalités des regex de P5. Personnellement, je n'ai jamais utilisé 5, si ce n'est pour tester comment ça marchait, je préfère largement la syntaxe de P6.
Citation Envoyé par CosmoKnacki Voir le message


comme par exemple les séquences d'échappement \G \K, la section (?(DEFINE)...) ou bien les verbes de contrôle du bactracking. Un peu comme si l'utilisation d'une de ces facilités devenait le signe de plutôt en passer par la définition d'une grammaire pour ensuite parser.
ces fonctionnalités existent avec les adverbes :continue ou :c (reprendre la recherche où on était arrivé) et :pos ou :p (pour commencer à reconnaître à un endroit précis).

L'adverbe :ratchet ou :r permet de contrôler le backtracking, de même que les règles nommées de type token ou rule, que l'on peut tout-à-fait utiliser sans nécessairement avoir recours à une grammaire (même si l'objectif de ces règles est bien en définitive de permettre la construction de grammaires).

Citation Envoyé par CosmoKnacki Voir le message

À propos du fait qu'il faille échapper tout ce qui bouge, bien que ce soit contraignant, je pense que l'intention qu'il y a derrière est de pouvoir rendre disponible un maximum de caractères de la table ascii pour des fonctionnalités à venir. Certes on a plus à se demander si tel ou tel caractère doit être échappé (cela dit, c'est déjà le cas en perl 5 puisque les échappements inutiles sont ignorés), mais d'un autre coté ça peut alourdir certaines patterns.
La règle est tout de même nettement plus claire et facile à retenir. En P5, si je recherche par exemple dans une chaîne la séquence de caractères "\d" et ignore que \d est une classe de caractères prédéfinie, ma regex ne va pas marcher. En P6, la règle sur les caractères d'échappement est claire et ne souffre pas d'exceptions, donc pas de risque d'utiliser par erreur une classe prédéfinie.

Je reviendrai ultérieurement sur la fin de ton message.
1  0 
Avatar de Lolo78
Rédacteur/Modérateur https://www.developpez.com
Le 02/11/2018 à 17:55
Citation Envoyé par CosmoKnacki Voir le message

Coquilles relevées dans le tutoriel:
2-2. Littéraux:
Code : Sélectionner tout
1
2
3
4
my $chaîne = "Esperluette est le nom parfois donné au signe &";
if $chaîne ~~ m/ perl / {
    say "$chaîne contient 'perl'"; # -> esperluette contient 'perl'
}
Je me suis demandé si c'était la sortie qui était en commentaire et je me suis dit que lorsque la pattern était un littéral, alors le résultat renvoyé était le premier champ (délimité par des caractères blancs) qui correspondait à la pattern. Eh! Pas folle la guêpe!
Effectivement, j'ai modifié l'exemple (au départ, $chaîne ne contenait que le mot esperluette) et j'ai oublié de modifier le commentaire qui n'est plus correct.

Citation Envoyé par CosmoKnacki Voir le message

2-10-2. Assertions arrière: say "tititoto" ~~ rx{ toto <?after titi>}; # -> toto: L'assertion devrait-être placée à la position du premier t: say "tititoto" ~~ rx{ <?after titi> toto }; # -> toto.
Oui, tu as raison, je ne sais d'où vient cette erreur.
1  0 
Avatar de Pyramidev
Expert confirmé https://www.developpez.com
Le 03/11/2018 à 0:18
Bonjour,

Merci pour le tuto.

Je suis en train de le lire. Je n'ai pas encore fini.

Petites coquilles dans la section 2.8 : Il y a une regex nommée entête et un nom de capture clef puis, un peu plus loin, on peut lire $p<key> et $section<header>[0] au lieu de $p<clef> et $section<entête>[0].
1  0 
Avatar de Lolo78
Rédacteur/Modérateur https://www.developpez.com
Le 03/11/2018 à 23:45
Merci beaucoup, Pyramidev, pour tes remarques constructives et pertinentes.

Citation Envoyé par Pyramidev Voir le message

Autre coquille dans la partie 2-10-2 :
Texte actuel : « Par exemple, pour rechercher la chaîne toto non immédiatement suivie de la chaîne titi, on peut utiliser la regex rx{ toto < !after titi>}. »
Je pense que tu voulais écrire : « Par exemple, pour rechercher la chaîne toto non immédiatement précédée de la chaîne titi, on peut utiliser la regex rx{ <!after titi> toto }. »
Oui, tu as raison. J'ai pourtant testé mes bouts de code dans le REPL, je suppose que j'ai dû foirer ensuite mes copier-coller.

Citation Envoyé par Pyramidev Voir le message

Si on pinaille pour les anglicisme, les mots anglais mutable et mutability se traduisent par muable et muabilité et non pas mutable et mutabilité. Je faisais cette faute aussi avant.
Je me suis posé la question et j'ai choisi volontairement d'utiliser mutable après mûre réflexion. Certes, on dit par exemple immuable, mais le mot muable n'existe pas dans les dictionnaires que j'ai consultés, alors que le mot mutable figure bien, avec essentiellement le sens recherché ou un sens suffisamment proche (voir par exemple cette définition du Larousse. Voir aussi le wiktionnaire). Surtout, indépendamment des dictionnaires, le mot mutable me parle, mais pas le mot muable. Bref, pour moi, ce n'est pas une faute, du moins jusqu'à preuve du contraire.

Citation Envoyé par Pyramidev Voir le message

Si on pinaille encore plus, le caractère que tout le monde appelle le caractère dièse est en réalité le caractère croisillon (#). Le vrai caractère dièse est &#9839;.
Tu as parfaitement raison. J'ai là aussi hésité entre dièse, qui est clair pour tout le monde, et croisillon , qui est plus correct mais me parle beaucoup moins, et ai opté pour la clarté en me disant qu'il n'y avait pas de vraie différence de toute façon. Mais le fait que tu montres les deux caractères (et leur différence) presque côte à côte me convainc que ce choix n'était sans doute pas bon, car il y a bien une vraie différence (que je n'avais pas remarquée) entre les deux. Je vais amender le texte en conséquence.

Citation Envoyé par Pyramidev Voir le message

À part ça, dans le tutoriel, on peut lire :

Par curiosité, j'ai creusé un peu.

Dans la page http://design.perl6.org/ , on peut lire :
« In the past the Synopses have often been referred to as "the formal Perl 6 specification" and "specs", but this usage is being deprecated in favor of treating tests from the "roast" test suite as official specifications. This is consistent with Synopsis 1, which says "Perl 6 is anything that passes the official test suite." »
Oui, on est d'accord, j'ai bien dit que les Synopses constituaient la spécification d'origine. Et j'ai bien précisé dans d'autres de mes tutos sur Perl 6 que la suite de tests constituait la véritable spécification officielle.

En fait, j'ai écrit le texte de cet encadré à un moment où la documentation officielle était bien plus pauvre qu'aujourd'hui et je me posais vraiment la question de ce qu'il fallait en penser. J'ai failli supprimer cet encadré lors d'une des dernières mises à jour, mais je ne l'ai pas fait car il me semblait que la question se pose toujours (mais peut-être à tort).
Citation Envoyé par Pyramidev Voir le message

Du coup, j'ai regardé un peu les tests unitaires et il y avait un fichier "roast/S05-interpolation/regex-in-variable.t".

Dans ce fichier, il y a plusieurs exemples d'interpolations de variables dans des regex, donc on peut considérer que cette fonctionnalité est officielle. Exemple :
Code : Sélectionner tout
1
2
3
4
my $foo = "a+b";
[...]
ok("a+b" ~~ m/$foo/, 'Simple scalar match 3');
Oui, cela rejoint les tests que j'ai faits et ceux que je donne en exemple dans cet encadré.
Citation Envoyé par Pyramidev Voir le message

Là, par contre, dans le fichier "regex-in-variable.t", je n'ai pas trouvé de test qui couvre vraiment ce cas. J'ai trouvé celui-ci :
Code : Sélectionner tout
1
2
3
    my $u;
    ok 'a' !~~ /$u/, 'undefined variable does not match';
Mais ce cas n'est pas vraiment pareil.
Oui, mon exemple était différent et semble expliquer ce que voulait dire cette phrase pas très claire (à mon humble avis) de la Synopse 5. Je dois encore y réfléchir, mais je vais peut-être supprimer cet encadré qui exprimait mes doutes à l'époque de la rédaction initiale de ce tuto, doutes qui n'ont sans doute plus vraiment lieu d'être.
Citation Envoyé par Pyramidev Voir le message

En tout cas, Perl 6 m'a l'air intéressant. Il est dans ma to-do-list des langages à apprendre.
Je t'y encourage vivement. Il y a des liens vers d'autres tutos sur P6 dans ma signature et je ne peux que recommander la lecture mon livre (en anglais) sur Perl 6: Think Perl 6 - How to think like a computer scientist (2017, O'Reilly Media, Inc.), disponible gratuitement au format PDF à cette adresse. Ce livre a aussi été traduit en espagnol par Luis F. Uceta et est disponible au format PDF à l'adresse suivante : Piensa en Perl 6 - Cómo Pensar Como un Científico de la Computación.

Encore une fois, je te remercie pour tes commentaires très utiles et très constructifs.

Bonne soirée,
Laurent.
1  0 
Avatar de Lolo78
Rédacteur/Modérateur https://www.developpez.com
Le 04/11/2018 à 19:08
Bonsoir,

j'ai fait une nouvelle mise à jour (mineure) du tutoriel tenant compte de vos remarques. J'ai finalement supprimé l'encart sur l'interpolation des variables; le sujet présente bien quelques subtilités de détail, mais ce genre de point de détail n'a pas vraiment sa place dans un tel tutoriel, surtout pas tout au début de l'article comme c'était le cas.

Encore une fois merci à vous deux pour vos contributions.

Bonne fin de weekend,
Laurent.
1  0 
Avatar de CosmoKnacki
Expert confirmé https://www.developpez.com
Le 02/11/2018 à 17:26
Le but de l'adverbe 5 est de faciliter d'éventuelles migrations, pas forcément d'offrir l'intégralité des fonctionnalités des regex de P5.
J'entends bien, mais ça n'aurait pas coûté plus cher de les mettre quand même.

Quand je parlais de "verbes de contrôle du bactracking" je n'avais pas trop à l'idée :r qui en fait sert à remplacer les groupes atomiques, mais plutôt (*SKIP) (*FAIL) (*PRUNE) (*COMMIT) (*ACCEPT) (*THEN) (*MARK). Après recherche, des commandes de contrôle du backtracking ont été envisagées (source) mais elles ne sont pas implémentées pour le moment (::: not yet implemented).
0  0 
Avatar de Lolo78
Rédacteur/Modérateur https://www.developpez.com
Le 03/11/2018 à 11:15
Merci à toi, pyramidev, et à toi, CosmoKnacki, d'avoir signalé ces coquilles et de m'avoir ainsi permis d'améliorer le contenu de te tutoriel.
0  0