% !TeX TS-program = lualatex % !TeX encoding = UTF-8 % Ceci est la documentation en français du package "toktools" \documentclass[french,a4paper,10pt]{article} \usepackage[margin=1.75cm]{geometry} \usepackage[bottom]{footmisc} \usepackage{libertine,enumitem,babel,xspace,tokstools,hyperref,array,footnotehyper} \makesavenoteenv{tabular} \RequirePackage[most]{tcolorbox} \tcbuselibrary{listings} \usepackage[scaled=0.8]{GoMono} \def\tktl{\texttt\tktlname\xspace} \catcode`\_11 \long\def\def_active#1#2{% \catcode`#1=13 \begingroup \lccode`\~`#1 \lowercase{\endgroup\long\def~{#2}}% } %%%%%%%%%%%%% la macro \tktlcode %%%%%%%%%%%%% \def\nolig_list{\do\`\do\<\do\>\do\,\do\'\do\-} \def\do_noligs#1{% \catcode`#1\active \begingroup \lccode`\~`#1\relax \lowercase{\endgroup\def~{\leavevmode\kern0pt \char`#1\relax}}% } \def\no_ligs{\let\do\do_noligs \nolig_list} \newif\ifspecialcode \specialcodefalse \def\specialcode{\specialcodetrue} \def\tktlcode{\expandafter\tktlcode_i\string} \def\tktlcode_i#1{% \begingroup \nobreak\smallbreak \parindent0pt \parskip=0pt \leftskip2.5em \rightskip0pt \nonfrenchspacing \no_ligs \def\do##1{\catcode`##1=12\relax}\dospecials \ifspecialcode\else \def_active\<{\begingroup$\langle$\ttfamily\itshape}% \def_active\>{$\rangle$\endgroup}% \def_active\&{\string}% \def_active\_{\tktlsubscript}% \fi \ttfamily \def_active\^^I{\space\space\space\space}% \def_active\^^M{\par\noindent}% \def_active\ {\space}% \catcode`#1=12 \def\tktlcode_ii##1#1{##1\par\endgroup\specialcodefalse}% \tktlcode_ii } \catcode`\_8 \def\tktlsubscript#1{$_{#1}$} \makeatletter \let\Verb\verb \begingroup \catcode`\<13 \catcode`\>13 \gdef\verb{\relax\ifmmode\hbox\else\leavevmode\null\fi \bgroup \verb@eol@error \let\do\@makeother \dospecials \verbatim@font\@noligs \catcode`\<13 \catcode`\>13 \def<{\begingroup$\langle$\itshape}\def>{\/$\rangle$\endgroup}% \@ifstar\@sverb\@verb} \endgroup \def\longfrdate@i#1/#2/#3\@nil{\number#3\relax\space \ifcase#2 \or janvier\or février\or mars\or avril\or mai\or juin\or juillet\or aout\or septembre\or octobre\or novembre\or décembre\fi\space#1} \edef\longfrdate{\expandafter\longfrdate@i\tktldate\@nil} \def\<#1>{$\langle${\ttfamily\itshape#1\/}$\rangle$} \makeatother \newtcblisting{doclatex}{ boxrule=.5pt, boxsep=0pt, top=5pt, left=5pt, right=5pt, bottom=5pt, skin=bicolor, colbacklower = white, colback = black!15, listing options={% style=tcblatex, language={TeX}, showspaces=false, showstringspaces=false, commentstyle=\itshape\color{gray!80!white}, basicstyle=\ttfamily\footnotesize } } \begin{document} \parindent=0pt \thispagestyle{empty} \begin{titlepage} \begingroup \centering \null\vskip.25\vsize {\large\bfseries L'extension pour \TeX{} et \LaTeX\par \Huge \tktlname\par} \bigbreak v \tktlver \smallbreak \longfrdate \vskip1.5cm Christian \bsc{Tellechea}\par \texttt{unbonpetit@netc.fr}\par \endgroup \vskip2cm \leftskip=.2\linewidth \rightskip=.2\linewidth \small Cette extension pour \TeX{} ou \LaTeX{} met à disposition des outils pour manipuler des tokens. Dans un ensemble de tokens, il est possible d'établir des règles de correspondances à l'aide de grammaires de type PEG. Dès lors, il devient possible de tester si une correspondance existe, de les compter, d'effectuer des remplacements, de capturer des tokens, etc. \end{titlepage} \parindent0pt \pagestyle{plain} \tableofcontents \parskip\medskipamount \newpage \section{Présentation} L'extension \tktl fonctionne avec tout moteur. Elle n'est pas limité à \LaTeX{} seulement, comme l'est malheureusement le package \texttt{pegmatch}, et pour l'utiliser, il faut écrire \begin{itemize} \item \verb|\input tokstools.tex| sous (pdf)(Xe)(lua)(op)\TeX; \item \verb|\usepackage{tokstools}| sous (pdf)(Xe)(lua)\LaTeX. \end{itemize} Ce package ne requiert que le package \href{https://ctan.org/pkg/simplekv}{simplekv} qui sera chargé si ça n'a pas été le cas. \textit{Avertissement} : dans ce manuel, une (grande) liberté sera prise quant aux termes employés et des mots anglais seront très fréquemment utilisés, autant par commodité et habitude que par pure flemme de rédiger des tournures 100~\% françaises plus lourdes ou alambiquées. \begin{center} \renewcommand\arraystretch{1.15} \begin{tabular}{|p{5cm}|p{7cm}|}\hline \bfseries mot/expression & \bfseries en français \\\hline token & unité syntaxique \\\hline match & correspondance \\\hline les tokens ayant matché & les tokens ayant produit une correspondance \\\hline catcode & code de catégorie (est un entier de 0 à 16) \\\hline charcode & code de caractère (est un entier) \\\hline liste csv & liste d'éléments séparés par des virgules \\\hline marqueur & macro qui agit comme un repère afin d'être reconnue dans un argument, mais qui n'est pas modifiée par \tktl \\\hline package & extension ou paquet \\\hline \end{tabular} \end{center} \subsection{Tokens, charcode, catcode, moteurs} Le package \tktl agit sur des ensembles de tokens (ou chaines de tokens). Les tokens sont la plus petite unité du code source manipulée par \TeX. L'utilisateur doit avoir conscience que la notion de tokens dépend du type de moteur utilisé. Ce n'est \emph{que} pour les moteurs 8~bits, tels que pdf\LaTeX{} par exemple, que \hbox{1 token${}={}$1 octet}. À titre d'exemple, le caractère «\verb|€|» est vu \begin{itemize} \item par pdf\LaTeX{} comme 3 tokens dont les charcodes sont 226; 130 et 172 et les catcodes sont tous égaux à 13 ; \item par lua\LaTeX{} comme 1 seul token de charcode 8364 et de catcode 12. \end{itemize} Cette différence doit être prise en compte et peut être source d'erreurs plus ou moins compréhensibles lorsqu'on manipule des caractères UTF8 sur un moteur 8~bits. Ce manuel a été compilé avec lua\LaTeX, et donc des tokens ayant des charcodes supérieurs à 255 peuvent exister. Quelles que soient les macros mises à disposition par \tktl, elles décomposent toujours leur argument contenant les tokens, noté \, en liste de tokens, chacun possédant un charcode et un catcode. Les catcodes visibles par \tktl sont listés dans le tableau ci-dessous, avec pour chacun les tokens les plus courant de charcode inférieur à 255 qui possèdent ces catcodes par défaut. \begin{center} \renewcommand\arraystretch{1.15} \begin{tabular}{>{\leftskip0ptplus1fill \rightskip\leftskip}p{1.25cm}p{5.5cm}p{6.5cm}}\hline Catcode & Description & Tokens\\\hline 1 & début de groupe & \verb|{|\\ 2 & fin de groupe & \verb|}|\\ 3 & délimiteur de mode mathématique & \verb|$|\\ 4 & tabulation d'alignement & \verb|&|\\ 6 & caractère de paramètre & \verb|#|\\ 7 & exposant & \verb|^|\\ 8 & indice & \verb|_|\\ 10 & espace & \Verb*| | et \itshape HT\\ 11 & lettres & \verb|a-z| et \verb|A-Z|\\ 12 & autres caractères & chiffres (\verb|0-9|)\par signes de ponctuation (\verb|: . ; , ? ! ' "|)\par signes mathématiques (\Verb|+ - * / = < >|)\par autres signes (\verb/[ ] ( ) | @ `/)\\ 13 & caractère actif & \verb|~|\\ 16 & séquence ou caractère de contrôle & \verb|\| ou \verb|\| \\ \hline \end{tabular} \end{center} Aucune des macros mises à disposition par \tktl n'est développable. Si l'on souhaite que le résultat de ces macros ou bien des captures soient contenus dans des macros purement développables, il faut utiliser des consignes d'assignation qui seront définies dans ce manuel. \subsection{Notations} Dans tout le manuel : \begin{itemize} \item \ désigne un ensemble de tokens\footnote{La primitive \texttt{\textbackslash par} peut se trouver dans \.} équilibré en tokens de catcode 1 et 2 (accolades ouvrantes et fermantes) qui se trouve comme argument des macros ou des marqueurs en charge de traiter ces tokens; \item \<1-motif> représente un motif unique, c'est à dire constitué d'un marqueur avec son éventuel argument, précédé d'un prédicat optionnel et suivi d'une spécification optionnelle de répétition; \item \ représente un seul \<1-motif> ou une combinaison de plusieurs \<1-motif> obtenue avec l'opérateur de concaténation «\verb|:|» et l'opérateur de choix ordonné «\verb/|/» (seulement l'opérateur «\verb/|/» pour \verb|\toksdo| et \verb|\tokscount|); \item \verb|{}| est un groupement qui se comporte comme un \<1-motif>. \end{itemize} \subsection{La macro {\ttfamily\textbackslash printtoks}}\label{printtoks} La macro \tktlcode|\printtoks[=]{}| permet d'afficher les tokens avec, au-dessous de chacun, son charcode et son catcode. Si un token est une séquence de contrôle ou un caractère de contrôle, aucun charcode n'est affiché. \begin{doclatex} \printtoks[code=\ttfamily]{\def\foo#1#2#3{\hbox to 1cm{\hss$#1^#2_#3$\hss}}} \medbreak \printtoks[code=\ttfamily]{eéė€} \end{doclatex} Les \ disponibles sont : \begin{center} \renewcommand\arraystretch{1.25} \begin{tabular}{>\ttfamily p{3.5cm}>\ttfamily p{2.5cm}p{8cm}}\hline \rmfamily Clé & \rmfamily Valeur par défaut & Description\\\hline expand arg & 0 & nombre de développements que doit subir l'argument contenant les \ avant d'être pris en compte\\ code & \ & code exécuté avant d'afficher un token\\ intertoks & 0.33em & espace horizontale entre chaque token, insérée par la primitive \verb|\hskip|\\ printcharcode & true & affiche ou pas le charcode\\ printcatcode & true & affiche ou pas le catcode\\ hexcharcode & false & affiche le charcode en base 16 si \verb|true| et en base 10 sinon\\ baselinecoeff & 0.8 & coefficient d'espacement vertical\\ vlines & true & affiche ou pas les lignes verticales entre chaque token\\ boxed & true & met le tout dans une \verb|\hbox| si \verb|true|, ce qui rend le tout insécable\\\hline \end{tabular} \end{center} \section{Agir sur chaque token avec \texttt{\textbackslash toksdo}} Cette macro parcourt tous les tokens un par un et indépendamment les uns des autres. L'utilisateur peut spécifier des critères à l'aide de \ et pour chacun, une \ à effectuer sur le token ayant matché avec \. \subsection{Motifs élémentaires} 3 motifs élémentaires susceptibles de matcher avec un token sont mis à disposition, chacun étant accessible par le marqueur \verb|\r|, \verb|\R| et \verb|\S|. \subsection{Le motif \texttt{\textbackslash r}}\label{motif:r} La syntaxe de ce \<1-motif> est \tktlcode/\r{:}/ où un intervalle est de la forme «plage s'étendant entre deux tokens» de type \verb|-|, mais peut être réduit à un unique token \verb||. Dans la liste \ , le caractère «\verb|*|» tient lieu de joker et remplace tout intervalle. Si la \ est absente, elle est comprise comme «\verb|*|». La virgule, le tiret et «\verb|:|» ne peuvent pas être spécifiés comme token puisqu'ils font partie de la syntaxe (voir le marqueur \verb|\R| pour contourner cette limitation). À titre d'exemple :\par \begin{tabular}{>\raggedleft p{7cm}p{9cm}} \verb|\r{a-z:11}| & correspond avec tout token de \verb|a| à \verb|z| ayant un catcode de 11.\\ \verb|\r{a-z}| ou \verb|\r{a-z:*}| & correspond avec tout token de \verb|a| à \verb|z| quel que soit son catcode.\\ \verb|\r{a,e,i,o,u,y}| & correspond avec toute voyelle, quel que soit son catcode.\\ \verb|\r{a-z,A-Z,0-9:11,12}| & correspond avec tout caractère alphanumérique (minuscule, majuscule ou chiffre), ayant indifféremment un catcode de 11 ou 12. \end{tabular} \subsection{Le motif \texttt{\textbackslash R}}\label{motif:R} La syntaxe de ce \<1-motif> est \tktlcode/\R{:}/ Dans les deux listes csv, le caractère «\verb|*|» tient lieu de joker et remplace tout intervalle. Les charcodes sont des nombres écrits en chiffres (base 10) ou à la façon de \TeX : \verb|`\|. Ainsi, «\verb|`\:|», «\verb|`\,|» et «\verb|`\-|» sont les entiers correspondant respectivement aux charcodes des tokens «\verb|:|», «\verb|,|» et «\verb|-|». On a donc par exemple :\par \begin{tabular}{>\raggedleft p{6cm}p{9cm}} \verb|\R{*:10}| & correspond avec tout token de catcode 10 (qui est un espace pour \TeX)\\ \verb|\R{*:16}| & correspond avec tout token de catcode 16 (qui est un caractère ou une séquence de contrôle pour \TeX)\\ \verb|\R{106-115:11}| & correspond avec tout token de «\verb|j|» à «\verb|s|» ayant un catcode de 11\\ \verb|\R{`\a-`\z}| & est identique à \verb|\R{97-122}| qui est équivalent à \verb|\r{a-z}|\\ \verb|\R{`\,,`\;,`\::12}| & est identique à \verb|\R{44,59,58:12}| et correspond avec \verb|,| ou \verb|;| ou \verb|:| de catcode 12\\ \verb|\R{*:*}| & correspond avec n'importe quel token \end{tabular} \subsection{Le motif \texttt{\textbackslash S}}\label{motif:S} La syntaxe de ce \<1-motif> est \tktlcode/\S{}/ Un token correspond s'il figure dans \ passés comme argument à \verb|\S|. Dans les tokens «\verb|ab \foo{0 123}c d|», ceux qui matchent avec le motif «\verb|\S{1{a }\foo}|» sont encadrés en rouge\label{encadrerouge} : \begin{center} \fboxsep=1.5pt \toksdo{ \S{1{a }\foo} -> \ifnum\selfcatcode=10 % si espace \addtok{{\color{red}\fbox{\strut\textvisiblespace}}}% \else \setcatcode{12}% \addtok{{\ttfamily\color{red}\fbox{\strut\self}}}% \fi, \R{*:*} -> \addtok{\,{\ttfamily\self}\,} }{ab \foo{0 123}c d} \end{center} Les \ peuvent contenir un ou plusieurs occurrences \emph{non imbriquées} du marqueur \verb|\c|\label{marqueur:c:catcode}. La syntaxe de ce marqueur est \tktlcode/\c{}{}/ Dans l'argument de \verb|\S|, l'action de \verb|\c| est de donner aux \ le \ passé dansle permier argument. Si le \ est réduit à 1 chiffre, les accolades sont facultatives. Il en est de même pour le 2\ieme{} argument s'il contient un seul token. Si un token est une \, le seul catcode qu'elle peut recevoir est 12 auquel cas, les tokens de catcode 12 provenant de \verb|\string| seront créés. Les catcodes acceptés dans le 1\ier{} argument de\verb|\c| sont : 1, 2, 3, 4, 6, 7, 8, 10, 11, 12 et 13. L'utilisateur devra être \emph{extrêmement attentif} aux conséquences d'un changement de catcode vers les catégories sensibles portant les numéros 1, 2 et 6. Si l'on écrit \tktlcode/\S{12\c{12}\bar3abc\c{11}{4 5.6}7\c78 9}/ alors les \ contenus dans l'argument de \verb|\S| sont : \begin{center} \catcode`\_11 \tktl_catcode_string{12\c{12}\bar3abc\c{11}{4 5.6}7\c78 9} \tktl_earg\tktl_decode_enctoks{\the\tktl_string_toks}{\printtoks[intertoks=0.75em]} \end{center} \subsection{Motifs} Ce que l'on note \ pour \verb|\toksdo| est constitué d'un \<1-motif> élémentaire ou de plusieurs séparés par «\verb-|-» qui signifie «ou» :\par \begin{tabular}{>\raggedleft p{7cm}p{9cm}} \verb/\r{a-z:11} | \R{*:12}/ & correspond avec tout token étant une lettre de \verb|a| à \verb|z| de catcode 11 ou tout token de catcode 12 \\ \verb/\R{*:16} | S{01223456789.}/ & correspond avec tout token étant une macro, un chiffre ou un point\\ \verb/\r{0-9:12} | \r{a-z,A-Z:11} | \R{*:10}/ & correspond avec tout token ayant le catcode par défaut étant un chiffre, une lettre, ou un espace \end{tabular} \subsection{Utiliser \texttt{\textbackslash toksdo}}\label{toksdo} Cette macro s'utilise de la façon suivante : \tktlcode/ \toksdo[=] { -&> , -&> , etc. }{}/ On peut spécifier autant de \ et de \ associés que l'on souhaite. Chaque \ est un code arbitraire\footnote{Si ce \ contient une virgule qui n'est pas entre accolades, il faut utiliser la syntaxe \\texttt{->\char`\{ }\\texttt{\char`\}}.} susceptible de modifier le token qui a matché avec \. Dans ce \, on peut utiliser les macros suivantes : \begin{itemize} \item \verb|\tokslen| qui est le nombre total de tokens; \item \verb|\selfindex|, \verb|\selfcharcode| et \verb|\selfcatcode| qui, pour le token ayant matché, représentent son index (qui commence à 1 et finit à \verb|\tokslen|), son charcode et son catcode. Si le token est une macro, \verb|\selfcharcode| n'est \emph{pas} un nombre et vaut la macro elle-même ; \item \verb|\addtok{}| qui indique de quelle façon ajouter le token ayant matché au collecteur interne qui le recueille tous en vue des les afficher ou de les assigner en fin de processus; \item \verb|\deltok| supprime le token ayant matché; \item \verb|\setcharcode{}| et \verb|\setcatcode{}| changent le charcode et le catcode du token ayant matché. Une \ ne peut recevoir que le catcode 12 et dans ce cas, les tokens provenant de \verb|\string| sont créés. Pour tout autre token, les catcodes acceptés par \verb|\setcatcode| sont 1, 2, 3, 4, 6, 7, 8, 10, 11, 12 et 13. Une attention particulière doit être portée à ce que l'on fait si on change un catcode pour 1, 2 ou 6. \end{itemize} Les \ acceptées par la macro \verb|\toksdo| sont : \begin{center} \renewcommand\arraystretch{1.25} \begin{tabular}{>\ttfamily p{3.5cm}>\ttfamily p{2.5cm}p{8cm}}\hline \rmfamily Clé & \rmfamily Valeur par défaut & Description\\\hline expand arg & 0 & nombre de développements que doit subir l'argument contenant les \ avant d'être pris en compte\\ collect & true & collecte tous les tokens retenus dans le but de les afficher ou les stocker. Aucune collecte n'est faite si ce booléen est \verb|false|\\ assign & \ & consigne d'assignation\footnote{Une consigne d'assignation est tout code susceptible de se trouver devant le résultat mis entre accolades. Le code qui est exécuté est donc {\ttfamily\\char`\{\\char`\}}.} du résultat. Si \, affiche le résultat. Si la valeur est une \, cette \ doit être un registre de tokens qui recevra le résultat. La valeur peut également être de la forme \verb|\def| où la \verb|| recevra le résultat\\\hline \end{tabular} \end{center} Voici comment programmer le ROT13 : \begin{doclatex} \toksdo{ \r{a-m,A-M} -> \setcharcode{\selfcharcode + 13}, \r{n-z,N-Z} -> \setcharcode{\selfcharcode - 13} }{Deux plus deux font quatre} \end{doclatex} Dans cet exemple, on remplace tout chiffre ou tiret par «\verb|x|» et tout espace par «\verb|_|» de catcode 12 : \begin{doclatex} \toksdo{ \r{0-9} | \S{-} -> \setcharcode{`x}, \R{*:10} -> \setcharcode{`\_}\setcatcode{12} }{Votre mot de passe est : \textbf{758-457-384}, ne n'oubliez pas !} \end{doclatex} Ne garde que la première moitié des tokens : \begin{doclatex} \toksdo{\R{*:*} -> \ifnum\selfindex>\numexpr\tokslen/2\relax \deltok \fi}{123abcd689} \end{doclatex} Il est parfois nécessaire d'assigner le résultat à un registre de token au cas où les tokens obtenus contiennent le token de catcode 6 (\verb|#| par défaut) : \begin{doclatex} \newtoks\myresult \toksdo[assign=\myresult] {\S{2} -> \deltok }% supprime les "2" {\def\foo#1{02#120}} \the\myresult% exécute : \def\foo#1{0#10} \foo{A}, \foo{xYz} \end{doclatex} Si l'on avant écrit «\verb|assign = \def\mymacro|», le code qui aurait été exécuté en coulisses est \tktlcode/\def\mymacro{\def\foo#1{0#10}}/ Ce code est illégal en \TeX{} (erreur du type «\verb|Illegal parameter number in definition of \mymacro|»). La clé \verb|collect|, lorsque \verb|false| indique de ne pas collecter les tokens. Cela peut faire sens si le code sur les tokens ayant matché ne les modifie pas. Voici comment compter les voyelles à l'aide d'un compteur : \begin{doclatex} \newcount\voyel \voyel=0 \toksdo[collect=false]{ \S{aeiouy} -> \advance\voyel 1 }{happy texing}<\the\voyel> \end{doclatex} L'argument de \verb|\setcharcode| et de \verb|\setcatcode| est évalué avec la primitive \verb|\numexpr| et donc, toute expression arithmétique acceptée par cette primitive est correcte. Ici, toutes les voyelles sont mises en majuscule : \begin{doclatex} \toksdo{ \S{aeiouy} -> \setcharcode{\selfcharcode + `A - `a} }{Deux plus deux font quatre} \end{doclatex} Voici comment, en 2 passes, extraire les tokens se trouvant dans le plus haut niveau d'imbrication d'accolades : \begin{doclatex} \newcount\nestcnt \nestcnt=0 % compte le niveau d'imbrication \newcount\maxnestcnt \maxnestcnt=0 % est le plus haut niveau d'imbrication \def\mycode{12{34{5{67}8}}9{{ab}c}{{d{e}f}}g} \toksdo[expand arg=1,collect=false]{ \R{*:1} -> \advance\nestcnt1 \ifnum\nestcnt>\maxnestcnt \maxnestcnt=\nestcnt \fi, \R{*:2} -> \advance\nestcnt-1 }{\mycode}Imbrication max = \the\maxnestcnt\par Tokens les plus imbriqués : \toksdo[expand arg=1]{ \R{*:1} -> \advance\nestcnt1 \deltok,% supprimer accolades ouvrantes \R{*:2} -> \advance\nestcnt-1 \deltok,% supprimer accolades fermantes \R{*:*} -> \ifnum\nestcnt<\maxnestcnt \deltok \fi% supprimer tout sauf au plus haut niveau d'imbrication }{\mycode} \end{doclatex} \subsection{Utiliser \texttt{\textbackslash toksdo} et \texttt{\textbackslash addtok}}\label{addtok} Lorsque la clé \verb|collect| est \verb|true|, les tokens sont collectés. Une fois qu'ils ont été traités et éventuellement modifié par \verb|\setcharcode| ou \verb|\setcatcode|, chacun est ajouté tel quel au collecteur interne qui est sollicité en fin de processus pour afficher les tokens ou les assigner si la clé \verb|assign| le spécifie. Il est possible de modifier la façon dont sont ajoutés les tokens au collecteur interne via la macro \verb|\addtok{}|, où \ est un code arbitraire dans lequel \verb|\self|\label{marqueur:self} représente le token lui-même. Par défaut et au début de chaque code qui suit «\hbox{\verb||\Verb| -> |}», la macro \verb|\addtok| est initialisée à sa valeur par défaut: \tktlcode|\addtok{\self}| ce qui signifie que chaque token doit être ajouté tel quel. Si l'on écrit \verb|\addtok{\self\self}|, les tokens ayant matché sont doublés. Avec \verb|\addtok{\fbox{\self}}|, ils sont encadrés à l'aide de la macro \verb|\fbox| de \LaTeX. La macro \verb|\deltok| est équivalente à \verb|\addtok{}|. Dans la majorité des cas, \verb|\self| représente un seul token : celui qui est en cours de traitement. Ce n'est \emph{que} lorsqu'une macro est détokénisée via \verb|\setcatcode{12}| que \verb|\self| représente plusieurs tokens. Dans cet exemple, chaque macro est détokénisée et encadrée, et tous les espaces sont remplacés par «\Verb*| _ |»: \begin{doclatex} \fboxsep=2pt \toksdo{ \R{*:16} -> \setcatcode{12}\addtok{\fbox{\self}},% détokenize et encadre \R{*:10} -> \addtok{ \string_ } }{a b\foo12. 3\baz- 9} \end{doclatex} Chaque chiffre 1 est doublé et chaque 0 est remplacé par un espace : \begin{doclatex} \toksdo{ \S{1} -> \addtok{\self\self}, \S{0} -> \setcatcode{10}% autre possibilité : \addtok{ } }{10110101} \end{doclatex} Les macros \verb|\selfindex|, \verb|\selfcharcode| et \verb|\selfcatcode| ne doivent \emph{pas} être utilisées dans l'argument de \verb|\addtok|, car elles seront ajoutées telles quelles dans le collecteur interne. Ce n'est qu'au moment de l'exécution et après avoir collecté le dernier token qu'elles seront développées, et contiendront à ce moment les données du dernier token. Si l'on souhaite effectuer des tests sur l'index, le charcode ou le catcode du token à ajouter, il faut le faire à l'extérieur de l'argument de \verb|\addtok|. Voici le code source dont le résultat est visible en page~\pageref{encadrerouge}: \begin{doclatex} Dans les tokens «\verb|ab \foo{0 123}c d|», ceux qui matchent avec le motif «\verb|\S{1{a }\foo}|» sont encadrés en rouge :\par \hfill \fboxsep=1.5pt \toksdo{ \S{1{a }\foo} -> \ifnum\selfcatcode=10 % si espace \addtok{{\color{red}\fbox{\strut\textvisiblespace}}}% \else% si pas espace \setcatcode{12}% détokéniser \addtok{{\ttfamily\color{red}\fbox{\strut\self}}}% encadrer en rouge \fi, \R{*:*} -> \addtok{\,{\ttfamily\self}\,}% pour tout autre token, espacer un petit peu }{ab \foo{0 123}c d}% \hfill\null \end{doclatex} \section{Compter les tokens avec {\ttfamily\textbackslash tokscount}}\label{tokscount} La macro \tktlcode/\tokscount[=]{}{}/ compte combien de tokens matchent avec \ dans les \. Si aucun motif n'est spécifié (argument vide), la macro compte tous les tokens. Les \ disponibles sont les suivantes : \begin{center} \renewcommand\arraystretch{1.25} \begin{tabular}{>\ttfamily p{3.5cm}>\ttfamily p{2.5cm}p{8cm}}\hline \rmfamily Clé & \rmfamily Valeur par défaut & Description \\\hline expand arg & 0 & nombre de développements que doit subir l'argument contenant les \ avant d'être pris en compte\\ assign & \ & consigne d 'assignation. Si \, affiche le nombre de tokens ayant matché. Sinon, doit contenir une consigne d'assignation du type \verb|\def| pour assigner à la \ le résultat\\ assign match & \ & consigne d'assignation. Si \ les tokens ayant matché ne sont pas collectés. Sinon, doit contenir une consigne d'assignation \verb|\def| pour les assigner à une macro ou \verb|| pour les assigner à un registre de tokens\\\hline \end{tabular} \end{center} Les \ acceptés par \verb|\tokscount| sont les mêmes que pour \verb|\toksdo|. \begin{doclatex} 1) \tokscount{ \r{a-z} | \S{10} }{ab1023truc098}\quad 2) \tokscount[assign=\def\cc]{ \R{*:16} }{ab\x123truc\zzz0\yy98}<\cc>\quad% compte les macros 3) \tokscount[assign=\def\cc,assign match=\def\xx]{ \S{01} }{1{a01}1{0{b100}}1}<\cc><\xx>\quad% compte les 0 et 1 4) \tokscount{ \R{*:12} | \S{\foo\bar\zid} }{ab\foo c12d*-ef}\quad% compte les tokens "lettre" ou macros \foo\bar\zid 5) \tokscount{}{12{34}5}% compte tous les tokens \end{doclatex} \section{Grammaires PEG} Dans un ensemble de tokens, certains peuvent matcher avec des motifs que l'on peut organiser en grammaire de type PEG (Parsing Expresion Grammar). À chaque fois qu'une correspondance a lieu avec un motif, les tokens ayant matché sont consommés et ne sont plus disponibles pour les motifs suivants (sauf pour les prédicats, voir plus bas). S'il n'y a pas de correspondance, aucun token n'est consommé. \subsection{Les 5 marqueurs de motifs}\label{motifs} Le package \tktl met à disposition 5 motifs élémentaires définis par 5 marqueurs pour construire des motifs plus complexes : \begin{itemize} \item le motif \verb|\r{:}| décrit à la page~\pageref{motif:r}; \item le motif \verb|\R{:}| décrit à la page~\pageref{motif:R}; \item le motif \verb|\S{}| décrit à la page~\pageref{motif:S}; \item le motif \verb|\s{}|\label{motif:s} : tout ensemble de tokens exactement constitué des \ passé en argument de \verb|\s| matche avec ce motif : il s'agit donc d'une correspondance exacte entre chaines de tokens.\par Tout comme avec le marqueur \verb|\S|, il est possible de changer les catcodes de certains tokens à l'aide du marqueur \verb|\c| selon la syntaxe \verb|\c{}{}|; \item le motif \verb|\.|\label{motif:dot} qui matche avec tout token et qui est équivalent à \verb|\R{*:*}|. \end{itemize} \subsection{Répétitions} Chaque \<1-motif> peut être suivi d'un indicateur de répétition si l'on souhaite spécifier le nombre de fois que la correspondance se produit. Les marqueurs de répétition sont : \begin{itemize} \item \verb|^| ou \verb|^{}| : demande à ce que la correspondance se répète exactement le nombre de fois passé en argument de \verb|^|; \item \verb|^{-}| : demande à ce que la correspondance se répète entre \verb|| et \verb||. Si \verb|| est absent, il est compris comme 0. Si \verb|| est absent, il n'y a aucune limite sur nombre de répétition maximal. Les deux nombres ne peuvent pas être absents en même temps. \item «\verb|+|» : 1 ou plusieurs répétitions (est équivalent à \verb|^{1-}|); \item «\verb|*|» : 0 ou plusieurs répétitions (est équivalent à \verb|^{0-}|); \item «\verb|?|» : 0 ou 1 répétition (est équivalent à \verb|^{0-1}|); \end{itemize} Si aucun marqueur de répétition n'est présent après un \<1-motif>, la consigne \verb|^1| est implicitement passée. Il est important de noter que \emph{dans tous les cas}, le plus grand nombre possible de répétitions est consommé ; c'est un comportement qui est toujours «gourmand». \subsection{Prédicats} Chaque \<1-motif> peut être précédé d'un prédicat qui est «\verb|!|» ou «\verb|&|» : \begin{itemize} \item le prédicat \verb|!<1-motif>| matche s'il n'y a pas correspondance avec le \<1-motif> \item le prédicat \verb|&<1-motif>| matche s'il y a correspondance avec le \<1-motif>. \end{itemize} Dans les deux cas, aucun token n'est consommé s'il y a correspondance. \subsection{Concaténation de motifs} Le caractère «\verb|:|» entre 2 \<1-motif> indique de matcher avec le premier \emph{et} le second. On n'est évidemment pas limité à 2 \<1-motif>, il peut y en avoir autant que l'on veut. \begin{tabular}{>\raggedleft p{6cm}p{9cm}} \verb|&\r{0-9}^{3-} : \r{0-9}^2| & s'il y a au moins 3 chiffres, matche avec les 2 premiers\\ \verb|\r{a-z}+ : \R{*:10} : \S{01}^2| & matche avec une ou plusieurs lettres suivies d'un espace suivi de 2 chiffres binaires\\ \verb|\r{1-9}+ : \s{00} : !\.| & matche avec un nombre constitué d'au moins 1 chiffre non nul suivi de "\verb|00|" qui doivent être les \emph{derniers tokens}, car le prédicat «\verb|!\.|» signifie «ne doit pas être suivi d'un token» \end{tabular} \subsection{Choix entre motifs} Le caractère «\verb/|/» entre 2 \<1-motif> indique de matcher avec le premier \emph{ou} avec le second. On n'est évidemment pas limité à 2 motifs, il peut y en avoir autant que l'on veut. Si une correspondance a lieu pour un \<1-motif>, elle est retenue et aucun autre \<1-motif> qui suit ne sera testé : il s'agit donc d'un choix ordonné. Si l'on écrit \tktlcode/\r{0-9}^5 | \S{01}^2/ le 2\ieme{} test ne sera jamais effectué puisqu'il est inclus dans le premier. Il est donc important de commencer par les tests les plus spécifiques et de terminer par les plus généraux si les portées des motifs se chevauchent ou pire sont imbriquées. L'opérateur de concaténation «\verb|:|» est prioritaire sur celui du choix «\verb/|/» et donc \tktlcode/ : | | : / se comprend comme \verb|:| ou \verb|| ou \verb|:|. \subsection{Groupement de motifs} Tout \<1-motif> ou combinaison de \<1-motif> notée \, peut être mis entre accolades pour devenir un nouveau \<1-motif> qui peut, à son tour, être précédé d'un prédicat et suivi d'une spécification de répétitions selon la syntaxe déjà décrite: \tktlcode/{}/ \subsection{Espaces} Dans la syntaxe des motifs, les espaces sont ignorés. Ainsi \tktlcode/\r{0-9} ^ 2 : & \r{a-z}^3 : \r{a-z}^ 2/ est équivalent à \tktlcode/\r{0-9}^2:&\r{a-z}^3:\r{a-z}^2/ \subsection{Priorités} Les priorités entre opérateurs sur les \<1-motif> sont les suivantes (plus le numéro est élevé, plus la priorité l'est) : \begin{center} \renewcommand\arraystretch{1.25} \begin{tabular}{>\ttfamily p{3.5cm}>\ttfamily p{1.5cm}p{8.5cm}}\hline Opérateur & \rmfamily Priorité & Description\\\hline \verb|{}| & 5 & groupement de motifs qui devient un \<1-motif>\\ \verb|<1-motif>?| & 4 & matche 0 ou 1 fois\\ \verb|<1-motif>*| & 4 & matche 0 fois ou plus\\ \verb|<1-motif>+| & 4 & matche 1 fois ou plu\\ \verb|<1-motif>^{n}| & 4 & matche \verb|n| fois\\ \verb|<1-motif>^{a-b}| & 4 & matche entre \verb|a| et \verb|b| fois\\ \verb/!<1-motif>/ & 3 & matche si \<1-motif> ne matche pas, sans consommer de token\\ \verb/&<1-motif>/ & 3 & matche si \<1-motif> matche, sans consommer de token\\ \verb/<1-motif1>:<1-motif2>/ & 2 & matche avec \<1-motif1> puis avec \<1-motif2>\\ \verb/<1-motif1>|<1-motif2>/ & 1 & matche avec \<1-motif1> ou \<1-motif2> (choix ordonné)\\\hline \end{tabular} \end{center} \subsection{Nom des motifs} Tout motif peut être défini et nommé pour réutiliser ce motif ultérieurement avec une syntaxe plus légère et facile à retenir\label{defpattern} : \tktlcode|\defpattern{}| Le \ \emph{doit} être une séquence de contrôle. Cette séquence de contrôle n'est pas définie ou redéfinie par \verb|\defpattern|, c'est également un marqueur dont la signification n'a pas d'importance. Si \ contient un \, ce nom doit avoir été défini auparavant, sans quoi une erreur de compilation se produira. \section{Tester une correspondance avec {\ttfamily\textbackslash ifpegmatch}}\label{ifpegmatch} \subsection{Syntaxe} La macro \verb|\ifpegmatch| a la syntaxe suivante \tktlcode/\ifpegmatch[=]{}{}{}{}/ Lorsque toutes les valeurs sont par défaut, cette macro teste si les \ font matcher des tokens se trouvant en début des \. Les \ disponibles sont : \begin{center} \renewcommand\arraystretch{1.25} \begin{tabular}{>\ttfamily p{3.5cm}>\ttfamily p{3cm}p{8cm}}\hline \rmfamily Clé & \rmfamily Valeur par défaut & Description\\\hline expand arg & 0 & nombre de développements que doit subir l'argument contenant les \ avant d'être pris en compte \\ mode & 1 & mode de recherche de correspondances \\ capture name & \ & nom des captures \\ assign prematch & \verb|\def\prematchtoks| & consigne d'assignation pour les tokens précédant ceux qui ont matché \\ assign match & \verb|\def\matchtoks| & consigne d'assignation pour les tokens ayant matché \\ assign postmatch & \verb|\def\remaintoks| & consigne d'assignation pour les tokens précédant ceux qui ont matché \\\hline \end{tabular} \end{center} Ici, on teste si les \ commencent par 2 chiffres, 1 espace optionnel et au moins 1 lettre minuscule \begin{doclatex} \defpattern\okmatch{ \r{0-9:12}^2 : \R{*:10}? : \r{a-z:11}+ } 1) \ifpegmatch{\okmatch}{73 ab:*ij}{V}{F}\quad 2) \ifpegmatch{\okmatch}{45foobar2000}{V}{F}\quad 3) \ifpegmatch{\okmatch}{854tex 8}{V}{F}\quad 4) \ifpegmatch{\okmatch}{1 2 b3c}{V}{F}\quad \end{doclatex} Construisons une grammaire simple pour tester si un argument commence une opération arithmétique du type \tktlcode// \begin{doclatex} \defpattern\sp{ \R{*:10} } % espace \defpattern\digit{ \r{0-9} }% chiffre \defpattern\posint{ \digit+ }% entier positif \defpattern\int{ \S{+-}? : \posint }% entier relatif \defpattern\op{ \S{+-*/} }% opération math \defpattern\okmatch{ \sp* : \int : \sp* : \op : \sp* : \posint : \sp* } 1) \ifpegmatch\okmatch{2*3}{V}{F}\quad 2) \ifpegmatch\okmatch{-7 + 1 }{V}{F}\quad 3) \ifpegmatch\okmatch{ a + 9 }{V}{F}\quad 4) \ifpegmatch\okmatch{ -2 / 6 + 3 }{V}{F}\quad 5) \ifpegmatch\okmatch{ +2026- 4068}{V}{F}\quad 6) \ifpegmatch\okmatch{ -3 }{V}{F}\quad 7) \ifpegmatch\okmatch{2a-3b}{V}{F}\par La primitive \verb|\int| n'est pas redéfinie : $\int x^2dx$ \end{doclatex} Avec le prédicat «\verb|: !\.|» rajouté à la fin de \verb|\okmatch|, la ligne 4 aurait affiché «F» car il reste «\Verb*|+ 3 |» après les tokens ayant matché. \subsection{Mode} La macro \verb|\ifpegmatch| peut chercher des correspondances selon plusieurs modes, spécifiés via la clé «\verb|mode|» : \begin{itemize} \item par défaut, \verb|mode=1| indique que le match doit se produire au début des \ ; \item \verb|mode=0| indique que tous les \ doivent matcher ; c'est le mode le plus strict ; \item \verb|mode=2| indique que le match peut se produire n'importe où dans les \ ; c'est le mode le moins contraignant. \end{itemize} \subsection{Délivrance de tokens} La macro \verb|\ifpegmatch| renvoie également quelques informations : \begin{itemize} \item par défaut, la macro \verb|\matchtoks| contient les tokens qui ont matché et elle est vide si aucune correspondance n'a été trouvée ; \item par défaut, la macro \verb|\remaintoks| contient les tokens qui restent après ceux qui ont matché; \item par défaut, la macro \verb|\prematchtoks| contient les tokens qui précèdent ceux qui ont matché (ne peut contenir des tokens uniquement lorsque \verb|mode=2|); \item la macro \verb|\matchposition| contient la position du premier token ayant matché et 0 si aucun match ne s'est produit. \end{itemize} \begin{doclatex} 1) \ifpegmatch[mode=0]{ \r{A-Z}^3 }{1ABC6}{V}{F}, match=<\matchtoks>, reste=<\remaintoks>, pos=\matchposition\par 2) \ifpegmatch[mode=1]{ \r{A-Z}^3 }{1ABC6}{V}{F}, match=<\matchtoks>, reste=<\remaintoks>, pos=\matchposition\par 3) \ifpegmatch[mode=2]{ \r{A-Z}^3 }{1ABC6}{V}{F}, match=<\matchtoks>, reste=<\remaintoks>, pos=\matchposition\par 4) \ifpegmatch[mode=0]{ \r{A-Z}^3 }{ZZZ12}{V}{F}, match=<\matchtoks>, reste=<\remaintoks>, pos=\matchposition\par 5) \ifpegmatch[mode=1]{ \r{A-Z}^3 }{ZZZ12}{V}{F}, match=<\matchtoks>, reste=<\remaintoks>, pos=\matchposition\par 6) \ifpegmatch[mode=2]{ \r{A-Z}^3 }{ZZZ12}{V}{F}, match=<\matchtoks>, reste=<\remaintoks>, pos=\matchposition \end{doclatex} \subsection{Captures}\label{marqueur:c:capture} Le marqueur \verb|\c|, lorsqu'il est placé devant un \<1-motif>, indique que les tokens qui matchent avec ce \<1-motif> doivent être capturés ainsi que leur position. Si un \<1-motif> est précédé d'un prédicat, aucune capture n'est faite. Les captures sont rangée dans l'ordre chronologique dans lequel elles ont été faites et sont délivrées, en 2 développements, par \verb|\tokscapture{}| ou par \verb|\tokscapture{:}| . Le \verb|| est optionnel se règle avec la clé \verb|name| et l'\verb|| est le numéro d'ordre de la capture. Si l'\verb|| vaut 0, toutes les captures sont mises entre accolades et listées dans une csv de la forme : \tktlcode/{},{},...,{}/ De la même façon, la macro \verb|\poscapture{}| ou \verb|\poscapture{[:]}| rend les positions de captures à la différence que si \ vaut 0, les positions sont mises dans une csv \emph{sans être mises entre accolades} : \tktlcode/,,...,/ Si un \ dépasse l'index maximal, un message d'erreur est émis. Si \verb|\c| se trouve après un \<1-motif>, seule la position est capturée. Dans cet exemple, 2 captures complètes (tokens+position) et une capture de position sont faites : \begin{doclatex} \ifpegmatch[mode=2]{ \c\r{a-z}+ : \c\r{0-9}^2\c }{12abc666def}{V}{F}\par toks : <\detokenize\expandafter\expandafter\expandafter{\tokscapture{0}}>\qquad 1=<\tokscapture{1}>, 2=<\tokscapture{2}>\par pos : <\poscapture{0}>\qquad 1=<\poscapture{1}>, 2=<\poscapture{2}>, 3=<\poscapture{3}> \end{doclatex} Dans cet exemple, on définit une grammaire qui fait matcher une écriture scientifique de la forme $a\times10^{b}$ et qui capture les deux nombres $a$ et $b$ : \begin{doclatex} \defpattern\sp{ \R{*:10} } \defpattern\sign{ \S{+-} } \defpattern\digit{ \r{0-9} } \defpattern\integer{ \digit+ } \defpattern\decsep{ \S{.,} } \defpattern\scidec{ \sign? : \r{1-9} : {\decsep : \digit+}? } \defpattern\opbr{ \R{*:1} } \defpattern\clbr{ \R{*:2} } \defpattern\^{ \R{*:7} } \defpattern\exponent{ \opbr : \sp? : \c{\sign? : \sp? : \integer} : \sp? : \clbr | \c\digit } \defpattern\sci{\c\scidec : \sp? : \s{\times10} : \sp? : \^ : \sp? :\exponent} 1) \ifpegmatch\sci{3\times10^5} {<\tokscapture{1}> <\tokscapture{2}>}{Faux}\par 2) \ifpegmatch\sci{-2.25\times10^{-3}} {<\tokscapture{1}> <\tokscapture{2}>}{Faux}\par 3) \ifpegmatch\sci{-0.75\times10^7 } {<\tokscapture{1}> <\tokscapture{2}>}{Faux}\par 4) \ifpegmatch\sci{15\times10^0} {<\tokscapture{1}> <\tokscapture{2}>}{Faux}\par 5) \ifpegmatch\sci{1.5\times10^ 1 } {<\tokscapture{1}> <\tokscapture{2}>}{Faux}\par 6) \ifpegmatch\sci{-2.75 \times 10 ^ { 11 }}{<\tokscapture{1}> <\tokscapture{2}>}{Faux}\par 7) \ifpegmatch\sci{-9.96\times10^{ -2 }} {<\tokscapture{1}> <\tokscapture{2}>}{Faux}\par 8) \ifpegmatch\sci{-0\times10 ^0} {<\tokscapture{1}> <\tokscapture{2}>}{Faux}\par 9) \ifpegmatch\sci{-1\times10^ {- 7 }} {<\tokscapture{1}> <\tokscapture{2}>}{Faux} \end{doclatex} \subsection{Grammaires récursives} Le package \tktl admet des grammaires récursives, mais aucune optimisation n'est faite et la façon de les traiter reste naïve. Par conséquent, certaines grammaires récursives, en particulier celles conduisant à des «récursivités à gauche» vont mener à des boucles infinies. Cela étant, il est possible d'utiliser des grammaires récursives, mais y mettre des captures tend à être un peu aléatoire car l'ordre de ces captures n'est pas évident et dépend de la définition même de cette grammaire et donc du parcours de l'arbre qui en découle. Voici une grammaire récursive capturant une expression arithmétique comportant les 4 opérations avec parenthèses : \begin{doclatex} \defpattern\num{ \r{0-9}+ } \defpattern\term{ \num | \s{(} : \expr : \s{)} } \defpattern\factor{ \term : {\S{*/} : \term }* } \defpattern\expr{ \factor : {\S{+-} : \factor }* } 1) \ifpegmatch[mode=0]\expr{1+3}{V}{F}\quad 2) \ifpegmatch[mode=0]\expr{1-2*3}{V}{F}\quad 3) \ifpegmatch[mode=0]\expr{3*4+6}{V}{F}\quad 4) \ifpegmatch[mode=0]\expr{3-(1-2*3)}{V}{F}\quad 5) \ifpegmatch[mode=0]\expr{3*4*(1-3*2-(1-3/7)*3)/(1/7+2*3)*3-5}{V}{F}\quad 6) \ifpegmatch[mode=0]\expr{6-9*(2-3)+4/5}{V}{F} \end{doclatex} Cette grammaire s'assure que l'expression est commence par une parenthèse, contient une expression équilibrée en parenthèses : \begin{doclatex} \defpattern\nobrtext{ { !\S{()} : \. }+ } \defpattern\inparen{ \nobrtext : \inparen* | \s{(} : \inparen* : \s{)} } \defpattern\expr{ &\s{(} : \inparen : !\. }% prédicats -> doit commencer par '(' et finir par ')' 1) \ifpegmatch\expr{a(b)c}{V}{F}\quad 2) \ifpegmatch\expr{(a(abc)()d)}{V}{F}\quad 3) \ifpegmatch\expr{(a(bc))df)}{V}{F}\quad 4) \ifpegmatch\expr{((abc)d((e)f)g)}{V}{F}\quad 5) \ifpegmatch\expr{((foo)b(((b)a)r)}{V}{F} \end{doclatex} \section{Compter les correspondances avec {\ttfamily\textbackslash pegcount}}\label{pegcount} La macro \tktlcode/\pegcount[=]{}{}/ compte combien de fois les \ matchent dans les \. Chaque position est sauvegardée et chaque correspondance est capturée pour être facilement restituée. Aucune capture explicitement demandée par \verb|\c| n'est permise et est ignorée. Les \ disponibles sont : \begin{center} \renewcommand\arraystretch{1.25} \begin{tabular}{>\ttfamily p{3.5cm}>\ttfamily p{2.5cm}p{8cm}}\hline \rmfamily Clé & \rmfamily Valeur par défaut & Description\\\hline expand arg & 0 & nombre de développements que doit subir l'argument contenant les \ avant d'être pris en compte.\\ assign & \ & si vide, affiche le nombre de correspondances. Sinon, doit contenir une consigne d'assignation du type \verb|\def| pour assigne à la \ le résultat.\\ assign positions & \verb|\def\matchposlist| & consigne d'assignation de la liste des positions. Si \ aucune capture n'est effectuée. Sinon, doit contenir une consigne d'assignation \verb|\def| pour assigner la liste des positions à une \\\ name & \ & est le nom des captures qui sont restituées par \verb|\tokscapture|\\\hline \end{tabular} \end{center} Les captures sont délivrées, en 2 développements, par \verb|\tokscapture{[:]}|. Le \verb|| est optionnel se règle avec la clé \verb|name| et l'\verb|| est le numéro d'ordre de la capture. Si l'\verb|| vaut 0, toutes les captures sont mises entre accolades et listées dans une csv de la forme : \tktlcode/{},{},...,{}/ \begin{doclatex} 1) \pegcount{ \r{0-9}+ : \r{a-z}+ }{foo25bar}, <\matchposlist>\par% chiffres suivis de lettres 2) \pegcount{ \r{0-9}+ : \r{a-z}+ }{a12bcd,4b,z875bar}, <\matchposlist>, "\tokscapture{0}", 1="\tokscapture{1}", 2="\tokscapture{2}", 3="\tokscapture{3}"\par% chiffres suivis de lettres 3) \pegcount{ \s{+} : {\r{a-c}^2 : \r{0-9}}+ : \s{+} }{+ab3+..+bb6ab8ca7+..+aa1bb2+..}, <\matchposlist>, 1="\tokscapture{1}", 2="\tokscapture{2}", 3="\tokscapture{3}" \end{doclatex} \section{Remplacements avec {\ttfamily\textbackslash pegreplace}}\label{pegreplace} La macro \tktlcode/\pegreplace[=]{}{}{}/ cherche toutes les correspondances de \ dans les \ et pour chacune remplace les tokens ayant matché par le code défini dans \. Les \ disponibles sont : \begin{center} \renewcommand\arraystretch{1.25} \begin{tabular}{>\ttfamily p{3.5cm}>\ttfamily p{2.5cm}p{8cm}}\hline \rmfamily Clé & \rmfamily Valeur par défaut & Description\\\hline expand arg & 0 & nombre de développements que doit subir l'argument contenant les \ avant d'être pris en compte.\\ all & true & cherche toutes les correspondances si \verb|true| et seulement la première si \verb|false|\\ assign & \ & si vide, affiche le \ obtenus après les avoir fait les remplacements. Sinon, doit contenir une consigne d'assignation pour assigner le résultat à une macro avec \verb|\def| ou à un registre de tokens.\\\hline \end{tabular} \end{center} Le \ est un code arbitraire où peut figurer «\verb|\0|»\label{marqueur:0} qui signifie «tokens qui ont matché», «\verb|\1|» est la première capture faite par \verb|\c|, «\verb|\2|» est la deuxième et ainsi de suite jusqu'à «\verb|\9|». Encadrement de \verb|x| et \verb|y| dans une expression mathématique, puis de \verb|\alpha| et \verb|\beta| avec leur coefficient mais en mode mathématique : \begin{doclatex} \fboxsep=1pt \pegreplace{ \S{xy} }{2x-3y=-4-x+4y}{\fbox{\strut\0}}\par \pegreplace{ \r{1-9}* : \S{\alpha\beta} }{$2\alpha-3\beta=-4-\alpha+4\beta$}{\fbox{\strut$\0$}} \end{doclatex} On créé une grammaire qui matche avec le code postal et le nom d'une ville (composé de mots et de tirets). \begin{doclatex} \defpattern\sp{ \R{*:10} } \defpattern\CP{\c\r{0-9}^2 : \sp? : \c\r{0-9}^3 }% \1=2 premiers chiffres \2=3 derniers \defpattern\upcase{ \r{A-Z,À,É} } \defpattern\lowcase{ \r{a-z,é,è,à,ê,ô,ç} } \defpattern\ville{ \upcase : \lowcase+ : { \S{-} : {\upcase | \lowcase} : \lowcase+ }* } \defpattern\CPville{ \CP : \sp : \c\ville }% capturer CP et capturer Ville 1) \pegreplace\CPville{La ville de 75000 Paris}{CodePostal=\textbf{\1\2} est \fbox{\3}}\par 2) \pegreplace\CPville{Destination 64 500 Saint-Jean-de-Luz suite}{CodePostal=\textbf{\1\2} est \fbox{\3}} \end{doclatex} Crée une petite devinette concernant des nombres ayant de 2 chiffres non nuls : \begin{doclatex} \defpattern\num{ \c\r{1-9} : \c\r{1-9} : !\r{0-9} } Si \pegreplace\num{27, 34 et 43}{\1\2 donne \the\numexpr\1*\2+\2\relax}, que donne 57 ? (Répondez dans 7,5~millions d'années) \end{doclatex} \section{Erreurs} Parmi les nombreuses erreurs qui peuvent se produire, en voici quelques unes... \subsection{Accolades non équilibrées} Si un résultat ou une capture est constitué de tokens dont les accolades ne sont pas équilibrées, une erreur de compilation se produira. Par exemple, si à l'aide de \verb|\toksdo|, on supprime les accolades fermantes : \tktlcode/\toksdo{ \R{*:2} -&> \deltok }{foo{\bfseries123}bar}/ l'erreur émise par \tktl est «\texttt{! Unbalanced open-group token, 1 close-group token added}». Pour équilibrer les accolades, une accolade fermante est donc rajoutée à la fin des tokens passés en argument et les tokens «\verb|foo{\bfseries123bar}|» sont dirigés vers l'affichage. De la même façon, si on supprime les accolades ouvrantes : \tktlcode/\toksdo{ \R{*:1} -&> \deltok}{foo{\bfseries123}bar}/ l'erreur émise est «\texttt{! Unbalanced close-group token ignored}». L'accolade fermante en sur-nombre est donc ignorée et les tokens «\verb|foo\bfseries123bar|» sont dirigés vers l'affichage \subsection{Moteur non adapté} L'utilisation d'un moteur 8~bits \emph{impose} de n'utiliser que des tokens, notamment pour le marqueur \verb|\r|. Compiler ce code avec un moteur 8~bits \tktlcode/\ifpegmatch{ \r{a,e,i,o,u,y,é,à,ê,ù} }{Un été à l'océan}{V}{F}/ provoque une erreur de compilation car «\verb|é|» est constitué de 2 tokens (charcodes 195 et 169, catcodes égaux à 13) alors que la syntaxe de \verb|\r| impose qu'il n'y en ait qu'un. L'erreur de compilation émaise par \tktl est «\texttt{! Multiple token 'é', '0' inserted}». La syntaxe correcte serait \tktlcode/\ifpegmatch{ \r{a,e,i,o,u,y} | \S{éàêù} }{Un été à l'océan}{V}{F}/ \subsection{Intervalle incorrect} Les intervalles de la forme \verb|-|, que \verb|a| et \verb|b| soit des tokens ou des nombres \emph{doivent} être mis dans l'odre. Comme le token «ń» vient \emph{après} «ó» en UTF8, le code \tktlcode/\ifpegmatch{ \r{ń-ó} }{Un texte quelconque}{V}{F}/ provoque l'erreur de compilation «\texttt{! Unsorted interval 'ń-ó', 'ó-ń' inserted}». L'intervalle est corrigé par \tktl. \subsection{Syntaxe de motif non respectée} Espaces mis à part car ils sont ignorés, toute syntaxe de motif non conforme à ce qui a été décrit à partir de la page~\pageref{motifs} provoque une erreur de compilation. Par exemple \tktlcode/\pegcount{ \r{a-z} | S{10} }{ab1023truc098}/ provoque l'erreur «\texttt{! Found "S" when expecting \string\r, \string\R, \string\s, \string\S\space or \string\.}». \subsection{Erreurs de capture} Si un \ n'a pas été défini ou si un \ est demandé hors de ceux assignés lors des captures, une erreur de compilation est renvoyée. \tktlcode/\pegcount{ \r{a-z}^2 }{ab1023truc098}/ crée 3 captures et donc demander \tktlcode/\tokscapture{4}/ envoie l'erreur de compilation «\texttt{! Undefined token capture at index "4"}». \section{Listes des macros et marqueurs} \subsection{Liste des commandes} Voici les macros mises à disposition de l'utilisateur : \begin{itemize} \item \verb|\printtoks|, voir page~\pageref{printtoks}; \item \verb|\toksdo|, \verb|\setcharcode|, \verb|\setcatcode|, \verb|\deltok|, \verb|\addtok|, \verb|\selfcharcode|, \verb|\selfcatcode| et \verb|\selfindex|, voir pages~\pageref{toksdo} et suivantes; \item \verb|\tokscount|, voir page~\pageref{tokscount}; \item \verb|\defpattern|, voir page~\pageref{defpattern}; \item \verb|\ifpegmatch|, voir page~\pageref{ifpegmatch}; \item \verb|\pegcount|, voir page~\pageref{pegcount}; \item \verb|\pegreplace|, voir page~\pageref{pegreplace}. \end{itemize} Les macros suivantes sont modifiées par la macro \verb|\toksdo|, mais sont cependant restaurées à leur état antérieur après la fin de l'exécution de \verb|\toksdo| : \verb|\setcharcode|, \verb|\setcatcode|, \verb|\deltok|, \verb|\addtok|, \verb|\selfcharcode|, \verb|\selfcatcode| et \verb|\selfindex|. \subsection{Liste des marqueurs} \begin{itemize}[topsep=0pt] \item\verb|\r{:}|, voir page~\pageref{motif:r}; \item\verb|\R{:}|, voir page~\pageref{motif:R}; \item\verb|\s{}|, voir page~\pageref{motif:s}; \item\verb|\S{}|, voir page~\pageref{motif:S}; \item\verb|\.|, voir page~\pageref{motif:dot}; \item\verb|\c| peut avoir la syntaxe \begin{itemize}[label={}] \item \verb|\c{}{}| lorsque utilisé dans l'argument de \verb|\s| ou \verb|\S|, voir page~\pageref{marqueur:c:catcode}; \item \verb|\c| lorsque placé avant ou après un \<1-motif>, voir page~\pageref{marqueur:c:capture}; \end{itemize} \item\verb|\self|, voir page~\pageref{marqueur:self}; \item \verb|\0|, \verb|\1| jusqu'à \verb|\9|, voir page~\pageref{marqueur:0}. \end{itemize} \begin{center} \parskip0pt $\star$\par $\star\quad\star$ \end{center} Ce package en version \tktlver{} se trouve encore à un stade expérimental et il est très probable que, malgré les tests qui ont été faits, il contienne de nombreux bugs. Par ailleurs, certaines fonctionnalités ou syntaxes peuvent encore évoluer. Quoiqu'il en soit, j'espère que \tktl vous est utile. N'hésitez pas à me contacter par \href{mailto:unbonpetit@netc.fr}{\texttt{\textbf{email}}} pour me faire part de bugs, dysfonctionnements ou suggestions de fonctionnalités \emph{réalistes} et surtout, ne perdez pas votre temps à le faire sur \verb|https://tex.stackexchange.com| ou tout autre site. \end{document}