texlive[70446] branches/branch2023.final/Master/texmf-dist: piton

commits+karl at tug.org commits+karl at tug.org
Wed Mar 6 22:09:36 CET 2024


Revision: 70446
          https://tug.org/svn/texlive?view=revision&revision=70446
Author:   karl
Date:     2024-03-06 22:09:36 +0100 (Wed, 06 Mar 2024)
Log Message:
-----------
piton (branch) (6mar24)

Modified Paths:
--------------
    branches/branch2023.final/Master/texmf-dist/doc/lualatex/piton/piton-french.pdf
    branches/branch2023.final/Master/texmf-dist/doc/lualatex/piton/piton-french.tex
    branches/branch2023.final/Master/texmf-dist/doc/lualatex/piton/piton.pdf
    branches/branch2023.final/Master/texmf-dist/source/lualatex/piton/piton.dtx
    branches/branch2023.final/Master/texmf-dist/tex/lualatex/piton/piton.lua
    branches/branch2023.final/Master/texmf-dist/tex/lualatex/piton/piton.sty

Modified: branches/branch2023.final/Master/texmf-dist/doc/lualatex/piton/piton-french.pdf
===================================================================
(Binary files differ)

Modified: branches/branch2023.final/Master/texmf-dist/doc/lualatex/piton/piton-french.tex
===================================================================
--- branches/branch2023.final/Master/texmf-dist/doc/lualatex/piton/piton-french.tex	2024-03-06 21:09:27 UTC (rev 70445)
+++ branches/branch2023.final/Master/texmf-dist/doc/lualatex/piton/piton-french.tex	2024-03-06 21:09:36 UTC (rev 70446)
@@ -360,15 +360,16 @@
 \item \index{path-write} \colorbox{yellow!50}{\bfseries Nouveau 2.5}\enskip La clé \Definition{path-write} indique
 un chemin où seront écrits les fichiers écrits par l'emploi de la clé |write| précédente.
 
-\item \index{line-numbers} La clé \Definition{line-numbers} active la numérotation des lignes (en débordement à gauche) dans les
-environnements |{Piton}| et dans les listings produits par la commande |\PitonInputFile|.
+\item \index{line-numbers} La clé \Definition{line-numbers} active la numérotation des lignes (en débordement à
+gauche) dans les environnements |{Piton}| et dans les listings produits par la commande |\PitonInputFile|.
 
 Cette clé propose en fait plusieurs sous-clés.
 \begin{itemize}
-\item La clé \Definition{line-numbers/skip-empty-lines} demande que les lignes vides soient considérées comme non existantes en
-ce qui concerne la numérotation des lignes (si la clé |/absolute| est active, la clé |/skip-empty-lines|
-n'a pas d'effet dans |\PitonInputFile|). La valeur initiale de cette clé est |true| (et non
-|false|).\footnote{Avec le langage Python, les lignes vides des \emph{docstrings} sont prises en compte.}
+\item La clé \Definition{line-numbers/skip-empty-lines} demande que les lignes vides (qui ne contiennent que des
+espaces) soient considérées comme non existantes en ce qui concerne la numérotation des lignes (si la clé
+|/absolute| est active, la clé |/skip-empty-lines| n'a pas d'effet dans |\PitonInputFile|). La valeur initiale de
+cette clé est |true| (et non |false|).\footnote{Avec le langage Python, les lignes vides des \emph{docstrings} sont
+  prises en compte.}
 
 \item La clé \Definition{line/numbers/label-empty-lines} demande que les labels (c'est-à-dire les numéros) des lignes vides
 soient affichés. Si la clé |/skip-empty-lines| est active, la clé |/label-empty-lines| est sans effet. La
@@ -383,7 +384,7 @@
 
 \item La clé \Definition{line-numbers/start} impose que la numérotation commence à ce numéro. 
 
-\item La clé \Definition{sep} est la distance horizontale entre les numéros de lignes (insérés par |line-numbers|)
+\item La clé \Definition{line-numbers/sep} est la distance horizontale entre les numéros de lignes (insérés par |line-numbers|)
 et les lignes du code informatique. La valeur initiale est 0.7~em.
 \end{itemize}
 
@@ -451,9 +452,10 @@
 Exemple : \piton{my_string = 'Très bonne réponse'}
 \endgroup
 
-\item \index{show-spaces} Avec la clé \Definition{show-spaces}, tous les espaces sont matérialisés (et aucune coupure de ligne ne peut
-plus intervenir sur ces espaces matérialisés, même si la clé |break-lines|\footnote{cf. \ref{line-breaks}
-  p.~\pageref{line-breaks}.} est active).
+\item \index{show-spaces} Avec la clé \Definition{show-spaces}, tous les espaces sont matérialisés (et aucune
+coupure de ligne ne peut plus intervenir sur ces espaces matérialisés, même si la clé |break-lines|\footnote{cf.
+  \ref{line-breaks} p.~\pageref{line-breaks}.} est active). Il faut néanmoins remarquer que les espaces en fin de
+ligne sont tous supprimés par \pkg{piton}. Les tabulations de début de ligne sont représentées par des flèches.
 \end{itemize}
 
 \bigskip
@@ -1558,7 +1560,7 @@
 |piton.get_last_code()|. Cela s'applique aux commandes LaTeX déclarées par la clé |detected-commands| (cf.
 partie~\ref{detected-commands}) et aux éléments insérés avec le mécanisme «|escape|» (cf. partie~\ref{escape}).
 
-\item |piton.get_last_code| est une fonction Lua et non une chaîne de caracètres : les traitements présentés
+\item |piton.get_last_code| est une fonction Lua et non une chaîne de caractères : les traitements présentés
 précédemment son exécutés lorsque la fonction est appelée. De ce fait, il peut être judicieux de sotcker la valeur
 renvoyée par |piton.get_last_code()| dans une variable Lua si on doit l'utiliser plusieurs fois.
 \end{itemize}
@@ -1660,7 +1662,7 @@
 \vspace{1cm}
 On peut aussi faire afficher les commentaires dans une deuxième colonne à droite si on limite la largeur du code
 proprement dit avec la clé |width|. Dans l'exemple qui suit, on utilise la clé |width| avec la valeur
-spéciale~|min|. 
+spéciale~|min|. Plusieurs compilations sont nécessaires.
 
 
 \begingroup

Modified: branches/branch2023.final/Master/texmf-dist/doc/lualatex/piton/piton.pdf
===================================================================
(Binary files differ)

Modified: branches/branch2023.final/Master/texmf-dist/source/lualatex/piton/piton.dtx
===================================================================
--- branches/branch2023.final/Master/texmf-dist/source/lualatex/piton/piton.dtx	2024-03-06 21:09:27 UTC (rev 70445)
+++ branches/branch2023.final/Master/texmf-dist/source/lualatex/piton/piton.dtx	2024-03-06 21:09:36 UTC (rev 70446)
@@ -72,12 +72,12 @@
 % \iffalse
 %<*STY>
 % \fi
-\def\PitonFileVersion{2.6}
-\def\PitonFileDate{2024/02/27}
+\def\PitonFileVersion{2.6a}
+\def\PitonFileDate{2024/03/06}
 % \iffalse
 %</STY>
 %<*LUA>
--- Version 2.6 of 2024/02/27
+-- Version 2.6a of 2024/03/06
 %</LUA>
 %\fi
 %
@@ -372,11 +372,11 @@
 % In fact, the key |line-numbers| has several subkeys.
 % \begin{itemize}
 % \item With the key \Definition{line-numbers/skip-empty-lines}, the empty lines
-% are considered as non existent for the line numbering (if the key |/absolute|
-% is in force, the key |/skip-empty-lines| is no-op in |\PitonInputFile|). The
-% initial value of that key is |true| (and not |false|).\footnote{For the
-% language Python, the empty lines in the docstrings are taken into account (by
-% design).}
+% (which contains only spaces) are considered as non existent for the line
+% numbering (if the key |/absolute| is in force, the key |/skip-empty-lines| is
+% no-op in |\PitonInputFile|). The initial value of that key is |true| (and not
+% |false|).\footnote{For the language Python, the empty lines in the docstrings
+% are taken into account (by design).}
 % \item With the key \Definition{line-numbers/label-empty-lines}, the labels
 % (that is to say the numbers) of the empty lines are displayed. If the key
 % |/skip-empty-line| is in force, the clé |/label-empty-lines| is no-op. The
@@ -479,7 +479,9 @@
 % With the key \index{show-spaces} \Definition{show-spaces}, all the spaces are
 % replaced by U+2423 (and no line break can occur on those ``visible spaces'',
 % even when the key |break-lines|\footnote{cf. \ref{line-breaks}
-% p.~\pageref{line-breaks}} is in force).
+% p.~\pageref{line-breaks}} is in force). By the way, one should remark that all
+% the trailing spaces (at the end of a line) are deleted by \pkg{piton}. The
+% tabulations at the beginning of the lines are represented by arrows.
 % \end{itemize}
 %
 % \bigskip
@@ -1742,8 +1744,8 @@
 % It's also possible to display these LaTeX comments in a kind of second column
 % by limiting the width of the Python code with the key |width|. In the
 % following example, we use the key |width| with the special value~|min|.
+% Several compilations are required.
 %
-%
 % \begingroup
 % \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
 % \begin{Verbatim}
@@ -2282,7 +2284,7 @@
 % \midrule
 % Number & the numbers \\
 % String & the strings (between \texttt{"}) \\
-% Comment & les comments (which begins with |#|) \\
+% Comment & the comments (which begin with |#|) \\
 % Comment.LaTeX &  the comments beginning with \texttt{\#>}, which are composed by
 %   \pkg{piton} as LaTeX code (merely named ``LaTeX comments'' in this document) \\
 % \bottomrule
@@ -2583,7 +2585,8 @@
 %    \begin{macrocode}
 \@ifclassloaded { beamer } { \bool_gset_true:N \g_@@_beamer_bool } { }
 \@ifpackageloaded { beamerarticle } { \bool_gset_true:N \g_@@_beamer_bool } { }
-\bool_if:NT \g_@@_beamer_bool { \lua_now:n { piton_beamer = true } } 
+\lua_now:n { piton = piton~or~{ } }
+\bool_if:NT \g_@@_beamer_bool { \lua_now:n { piton.beamer = true } } 
 %    \end{macrocode}
 % 
 % \bigskip
@@ -2674,7 +2677,6 @@
 %    \begin{macrocode}
 \lua_now:n 
   { 
-    piton = piton~or { } 
     piton.ListCommands = lpeg.P ( false ) 
     piton.last_code = ''
     piton.last_language = ''
@@ -2948,6 +2950,22 @@
   }
 \@@_set_tab_tl:n { 4 }
 %    \end{macrocode}
+%
+% \medskip
+% When the key |show-spaces| is in force, |\l_@@_tab_tl| will be replaced by an
+% arrow by using the following command.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_convert_tab_tl:
+  {
+    \hbox_set:Nn \l_tmpa_box { \l_@@_tab_tl }
+    \dim_set:Nn \l_tmpa_dim { \box_wd:N \l_tmpa_box }
+    \tl_set:Nn \l_@@_tab_tl 
+      { 
+        \( \mathcolor { gray } 
+             { \hbox_to_wd:nn \l_tmpa_dim { \rightarrowfill } \) } 
+      }
+  }
+%    \end{macrocode}
 % 
 % \medskip
 % The following integer corresponds to the key |gobble|.
@@ -2956,9 +2974,10 @@
 %    \end{macrocode}
 %
 % \medskip
+% The following token list will be used only for the spaces in the strings.
 %    \begin{macrocode}
 \tl_new:N \l_@@_space_tl
-\tl_set:Nn \l_@@_space_tl { ~ } 
+\tl_set_eq:NN \l_@@_space_tl \nobreakspace 
 %    \end{macrocode}
 % 
 %
@@ -3126,6 +3145,7 @@
 % Now, we add the potential number of line, the potential left margin and the
 % potential background.
 %    \begin{macrocode}
+    \tl_log:n { Contenu : #1.}
     \hbox_set:Nn \l_tmpa_box 
       { 
         \skip_horizontal:N \l_@@_left_margin_dim
@@ -3137,7 +3157,7 @@
                 && 
                 \l_@@_skip_empty_lines_bool 
               }
-              { \int_gincr:N \g_@@_visual_line_int}
+              { \int_gincr:N \g_@@_visual_line_int }
 
             \bool_if:nT
               { 
@@ -3280,9 +3300,9 @@
           { \l_@@_nb_lines_int - \g_@@_line_int } > \l_@@_splittable_int 
           {
             \egroup
-            \bool_if:NT \g_@@_footnote_bool { \end { savenotes } } 
+            \bool_if:NT \g_@@_footnote_bool { \endsavenotes } 
             \par \mode_leave_vertical: 
-            \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } } 
+            \bool_if:NT \g_@@_footnote_bool { \savenotes } 
             \vtop \bgroup
           }
      }
@@ -3522,8 +3542,10 @@
 
     tab-size         .code:n            = \@@_set_tab_tl:n { #1 } ,
     tab-size         .value_required:n  = true , 
-    show-spaces      .bool_set:N        = \l_@@_show_spaces_bool , 
-    show-spaces      .default:n         = true , 
+    show-spaces      .code:n            = 
+         \bool_set_true:N \l_@@_show_spaces_bool 
+         \@@_convert_tab_tl: ,
+    show-spaces      .value_forbidden:n = true ,
     show-spaces-in-strings .code:n      = \tl_set:Nn \l_@@_space_tl { ␣ } , % U+2423
     show-spaces-in-strings .value_forbidden:n = true ,
     break-lines-in-Piton .bool_set:N    = \l_@@_break_lines_in_Piton_bool ,
@@ -3683,6 +3705,12 @@
 %
 % \bigskip
 %    \begin{macrocode}
+\NewDocumentCommand { \NewPitonLanguage } { m m }
+  { \lua_now:e { piton.new_language("#1","\lua_escape:n{#2}") } }
+%    \end{macrocode}
+% 
+% \bigskip
+%    \begin{macrocode}
 \NewDocumentCommand { \piton } { }
   { \peek_meaning:NTF \bgroup \@@_piton_standard \@@_piton_verbatim }
 %    \end{macrocode}
@@ -3715,7 +3743,9 @@
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
 %    \end{macrocode}
 % The following code replaces the characters U+0020 (spaces) by characters
-% U+0020 of catcode~10: thus, they become breakable by an end of line.
+% U+0020 of catcode~10: thus, they become breakable by an end of line. Maybe,
+% this programmation is not very efficient but the key |break-lines-in-piton|
+% will be rarely used.
 %    \begin{macrocode}
       {
         \bool_if:NT \l_@@_break_lines_in_piton_bool
@@ -3973,7 +4003,7 @@
 %    \end{macrocode}
 % We count with Lua the number of lines of the argument. The result will be
 % stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow
-% or disallow page breaks.
+% or disallow page breaks. We use the technic of |token.scan_argument| for optimisation.
 %    \begin{macrocode}
             \lua_now:n { piton.CountLines(token.scan_argument()) } { ##1 }  
 %    \end{macrocode}
@@ -3988,7 +4018,7 @@
 % |\g_@@_footnote_bool| is raised when the package \pkg{piton} has been loaded
 % with the key |footnote| \emph{or} the key |footnotehyper|.
 %    \begin{macrocode}
-            \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } } 
+            \bool_if:NT \g_@@_footnote_bool { \savenotes } 
 %    \end{macrocode}
 % 
 % Now, the key |write|.
@@ -4008,20 +4038,23 @@
                     \seq_gput_left:NV \g_@@_write_seq \l_@@_write_str
                   }
               }  
-            \vbox \bgroup 
+            \vtop \bgroup % modified 2024/03/02
+%    \end{macrocode}
+% Now, the main job. We use |token.scan_argument()| for optimisation.
+%    \begin{macrocode}
             \lua_now:e 
               { 
                 piton.GobbleParse
                   ( 
                     '\l_piton_language_str' , 
-                    \int_use:N \l_@@_gobble_int , 
-                    token.scan_argument() 
+                    \int_use:N \l_@@_gobble_int ,
+                    token.scan_argument ( )
                   ) 
               } 
               { ##1 }
             \vspace { 2.5 pt } 
             \egroup
-            \bool_if:NT \g_@@_footnote_bool { \end { savenotes } } 
+            \bool_if:NT \g_@@_footnote_bool { \endsavenotes } 
 %    \end{macrocode}
 % If the user has used the key |width| with the special value~|min|, we write on
 % the |aux| file the value of |\l_@@_line_width_dim| (largest width of the lines
@@ -4075,15 +4108,15 @@
 % Now, we define the environment |{Piton}|, which is the main environment
 % provided by the package \pkg{piton}. Of course, you use
 % |\NewPitonEnvironment|. 
-%    \begin{macrocode}
+%    \begin{macrocode} 
 \bool_if:NTF \g_@@_beamer_bool
   {
     \NewPitonEnvironment { Piton } { d < > O { } }
       { 
         \keys_set:nn { PitonOptions } { #2 } 
-        \IfValueTF { #1 }
+        \tl_if_novalue:nTF { #1 }
+          { \begin { uncoverenv } }
           { \begin { uncoverenv } < #1 > }
-          { \begin { uncoverenv } }
       }
       { \end { uncoverenv } } 
   }
@@ -4116,7 +4149,8 @@
   }
 %    \end{macrocode}
 %
-% The following command uses as implicit argument the name of the file in |\l_@@_file_name_str|.
+% The following command uses as implicit argument the name of the file in
+% |\l_@@_file_name_str|. 
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_input_file:nn #1 #2 
   {
@@ -4185,7 +4219,7 @@
 % stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow
 % or disallow page breaks.
 %    \begin{macrocode}
-      \lua_now:e { piton.CountLinesFile('\l_@@_file_name_str') } 
+      \lua_now:e { piton.CountLinesFile ( '\l_@@_file_name_str' ) } 
 %    \end{macrocode}
 % The first argument of the following function is the name of the Lua function
 % that will be applied to the second argument in order to count the number of lines.
@@ -4193,7 +4227,7 @@
       \@@_compute_left_margin:no { CountNonEmptyLinesFile } \l_@@_file_name_str
       \@@_compute_width:
       \ttfamily
-      \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } } 
+      \bool_if:NT \g_@@_footnote_bool { \savenotes } 
       \vtop \bgroup 
       \lua_now:e
         { 
@@ -4204,7 +4238,7 @@
            \int_use:N \l_@@_last_line_int ) 
         } 
       \egroup 
-      \bool_if:NT \g_@@_footnote_bool { \end { savenotes } } 
+      \bool_if:NT \g_@@_footnote_bool { \endsavenotes } 
       \bool_if:NT \l_@@_width_min_bool \@@_width_to_aux:
     \group_end:
 %    \end{macrocode}
@@ -4433,7 +4467,7 @@
 \NewDocumentCommand { \SetPitonIdentifier } { o m m } 
   { 
     \clist_set:Nn \l_tmpa_clist { #2 }
-    \IfNoValueTF { #1 }
+    \tl_if_novalue:nTF { #1 }
       { 
         \clist_map_inline:Nn \l_tmpa_clist 
           { \cs_set:cpn { pitonIdentifier _ ##1 } { #3 } }
@@ -4680,18 +4714,13 @@
 %   \begin{macrocode}
 \@@_msg_new:nn { syntax~error }
   {
-    Your~code~of~the~language~"\l_piton_language_str"~is~not~syntactically~correct.\\ 
+    Your~code~of~the~language~"\l_piton_language_str"~is~not~
+    syntactically~correct.\\  
     It~won't~be~printed~in~the~PDF~file.
   }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\NewDocumentCommand \PitonSyntaxError { }
-  { \@@_error:n { syntax~error } }
-%    \end{macrocode}
-%
-%
-%    \begin{macrocode}
 \@@_msg_new:nn { begin~marker~not~found }
   {
     Marker~not~found.\\
@@ -4713,13 +4742,6 @@
   }
 %    \end{macrocode}
 % 
-%
-%    \begin{macrocode}
-\NewDocumentCommand \PitonBeginMarkerNotFound { } 
-  { \@@_error:n { begin~marker~not~found } }
-\NewDocumentCommand \PitonEndMarkerNotFound { } 
-  { \@@_error:n { end~marker~not~found } }
-%    \end{macrocode}
 % 
 %    \begin{macrocode}
 \@@_msg_new:nn { Unknown~file }
@@ -4832,7 +4854,7 @@
           end
     local my_lpeg = 
       P {  "E" ,
-           E = ( V "F" * ( P "," * V "F" ) ^ 0 ) / add ,
+           E = ( V "F" * ( "," * V "F" ) ^ 0 ) / add ,
            F = space ^ 0 * ( alpha ^ 1 ) / "\\%0" * space ^ 0 
         }
     function piton.addListCommands( key_value )
@@ -4880,7 +4902,7 @@
 % define first aliases for several functions of that library.
 %    \begin{macrocode}
 local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc
-local Cs , Cg , Cmt , Cb = lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb
+local Cs , Cg , Cmt , Cb = lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb 
 local R = lpeg.R
 %    \end{macrocode}
 %
@@ -4893,7 +4915,7 @@
 % of the Python listings that \pkg{piton} will typeset verbatim (thanks to the
 % catcode ``other''). 
 %    \begin{macrocode}
-local function Q(pattern)
+local function Q ( pattern )
   return Ct ( Cc ( luatexbase.catcodetables.CatcodeTableOther ) * C ( pattern ) )
 end 
 %    \end{macrocode}
@@ -4907,7 +4929,7 @@
 % comments'' in the environments |{Piton}| and the elements beetween 
 % |begin-escape| and |end-escape|. That function won't be much used.
 %    \begin{macrocode}
-local function L(pattern)
+local function L ( pattern )
   return Ct ( C ( pattern ) ) 
 end
 %    \end{macrocode}
@@ -4920,7 +4942,7 @@
 % in order to do the syntactic highlighting (that's the main job of
 % \pkg{piton}). That function will be widely used.
 %    \begin{macrocode}
-local function Lc(string)
+local function Lc ( string )
   return Cc ( { luatexbase.catcodetables.expl , string } ) 
 end 
 %    \end{macrocode}
@@ -4932,12 +4954,12 @@
 % Python chunk). The first argument is a Lua string corresponding to the name of
 % a \pkg{piton} style and the second element is a pattern (that is to say a
 % \textsc{lpeg} without capture)
-%    \begin{macrocode}
-local function K(style, pattern)
+%    \begin{macrocode}e
+local function K ( style , pattern )
   return
      Lc ( "{\\PitonStyle{" .. style .. "}{" )
      * Q ( pattern )
-     * Lc ( "}}" )
+     * Lc "}}"
 end
 %    \end{macrocode}
 % The formatting commands in a given \pkg{piton} style (eg. the style |Keyword|)
@@ -4951,7 +4973,7 @@
 % The following function |WithStyle| is similar to the function |K| but should
 % be used for multi-lines elements. 
 %    \begin{macrocode}
-local function WithStyle(style,pattern)
+local function WithStyle ( style , pattern )
   return 
        Ct ( Cc "Open" * Cc ( "{\\PitonStyle{" .. style .. "}{" ) * Cc "}}" ) 
      * pattern 
@@ -4968,17 +4990,17 @@
 if piton.begin_escape ~= nil
 then 
   Escape = 
-    P(piton.begin_escape)
-    * L ( ( 1 - P(piton.end_escape) ) ^ 1 ) 
-    * P(piton.end_escape)
+    P ( piton.begin_escape )
+    * L ( ( 1 - P ( piton.end_escape ) ) ^ 1 ) 
+    * P ( piton.end_escape )
 %    \end{macrocode}
 % The LPEG |EscapeClean| will be used in the LPEG Clean (and that LPEG is used
 % to ``clean'' the code by removing the formatting elements).
 %    \begin{macrocode}
   EscapeClean = 
-    P(piton.begin_escape)
-    * ( 1 - P(piton.end_escape) ) ^ 1 
-    * P(piton.end_escape)
+    P ( piton.begin_escape )
+    * ( 1 - P ( piton.end_escape ) ) ^ 1 
+    * P ( piton.end_escape )
 end
 %    \end{macrocode}
 % 
@@ -4987,11 +5009,11 @@
 if piton.begin_escape_math ~= nil
 then 
   EscapeMath = 
-    P(piton.begin_escape_math)
-    * Lc ( "\\ensuremath{" ) 
+    P ( piton.begin_escape_math )
+    * Lc "\\ensuremath{" 
     * L ( ( 1 - P(piton.end_escape_math) ) ^ 1 )
     * Lc ( "}" ) 
-    * P(piton.end_escape_math)
+    * P ( piton.end_escape_math )
 end
 %    \end{macrocode}
 % 
@@ -5005,7 +5027,7 @@
 % \paragraph{The basic syntactic LPEG}
 %
 %    \begin{macrocode}
-local alpha, digit = lpeg.alpha, lpeg.digit
+local alpha , digit = lpeg.alpha , lpeg.digit
 local space = P " " 
 %    \end{macrocode}
 %
@@ -5013,10 +5035,9 @@
 % |ç|, etc. are in fact strings of length 2 (2 bytes) because \pkg{lpeg} is not
 % Unicode-aware. 
 %    \begin{macrocode}
-local letter = alpha + P "_" 
-  + P "â" + P "à" + P "ç" + P "é" + P "è" + P "ê" + P "ë" + P "ï" + P "î" 
-  + P "ô" + P "û" + P "ü" + P "Â" + P "À" + P "Ç" + P "É" + P "È" + P "Ê" 
-  + P "Ë" + P "Ï" + P "Î" + P "Ô" + P "Û" + P "Ü" 
+local letter = alpha + "_" + "â" + "à" + "ç" + "é" + "è" + "ê" + "ë" + "ï" + "î"
+                    + "ô" + "û" + "ü" + "Â" + "À" + "Ç" + "É" + "È" + "Ê" + "Ë"
+                    + "Ï" + "Î" + "Ô" + "Û" + "Ü"
 
 local alphanum = letter + digit
 %    \end{macrocode}
@@ -5052,9 +5073,11 @@
 %    \begin{macrocode}
 local Number =
   K ( 'Number' ,
-      ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 )
-      * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1
-      + digit^1 
+      ( digit ^ 1 * P "." * # ( 1 - P "." ) * digit ^ 0 
+        + digit ^ 0 * P "." * digit ^ 1 
+        + digit ^ 1 )
+      * ( S "eE" * S "+-" ^ -1 * digit ^ 1 ) ^ -1
+      + digit ^ 1 
     ) 
 %    \end{macrocode}
 %
@@ -5064,7 +5087,7 @@
 %    \begin{macrocode}
 local Word
 if piton.begin_escape ~= nil 
-then Word = Q ( ( ( 1 - space - P(piton.begin_escape) - P(piton.end_escape) ) 
+then Word = Q ( ( ( 1 - space - P ( piton.begin_escape ) - P ( piton.end_escape ) ) 
                    - S "'\"\r[({})]" - digit ) ^ 1 )
 else Word = Q ( ( ( 1 - space ) - S "'\"\r[({})]" - digit ) ^ 1 )
 end
@@ -5072,21 +5095,20 @@
 %
 % \bigskip
 %    \begin{macrocode}
-local Space = ( Q " " ) ^ 1
+local Space = Q " " ^ 1
 
-local SkipSpace = ( Q " " ) ^ 0 
+local SkipSpace = Q " " ^ 0 
 
 local Punct = Q ( S ".,:;!" )
 
-local Tab = P "\t" * Lc ( '\\l_@@_tab_tl' )
+local Tab = "\t" * Lc "\\l_@@_tab_tl"
 %    \end{macrocode}
 % 
 % \bigskip
 %    \begin{macrocode}
-local SpaceIndentation = Lc ( '\\@@_an_indentation_space:' ) * ( Q " " )
+local SpaceIndentation = Lc "\\@@_an_indentation_space:" * Q " "
 %    \end{macrocode}
 %
-%
 % \bigskip
 %    \begin{macrocode}
 local Delim = Q ( S "[({})]" )
@@ -5101,8 +5123,71 @@
 %    \begin{macrocode}
 local VisualSpace = space * Lc "\\l_@@_space_tl" 
 %    \end{macrocode}
+%
+% \bigskip
+% \paragraph{Several tools for the construction of the main LPEG}
+%
+%    \begin{macrocode}
+local LPEG1 = { }
+local LPEG2 = { }
+local LPEG_cleaner = { }
+%    \end{macrocode}
+%
+% \bigskip
+% For each language, we will need a pattern to match expressions with balanced
+% braces. Those balanced braces must \emph{not} take into account the braces
+% present in strings of the language. However, the syntax for the strings is
+% language-dependent. That's why we write a Lua function |Compute_braces| which
+% will compute the pattern by taking in as argument a pattern for the strings of
+% the language (at least the shorts strings).
+%    \begin{macrocode}
+local function Compute_braces ( lpeg_string ) return 
+    P { "E" ,
+         E = 
+             (
+               P "{" * V "E" * P "}" 
+               + 
+               lpeg_string
+               + 
+               ( 1 - S "{}" ) 
+             ) ^ 0 
+      }
+end 
+%    \end{macrocode}
+%
+% \bigskip
+% The following Lua function will compute the \text{lpeg} |DetectedCommands|
+% which is a \textsc{lpeg} with captures).
+%    \begin{macrocode}
+local function Compute_DetectedCommands ( lang , braces ) return 
+  Ct ( Cc "Open" 
+        * C ( piton.ListCommands * P "{" ) 
+        * Cc "}" 
+     ) 
+   * ( braces / (function ( s ) return LPEG1[lang] : match ( s ) end ) )
+   * P "}" 
+   * Ct ( Cc "Close" ) 
+end
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+local function Compute_LPEG_cleaner ( lang , braces ) return 
+  Ct ( ( piton.ListCommands * P "{" 
+          * (  braces 
+              / ( function ( s ) return LPEG_cleaner[lang] : match ( s ) end ) )
+          * P "}" 
+         + EscapeClean
+         +  C ( P ( 1 ) )
+        ) ^ 0 ) / table.concat 
+end
+%    \end{macrocode}
 % 
+%
 % \bigskip
+% \paragraph{Constructions for Beamer}
+%
+% \bigskip
 % If the classe Beamer is used, some environemnts and commands of Beamer are
 % automatically detected in the listings of \pkg{piton}.
 %    \begin{macrocode}
@@ -5109,67 +5194,210 @@
 local Beamer = P ( false ) 
 local BeamerBeginEnvironments = P ( true ) 
 local BeamerEndEnvironments = P ( true ) 
-if piton_beamer 
-then
+%    \end{macrocode}
+%
 % \bigskip
-% The following function will return a \textsc{lpeg} which will catch an
-% environment of Beamer (supported by \pkg{piton}), that is to say |{uncover}|,
-% |{only}|, etc.
 %    \begin{macrocode}
-  local BeamerNamesEnvironments =  
-    P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv" 
-    + P "alertenv" + P "actionenv"
-  BeamerBeginEnvironments = 
-      ( space ^ 0 * 
-        L 
-          ( 
-            P "\\begin{" * BeamerNamesEnvironments * "}"
-            * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
-          )
-        * P "\r" 
-      ) ^ 0 
-  BeamerEndEnvironments = 
-      ( space ^ 0 * 
-        L ( P "\\end{" * BeamerNamesEnvironments * P "}" ) 
-        * P "\r" 
-      ) ^ 0 
+local list_beamer_env =
+  { "uncoverenv" , "onlyenv" , "visibleenv" , "invisibleenv" , "alertenv" , "actionenv" }
 %    \end{macrocode}
 %
+% \bigskip
+%    \begin{macrocode}
+local BeamerNamesEnvironments = P ( false ) 
+for _ , x in ipairs ( list_beamer_env ) do
+  BeamerNamesEnvironments = BeamerNamesEnvironments + x 
+end 
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+BeamerBeginEnvironments = 
+    ( space ^ 0 * 
+      L 
+        ( 
+          P "\\begin{" * BeamerNamesEnvironments * "}"
+          * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
+        )
+      * P "\r" 
+    ) ^ 0 
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+BeamerEndEnvironments = 
+    ( space ^ 0 * 
+      L ( P "\\end{" * BeamerNamesEnvironments * P "}" ) 
+      * P "\r" 
+    ) ^ 0 
+%    \end{macrocode}
+%
 % 
 % \bigskip
-% The following function will return a \textsc{lpeg} which will catch an
-% environment of Beamer (supported by \pkg{piton}), that is to say
-% |{uncoverenv}|, etc. The argument |lpeg| should be |MainLoopPython|,
-% |MainLoopC|, etc. 
+% The following Lua function will be used to compute the \textsc{lpeg} |Beamer|
+% for each informatic language.
 %    \begin{macrocode}
-  function OneBeamerEnvironment(name,lpeg)
-    return 
+local function Compute_Beamer ( lang , braces ) 
+%    \end{macrocode}
+%
+% \bigskip
+% We will compute in |lpeg| the \textsc{lpeg} that we will return.
+%    \begin{macrocode}
+  local lpeg = L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
+  lpeg = lpeg + 
+      Ct ( Cc "Open" 
+            * C ( ( P "\\uncover" + "\\only" + "\\alert" + "\\visible"
+                    + "\\invisible" + "\\action" ) 
+                  * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1 
+                  * P "{" 
+                ) 
+            * Cc "}" 
+         ) 
+       * ( braces / ( function ( s ) return LPEG1[lang] : match ( s ) end ) )
+       * P "}" 
+       * Ct ( Cc "Close" ) 
+%    \end{macrocode}
+% 
+%
+% \bigskip
+% For the command |\\alt|, the specification of the overlays (between angular
+% brackets) is mandatory. 
+%    \begin{macrocode}
+  lpeg = lpeg +
+    L ( P "\\alt" * P "<" * ( 1 - P ">" ) ^ 0 * P ">" * P "{" )
+     * K ( 'ParseAgain.noCR' , braces ) 
+     * L ( P "}{" )
+     * K ( 'ParseAgain.noCR' , braces ) 
+     * L ( P "}" )
+%    \end{macrocode}
+%
+% \bigskip
+% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
+%    \begin{macrocode}
+  lpeg = lpeg +
+      L ( ( P "\\temporal" ) * P "<" * ( 1 - P ">" ) ^ 0 * P ">" * P "{" )
+      * K ( 'ParseAgain.noCR' , braces ) 
+      * L ( P "}{" )
+      * K ( 'ParseAgain.noCR' , braces ) 
+      * L ( P "}{" )
+      * K ( 'ParseAgain.noCR' , braces ) 
+      * L ( P "}" )
+%    \end{macrocode}
+%
+% \bigskip
+% Now, the environments of Beamer.
+%    \begin{macrocode}
+  for _ , x in ipairs ( list_beamer_env ) do
+  lpeg = lpeg + 
         Ct ( Cc "Open" 
-              * C ( 
-                    P ( "\\begin{" .. name ..   "}" )
+             * C ( 
+                    P ( "\\begin{" .. x .. "}" )
                     * ( P "<" * ( 1 - P ">") ^ 0 * P ">" ) ^ -1 
                   ) 
-             * Cc ( "\\end{" .. name ..  "}" )
+             * Cc ( "\\end{" .. x ..  "}" )
             ) 
-       * ( 
-           ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 ) 
-              / ( function (s) return lpeg : match(s) end ) 
-         )
-       * P ( "\\end{" .. name ..  "}" ) * Ct ( Cc "Close" ) 
+        * ( 
+            ( ( 1 - P ( "\\end{" .. x .. "}" ) ) ^ 0 ) 
+                / ( function ( s ) return LPEG1[lang] : match ( s ) end ) 
+          )
+        * P ( "\\end{" .. x .. "}" ) 
+        * Ct ( Cc "Close" ) 
   end 
+%    \end{macrocode}
+%
+% \bigskip
+% Now, you can return the value we have computed.
+%    \begin{macrocode}
+  return lpeg 
 end
 %    \end{macrocode}
+%
 % 
+% \bigskip
+% The following LPEG is in relation with the key |math-comments|. It will be
+% used in all the languages.
+%    \begin{macrocode}
+local CommentMath = 
+  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$" -- $
+%    \end{macrocode}
 % 
 %
 % \bigskip
+% \paragraph{EOL}
+%
+% \bigskip
+% The following LPEG will detect the Python prompts when the user is typesetting
+% an interactive session of Python (directly or through |{pyconsole}| of
+% \pkg{pyluatex}). We have to detect that prompt twice. The first detection
+% (called \emph{hasty detection}) will be before the |\@@_begin_line:| because
+% you want to trigger a special background color for that row (and, after the
+% |\@@_begin_line:|, it's too late to change de background).
 %    \begin{macrocode}
-local languages = { }
-local CleanLPEGs = { }
+local PromptHastyDetection = 
+  ( # ( P ">>>" + "..." ) * Lc ( '\\@@_prompt:' ) ) ^ -1 
 %    \end{macrocode}
+% We remind that the marker |#| of \textsc{lpeg} specifies that the pattern will be
+% detected but won't consume any character.
+%
+% \medskip
+% With the following \textsc{lpeg}, a style will actually be applied to the
+% prompt (for instance, it's possible to decide to discard these prompts).
+%    \begin{macrocode}
+local Prompt = K ( 'Prompt' , ( ( P ">>>" + "..." ) * P " " ^ -1 ) ^ -1  ) 
+%    \end{macrocode}
+%    
+%
+%
+% \bigskip
+% The following \textsc{lpeg} |EOL| is for the end of lines.
+%    \begin{macrocode}
+local EOL = 
+  P "\r" 
+  *
+  (
+    ( space ^ 0 * -1 )
+    + 
+%    \end{macrocode}
+% We recall that each line in the Python code we have to parse will be sent
+% back to LaTeX between a pair |\@@_begin_line:| --
+% |\@@_end_line:|\footnote{Remember that the \texttt{\textbackslash
+% @@\_end\_line:} must be explicit because it will be used as marker in order to
+% delimit the argument of the command \texttt{\textbackslash @@\_begin\_line:}}.
+%    \begin{macrocode}
+    Ct ( 
+         Cc "EOL"
+         * 
+         Ct (
+              Lc "\\@@_end_line:"
+              * BeamerEndEnvironments 
+              * BeamerBeginEnvironments 
+              * PromptHastyDetection
+              * Lc "\\@@_newline: \\@@_begin_line:"
+              * Prompt
+            )
+       )
+  ) 
+  * ( SpaceIndentation ^ 0 * # ( 1 - S " \r" ) ) ^ -1
+%    \end{macrocode}
+%
+% \bigskip
+% The following \textsc{lpeg} |CommentLaTeX| is for what is called in that
+% document the ``LaTeX comments''. Since the elements that will be catched must
+% be sent to LaTeX with standard LaTeX catcodes, we put the capture (done by
+% the function~|C|) in a table (by using~|Ct|, which is an alias for |lpeg.Ct|).
+%    \begin{macrocode}
+local CommentLaTeX =
+  P(piton.comment_latex) 
+  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
+  * L ( ( 1 - P "\r" ) ^ 0 ) 
+  * Lc "}}" 
+  * ( EOL + -1 )  
+%    \end{macrocode}
 % 
+%
+% 
 % \bigskip
-% \subsubsection{The LPEG python}
+% \subsubsection{The language Python}
 % 
 % \bigskip
 % Some strings of length 2 are explicit because we want the corresponding
@@ -5177,63 +5405,59 @@
 %    \begin{macrocode}
 local Operator = 
   K ( 'Operator' ,
-      P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" 
-      + P "//" + P "**" + S "-~+/*%=<>&.@|" 
-    )
+      P "!=" + "<>" + "==" + "<<" + ">>" + "<=" + ">=" + ":=" + "//" + "**" 
+      + S "-~+/*%=<>&.@|" )
 
 local OperatorWord = 
-  K ( 'Operator.Word' , P "in" + P "is" + P "and" + P "or" + P "not" )
+  K ( 'Operator.Word' , P "in" + "is" + "and" + "or" + "not" )
 
 local Keyword = 
   K ( 'Keyword' ,
-      P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue" 
-      + P "def" + P "del" + P "elif" + P "else" + P "except" + P "exec" 
-      + P "finally" + P "for" + P "from" + P "global" + P "if" + P "import" 
-      + P "lambda" + P "non local" + P "pass" + P "return" + P "try" 
-      + P "while" + P "with" + P "yield" + P "yield from" )
-  + K ( 'Keyword.Constant' ,P "True" + P "False" + P "None" ) 
+      P "as" + "assert" + "break" + "case" + "class" + "continue" + "def" +
+      "del" + "elif" + "else" + "except" + "exec" + "finally" + "for" + "from" +
+      "global" + "if" + "import" + "lambda" + "non local" + "pass" + "return" +
+      "try" + "while" + "with" + "yield" + "yield from" )
+  + K ( 'Keyword.Constant' , P "True" + "False" + "None" ) 
 
 local Builtin = 
   K ( 'Name.Builtin' ,
-      P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool" 
-    + P "bytearray" + P "bytes" + P "chr" + P "classmethod" + P "compile" 
-    + P "complex" + P "delattr" + P "dict" + P "dir" + P "divmod" 
-    + P "enumerate" + P "eval" + P "filter" + P "float" + P "format" 
-    + P "frozenset" + P "getattr" + P "globals" + P "hasattr" + P "hash" 
-    + P "hex" + P "id" + P "input" + P "int" + P "isinstance" + P "issubclass"
-    + P "iter" + P "len" + P "list" + P "locals" + P "map" + P "max" 
-    + P "memoryview" + P "min" + P "next" + P "object" + P "oct" + P "open" 
-    + P "ord" + P "pow" + P "print" + P "property" + P "range" + P "repr" 
-    + P "reversed" + P "round" + P "set" + P "setattr" + P "slice" + P "sorted" 
-    + P "staticmethod" + P "str" + P "sum" + P "super" + P "tuple" + P "type"
-    + P "vars" + P "zip" )
+      P "__import__" + "abs" + "all" + "any" + "bin" + "bool" + "bytearray" +
+      "bytes" + "chr" + "classmethod" + "compile" + "complex" + "delattr" +
+      "dict" + "dir" + "divmod" + "enumerate" + "eval" + "filter" + "float" +
+      "format" + "frozenset" + "getattr" + "globals" + "hasattr" + "hash" +
+      "hex" + "id" + "input" + "int" + "isinstance" + "issubclass" + "iter" +
+      "len" + "list" + "locals" + "map" + "max" + "memoryview" + "min" + "next"
+      + "object" + "oct" + "open" + "ord" + "pow" + "print" + "property" +
+      "range" + "repr" + "reversed" + "round" + "set" + "setattr" + "slice" +
+      "sorted" + "staticmethod" + "str" + "sum" + "super" + "tuple" + "type" +
+      "vars" + "zip" ) 
 
 
 local Exception =
   K ( 'Exception' ,
-      P "ArithmeticError" + P "AssertionError" + P "AttributeError"
-   + P "BaseException" + P "BufferError" + P "BytesWarning" + P "DeprecationWarning"
-   + P "EOFError" + P "EnvironmentError" + P "Exception" + P "FloatingPointError"
-   + P "FutureWarning" + P "GeneratorExit" + P "IOError" + P "ImportError"
-   + P "ImportWarning" + P "IndentationError" + P "IndexError" + P "KeyError"
-   + P "KeyboardInterrupt" + P "LookupError" + P "MemoryError" + P "NameError"
-   + P "NotImplementedError" + P "OSError" + P "OverflowError"
-   + P "PendingDeprecationWarning" + P "ReferenceError" + P "ResourceWarning"
-   + P "RuntimeError" + P "RuntimeWarning" + P "StopIteration"
-   + P "SyntaxError" + P "SyntaxWarning" + P "SystemError" + P "SystemExit"
-   + P "TabError" + P "TypeError" + P "UnboundLocalError" + P "UnicodeDecodeError"
-   + P "UnicodeEncodeError" + P "UnicodeError" + P "UnicodeTranslateError"
-   + P "UnicodeWarning" + P "UserWarning" + P "ValueError" + P "VMSError"
-   + P "Warning" + P "WindowsError" + P "ZeroDivisionError"
-   + P "BlockingIOError" + P "ChildProcessError" + P "ConnectionError"
-   + P "BrokenPipeError" + P "ConnectionAbortedError" + P "ConnectionRefusedError"
-   + P "ConnectionResetError" + P "FileExistsError" + P "FileNotFoundError"
-   + P "InterruptedError" + P "IsADirectoryError" + P "NotADirectoryError"
-   + P "PermissionError" + P "ProcessLookupError" + P "TimeoutError"
-   + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" )
+      P "ArithmeticError" + "AssertionError" + "AttributeError" +
+      "BaseException" + "BufferError" + "BytesWarning" + "DeprecationWarning" +
+      "EOFError" + "EnvironmentError" + "Exception" + "FloatingPointError" +
+      "FutureWarning" + "GeneratorExit" + "IOError" + "ImportError" +
+      "ImportWarning" + "IndentationError" + "IndexError" + "KeyError" +
+      "KeyboardInterrupt" + "LookupError" + "MemoryError" + "NameError" +
+      "NotImplementedError" + "OSError" + "OverflowError" +
+      "PendingDeprecationWarning" + "ReferenceError" + "ResourceWarning" +
+      "RuntimeError" + "RuntimeWarning" + "StopIteration" + "SyntaxError" +
+      "SyntaxWarning" + "SystemError" + "SystemExit" + "TabError" + "TypeError"
+      + "UnboundLocalError" + "UnicodeDecodeError" + "UnicodeEncodeError" +
+      "UnicodeError" + "UnicodeTranslateError" + "UnicodeWarning" +
+      "UserWarning" + "ValueError" + "VMSError" + "Warning" + "WindowsError" +
+      "ZeroDivisionError" + "BlockingIOError" + "ChildProcessError" +
+      "ConnectionError" + "BrokenPipeError" + "ConnectionAbortedError" +
+      "ConnectionRefusedError" + "ConnectionResetError" + "FileExistsError" +
+      "FileNotFoundError" + "InterruptedError" + "IsADirectoryError" +
+      "NotADirectoryError" + "PermissionError" + "ProcessLookupError" +
+      "TimeoutError" + "StopAsyncIteration" + "ModuleNotFoundError" +
+      "RecursionError" ) 
 
 
-local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( P "(" ) 
+local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q "("  
 
 %    \end{macrocode}
 %
@@ -5241,7 +5465,7 @@
 % In Python, a ``decorator'' is a statement whose begins by |@| which patches
 % the function defined in the following statement.
 %    \begin{macrocode}
-local Decorator = K ( 'Name.Decorator' , P "@" * letter^1  ) 
+local Decorator = K ( 'Name.Decorator' , P "@" * letter ^ 1  ) 
 %    \end{macrocode}
 % 
 % \bigskip
@@ -5253,7 +5477,7 @@
 % Example:\enskip \piton{class myclass:}
 %    \begin{macrocode}
 local DefClass = 
-  K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) 
+  K ( 'Keyword' , "class" ) * Space * K ( 'Name.Class' , identifier ) 
 %    \end{macrocode}
 % 
 % If the word |class| is not followed by a identifier, it will be catched as
@@ -5277,15 +5501,14 @@
 % Example:\enskip \piton{import math, numpy}
 %    \begin{macrocode}
 local ImportAs = 
-  K ( 'Keyword' , P "import" )
+  K ( 'Keyword' , "import" )
    * Space 
-   * K ( 'Name.Namespace' , 
-         identifier * ( P "." * identifier ) ^ 0 )
+   * K ( 'Name.Namespace' , identifier * ( "." * identifier ) ^ 0 )
    * ( 
-       ( Space * K ( 'Keyword' , P "as" ) * Space 
+       ( Space * K ( 'Keyword' , "as" ) * Space 
           * K ( 'Name.Namespace' , identifier ) )
        + 
-       ( SkipSpace * Q ( P "," ) * SkipSpace 
+       ( SkipSpace * Q "," * SkipSpace 
           * K ( 'Name.Namespace' , identifier ) ) ^ 0 
      ) 
 %    \end{macrocode}
@@ -5304,9 +5527,9 @@
 % \smallskip
 %    \begin{macrocode}
 local FromImport =
-  K ( 'Keyword' , P "from" ) 
+  K ( 'Keyword' , "from" ) 
     * Space * K ( 'Name.Namespace' , identifier )
-    * Space * K ( 'Keyword' , P "import" ) 
+    * Space * K ( 'Keyword' , "import" ) 
 %    \end{macrocode}
 %
 % \bigskip
@@ -5349,7 +5572,7 @@
       * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1 
       * ( S "-#0 +" ) ^ 0 
       * ( digit ^ 1 + P "*" ) ^ -1 
-      * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1 
+      * ( "." * ( digit ^ 1 + "*" ) ) ^ -1 
       * ( S "HlL" ) ^ -1
       * S "sdfFeExXorgiGauc%" 
     ) 
@@ -5368,53 +5591,52 @@
 %    \end{macrocode}
 % First, we deal with the f-strings of Python, which are prefixed by |f| or |F|.
 %    \begin{macrocode}
-         Q ( P "f'" + P "F'" ) 
+         Q ( P "f'" + "F'" ) 
          * ( 
-             K ( 'String.Interpol' , P "{" )
+             K ( 'String.Interpol' , "{" )
               * K ( 'Interpol.Inside' , ( 1 - S "}':" ) ^ 0  )
-              * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
-              * K ( 'String.Interpol' , P "}" )
+              * Q ( P ":" * ( 1 - S "}:'" ) ^ 0 ) ^ -1
+              * K ( 'String.Interpol' , "}" )
              + 
              VisualSpace 
              + 
-             Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 )
+             Q ( ( P "\\'" + "{{" + "}}" + 1 - S " {}'" ) ^ 1 )
            ) ^ 0 
-         * Q ( P "'" )
+         * Q "'" 
        + 
 %    \end{macrocode}
 % Now, we deal with the standard strings of Python, but also the ``raw strings''.
 %    \begin{macrocode}
-         Q ( P "'" + P "r'" + P "R'" ) 
+         Q ( P "'" + "r'" + "R'" ) 
          * ( Q ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 ) 
              + VisualSpace 
              + PercentInterpol 
-             + Q ( P "%" ) 
+             + Q "%" 
            ) ^ 0 
-         * Q ( P "'" ) )
+         * Q "'" )
 
-
 local DoubleShortString =
   WithStyle ( 'String.Short' , 
-         Q ( P "f\"" + P "F\"" ) 
+         Q ( P "f\"" + "F\"" ) 
          * ( 
-             K ( 'String.Interpol' , P "{" )
+             K ( 'String.Interpol' , "{" )
                * K ( 'Interpol.Inside' , ( 1 - S "}\":" ) ^ 0 )
-               * ( K ( 'String.Interpol' , P ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1
-               * K ( 'String.Interpol' , P "}" )
+               * ( K ( 'String.Interpol' , ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1
+               * K ( 'String.Interpol' , "}" )
              + 
              VisualSpace 
              + 
-             Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) 
+             Q ( ( P "\\\"" + "{{" + "}}" + 1 - S " {}\"" ) ^ 1 ) 
             ) ^ 0
-         * Q ( P "\"" )
+         * Q "\"" 
        +
-         Q ( P "\"" + P "r\"" + P "R\"" ) 
+         Q ( P "\"" + "r\"" + "R\"" ) 
          * ( Q ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 ) 
              + VisualSpace 
              + PercentInterpol 
-             + Q ( P "%" ) 
+             + Q "%"
            ) ^ 0 
-         * Q ( P "\"" ) )
+         * Q "\""  )
 
 local ShortString = SingleShortString + DoubleShortString
 %    \end{macrocode}
@@ -5422,171 +5644,27 @@
 % \bigskip
 % \paragraph{Beamer}
 %
-% The following pattern |balanced_braces| will be used for the (mandatory)
-% argument of the commands |\only| and \emph{al.} of Beamer. It's necessary to
-% use a \emph{grammar} because that pattern mainly checks the correct nesting of
-% the delimiters (and it's known in the theory of formal languages that this
-% can't be done with regular expressions \emph{stricto sensu} only).
 %    \begin{macrocode}
-local balanced_braces =
-  P { "E" ,
-       E = 
-           (
-             P "{" * V "E" * P "}" 
-             + 
-             ShortString  
-             + 
-             ( 1 - S "{}" ) 
-           ) ^ 0 
-    }
+local braces = Compute_braces ( ShortString ) 
+if piton.beamer then Beamer = Compute_Beamer ( 'python' , braces ) end
 %    \end{macrocode}
 %
 % \bigskip
-%    \begin{macrocode}
-if piton_beamer 
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
-    + 
-      Ct ( Cc "Open" 
-            * C ( 
-                  ( 
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action" 
-                  ) 
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
-                  * P "{" 
-                ) 
-            * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopPython:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopPython ) 
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopPython ) 
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopPython )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopPython ) 
-    + OneBeamerEnvironment ( "alertenv" , MainLoopPython ) 
-    + OneBeamerEnvironment ( "actionenv" , MainLoopPython ) 
-    +
-      L ( 
-%    \end{macrocode}
-% For |\\alt|, the specification of the overlays (between angular brackets) is mandatory.
-%    \begin{macrocode}
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-    +  
-      L ( 
-%    \end{macrocode}
-% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
-%    \begin{macrocode}
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-end
-%    \end{macrocode}
-%
-% \bigskip
 % \paragraph{Detected commands}
 %
 %    \begin{macrocode}
-DetectedCommands = 
-      Ct ( Cc "Open" 
-            * C ( piton.ListCommands * P "{" ) 
-            * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopPython:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
+DetectedCommands = Compute_DetectedCommands ( 'python' , braces ) 
 %    \end{macrocode}
 %
 % \bigskip
 %
-% \paragraph{The LPEG Clean}
+% \paragraph{LPEG_cleaner}
 %
 %    \begin{macrocode}
-CleanLPEGs['python']
-      = Ct ( ( piton.ListCommands * P "{" 
-                * (  balanced_braces 
-                    / ( function (s) return CleanLPEGs['python']:match(s) end ) )
-                * P "}" 
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat 
+LPEG_cleaner['python'] = Compute_LPEG_cleaner ( 'python' , braces ) 
 %    \end{macrocode}
 % 
-% 
 % \bigskip
-% \paragraph{EOL}
-%
-% \bigskip
-% The following LPEG will detect the Python prompts when the user is typesetting
-% an interactive session of Python (directly or through |{pyconsole}| of
-% \pkg{pyluatex}). We have to detect that prompt twice. The first detection
-% (called \emph{hasty detection}) will be before the |\@@_begin_line:| because
-% you want to trigger a special background color for that row (and, after the
-% |\@@_begin_line:|, it's too late to change de background).
-%    \begin{macrocode}
-local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\@@_prompt:' ) ) ^ -1 
-%    \end{macrocode}
-% We remind that the marker |#| of \textsc{lpeg} specifies that the pattern will be
-% detected but won't consume any character.
-%
-% \medskip
-% With the following \textsc{lpeg}, a style will actually be applied to the
-% prompt (for instance, it's possible to decide to discard these prompts).
-%    \begin{macrocode}
-local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1  ) 
-%    \end{macrocode}
-%    
-%
-%
-% \bigskip
-% The following \textsc{lpeg} |EOL| is for the end of lines.
-%    \begin{macrocode}
-local EOL = 
-  P "\r" 
-  *
-  (
-    ( space^0 * -1 )
-    + 
-%    \end{macrocode}
-% We recall that each line in the Python code we have to parse will be sent
-% back to LaTeX between a pair |\@@_begin_line:| --
-% |\@@_end_line:|\footnote{Remember that the \texttt{\textbackslash
-% @@\_end\_line:} must be explicit because it will be used as marker in order to
-% delimit the argument of the command \texttt{\textbackslash @@\_begin\_line:}}.
-%    \begin{macrocode}
-    Ct ( 
-         Cc "EOL"
-         * 
-         Ct (
-              Lc "\\@@_end_line:"
-              * BeamerEndEnvironments 
-              * BeamerBeginEnvironments 
-              * PromptHastyDetection
-              * Lc "\\@@_newline: \\@@_begin_line:"
-              * Prompt
-            )
-       )
-  ) 
-  *
-  SpaceIndentation ^ 0
-%    \end{macrocode}
-%
-% 
-% \bigskip
 % \paragraph{The long strings}
 % 
 % 
@@ -5595,10 +5673,10 @@
   WithStyle ( 'String.Long' , 
      ( Q ( S "fF" * P "'''" )
          * (
-             K ( 'String.Interpol' , P "{"  )
-               * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "'''" ) ^ 0  )
-               * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
-               * K ( 'String.Interpol' , P "}"  )
+             K ( 'String.Interpol' , "{" )
+               * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - "'''" ) ^ 0  )
+               * Q ( P ":" * (1 - S "}:\r" - "'''" ) ^ 0 ) ^ -1
+               * K ( 'String.Interpol' , "}"  )
              + 
              Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
              + 
@@ -5605,7 +5683,7 @@
              EOL
            ) ^ 0 
        +
-         Q ( ( S "rR" ) ^ -1  * P "'''" )
+         Q ( ( S "rR" ) ^ -1  * "'''" )
          * (
              Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 )  
              + 
@@ -5616,25 +5694,25 @@
              EOL
            ) ^ 0 
       )
-      * Q ( P "'''" ) ) 
+      * Q "'''"  ) 
 
 
 local DoubleLongString =
   WithStyle ( 'String.Long' ,
      (
-        Q ( S "fF" * P "\"\"\"" )
+        Q ( S "fF" * "\"\"\"" )
         * (
-            K ( 'String.Interpol', P "{"  )
-              * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 )
-              * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
-              * K ( 'String.Interpol' , P "}"  )
+            K ( 'String.Interpol', "{"  )
+              * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - "\"\"\"" ) ^ 0 )
+              * Q ( ":" * (1 - S "}:\r" - "\"\"\"" ) ^ 0 ) ^ -1
+              * K ( 'String.Interpol' , "}"  )
             + 
-            Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 ) 
+            Q ( ( 1 - S "{}\"\r" - "\"\"\"" ) ^ 1 ) 
             + 
             EOL
           ) ^ 0 
       +
-        Q ( ( S "rR" ) ^ -1  * P "\"\"\"" )
+        Q ( S "rR" ^ -1  * "\"\"\"" )
         * (
             Q ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 )  
             + 
@@ -5645,7 +5723,7 @@
             EOL
           ) ^ 0 
      )
-     * Q ( P "\"\"\"" ) 
+     * Q "\"\"\"" 
   ) 
 %    \end{macrocode}
 %
@@ -5659,11 +5737,11 @@
 % of a function definition (which begins with |def|).
 %    \begin{macrocode}
 local StringDoc = 
-    K ( 'String.Doc' , P "r" ^ -1 * P "\"\"\"" )
-      * ( K ( 'String.Doc' , (1 - P "\"\"\"" - P "\r" ) ^ 0  ) * EOL
+    K ( 'String.Doc' , P "r" ^ -1 * "\"\"\"" )
+      * ( K ( 'String.Doc' , (1 - P "\"\"\"" - "\r" ) ^ 0  ) * EOL
           * Tab ^ 0 
         ) ^ 0
-      * K ( 'String.Doc' , ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" )
+      * K ( 'String.Doc' , ( 1 - P "\"\"\"" - "\r" ) ^ 0 * "\"\"\"" )
 %    \end{macrocode}
 %
 % \bigskip
@@ -5672,31 +5750,12 @@
 % We define different \textsc{lpeg} dealing with comments in the Python
 % listings.
 %    \begin{macrocode}
-local CommentMath = 
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"
-
 local Comment = 
   WithStyle ( 'Comment' ,
-     Q ( P "#" ) 
-     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) 
-  * ( EOL + -1 )
+     Q "#" * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) -- $
+           * ( EOL + -1 )
 %    \end{macrocode}
 % 
-%
-%
-% \bigskip
-% The following \textsc{lpeg} |CommentLaTeX| is for what is called in that
-% document the ``LaTeX comments''. Since the elements that will be catched must
-% be sent to LaTeX with standard LaTeX catcodes, we put the capture (done by
-% the function~|C|) in a table (by using~|Ct|, which is an alias for |lpeg.Ct|).
-%    \begin{macrocode}
-local CommentLaTeX =
-  P(piton.comment_latex) 
-  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
-  * L ( ( 1 - P "\r" ) ^ 0 ) 
-  * Lc "}}" 
-  * ( EOL + -1 )  
-%    \end{macrocode}
 % 
 % \bigskip
 % \paragraph{DefFunction}
@@ -5709,15 +5768,15 @@
 %    \begin{macrocode}
 local expression =
   P { "E" ,
-       E = ( P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'"
-             + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\""
-             + P "{" * V "F" * P "}"
-             + P "(" * V "F" * P ")"
-             + P "[" * V "F" * P "]" 
+       E = ( "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * "'" 
+             + "\"" * ( P "\\\"" + 1 - S "\"\r" ) ^ 0 * "\""
+             + "{" * V "F" * "}"
+             + "(" * V "F" * ")"
+             + "[" * V "F" * "]" 
              + ( 1 - S "{}()[]\r," ) ) ^ 0 ,
-       F = ( P "{" * V "F" * P "}"
-             + P "(" * V "F" * P ")"
-             + P "[" * V "F" * P "]"
+       F = (   "{" * V "F" * "}"
+             + "(" * V "F" * ")"
+             + "[" * V "F" * "]"
              + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
     }
 %    \end{macrocode}
@@ -5739,8 +5798,8 @@
 local Param = 
   SkipSpace * ( Identifier + Q "*args" + Q "**kwargs" ) * SkipSpace
    * ( 
-         K ( 'InitialValues' , P "=" * expression )
-       + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter ^ 1  ) 
+         K ( 'InitialValues' , "=" * expression )
+       + Q ":" * SkipSpace * K ( 'Name.Type' , letter ^ 1  ) 
      ) ^ -1
 %    \end{macrocode}
 % 
@@ -5757,13 +5816,13 @@
 % |Comment|, |CommentLaTeX|, |Params|, |StringDoc|...
 %    \begin{macrocode}
 local DefFunction =
-  K ( 'Keyword' , P "def" )
+  K ( 'Keyword' , "def" )
   * Space
   * K ( 'Name.Function.Internal' , identifier ) 
   * SkipSpace 
-  * Q ( P "(" ) * Params * Q ( P ")" ) 
+  * Q "("  * Params * Q ")" 
   * SkipSpace
-  * ( Q ( P "->" ) * SkipSpace * K ( 'Name.Type' , identifier  ) ) ^ -1
+  * ( Q "->" * SkipSpace * K ( 'Name.Type' , identifier ) ) ^ -1
 %    \end{macrocode}
 % Here, we need a \pkg{piton} style |ParseAgain| which will be linked to
 % |\@@_piton:n| (that means that the capture will be parsed once again by
@@ -5770,8 +5829,8 @@
 % \pkg{piton}). We could avoid that kind of trick by using a non-terminal of a
 % grammar but we have probably here a better legibility.
 %    \begin{macrocode}
-  * K ( 'ParseAgain' , ( 1 - S ":\r" )^0  ) 
-  * Q ( P ":" )
+  * K ( 'ParseAgain' , ( 1 - S ":\r" ) ^ 0 ) 
+  * Q ":" 
   * ( SkipSpace
       * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
       * Tab ^ 0 
@@ -5801,8 +5860,9 @@
 %
 % First, the main loop :
 %    \begin{macrocode}
-local MainPython = 
-       EOL
+local Main = 
+       space ^ 1 * -1
+     + space ^ 0 * EOL 
      + Space 
      + Tab
      + Escape + EscapeMath
@@ -5831,10 +5891,7 @@
 %
 % Here, we must not put |local|!
 %    \begin{macrocode}
-MainLoopPython = 
-  (  ( space^1 * -1 ) 
-     + MainPython
-  ) ^ 0 
+LPEG1['python'] = Main ^ 0 
 %    \end{macrocode}
 %
 % \bigskip
@@ -5844,31 +5901,26 @@
 % will be used as marker in order to delimit the argument of the command
 % \texttt{\textbackslash @@\_begin\_line:}}.
 %    \begin{macrocode}
-local python = P ( true ) 
-
-python =
+LPEG2['python'] = 
   Ct (
-       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
+       ( space ^ 0 * "\r" ) ^ -1 
        * BeamerBeginEnvironments 
        * PromptHastyDetection
        * Lc '\\@@_begin_line:'
        * Prompt 
        * SpaceIndentation ^ 0 
-       * MainLoopPython
+       * LPEG1['python']
        * -1 
        * Lc '\\@@_end_line:' 
      )
 %    \end{macrocode}
 %
-%    \begin{macrocode}
-languages['python'] = python
-%    \end{macrocode}
 %
 % \bigskip
-% \subsubsection{The LPEG ocaml}
+% \subsubsection{The language Ocaml}
 % 
 %    \begin{macrocode}
-local Delim = Q ( P "[|" + P "|]" + S "[()]" )
+local Delim = Q ( P "[|" + "|]" + S "[()]" )
 %    \end{macrocode}
 %
 %    \begin{macrocode}
@@ -5889,8 +5941,7 @@
 % The identifiers which begin with a lower case letter or an underscore are used 
 % elsewhere in OCaml.
 %    \begin{macrocode}
-local identifier = 
-  ( R "az" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 
+local identifier = ( R "az" + "_" ) * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 
 local Identifier = K ( 'Identifier' , identifier )
 %    \end{macrocode}
 %
@@ -5900,15 +5951,15 @@
 %    \begin{macrocode}
 local expression_for_fields =
   P { "E" ,
-       E = ( P "{" * V "F" * P "}"
-             + P "(" * V "F" * P ")"
-             + P "[" * V "F" * P "]" 
-             + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\""
-             + P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'"
+       E = (   "{" * V "F" * "}"
+             + "(" * V "F" * ")"
+             + "[" * V "F" * "]" 
+             + "\"" * ( P "\\\"" + 1 - S "\"\r" ) ^ 0 * "\""
+             + "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * "'"
              + ( 1 - S "{}()[]\r;" ) ) ^ 0 ,
-       F = ( P "{" * V "F" * P "}"
-             + P "(" * V "F" * P ")"
-             + P "[" * V "F" * P "]"
+       F = (   "{" * V "F" * "}"
+             + "(" * V "F" * ")"
+             + "[" * V "F" * "]"
              + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
     }
 %    \end{macrocode}
@@ -5915,7 +5966,7 @@
 % 
 %    \begin{macrocode}
 local OneFieldDefinition = 
-    ( K ( 'KeyWord' , P "mutable" ) * SkipSpace ) ^ -1
+    ( K ( 'Keyword' , "mutable" ) * SkipSpace ) ^ -1
   * K ( 'Name.Field' , identifier ) * SkipSpace
   * Q ":" * SkipSpace
   * K ( 'Name.Type' , expression_for_fields ) 
@@ -5924,7 +5975,7 @@
 local OneField = 
     K ( 'Name.Field' , identifier ) * SkipSpace
   * Q "=" * SkipSpace
-  * ( expression_for_fields / ( function (s) return LoopOCaml:match(s) end ) )
+  * ( expression_for_fields / ( function ( s ) return LPEG1['ocaml'] : match ( s ) end ) )
   * SkipSpace
 
 local Record = 
@@ -5948,7 +5999,6 @@
       K ( 'Name.Module' , cap_identifier ) 
         * Q "." 
         * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" ) 
-
       + 
       Identifier 
         * Q "."
@@ -5960,32 +6010,27 @@
 %    \begin{macrocode}
 local Operator = 
   K ( 'Operator' ,
-      P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" 
-      + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->" 
-      + P "+." + P "-." + P "*." + P "/." 
-      + S "-~+/*%=<>&@|" 
-    )
+      P "!=" + "<>" + "==" + "<<" + ">>" + "<=" + ">=" + ":=" + "||" + "&&" +
+      "//" + "**" + ";;" + "::" + "->" + "+." + "-." + "*." + "/." 
+      + S "-~+/*%=<>&@|" )
 
 local OperatorWord = 
   K ( 'Operator.Word' ,
-      P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor" 
-      + P "mod" + P "or" )
+      P "and" + "asr" + "land" + "lor" + "lsl" + "lxor" + "mod" + "or" )
 
 local Keyword = 
   K ( 'Keyword' ,
-      P "assert" + P "and" + P "as" + P "begin" + P "class" + P "constraint" + P "done" 
-  + P "downto" + P "do" + P "else" + P "end" + P "exception" + P "external" 
-  + P "for" + P "function" + P "functor" + P "fun" + P "if" 
-  + P "include" + P "inherit" + P "initializer" + P "in"  + P "lazy" + P "let" 
-  + P "match" + P "method" + P "module" + P "mutable" + P "new" + P "object" 
-  + P "of" + P "open" + P "private" + P "raise" + P "rec" + P "sig" 
-  + P "struct" + P "then" + P "to" + P "try" + P "type" 
-  + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" )
-  + K ( 'Keyword.Constant' , P "true" + P "false" )  
+      P "assert" + "and" + "as" + "begin" + "class" + "constraint" + "done" 
+  + "downto" + "do" + "else" + "end" + "exception" + "external" + "for" +
+  "function" + "functor" + "fun" + "if" + "include" + "inherit" + "initializer"
+  + "in"  + "lazy" + "let" + "match" + "method" + "module" + "mutable" + "new" +
+  "object" + "of" + "open" + "private" + "raise" + "rec" + "sig" + "struct" +
+  "then" + "to" + "try" + "type" + "value" + "val" + "virtual" + "when" +
+  "while" + "with" ) 
+  + K ( 'Keyword.Constant' , P "true" + "false" )  
 
-
 local Builtin = 
-  K ( 'Name.Builtin' , P "not" + P "incr" + P "decr" + P "fst" + P "snd" )
+  K ( 'Name.Builtin' , P "not" + "incr" + "decr" + "fst" + "snd" )
 %    \end{macrocode}
 % 
 % \bigskip
@@ -5993,10 +6038,9 @@
 %    \begin{macrocode}
 local Exception =
   K (   'Exception' ,
-       P "Division_by_zero" + P "End_of_File" + P "Failure" 
-     + P "Invalid_argument" + P "Match_failure" + P "Not_found" 
-     + P "Out_of_memory" + P "Stack_overflow" + P "Sys_blocked_io" 
-     + P "Sys_error" + P "Undefined_recursive_module" )
+       P "Division_by_zero" + "End_of_File" + "Failure" + "Invalid_argument" +
+       "Match_failure" + "Not_found" + "Out_of_memory" + "Stack_overflow" +
+       "Sys_blocked_io" + "Sys_error" + "Undefined_recursive_module" )
 %    \end{macrocode}
 %
 % \bigskip
@@ -6004,7 +6048,7 @@
 %
 %    \begin{macrocode}
 local Char = 
-  K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" ) 
+  K ( 'String.Short' , "'" * ( ( 1 - P "'" ) ^ 0 + "\\'" ) * "'" ) 
 %    \end{macrocode}
 % 
 %
@@ -6011,127 +6055,24 @@
 % \bigskip
 % \paragraph{Beamer}
 %
-%    \begin{macrocode}
-local balanced_braces =
-  P { "E" ,
-       E = 
-           (
-             P "{" * V "E" * P "}" 
-             + 
-             P "\"" * ( 1 - S "\"" ) ^ 0 * P "\""  -- OCaml strings
-             + 
-             ( 1 - S "{}" ) 
-           ) ^ 0 
-    }
-%    \end{macrocode}
-%
-%
 % \bigskip
 %    \begin{macrocode}
-if piton_beamer 
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
-    + 
-      Ct ( Cc "Open" 
-            * C ( 
-                  ( 
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action" 
-                  ) 
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
-                  * P "{" 
-                ) 
-            * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopOCaml:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopOCaml ) 
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopOCaml ) 
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopOCaml )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopOCaml ) 
-    + OneBeamerEnvironment ( "alertenv" , MainLoopOCaml ) 
-    + OneBeamerEnvironment ( "actionenv" , MainLoopOCaml ) 
-    +
-      L ( 
-%    \end{macrocode}
-% For |\\alt|, the specification of the overlays (between angular brackets) is mandatory.
-%    \begin{macrocode}
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-    +  
-      L ( 
-%    \end{macrocode}
-% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
-%    \begin{macrocode}
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
+braces = Compute_braces ( "\"" * ( 1 - S "\"" ) ^ 0 * "\"" ) 
+if piton.beamer then 
+  Beamer = Compute_Beamer ( 'ocaml' , "\"" * ( 1 - S "\"" ) ^ 0 * "\"" ) 
 end
 %    \end{macrocode}
-%
+% 
 %    \begin{macrocode}
-DetectedCommands = 
-      Ct ( Cc "Open" 
-            * C ( piton.ListCommands * P "{" ) * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopOCaml:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
+DetectedCommands = Compute_DetectedCommands ( 'ocaml' , braces ) 
 %    \end{macrocode}
 %
 % \bigskip
 %    \begin{macrocode}
-CleanLPEGs['ocaml']
-      = Ct ( ( piton.ListCommands * P "{" 
-                * ( balanced_braces 
-                    / ( function (s) return CleanLPEGs['ocaml']:match(s) end ) )
-                * P "}" 
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat 
+LPEG_cleaner['ocaml'] = Compute_LPEG_cleaner ( 'ocaml' , braces ) 
 %    \end{macrocode}
-% 
-
-% 
 %
 % \bigskip
-% \paragraph{EOL}
-%    \begin{macrocode}
-local EOL = 
-  P "\r" 
-  *
-  (
-    ( space^0 * -1 )
-    + 
-    Ct ( 
-         Cc "EOL"
-         * 
-         Ct (
-              Lc "\\@@_end_line:"
-              * BeamerEndEnvironments 
-              * BeamerBeginEnvironments 
-              * PromptHastyDetection
-              * Lc "\\@@_newline: \\@@_begin_line:"
-              * Prompt
-            )
-       )
-  ) 
-  *
-  SpaceIndentation ^ 0
-%    \end{macrocode}
 %
 % 
 % \paragraph{The strings en OCaml}
@@ -6140,7 +6081,7 @@
 % within the comments of OCaml.
 %    \begin{macrocode}
 local ocaml_string =
-       Q ( P "\"" )
+       Q "\"" 
      * ( 
          VisualSpace
          + 
@@ -6148,7 +6089,7 @@
          +  
          EOL
        ) ^ 0 
-     * Q ( P "\"" ) 
+     * Q "\"" 
 %    \end{macrocode}
 % 
 %    \begin{macrocode}
@@ -6167,12 +6108,12 @@
 % programmation, see the paragraphe \emph{Lua's long % strings} in
 % |www.inf.puc-rio.br/~roberto/lpeg|. 
 %    \begin{macrocode}
-local ext = ( R "az" + P "_" ) ^ 0
-local open = "{" * Cg(ext, 'init') * "|" 
-local close = "|" * C(ext) * "}"
+local ext = ( R "az" + "_" ) ^ 0
+local open = "{" * Cg ( ext , 'init' ) * "|" 
+local close = "|" * C ( ext ) * "}"
 local closeeq = 
-  Cmt ( close * Cb('init'), 
-        function (s, i, a, b) return a == b end ) 
+  Cmt ( close * Cb ( 'init' ) , 
+        function ( s , i , a , b ) return a == b end ) 
 %    \end{macrocode}
 %
 % \medskip
@@ -6187,7 +6128,6 @@
         +  
         EOL
       ) ^ 0  ) 
-
 %    \end{macrocode}
 % 
 % \medskip
@@ -6196,7 +6136,7 @@
 %    \begin{macrocode}
 local QuotedString = 
    C ( open * ( 1 - closeeq ) ^ 0  * close ) /
-  ( function (s) return QuotedStringBis : match(s) end ) 
+  ( function ( s ) return QuotedStringBis : match ( s ) end ) 
 %    \end{macrocode}
 % 
 %
@@ -6204,7 +6144,7 @@
 % \paragraph{The comments in the OCaml listings}
 %
 % In OCaml, the delimiters for the comments are |(*| and |*)|. There are
-% unsymmetrical and OCaml allow those comments to be nested. That's why we need a
+% unsymmetrical and OCaml allows those comments to be nested. That's why we need a
 % grammar.
 % 
 % In these comments, we embed the math comments (between |$| and |$|) and we
@@ -6217,9 +6157,9 @@
          "A" ,
          A = Q "(*"
              * ( V "A" 
-                 + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $
+                 + Q ( ( 1 - S "\r$\"" - "(*" - "*)" ) ^ 1 ) -- $
                  + ocaml_string 
-                 + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $
+                 + "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * "$" -- $
                  + EOL
                ) ^ 0 
              * Q "*)" 
@@ -6231,14 +6171,7 @@
 %
 %    \begin{macrocode}
 local balanced_parens =
-  P { "E" ,
-       E = 
-           (
-             P "(" * V "E" * P ")" 
-             + 
-             ( 1 - S "()" ) 
-           ) ^ 0 
-    }
+  P { "E" , E = ( "(" * V "E" * ")" + 1 - S "()" ) ^ 0 }
 %    \end{macrocode}
 % 
 %    \begin{macrocode}
@@ -6255,16 +6188,16 @@
 % which opens locally a module.
 %    \begin{macrocode}
 local DefFunction = 
-  K ( 'Keyword' , P "let open" ) 
+  K ( 'Keyword' , "let open" ) 
    * Space
    * K ( 'Name.Module' , cap_identifier ) 
   + 
-  K ( 'Keyword' , P "let rec" + P "let" + P "and" ) 
+  K ( 'Keyword' , P "let rec" + "let" + "and" ) 
     * Space
     * K ( 'Name.Function.Internal' , identifier ) 
     * Space 
     * (
-        Q "=" * SkipSpace * K ( 'Keyword' , P "function" ) 
+        Q "=" * SkipSpace * K ( 'Keyword' , "function" ) 
         + 
         Argument 
          * ( SkipSpace * Argument ) ^ 0 
@@ -6284,10 +6217,10 @@
 % definitions of \emph{types} of modules.
 %    \begin{macrocode}
 local DefModule = 
-  K ( 'Keyword' , P "module" ) * Space
+  K ( 'Keyword' , "module" ) * Space
   *
     (
-          K ( 'Keyword' , P "type" ) * Space
+          K ( 'Keyword' , "type" ) * Space
         * K ( 'Name.Type' , cap_identifier ) 
       + 
         K ( 'Name.Module' , cap_identifier ) * SkipSpace 
@@ -6322,7 +6255,7 @@
           ) ^ -1
     )
   + 
-  K ( 'Keyword' , P "include" + P "open" )
+  K ( 'Keyword' , P "include" + "open" )
   * Space * K ( 'Name.Module' , cap_identifier ) 
 %    \end{macrocode}
 % 
@@ -6330,7 +6263,7 @@
 % \paragraph{The parameters of the types}
 % 
 %    \begin{macrocode}
-local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) ) 
+local TypeParameter = K ( 'TypeParameter' , "'" * alpha * # ( 1 - P "'" ) ) 
 %    \end{macrocode}
 % 
 % \bigskip
@@ -6338,8 +6271,9 @@
 %
 % First, the main loop :
 %    \begin{macrocode}
-MainOCaml = 
-       EOL
+local Main = 
+       space ^ 1 * -1
+     + space ^ 0 * EOL 
      + Space 
      + Tab
      + Escape + EscapeMath
@@ -6365,41 +6299,31 @@
      + Number
      + Word
 
-LoopOCaml = MainOCaml ^ 0 
-
-MainLoopOCaml = 
-  (  ( space^1 * -1 ) 
-     + MainOCaml
-  ) ^ 0 
+LPEG1['ocaml'] = Main ^ 0 
 %    \end{macrocode}
 %
 % \bigskip
-% We recall that each line in the Python code to parse will be sent back to
+% We recall that each line in the code to parse will be sent back to
 % LaTeX between a pair |\@@_begin_line:| -- |\@@_end_line:|\footnote{Remember
 % that the \texttt{\textbackslash @@\_end\_line:} must be explicit because it
 % will be used as marker in order to delimit the argument of the command
 % \texttt{\textbackslash @@\_begin\_line:}}.
 %    \begin{macrocode}
-local ocaml = P ( true ) 
-
-ocaml =
+LPEG2['ocaml'] = 
   Ct (
-       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
+       ( space ^ 0 * "\r" ) ^ -1 
        * BeamerBeginEnvironments 
-       * Lc ( '\\@@_begin_line:' ) 
+       * Lc '\\@@_begin_line:' 
        * SpaceIndentation ^ 0 
-       * MainLoopOCaml
+       * LPEG1['ocaml']
        * -1 
-       * Lc ( '\\@@_end_line:' )
+       * Lc '\\@@_end_line:' 
      )
 %    \end{macrocode}
 %
-%    \begin{macrocode}
-languages['ocaml'] = ocaml
-%    \end{macrocode}
 %
 % \bigskip
-% \subsubsection{The LPEG for the language C}
+% \subsubsection{The language C}
 % 
 %    \begin{macrocode}
 local Delim = Q ( S "{[()]}" )
@@ -6417,42 +6341,34 @@
 
 local Operator = 
   K ( 'Operator' ,
-      P "!=" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" 
-      + P "||" + P "&&" + S "-~+/*%=<>&.@|!" 
-    )
+      P "!=" + "==" + "<<" + ">>" + "<=" + ">=" + "||" + "&&" 
+        + S "-~+/*%=<>&.@|!" )
 
 local Keyword = 
   K ( 'Keyword' ,
-      P "alignas" + P "asm" + P "auto" + P "break" + P "case" + P "catch"
-      + P "class" + P "const" + P "constexpr" + P "continue" 
-      + P "decltype" + P "do" + P "else" + P "enum" + P "extern" 
-      + P "for" + P "goto" + P "if" + P "nexcept" + P "private" + P "public" 
-      + P "register" + P "restricted" + P "return" + P "static" + P "static_assert" 
-      + P "struct" + P "switch" + P "thread_local" + P "throw" + P "try" 
-      + P "typedef" + P "union" + P "using" + P "virtual" + P "volatile" 
-      + P "while" 
+      P "alignas" + "asm" + "auto" + "break" + "case" + "catch" + "class" +
+      "const" + "constexpr" + "continue" + "decltype" + "do" + "else" + "enum" +
+      "extern" + "for" + "goto" + "if" + "nexcept" + "private" + "public" +
+      "register" + "restricted" + "return" + "static" + "static_assert" +
+      "struct" + "switch" + "thread_local" + "throw" + "try" + "typedef" +
+      "union" + "using" + "virtual" + "volatile" + "while" 
     )
-  + K ( 'Keyword.Constant' , 
-        P "default" + P "false" + P "NULL" + P "nullptr" + P "true" 
-      ) 
+  + K ( 'Keyword.Constant' , P "default" + "false" + "NULL" + "nullptr" + "true" ) 
 
 local Builtin = 
   K ( 'Name.Builtin' ,
-      P "alignof" + P "malloc" + P "printf" + P "scanf" + P "sizeof" 
-    )
+      P "alignof" + "malloc" + "printf" + "scanf" + "sizeof" )
 
 local Type = 
   K ( 'Name.Type' ,
-      P "bool" + P "char" + P "char16_t" + P "char32_t" + P "double" 
-      + P "float" + P "int" + P "int8_t" + P "int16_t" + P "int32_t" 
-      + P "int64_t" + P "long" + P "short" + P "signed" + P "unsigned" 
-      + P "void" + P "wchar_t" 
-    )
+      P "bool" + "char" + "char16_t" + "char32_t" + "double" + "float" + "int" +
+      "int8_t" + "int16_t" + "int32_t" + "int64_t" + "long" + "short" + "signed"
+      + "unsigned" + "void" + "wchar_t" )
 
 local DefFunction = 
   Type 
   * Space 
-  * Q ( "*" ) ^ -1 
+  * Q "*" ^ -1 
   * K ( 'Name.Function.Internal' , identifier ) 
   * SkipSpace 
   * # P "("
@@ -6469,7 +6385,7 @@
 % Example:\enskip \piton{class myclass:}
 %    \begin{macrocode}
 local DefClass = 
-  K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) 
+  K ( 'Keyword' , "class" ) * Space * K ( 'Name.Class' , identifier ) 
 %    \end{macrocode}
 % 
 % If the word |class| is not followed by a identifier, it will be catched as
@@ -6480,12 +6396,12 @@
 % \paragraph{The strings of C}
 %
 %    \begin{macrocode}
-local String = 
+String = 
   WithStyle ( 'String.Long' ,
       Q "\"" 
       * ( VisualSpace 
           + K ( 'String.Interpol' , 
-                P "%" * ( S "difcspxXou" + P "ld" + P "li" + P "hd" + P "hi" )
+                "%" * ( S "difcspxXou" + "ld" + "li" + "hd" + "hi" )
               ) 
           + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 ) 
         ) ^ 0 
@@ -6496,146 +6412,25 @@
 % \bigskip
 % \paragraph{Beamer}
 %
-% The following \textsc{lpeg} |balanced_braces| will be used for the (mandatory)
-% argument of the commands |\only| and \emph{al.} of Beamer. It's necessary to
-% use a \emph{grammar} because that pattern mainly checks the correct nesting of
-% the delimiters (and it's known in the theory of formal languages that this
-% can't be done with regular expressions \emph{stricto sensu} only).
-%    \begin{macrocode}
-local balanced_braces =
-  P { "E" ,
-       E = 
-           (
-             P "{" * V "E" * P "}" 
-             + 
-             String  
-             + 
-             ( 1 - S "{}" ) 
-           ) ^ 0 
-    }
-%    \end{macrocode}
-%
-%
 % \bigskip
 %    \begin{macrocode}
-if piton_beamer 
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
-    + 
-      Ct ( Cc "Open" 
-            * C ( 
-                  ( 
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action" 
-                  ) 
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
-                  * P "{" 
-                ) 
-            * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopC:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopC ) 
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopC ) 
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopC )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopC ) 
-    + OneBeamerEnvironment ( "alertenv" , MainLoopC ) 
-    + OneBeamerEnvironment ( "actionenv" , MainLoopC ) 
-    +
-      L ( 
+braces = Compute_braces ( "\"" * ( 1 - S "\"" ) ^ 0 * "\"" ) 
+if piton.beamer then Beamer = Compute_Beamer ( 'c' , braces ) end
 %    \end{macrocode}
-% For |\\alt|, the specification of the overlays (between angular brackets) is mandatory.
-%    \begin{macrocode}
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-    +  
-      L ( 
-%    \end{macrocode}
-% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
-%    \begin{macrocode}
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-end
-%    \end{macrocode}
 %
 %    \begin{macrocode}
-DetectedCommands = 
-      Ct ( Cc "Open" 
-            * C ( piton.ListCommands * P "{" ) * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopC:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
+DetectedCommands = Compute_DetectedCommands ( 'c' , braces ) 
 %    \end{macrocode}
 %
-% \bigskip
 %    \begin{macrocode}
-CleanLPEGs['c']
-      = Ct ( ( piton.ListCommands * P "{" 
-                * ( balanced_braces 
-                    / ( function (s) return CleanLPEGs['c']:match(s) end ) )
-                * P "}" 
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat 
+LPEG_cleaner['c'] = Compute_LPEG_cleaner ( 'c' , braces ) 
 %    \end{macrocode}
 % 
 % \bigskip
-% \paragraph{EOL}
-%
-%
-% The following \textsc{lpeg} |EOL| is for the end of lines.
-%    \begin{macrocode}
-local EOL = 
-  P "\r" 
-  *
-  (
-    ( space^0 * -1 )
-    + 
-%    \end{macrocode}
-% We recall that each line in the Python code we have to parse will be sent
-% back to LaTeX between a pair |\@@_begin_line:| --
-% |\@@_end_line:|\footnote{Remember that the \texttt{\textbackslash
-% @@\_end\_line:} must be explicit because it will be used as marker in order to
-% delimit the argument of the command \texttt{\textbackslash @@\_begin\_line:}}.
-%    \begin{macrocode}
-    Ct ( 
-         Cc "EOL"
-         * 
-         Ct (
-              Lc "\\@@_end_line:"
-              * BeamerEndEnvironments 
-              * BeamerBeginEnvironments 
-              * PromptHastyDetection
-              * Lc "\\@@_newline: \\@@_begin_line:"
-              * Prompt
-            )
-       )
-  ) 
-  *
-  SpaceIndentation ^ 0
-%    \end{macrocode}
-%
-% \bigskip
 % \paragraph{The directives of the preprocessor}
 %
 %    \begin{macrocode}
-local Preproc = 
-  K ( 'Preproc' , P "#" * (1 - P "\r" ) ^ 0  ) * ( EOL + -1 )
+local Preproc = K ( 'Preproc' , "#" * ( 1 - P "\r" ) ^ 0  ) * ( EOL + -1 )
 %    \end{macrocode}
 % 
 %
@@ -6644,40 +6439,21 @@
 %
 % We define different \textsc{lpeg} dealing with comments in the C listings.
 %    \begin{macrocode}
-local CommentMath = 
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"
-
 local Comment = 
   WithStyle ( 'Comment' ,
-     Q ( P "//" ) 
-     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) 
-  * ( EOL + -1 )
+     Q "//" * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) -- $
+            * ( EOL + -1 )
 
 local LongComment = 
   WithStyle ( 'Comment' , 
-               Q ( P "/*" ) 
+               Q "/*" 
                * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0 
-               * Q ( P "*/" ) 
+               * Q "*/" 
             ) -- $
 %    \end{macrocode}
 %
 %
-% \bigskip
-% The following \textsc{lpeg} |CommentLaTeX| is for what is called in that
-% document the ``LaTeX comments''. Since the elements that will be catched must
-% be sent to LaTeX with standard LaTeX catcodes, we put the capture (done by
-% the function~|C|) in a table (by using~|Ct|, which is an alias for |lpeg.Ct|).
-%    \begin{macrocode}
-local CommentLaTeX =
-  P(piton.comment_latex) 
-  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
-  * L ( ( 1 - P "\r" ) ^ 0 ) 
-  * Lc "}}" 
-  * ( EOL + -1 )  
-%    \end{macrocode}
-% 
 %
-%
 % 
 % \bigskip
 % \paragraph{The main LPEG for the language C}
@@ -6684,8 +6460,9 @@
 %
 % First, the main loop :
 %    \begin{macrocode}
-local MainC = 
-       EOL
+local Main = 
+       space ^ 1 * -1
+     + space ^ 0 * EOL 
      + Space 
      + Tab
      + Escape + EscapeMath 
@@ -6700,7 +6477,7 @@
      + Punct
      + DefFunction
      + DefClass 
-     + Type * ( Q ( "*" ) ^ -1 + Space + Punct + Delim + EOL + -1 ) 
+     + Type * ( Q "*" ^ -1 + Space + Punct + Delim + EOL + -1 ) 
      + Keyword * ( Space + Punct + Delim + EOL + -1 ) 
      + Builtin * ( Space + Punct + Delim + EOL + -1 ) 
      + Identifier 
@@ -6710,10 +6487,7 @@
 %
 % Here, we must not put |local|!
 %    \begin{macrocode}
-MainLoopC = 
-  (  ( space^1 * -1 ) 
-     + MainC
-  ) ^ 0 
+LPEG1['c'] = Main ^ 0 
 %    \end{macrocode}
 %
 % \bigskip
@@ -6723,39 +6497,46 @@
 % will be used as marker in order to delimit the argument of the command
 % \texttt{\textbackslash @@\_begin\_line:}}.
 %    \begin{macrocode}
-languageC =
+LPEG2['c'] = 
   Ct (
-       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
+       ( space ^ 0 * P "\r" ) ^ -1 
        * BeamerBeginEnvironments 
        * Lc '\\@@_begin_line:'
        * SpaceIndentation ^ 0 
-       * MainLoopC
+       * LPEG1['c']
        * -1 
        * Lc '\\@@_end_line:' 
      )
 %    \end{macrocode}
 %
+%
+% \bigskip
+% \subsubsection{The language SQL}
+% 
 %    \begin{macrocode}
-languages['c'] = languageC
+local function LuaKeyword ( name ) 
+return 
+   Lc "{\\PitonStyle{Keyword}{" 
+   * Q ( Cmt ( 
+               C ( identifier ) , 
+               function ( s , i , a ) return string.upper ( a ) == name end 
+             ) 
+       ) 
+   * Lc "}}" 
+end 
 %    \end{macrocode}
 %
-%
 % \bigskip
-% \subsubsection{The LPEG language SQL}
-% 
-% \bigskip
 % In the identifiers, we will be able to catch those contening spaces, that is
 % to say like |"last name"|. 
 %    \begin{macrocode}
 local identifier = 
-  letter * ( alphanum + P "-" ) ^ 0 
-  + P '"' * ( ( alphanum + space - P '"' ) ^ 1 ) * P '"' 
+  letter * ( alphanum + "-" ) ^ 0 
+  + '"' * ( ( alphanum + space - '"' ) ^ 1 ) * '"' 
 
 
 local Operator = 
-  K ( 'Operator' ,
-      P "=" + P "!=" + P "<>" + P ">=" + P ">" + P "<=" + P "<"  + S "*+/"
-    )
+  K ( 'Operator' , P "=" + "!=" + "<>" + ">=" + ">" + "<=" + "<"  + S "*+/" )
 %    \end{macrocode}
 %
 % In SQL, the keywords are case-insensitive. That's why we have a little
@@ -6763,9 +6544,9 @@
 % distinguish the keywords with a Lua function. However, some keywords will be
 % catched in special LPEG because we want to detect the names of the SQL tables.
 %    \begin{macrocode}
-local function Set (list)
-  local set = {}
-  for _, l in ipairs(list) do set[l] = true end
+local function Set ( list )
+  local set = { }
+  for _, l in ipairs ( list ) do set[l] = true end
   return set
 end
 
@@ -6819,145 +6600,26 @@
 % \paragraph{The strings of SQL}
 %
 %    \begin{macrocode}
-local String = 
-  K ( 'String.Long' , P "'" * ( 1 - P "'" ) ^ 1 * P "'" ) 
+local String = K ( 'String.Long' , "'" * ( 1 - P "'" ) ^ 1 * "'" ) 
 %    \end{macrocode}
 % 
 % \bigskip
 % \paragraph{Beamer}
 %
-% The following \textsc{lpeg} |balanced_braces| will be used for the (mandatory)
-% argument of the commands |\only| and \emph{al.} of Beamer. It's necessary to
-% use a \emph{grammar} because that pattern mainly checks the correct nesting of
-% the delimiters (and it's known in the theory of formal languages that this
-% can't be done with regular expressions \emph{stricto sensu} only).
-%    \begin{macrocode}
-local balanced_braces =
-  P { "E" ,
-       E = 
-           (
-             P "{" * V "E" * P "}" 
-             + 
-             String  
-             + 
-             ( 1 - S "{}" ) 
-           ) ^ 0 
-    }
-%    \end{macrocode}
-%
-%
 % \bigskip
 %    \begin{macrocode}
-if piton_beamer 
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
-    + 
-      Ct ( Cc "Open" 
-            * C ( 
-                  ( 
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action" 
-                  ) 
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
-                  * P "{" 
-                ) 
-            * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopSQL:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopSQL ) 
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopSQL ) 
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopSQL )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopSQL ) 
-    + OneBeamerEnvironment ( "alertenv" , MainLoopSQL ) 
-    + OneBeamerEnvironment ( "actionenv" , MainLoopSQL ) 
-    +
-      L ( 
+braces = Compute_braces ( String ) 
+if piton.beamer then Beamer = Compute_Beamer ( 'sql' , braces ) end
 %    \end{macrocode}
-% For |\\alt|, the specification of the overlays (between angular brackets) is mandatory.
+% 
 %    \begin{macrocode}
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-    +  
-      L ( 
+DetectedCommands = Compute_DetectedCommands ( 'sql' , braces ) 
 %    \end{macrocode}
-% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
-%    \begin{macrocode}
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-end
-%    \end{macrocode}
 %
 %    \begin{macrocode}
-DetectedCommands = 
-      Ct ( Cc "Open" 
-            * C ( piton.ListCommands * P "{" ) * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopSQL:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
+LPEG_cleaner['sql'] = Compute_LPEG_cleaner ( 'sql' , braces ) 
 %    \end{macrocode}
 %
-% \bigskip
-%    \begin{macrocode}
-CleanLPEGs['sql']
-      = Ct ( ( piton.ListCommands * P "{" 
-                * ( balanced_braces 
-                    / ( function (s) return CleanLPEGs['sql']:match(s) end ) )
-                * P "}" 
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat 
-%    \end{macrocode}
-%
-% \bigskip
-% \paragraph{EOL}
-%
-% \bigskip
-% The following \textsc{lpeg} |EOL| is for the end of lines.
-%    \begin{macrocode}
-local EOL = 
-  P "\r" 
-  *
-  (
-    ( space^0 * -1 )
-    + 
-%    \end{macrocode}
-% We recall that each line in the SQL code we have to parse will be sent
-% back to LaTeX between a pair |\@@_begin_line:| --
-% |\@@_end_line:|\footnote{Remember that the \texttt{\textbackslash
-% @@\_end\_line:} must be explicit because it will be used as marker in order to
-% delimit the argument of the command \texttt{\textbackslash @@\_begin\_line:}}.
-%    \begin{macrocode}
-    Ct ( 
-         Cc "EOL"
-         * 
-         Ct (
-              Lc "\\@@_end_line:"
-              * BeamerEndEnvironments 
-              * BeamerBeginEnvironments 
-              * Lc "\\@@_newline: \\@@_begin_line:"
-            )
-       )
-  ) 
-  *
-  SpaceIndentation ^ 0
-%    \end{macrocode}
-%
 % 
 %
 % \bigskip
@@ -6965,95 +6627,63 @@
 %
 % We define different \textsc{lpeg} dealing with comments in the SQL listings.
 %    \begin{macrocode}
-local CommentMath = 
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"
-
 local Comment = 
   WithStyle ( 'Comment' ,
-     Q ( P "--" )  -- syntax of SQL92
-     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) 
+     Q "--"   -- syntax of SQL92
+     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) -- $
   * ( EOL + -1 )
 
 local LongComment = 
   WithStyle ( 'Comment' , 
-               Q ( P "/*" ) 
+               Q "/*" 
                * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0 
-               * Q ( P "*/" ) 
+               * Q "*/" 
             ) -- $
 %    \end{macrocode}
 %
 %
-% \bigskip
-% The following \textsc{lpeg} |CommentLaTeX| is for what is called in that
-% document the ``LaTeX comments''. Since the elements that will be catched must
-% be sent to LaTeX with standard LaTeX catcodes, we put the capture (done by
-% the function~|C|) in a table (by using~|Ct|, which is an alias for |lpeg.Ct|).
-%    \begin{macrocode}
-local CommentLaTeX =
-  P(piton.comment_latex) 
-  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
-  * L ( ( 1 - P "\r" ) ^ 0 ) 
-  * Lc "}}" 
-  * ( EOL + -1 )  
-%    \end{macrocode}
 % 
-%
-%
-% 
 % \bigskip
 % \paragraph{The main LPEG for the language SQL}
 %
 %
 %    \begin{macrocode}
-local function LuaKeyword ( name ) 
-return 
-   Lc ( "{\\PitonStyle{Keyword}{" )
-   * Q ( Cmt ( 
-               C ( identifier ) , 
-               function(s,i,a) return string.upper(a) == name end 
-             ) 
-       ) 
-   * Lc ( "}}" )
-end 
-%    \end{macrocode}
-% 
-%    \begin{macrocode}
 local TableField = 
-     K ( 'Name.Table' , identifier ) 
-     * Q ( P "." ) 
+       K ( 'Name.Table' , identifier ) 
+     * Q "." 
      * K ( 'Name.Field' , identifier ) 
 
 local OneField = 
   ( 
-    Q ( P "(" * ( 1 - P ")" ) ^ 0 * P ")" )
+    Q ( "(" * ( 1 - P ")" ) ^ 0 * ")" )
     + 
-    K ( 'Name.Table' , identifier ) 
-      * Q ( P "." ) 
+        K ( 'Name.Table' , identifier ) 
+      * Q "." 
       * K ( 'Name.Field' , identifier ) 
     + 
     K ( 'Name.Field' , identifier ) 
   )
   * ( 
-      Space * LuaKeyword ( "AS" ) * Space * K ( 'Name.Field' , identifier ) 
+      Space * LuaKeyword "AS" * Space * K ( 'Name.Field' , identifier ) 
     ) ^ -1
-  * ( Space * ( LuaKeyword ( "ASC" ) + LuaKeyword ( "DESC" ) ) ) ^ -1
+  * ( Space * ( LuaKeyword "ASC" + LuaKeyword "DESC" ) ) ^ -1
 
 local OneTable = 
      K ( 'Name.Table' , identifier ) 
    * ( 
        Space 
-       * LuaKeyword ( "AS" ) 
+       * LuaKeyword "AS"  
        * Space 
        * K ( 'Name.Table' , identifier ) 
      ) ^ -1 
 
 local WeCatchTableNames = 
-     LuaKeyword ( "FROM" ) 
+     LuaKeyword "FROM" 
    * ( Space + EOL ) 
-   * OneTable * ( SkipSpace * Q ( P "," ) * SkipSpace * OneTable ) ^ 0 
+   * OneTable * ( SkipSpace * Q "," * SkipSpace * OneTable ) ^ 0 
   + ( 
-      LuaKeyword ( "JOIN" ) + LuaKeyword ( "INTO" ) + LuaKeyword ( "UPDATE" ) 
-      + LuaKeyword ( "TABLE" ) 
+      LuaKeyword "JOIN" + LuaKeyword "INTO" + LuaKeyword "UPDATE" 
+      + LuaKeyword "TABLE" 
     ) 
     * ( Space + EOL ) * OneTable 
 %    \end{macrocode}
@@ -7061,8 +6691,9 @@
 %
 % First, the main loop :
 %    \begin{macrocode}
-local MainSQL = 
-       EOL
+local Main = 
+       space ^ 1 * -1
+     + space ^ 0 * EOL 
      + Space 
      + Tab
      + Escape + EscapeMath 
@@ -7082,169 +6713,57 @@
 %
 % Here, we must not put |local|!
 %    \begin{macrocode}
-MainLoopSQL = 
-  (  ( space^1 * -1 ) 
-     + MainSQL
-  ) ^ 0 
+LPEG1['sql'] = Main ^ 0 
 %    \end{macrocode}
 %
 % \bigskip
-% We recall that each line in the C code to parse will be sent back to
+% We recall that each line in the code to parse will be sent back to
 % LaTeX between a pair |\@@_begin_line:| -- |\@@_end_line:|\footnote{Remember
 % that the \texttt{\textbackslash @@\_end\_line:} must be explicit because it
 % will be used as marker in order to delimit the argument of the command
 % \texttt{\textbackslash @@\_begin\_line:}}.
 %    \begin{macrocode}
-languageSQL =
+LPEG2['sql'] =
   Ct (
-       ( ( space - P "\r" ) ^ 0 * P "\r" ) ^ -1 
+       ( space ^ 0 * "\r" ) ^ -1 
        * BeamerBeginEnvironments 
        * Lc '\\@@_begin_line:'
        * SpaceIndentation ^ 0 
-       * MainLoopSQL
+       * LPEG1['sql']
        * -1 
        * Lc '\\@@_end_line:' 
      )
 %    \end{macrocode}
 %
-%    \begin{macrocode}
-languages['sql'] = languageSQL
-%    \end{macrocode}
 % 
-% \subsubsection{The LPEG language Minimal}
+% \subsubsection{The language ``Minimal''}
 % 
 %    \begin{macrocode}
 local Punct = Q ( S ",:;!\\" )
 
-local CommentMath = 
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"
-
 local Comment = 
   WithStyle ( 'Comment' ,
-     Q ( P "#" ) 
-     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) 
-  * ( EOL + -1 )
+              Q "#" 
+              * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 -- $
+            )
+     * ( EOL + -1 )
 
-
 local String = 
   WithStyle ( 'String.Short' ,
-      Q "\"" 
-      * ( VisualSpace 
-          + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 ) 
-        ) ^ 0 
-      * Q "\""
-    )
+              Q "\"" 
+              * ( VisualSpace 
+                  + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 ) 
+                ) ^ 0 
+              * Q "\""
+            )
 
+braces = Compute_braces ( String ) 
+if piton.beamer then Beamer = Compute_Beamer ( 'minimal' , braces ) end
 
-local balanced_braces =
-  P { "E" ,
-       E = 
-           (
-             P "{" * V "E" * P "}" 
-             + 
-             String  
-             + 
-             ( 1 - S "{}" ) 
-           ) ^ 0 
-    }
+DetectedCommands = Compute_DetectedCommands ( 'minimal' , braces ) 
 
-if piton_beamer 
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
-    + 
-      Ct ( Cc "Open" 
-            * C ( 
-                  ( 
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action" 
-                  ) 
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
-                  * P "{" 
-                ) 
-            * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopMinimal:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopMinimal ) 
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopMinimal ) 
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopMinimal )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopMinimal ) 
-    + OneBeamerEnvironment ( "alertenv" , MainLoopMinimal ) 
-    + OneBeamerEnvironment ( "actionenv" , MainLoopMinimal ) 
-    +
-      L ( 
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-    +  
-      L ( 
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">" 
-          * P "{" 
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces ) 
-      * L ( P "}" )
-end
+LPEG_cleaner['minimal'] = Compute_LPEG_cleaner ( 'minimal' , braces ) 
 
-DetectedCommands = 
-      Ct ( Cc "Open" 
-            * C ( piton.ListCommands * P "{" ) * Cc "}" 
-         ) 
-       * ( balanced_braces / (function (s) return MainLoopMinimal:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" ) 
-
-
-CleanLPEGs['minimal']
-      = Ct ( ( piton.ListCommands * P "{" 
-                * ( balanced_braces 
-                    / ( function (s) return CleanLPEGs['minimal']:match(s) end ) )
-                * P "}" 
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat 
-
-
-
-local EOL = 
-  P "\r" 
-  *
-  (
-    ( space^0 * -1 )
-    + 
-    Ct ( 
-         Cc "EOL"
-         * 
-         Ct (
-              Lc "\\@@_end_line:"
-              * BeamerEndEnvironments 
-              * BeamerBeginEnvironments 
-              * Lc "\\@@_newline: \\@@_begin_line:"
-            )
-       )
-  ) 
-  *
-  SpaceIndentation ^ 0
-
-local CommentMath = 
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$" -- $
-
-local CommentLaTeX =
-  P(piton.comment_latex) 
-  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
-  * L ( ( 1 - P "\r" ) ^ 0 ) 
-  * Lc "}}" 
-  * ( EOL + -1 )  
-
 local identifier = letter * alphanum ^ 0
 
 local Identifier = K ( 'Identifier' , identifier )
@@ -7251,8 +6770,9 @@
 
 local Delim = Q ( S "{[()]}" )
 
-local MainMinimal = 
-       EOL
+local Main = 
+       space ^ 1 * -1
+     + space ^ 0 * EOL 
      + Space 
      + Tab
      + Escape + EscapeMath 
@@ -7267,22 +6787,18 @@
      + Number
      + Word
 
-MainLoopMinimal = 
-  (  ( space^1 * -1 ) 
-     + MainMinimal
-  ) ^ 0 
+LPEG1['minimal'] = Main ^ 0
 
-languageMinimal =
+LPEG2['minimal'] = 
   Ct (
-       ( ( space - P "\r" ) ^ 0 * P "\r" ) ^ -1 
+       ( space ^ 0 * "\r" ) ^ -1 
        * BeamerBeginEnvironments 
        * Lc '\\@@_begin_line:'
        * SpaceIndentation ^ 0 
-       * MainLoopMinimal
+       * LPEG1['minimal']
        * -1 
        * Lc '\\@@_end_line:' 
      )
-languages['minimal'] = languageMinimal
 
 % \bigskip
 % \subsubsection{The function Parse}
@@ -7291,32 +6807,33 @@
 % The function |Parse| is the main function of the package \pkg{piton}. It
 % parses its argument and sends back to LaTeX the code with interlaced
 % formatting LaTeX instructions. In fact, everything is done by the
-% \textsc{lpeg} corresponding to the considered language (|languages[language]|)
+% \textsc{lpeg} corresponding to the considered language (|LPEG2[language]|)
 % which returns as capture a Lua table containing data to send to LaTeX.
 % 
 % \bigskip
 %    \begin{macrocode}
-function piton.Parse(language,code)
-  local t = languages[language] : match ( code ) 
+function piton.Parse ( language , code )
+  local t = LPEG2[language] : match ( code ) 
   if t == nil 
   then 
-    tex.sprint("\\PitonSyntaxError")
+    tex.sprint(luatexbase.catcodetables.CatcodeTableExpl,
+               "\\@@_error:n { syntax~error }")
     return -- to exit in force the function
   end 
   local left_stack = {}
   local right_stack = {}
-  for _ , one_item in ipairs(t) 
+  for _ , one_item in ipairs ( t ) 
   do 
      if one_item[1] == "EOL"
      then 
-          for _ , s in ipairs(right_stack) 
-            do tex.sprint(s) 
+          for _ , s in ipairs ( right_stack ) 
+            do tex.sprint ( s ) 
             end
-          for _ , s in ipairs(one_item[2]) 
-            do tex.tprint(s)
+          for _ , s in ipairs ( one_item[2] ) 
+            do tex.tprint ( s )
             end
-          for _ , s in ipairs(left_stack) 
-            do tex.sprint(s) 
+          for _ , s in ipairs ( left_stack ) 
+            do tex.sprint ( s ) 
             end
      else 
 %    \end{macrocode}
@@ -7335,16 +6852,16 @@
           if one_item[1] == "Open"
           then
                tex.sprint( one_item[2] ) 
-               table.insert(left_stack,one_item[2])
-               table.insert(right_stack,one_item[3])
+               table.insert ( left_stack , one_item[2] )
+               table.insert ( right_stack , one_item[3] )
           else 
                if one_item[1] == "Close"
                then
-                    tex.sprint( right_stack[#right_stack] ) 
+                    tex.sprint ( right_stack[#right_stack] ) 
                     left_stack[#left_stack] = nil
                     right_stack[#right_stack] = nil
                else 
-                    tex.tprint(one_item)  
+                    tex.tprint ( one_item )  
                end 
           end 
      end 
@@ -7359,10 +6876,10 @@
 % That function merely reads the whole file (that is to say all its lines) and
 % then apply the function~|Parse| to the resulting Lua string.
 %    \begin{macrocode}
-function piton.ParseFile(language,name,first_line,last_line)
+function piton.ParseFile ( language , name , first_line , last_line )
   local s = ''
   local i = 0 
-  for line in io.lines(name) 
+  for line in io.lines ( name ) 
   do i = i + 1 
      if i >= first_line
      then s = s .. '\r' .. line 
@@ -7372,16 +6889,16 @@
 %    \end{macrocode}
 % We extract the BOM of utf-8, if present.
 %    \begin{macrocode}
-  if string.byte(s,1) == 13
-  then if string.byte(s,2) == 239
-       then if string.byte(s,3) == 187
-            then if string.byte(s,4) == 191
-                 then s = string.sub(s,5,-1)
+  if string.byte ( s , 1 ) == 13
+  then if string.byte ( s , 2 ) == 239
+       then if string.byte ( s , 3 ) == 187
+            then if string.byte ( s , 4 ) == 191
+                 then s = string.sub ( s , 5 , -1 )
                  end 
             end
        end
   end
-  piton.Parse(language,s)
+  piton.Parse ( language , s )
 end
 %    \end{macrocode}
 % 
@@ -7391,9 +6908,9 @@
 % The following command will be used by the user command |\piton|.
 % For that command, we have to undo the duplication of the symbols |#|.
 %    \begin{macrocode}
-function piton.ParseBis(language,code)
+function piton.ParseBis ( language , code )
   local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code )
-  return piton.Parse(language,s) 
+  return piton.Parse ( language , s ) 
 end
 %    \end{macrocode}
 %
@@ -7404,10 +6921,10 @@
 % element. In that case, you have to remove the potential |\@@_breakable_space:|
 % that have been inserted when the key |break-lines| is in force.
 %    \begin{macrocode}
-function piton.ParseTer(language,code)
+function piton.ParseTer ( language , code )
   local s = ( Cs ( ( P '\\@@_breakable_space:' / ' ' + 1 ) ^ 0 ) ) 
             : match ( code )
-  return piton.Parse(language,s)
+  return piton.Parse ( language , s )
 end
 %    \end{macrocode}
 % 
@@ -7424,13 +6941,13 @@
 % a \textsc{lpeg} that we have to compute dynamically because if depends on the
 % value of~$n$.
 %    \begin{macrocode}
-local function gobble(n,code)
+local function gobble ( n , code )
   if n==0 
   then return code
   else 
        return ( Ct ( 
-                     ( 1 - P "\r" ) ^ (-n)  * C ( ( 1 - P "\r" ) ^ 0 ) 
-                       * ( C ( P "\r" )
+                     ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 ) 
+                       * ( C "\r" 
                        * ( 1 - P "\r" ) ^ (-n)
                        * C ( ( 1 - P "\r" ) ^ 0 )
                       ) ^ 0 
@@ -7440,61 +6957,38 @@
 %    \end{macrocode}
 %
 % 
-% 
 % \bigskip
-% The following function |sum| will be used in the following \textsc{lpeg}
-% |AutoGobbleLPEG|, |TabsAutoGobbleLPEG| and |EnvGobbleLPEG|. It computes the
-% sum of all its arguments.
-%    \begin{macrocode}
-local function count_captures(...)
-    local acc = 0
-    for _ in ipairs({...}) do
-        acc = acc + 1
-    end
-    return acc
-end
-%    \end{macrocode}
-% 
-% \bigskip
 % The following \textsc{lpeg} returns as capture the minimal number of spaces at
 % the beginning of the lines of code. 
-%    begin{macrocode}
 %    \begin{macrocode}
-local AutoGobbleLPEG = 
-  (
-    (
+local AutoGobbleLPEG =
+      (  (
+           P " " ^ 0 * "\r"
+           +
+           Ct ( C " " ^ 0 ) / table.getn
+           * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * "\r"
+         ) ^ 0
+         * ( Ct ( C " " ^ 0 ) / table.getn
+              * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 
+       ) / math.min
 %    \end{macrocode}
-% We don't take into account the empty lines (those containing only spaces).
-%    \begin{macrocode}
-      P " " ^ 0 * P "\r"
-      + 
-      C ( P " " ) ^ 0 / count_captures * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * P "\r"
-    ) ^ 0
-%    \end{macrocode}
-% Now for the last line of the Python code...
-%    \begin{macrocode}
-    *
-    ( C ( P " " ) ^ 0 / count_captures * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 
-  ) / math.min
-%    \end{macrocode}
 %
 % \bigskip
-% The following \textsc{lpeg} is similar but works with the indentations.
+% The following \textsc{lpeg} is similar but works with the tabulations.
 %    \begin{macrocode}
-local TabsAutoGobbleLPEG = 
-  (
-    (
-      P "\t" ^ 0 * P "\r"
-      + 
-      C ( P " " ) ^ 0 / count_captures * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * P "\r"
-    ) ^ 0
-    *
-    ( C ( P " " ) ^ 0 / count_captures * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 
-  ) / math.min
+local TabsAutoGobbleLPEG =
+       (
+         (
+           P "\t" ^ 0 * "\r"
+           +
+           Ct ( C "\t" ^ 0 ) / table.getn
+           * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * "\r"
+         ) ^ 0
+         * ( Ct ( C "\t" ^ 0 ) / table.getn
+             * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 
+       ) / math.min
 %    \end{macrocode}
-% 
 %
-%
 % \bigskip
 % The following \textsc{lpeg} returns as capture the number of spaces at the
 % last line, that is to say before the |\end{Piton}| (and usually it's also the
@@ -7502,15 +6996,17 @@
 % traditionnal way to indent in LaTeX). 
 %    \begin{macrocode}
 local EnvGobbleLPEG =
-  ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0 * ( C ( P " " )  ^ 0 / count_captures ) * -1
+      ( ( 1 - P "\r" ) ^ 0 * "\r" ) ^ 0
+    * Ct ( C " " ^ 0 * -1 ) / table.getn 
 %    \end{macrocode}
 % 
 % \bigskip
 %    \begin{macrocode}
-local function remove_before_cr(input_string)
-    local match_result = P("\r") : match(input_string)
-    if match_result then
-        return string.sub(input_string, match_result ) 
+local function remove_before_cr ( input_string )
+    local match_result = ( P "\r" ) : match ( input_string )
+    if match_result 
+    then
+        return string.sub ( input_string , match_result ) 
     else
         return input_string 
     end
@@ -7518,20 +7014,21 @@
 %    \end{macrocode}
 %
 % \bigskip
+% In the following code, |n| is the value of |\l_@@_gobble_int|.
 %    \begin{macrocode}
-function piton.GobbleParse(language,n,code)
-  code = remove_before_cr(code)
-  if n==-1 
-  then n = AutoGobbleLPEG : match(code)
-  else if n==-2 
-       then n = EnvGobbleLPEG : match(code)
-       else if n==-3
-            then n = TabsAutoGobbleLPEG : match(code)
+function piton.GobbleParse ( language , n , code )
+  code = remove_before_cr ( code )
+  if n == -1 
+  then n = AutoGobbleLPEG : match ( code )
+  else if n == -2
+       then n = EnvGobbleLPEG : match ( code )
+       else if n == -3
+            then n = TabsAutoGobbleLPEG : match ( code )
             end
        end
   end
-  piton.last_code = gobble(n,code)
-  piton.Parse(language,piton.last_code)
+  piton.last_code = gobble ( n , code )
+  piton.Parse ( language , piton.last_code )
   piton.last_language = language
 %    \end{macrocode}
 % Now, if the final user has used the key |write| to write the code of the
@@ -7538,18 +7035,18 @@
 % environment on an external file.
 %    \begin{macrocode}
   if piton.write ~= ''
-  then local file = assert(io.open(piton.write,piton.write_mode))
-       file:write(piton.get_last_code()) 
-       file:close()
+  then local file = assert ( io.open ( piton.write , piton.write_mode ) )
+       file:write ( piton.get_last_code ( ) ) 
+       file:close ( )
   end
 end 
 %    \end{macrocode}
 %
 % \bigskip
-% The following Lua function is provided to the developper. 
+% The following public Lua function is provided to the developper. 
 %    \begin{macrocode}
 function piton.get_last_code ( ) 
-  return CleanLPEGs[piton.last_language] : match(piton.last_code) 
+  return LPEG_cleaner[piton.last_language] : match ( piton.last_code ) 
 end
 %    \end{macrocode}
 % 
@@ -7559,10 +7056,10 @@
 %
 % \medskip
 %    \begin{macrocode}
-function piton.CountLines(code)
+function piton.CountLines ( code )
   local count = 0 
   for i in code : gmatch ( "\r" ) do count = count + 1 end 
-  tex.sprint( 
+  tex.sprint ( 
       luatexbase.catcodetables.expl , 
       '\\int_set:Nn \\l_@@_nb_lines_int {' .. count .. '}' )
 end 
@@ -7569,15 +7066,15 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-function piton.CountNonEmptyLines(code)
-  local count = 0 
-  count = 
-  (  (  (  ( 
-            ( P " " ) ^ 0 * P "\r"  
-              + ( 1 - P "\r" ) ^ 0 * C ( P "\r" ) 
-            ) ^ 0 
-          * (1 - P "\r" ) ^ 0 
-       ) / count_captures ) * -1 ) : match (code) 
+function piton.CountNonEmptyLines ( code )
+  local count = 0
+  count =
+     ( Ct ( ( P " " ^ 0 * "\r"
+              + ( 1 - P "\r" ) ^ 0 * C "\r" ) ^ 0
+            * ( 1 - P "\r" ) ^ 0 
+            * -1
+          ) / table.getn
+     ) : match ( code )
   tex.sprint( 
       luatexbase.catcodetables.expl , 
       '\\int_set:Nn \\l_@@_nb_non_empty_lines_int {' .. count .. '}' )
@@ -7586,11 +7083,11 @@
 %
 % \bigskip
 %    \begin{macrocode}
-function piton.CountLinesFile(name)
+function piton.CountLinesFile ( name )
   local count = 0 
-  io.open(name) 
-  for line in io.lines(name) do count = count + 1 end
-  tex.sprint( 
+  io.open ( name ) 
+  for line in io.lines ( name ) do count = count + 1 end
+  tex.sprint ( 
       luatexbase.catcodetables.expl , 
       '\\int_set:Nn \\l_@@_nb_lines_int {' .. count .. '}' )
 end 
@@ -7599,14 +7096,14 @@
 %
 % \bigskip
 %    \begin{macrocode}
-function piton.CountNonEmptyLinesFile(name)
+function piton.CountNonEmptyLinesFile ( name )
   local count = 0 
-  for line in io.lines(name) 
-  do if not ( ( ( P " " ) ^ 0 * -1 ) : match ( line ) ) 
+  for line in io.lines ( name ) 
+  do if not ( ( P " " ^ 0 * -1 ) : match ( line ) ) 
      then count = count + 1 
      end
   end
-  tex.sprint( 
+  tex.sprint ( 
       luatexbase.catcodetables.expl , 
       '\\int_set:Nn \\l_@@_nb_non_empty_lines_int {' .. count .. '}' )
 end 
@@ -7624,12 +7121,12 @@
   local first_line = -1
   local count = 0
   local last_found = false
-  for line in io.lines(file_name)
+  for line in io.lines ( file_name )
   do if first_line == -1
-     then if string.sub(line,1,#s) == s 
+     then if string.sub ( line , 1 , #s ) == s 
           then first_line = count 
           end 
-     else if string.sub(line,1,#t) == t
+     else if string.sub ( line , 1 , #t ) == t
           then last_found = true 
                break 
           end 
@@ -7637,16 +7134,332 @@
      count = count + 1 
   end
   if first_line == -1 
-  then tex.sprint("\\PitonBeginMarkerNotFound")
+  then tex.sprint ( luatexbase.catcodetables.expl ,
+                    "\\@@_error:n { begin~marker~not~found }" )
   else if last_found == false
-       then tex.sprint("\\PitonEndMarkerNotFound")
+       then tex.sprint ( luatexbase.catcodetables.expl ,
+                         "\\@@_error:n { end~marker~not~found }" )
        end
   end
-  tex.sprint( 
+  tex.sprint ( 
       luatexbase.catcodetables.expl , 
       '\\int_set:Nn \\l_@@_first_line_int {' .. first_line .. ' + 2 }' 
       .. '\\int_set:Nn \\l_@@_last_line_int {' .. count .. ' }' )
 end
+%    \end{macrocode}
+%
+% \bigskip
+% \subsubsection{To create new languages with the syntax of listings}
+%
+%    \begin{macrocode}
+function piton.new_language ( lang , definition )
+  lang = string.lower ( lang )
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+  local alpha , digit = lpeg.alpha , lpeg.digit 
+  local letter = alpha + S "@_$" -- $
+%    \end{macrocode}
+%
+% \bigskip 
+% In the following \textsc{lpeg} we have a problem when we try to add |{| and
+% |}|. 
+%    \begin{macrocode}
+  local other = S "+-*/<>!?:;.()@[]~^=#&\"\'\\$" -- $
+%    \end{macrocode}
+% 
+% \bigskip
+%    \begin{macrocode}
+  function add_to_letter ( c )
+     if c ~= " " then letter = letter + c end 
+  end 
+  function add_to_digit ( c )
+     if c ~= " " then digit = digit + c end 
+  end 
+%    \end{macrocode}
+% 
+% \bigskip
+% Of course, the \textsc{lpeg} |b_braces| is for balanced braces (without the
+% question of strings of an informatic language). In fact, it \emph{won't} be
+% used for an informic language (as dealt by \pkg{piton}) but for LaTeX
+% instructions; 
+%    \begin{macrocode}
+  local strict_braces  =
+    P { "E" , 
+        E = ( "{" * V "F" * "}" + ( 1 - S ",{}" ) ) ^ 0  ,
+        F = ( "{" * V "F" * "}" + ( 1 - S "{}" ) ) ^ 0 
+      }
+%    \end{macrocode}
+%
+% \bigskip
+% Now, the first transformation of the definition of the language, as provided
+% by the final user in the argument |definition| of |piton.new_language|.
+%    \begin{macrocode}
+  local cut_definition =
+    P { "E" ,
+        E = Ct ( V "F" * ( "," * V "F" ) ^ 0 ) ,
+        F = Ct ( space ^ 0 * C ( alpha ^ 1 ) * space ^ 0 
+                * ( "=" * space ^ 0 * C ( strict_braces ) ) ^ -1 )
+      }
+  local def_table = cut_definition : match ( definition )
+%    \end{macrocode}
+% The definition of the language, provided by the final user of \pkg{piton} is
+% now in the Lua table |def_table|. We will use it several times.
+%
+% \medskip
+% \bigskip
+% We scan the definition of the language (i.e. the table |def_table|) in order
+% to detect the potential key |sensitive|. Indeed, we have to catch that key
+% before the treatment of the keywords of the language. We will also look for
+% the potential keys |alsodigit| and |alsoletter|. 
+%    \begin{macrocode}
+  local sensitive = true 
+  for _ , x in ipairs ( def_table )
+  do if x[1] == "sensitive"
+     then if x[2] == nil or ( P "true" ) : match ( x[2] ) 
+          then sensitive = true 
+          else if ( P "false" ) : match ( x[2] ) then sensitive = false end
+          end
+     end
+     if x[1] == "alsodigit" then x[2] : gsub ( "." , add_to_digit ) end 
+     if x[1] == "alsoletter" then x[2] : gsub ( "." , add_to_letter ) end 
+  end
+%    \end{macrocode}
+% Now, the \textsc{lpeg} for the numbers. Of course, it uses |digit| previously
+% computed. 
+%    \begin{macrocode}
+  local Number =
+    K ( 'Number' ,
+        ( digit ^ 1 * "." * # ( 1 - P "." ) * digit ^ 0 
+          + digit ^ 0 * "." * digit ^ 1 
+          + digit ^ 1 )
+        * ( S "eE" * S "+-" ^ -1 * digit ^ 1 ) ^ -1
+        + digit ^ 1 
+      ) 
+%    \end{macrocode}
+% 
+%    \begin{macrocode}
+  local alphanum = letter + digit
+  local identifier = letter * alphanum ^ 0
+  local Identifier = K ( 'Identifier' , identifier )
+%    \end{macrocode}
+%
+% 
+% \bigskip
+% Now, we scan the definition of the language (i.e. the table |def_table|) for
+% the keywords.
+%
+% The following LPEG catches the optional argument (between square brackets) in
+% first position.
+%    \begin{macrocode}
+  local option = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" 
+%    \end{macrocode}
+%
+% The following LPEG does \emph{not} catch the optional argument between square
+% brackets in first position.
+%    \begin{macrocode}
+  local split_clist = 
+    P { "E" ,
+         E = ( "[" * ( 1 - P "]" ) ^ 0 * "]" ) ^ -1  
+             * ( P "{" ) ^ 1
+             * Ct ( V "F" * ( "," * V "F" ) ^ 0 ) 
+             * ( P "}" ) ^ 1 * space ^ 0 ,
+         F = space ^ 0 * C ( letter * alphanum ^ 0 + other ^ 1 ) * space ^ 0 
+      }
+%    \end{macrocode}
+% The following function will be used if the keywords are not case-sensitive.
+%    \begin{macrocode}
+  local function keyword_to_lpeg ( name ) 
+  return 
+    Q ( Cmt ( 
+              C ( identifier ) , 
+              function(s,i,a) return string.upper(a) == string.upper(name) end 
+            ) 
+      ) 
+  end 
+  local Keyword = P ( false )  
+%    \end{macrocode}
+% Now, we actually treat all the keywords.
+%    \begin{macrocode}
+  for _ , x in ipairs ( def_table )
+  do if x[1] == "morekeywords" or x[1] == "otherkeywords" then
+        local keywords = P ( false ) 
+        for _ , word in ipairs ( split_clist : match ( x[2] ) )
+        do if sensitive 
+%    \end{macrocode}
+% The documentation of \pkg{lstlistings} specifies that, for the key
+% |otherkeywords|, if a keyword is a prefix of another keyword, then the prefix
+% must appear first. However, for the \text{lpeg}, it's rather the contrary.
+% That's why, here, we add the new element \emph{on the left}.
+%    \begin{macrocode}
+           then keywords = Q ( word  ) + keywords
+           else keywords = keyword_to_lpeg ( word ) + keywords
+           end 
+        end
+        Keyword = Keyword + 
+           Lc ( "{" 
+                 ..  ( option : match ( x[2] ) or "\\PitonStyle{Keyword}" ) 
+                 .. "{" )
+           * keywords * Lc "}}" 
+     end 
+     if x[1] == "keywordsprefix" then
+       local prefix = ( ( C ( 1 - P " " ) ^ 1 ) * P " " ^ 0 ) : match ( x[2] ) 
+       Keyword = Keyword + K ( 'Keyword' , P ( prefix ) * alphanum ^ 0 ) 
+     end 
+  end    
+%    \end{macrocode}
+%
+% \bigskip
+% Now, we scan the definition of the language (i.e. the table |def_table|) for
+% the strings.
+%    \begin{macrocode}
+  local long_string  = P ( false )
+  local LongString = P (false ) 
+  local args = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" 
+               * space ^ 0 
+               * ( "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" + Cc ( nil ) ) 
+               * space ^ 0 
+               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + C ( 1 ) ) 
+  local central_pattern = P ( false ) 
+  for _ , x in ipairs ( def_table )
+  do if x[1] == "morestring" then
+       arg1 , arg2 , arg3 = args : match ( x[2] ) 
+       arg2 = arg2 or "\\PitonStyle{String.Long}" 
+       if arg1 == "b" then 
+         central_pattern = Q ( ( P ( "\\" .. arg3 )  + 1 - S ( " \r" .. arg3 ) ) ^ 1 ) 
+       end
+       if arg1 == "d" then 
+         central_pattern = Q ( ( P ( arg3 .. arg3 )  + 1 - S ( " \r" .. arg3 ) ) ^ 1 ) 
+       end
+       if arg1 == "bd" then 
+         central_pattern = 
+           Q ( ( P ( arg3 .. arg3 ) + P ( "\\" .. arg3 ) + 1 - S ( " \r" .. arg3 ) ) ^ 1 ) 
+       end
+       if arg1 == "m" then 
+         central_pattern =  Q ( ( P ( arg3 .. arg3 ) + 1 - S ( " \r" .. arg3 ) ) ^ 1 ) 
+       end
+       if arg1 == "m" 
+       then prefix = P ( false ) 
+       else prefix = lpeg.B ( 1 - letter - ")" - "]" ) 
+       end
+%    \end{macrocode}
+% First, we create |long_string| because we need that \textsc{lpeg} in the
+% nested comments.
+%    \begin{macrocode}
+       long_string = long_string +
+         prefix * ( Q ( arg3 ) * ( VisualSpace + central_pattern + EOL ) ^ 0 * Q ( arg3 ) )
+       LongString = LongString +
+          Ct ( Cc "Open" * Cc ( "{" ..  arg2 .. "{" ) * Cc "}}" )
+          * long_string 
+          * Ct ( Cc "Close" ) 
+     end 
+  end
+
+  local braces = Compute_braces ( String ) 
+  if piton.beamer then Beamer = Compute_Beamer ( lang , braces ) end
+
+  DetectedCommands = Compute_DetectedCommands ( lang , braces ) 
+
+  LPEG_cleaner[lang] = Compute_LPEG_cleaner ( lang , braces ) 
+%    \end{macrocode}
+%
+% \bigskip
+% Now, we deal with the comments.
+%    \begin{macrocode}
+  local Comment = P ( false ) 
+
+  local args = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" 
+               * space ^ 0 
+               * ( "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" + Cc ( nil ) ) 
+               * space ^ 0
+               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + C ( 1 ) ) 
+               * space ^ 0
+               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + Cc ( nil ) ) 
+
+  for _ , x in ipairs ( def_table )
+  do if x[1] == "morecomment"
+     then local arg1 , arg2 , arg3 , arg4 = args : match ( x[2] ) 
+          arg2 = arg2 or "\\PitonStyle{Comment}"
+          if arg1 == "l" then 
+            if arg3 == [[\#]] then arg3 = "#" end -- mandatory
+            Comment = Comment + 
+                Ct ( Cc "Open" 
+                     * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
+                     *  Q ( arg3 ) 
+                     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 -- $
+                * Ct ( Cc "Close" ) 
+                * ( EOL + -1 )
+           end 
+           if arg1 == "s" then 
+             Comment = Comment +
+                 Ct ( Cc "Open" * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
+                 * Q ( arg3 ) 
+                 * ( 
+                     CommentMath 
+                     + Q ( ( 1 - P ( arg4 ) - S "$\r" ) ^ 1 ) -- $
+                     + EOL 
+                   ) ^ 0  
+                 * Q ( arg4 ) 
+                 * Ct ( Cc "Close" ) 
+           end
+           if arg1 == "n" then 
+             Comment = Comment +
+               Ct ( Cc "Open" * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
+                * P { "A" ,
+                     A = Q ( arg3 ) 
+                         * ( V "A" 
+                             + Q ( ( 1 - P ( arg3 ) - P ( arg4 ) 
+                                     - S "\r$\"" ) ^ 1 ) -- $
+                             + long_string
+                             +   "$" -- $
+                                 * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) --$
+                                 * "$" -- $
+                             + EOL
+                           ) ^ 0 
+                         * Q ( arg4 )
+                    }  
+               * Ct ( Cc "Close" ) 
+           end
+      end 
+  end 
+
+  local Delim = Q ( S "{[()]}" )
+  local Punct = Q ( S ",:;!\\'\"" )
+
+  local Main = 
+         space ^ 1 * -1
+       + space ^ 0 * EOL 
+       + Space 
+       + Tab
+       + Escape + EscapeMath 
+       + CommentLaTeX
+       + Beamer
+       + DetectedCommands
+       + Comment 
+       + Delim
+       + LongString
+        -- should maybe be after the following line!
+       + Keyword * ( Space + Punct + Delim + EOL + -1 ) 
+       + Punct 
+       + K ( 'Identifier' , letter * alphanum ^ 0 )
+       + Number
+       + Word
+
+  LPEG1[lang] = Main ^ 0 
+
+  LPEG2[lang] = 
+    Ct (
+         ( space ^ 0 * P "\r" ) ^ -1 
+         * BeamerBeginEnvironments 
+         * Lc '\\@@_begin_line:'
+         * SpaceIndentation ^ 0 
+         * LPEG1[lang]
+         * -1 
+         * Lc '\\@@_end_line:' 
+       )
+
+end
 %</LUA>
 %    \end{macrocode}
 % 
@@ -7723,7 +7536,7 @@
 %
 % \subsection*{Changes between versions 1.6 and 2.0}
 %
-% The extension \pkg{piton} nows supports the computer languages OCaml and C
+% The extension \pkg{piton} now supports the computer languages OCaml and C
 % (and, of course, Python).
 %
 % \subsection*{Changes between versions 1.5 and 1.6}
@@ -7777,48 +7590,6 @@
 % commands |\action|, |\alert|, |\invisible|, |\only|, |\uncover| and |\visible|
 % in the environments |{Piton}| when the class \cls{beamer} is used.
 %
-% \subsection*{Changes between versions 0.99 and 1.0}
-%
-% New key |tabs-auto-gobble|.
-% 
-% \subsection*{Changes between versions 0.95 and 0.99}
-%
-% New key |break-lines| to allow breaks of the lines of code (and other keys to
-% customize the appearance).
-%
-% \subsection*{Changes between versions 0.9 and 0.95}
-%
-% New key |show-spaces|.
-%
-% The key |left-margin| now accepts the special value |auto|.
-%
-% New key |latex-comment| at load-time and replacement of |##| by |#>|
-%
-% New key |math-comments| at load-time.
-%
-% New keys |first-line| and |last-line| for the command |\InputPitonFile|.
-%
-% \subsection*{Changes between versions 0.8 and 0.9}
-%
-% New key |tab-size|.
-%
-% Integer value for the key |splittable|.
-%
-% \subsection*{Changes between versions 0.7 and 0.8}
-% 
-% New keys |footnote| and |footnotehyper| at load-time.
-%
-% New key |left-margin|.
-% 
-% \subsection*{Changes between versions 0.6 and 0.7}
-% 
-% New keys |resume|, |splittable| and |background-color| in |\PitonOptions|.
-%
-% The file |piton.lua| has been embedded in the file |piton.sty|. That means
-% that the extension \pkg{piton} is now entirely contained in the file |piton.sty|.
-% 
-%
-%
 % \tableofcontents
 %
 % \end{document}

Modified: branches/branch2023.final/Master/texmf-dist/tex/lualatex/piton/piton.lua
===================================================================
--- branches/branch2023.final/Master/texmf-dist/tex/lualatex/piton/piton.lua	2024-03-06 21:09:27 UTC (rev 70445)
+++ branches/branch2023.final/Master/texmf-dist/tex/lualatex/piton/piton.lua	2024-03-06 21:09:36 UTC (rev 70446)
@@ -20,7 +20,7 @@
 -- -------------------------------------------
 -- 
 -- This file is part of the LuaLaTeX package 'piton'.
--- Version 2.6 of 2024/02/27
+-- Version 2.6a of 2024/03/06
 
 
 if piton.comment_latex == nil then piton.comment_latex = ">" end
@@ -34,22 +34,22 @@
 local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc
 local Cs , Cg , Cmt , Cb = lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb
 local R = lpeg.R
-local function Q(pattern)
+local function Q ( pattern )
   return Ct ( Cc ( luatexbase.catcodetables.CatcodeTableOther ) * C ( pattern ) )
 end
-local function L(pattern)
+local function L ( pattern )
   return Ct ( C ( pattern ) )
 end
-local function Lc(string)
+local function Lc ( string )
   return Cc ( { luatexbase.catcodetables.expl , string } )
 end
-local function K(style, pattern)
+local function K ( style , pattern )
   return
      Lc ( "{\\PitonStyle{" .. style .. "}{" )
      * Q ( pattern )
-     * Lc ( "}}" )
+     * Lc "}}"
 end
-local function WithStyle(style,pattern)
+local function WithStyle ( style , pattern )
   return
        Ct ( Cc "Open" * Cc ( "{\\PitonStyle{" .. style .. "}{" ) * Cc "}}" )
      * pattern
@@ -60,31 +60,30 @@
 if piton.begin_escape ~= nil
 then
   Escape =
-    P(piton.begin_escape)
-    * L ( ( 1 - P(piton.end_escape) ) ^ 1 )
-    * P(piton.end_escape)
+    P ( piton.begin_escape )
+    * L ( ( 1 - P ( piton.end_escape ) ) ^ 1 )
+    * P ( piton.end_escape )
   EscapeClean =
-    P(piton.begin_escape)
-    * ( 1 - P(piton.end_escape) ) ^ 1
-    * P(piton.end_escape)
+    P ( piton.begin_escape )
+    * ( 1 - P ( piton.end_escape ) ) ^ 1
+    * P ( piton.end_escape )
 end
 EscapeMath = P ( false )
 if piton.begin_escape_math ~= nil
 then
   EscapeMath =
-    P(piton.begin_escape_math)
-    * Lc ( "\\ensuremath{" )
+    P ( piton.begin_escape_math )
+    * Lc "\\ensuremath{"
     * L ( ( 1 - P(piton.end_escape_math) ) ^ 1 )
     * Lc ( "}" )
-    * P(piton.end_escape_math)
+    * P ( piton.end_escape_math )
 end
 lpeg.locale(lpeg)
-local alpha, digit = lpeg.alpha, lpeg.digit
+local alpha , digit = lpeg.alpha , lpeg.digit
 local space = P " "
-local letter = alpha + P "_"
-  + P "â" + P "à" + P "ç" + P "é" + P "è" + P "ê" + P "ë" + P "ï" + P "î"
-  + P "ô" + P "û" + P "ü" + P "Â" + P "À" + P "Ç" + P "É" + P "È" + P "Ê"
-  + P "Ë" + P "Ï" + P "Î" + P "Ô" + P "Û" + P "Ü"
+local letter = alpha + "_" + "â" + "à" + "ç" + "é" + "è" + "ê" + "ë" + "ï" + "î"
+                    + "ô" + "û" + "ü" + "Â" + "À" + "Ç" + "É" + "È" + "Ê" + "Ë"
+                    + "Ï" + "Î" + "Ô" + "Û" + "Ü"
 
 local alphanum = letter + digit
 local identifier = letter * alphanum ^ 0
@@ -91,143 +90,233 @@
 local Identifier = K ( 'Identifier' , identifier )
 local Number =
   K ( 'Number' ,
-      ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 )
-      * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1
-      + digit^1
+      ( digit ^ 1 * P "." * # ( 1 - P "." ) * digit ^ 0
+        + digit ^ 0 * P "." * digit ^ 1
+        + digit ^ 1 )
+      * ( S "eE" * S "+-" ^ -1 * digit ^ 1 ) ^ -1
+      + digit ^ 1
     )
 local Word
 if piton.begin_escape ~= nil
-then Word = Q ( ( ( 1 - space - P(piton.begin_escape) - P(piton.end_escape) )
+then Word = Q ( ( ( 1 - space - P ( piton.begin_escape ) - P ( piton.end_escape ) )
                    - S "'\"\r[({})]" - digit ) ^ 1 )
 else Word = Q ( ( ( 1 - space ) - S "'\"\r[({})]" - digit ) ^ 1 )
 end
-local Space = ( Q " " ) ^ 1
+local Space = Q " " ^ 1
 
-local SkipSpace = ( Q " " ) ^ 0
+local SkipSpace = Q " " ^ 0
 
 local Punct = Q ( S ".,:;!" )
 
-local Tab = P "\t" * Lc ( '\\l__piton_tab_tl' )
-local SpaceIndentation = Lc ( '\\__piton_an_indentation_space:' ) * ( Q " " )
+local Tab = "\t" * Lc "\\l__piton_tab_tl"
+local SpaceIndentation = Lc "\\__piton_an_indentation_space:" * Q " "
 local Delim = Q ( S "[({})]" )
 local VisualSpace = space * Lc "\\l__piton_space_tl"
+local LPEG1 = { }
+local LPEG2 = { }
+local LPEG_cleaner = { }
+local function Compute_braces ( lpeg_string ) return
+    P { "E" ,
+         E =
+             (
+               P "{" * V "E" * P "}"
+               +
+               lpeg_string
+               +
+               ( 1 - S "{}" )
+             ) ^ 0
+      }
+end
+local function Compute_DetectedCommands ( lang , braces ) return
+  Ct ( Cc "Open"
+        * C ( piton.ListCommands * P "{" )
+        * Cc "}"
+     )
+   * ( braces / (function ( s ) return LPEG1[lang] : match ( s ) end ) )
+   * P "}"
+   * Ct ( Cc "Close" )
+end
+local function Compute_LPEG_cleaner ( lang , braces ) return
+  Ct ( ( piton.ListCommands * P "{"
+          * (  braces
+              / ( function ( s ) return LPEG_cleaner[lang] : match ( s ) end ) )
+          * P "}"
+         + EscapeClean
+         +  C ( P ( 1 ) )
+        ) ^ 0 ) / table.concat
+end
 local Beamer = P ( false )
 local BeamerBeginEnvironments = P ( true )
 local BeamerEndEnvironments = P ( true )
-if piton_beamer
-then
-  local BeamerNamesEnvironments =
-    P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv"
-    + P "alertenv" + P "actionenv"
-  BeamerBeginEnvironments =
-      ( space ^ 0 *
-        L
-          (
-            P "\\begin{" * BeamerNamesEnvironments * "}"
-            * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
-          )
-        * P "\r"
-      ) ^ 0
-  BeamerEndEnvironments =
-      ( space ^ 0 *
-        L ( P "\\end{" * BeamerNamesEnvironments * P "}" )
-        * P "\r"
-      ) ^ 0
-  function OneBeamerEnvironment(name,lpeg)
-    return
+local list_beamer_env =
+  { "uncoverenv" , "onlyenv" , "visibleenv" , "invisibleenv" , "alertenv" , "actionenv" }
+local BeamerNamesEnvironments = P ( false )
+for _ , x in ipairs ( list_beamer_env ) do
+  BeamerNamesEnvironments = BeamerNamesEnvironments + x
+end
+BeamerBeginEnvironments =
+    ( space ^ 0 *
+      L
+        (
+          P "\\begin{" * BeamerNamesEnvironments * "}"
+          * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
+        )
+      * P "\r"
+    ) ^ 0
+BeamerEndEnvironments =
+    ( space ^ 0 *
+      L ( P "\\end{" * BeamerNamesEnvironments * P "}" )
+      * P "\r"
+    ) ^ 0
+local function Compute_Beamer ( lang , braces )
+  local lpeg = L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
+  lpeg = lpeg +
+      Ct ( Cc "Open"
+            * C ( ( P "\\uncover" + "\\only" + "\\alert" + "\\visible"
+                    + "\\invisible" + "\\action" )
+                  * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
+                  * P "{"
+                )
+            * Cc "}"
+         )
+       * ( braces / ( function ( s ) return LPEG1[lang] : match ( s ) end ) )
+       * P "}"
+       * Ct ( Cc "Close" )
+  lpeg = lpeg +
+    L ( P "\\alt" * P "<" * ( 1 - P ">" ) ^ 0 * P ">" * P "{" )
+     * K ( 'ParseAgain.noCR' , braces )
+     * L ( P "}{" )
+     * K ( 'ParseAgain.noCR' , braces )
+     * L ( P "}" )
+  lpeg = lpeg +
+      L ( ( P "\\temporal" ) * P "<" * ( 1 - P ">" ) ^ 0 * P ">" * P "{" )
+      * K ( 'ParseAgain.noCR' , braces )
+      * L ( P "}{" )
+      * K ( 'ParseAgain.noCR' , braces )
+      * L ( P "}{" )
+      * K ( 'ParseAgain.noCR' , braces )
+      * L ( P "}" )
+  for _ , x in ipairs ( list_beamer_env ) do
+  lpeg = lpeg +
         Ct ( Cc "Open"
-              * C (
-                    P ( "\\begin{" .. name ..   "}" )
+             * C (
+                    P ( "\\begin{" .. x .. "}" )
                     * ( P "<" * ( 1 - P ">") ^ 0 * P ">" ) ^ -1
                   )
-             * Cc ( "\\end{" .. name ..  "}" )
+             * Cc ( "\\end{" .. x ..  "}" )
             )
-       * (
-           ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 )
-              / ( function (s) return lpeg : match(s) end )
-         )
-       * P ( "\\end{" .. name ..  "}" ) * Ct ( Cc "Close" )
+        * (
+            ( ( 1 - P ( "\\end{" .. x .. "}" ) ) ^ 0 )
+                / ( function ( s ) return LPEG1[lang] : match ( s ) end )
+          )
+        * P ( "\\end{" .. x .. "}" )
+        * Ct ( Cc "Close" )
   end
+  return lpeg
 end
-local languages = { }
-local CleanLPEGs = { }
+local CommentMath =
+  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$" -- $
+local PromptHastyDetection =
+  ( # ( P ">>>" + "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1
+local Prompt = K ( 'Prompt' , ( ( P ">>>" + "..." ) * P " " ^ -1 ) ^ -1  )
+local EOL =
+  P "\r"
+  *
+  (
+    ( space ^ 0 * -1 )
+    +
+    Ct (
+         Cc "EOL"
+         *
+         Ct (
+              Lc "\\__piton_end_line:"
+              * BeamerEndEnvironments
+              * BeamerBeginEnvironments
+              * PromptHastyDetection
+              * Lc "\\__piton_newline: \\__piton_begin_line:"
+              * Prompt
+            )
+       )
+  )
+  * ( SpaceIndentation ^ 0 * # ( 1 - S " \r" ) ) ^ -1
+local CommentLaTeX =
+  P(piton.comment_latex)
+  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
+  * L ( ( 1 - P "\r" ) ^ 0 )
+  * Lc "}}"
+  * ( EOL + -1 )
 local Operator =
   K ( 'Operator' ,
-      P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":="
-      + P "//" + P "**" + S "-~+/*%=<>&.@|"
-    )
+      P "!=" + "<>" + "==" + "<<" + ">>" + "<=" + ">=" + ":=" + "//" + "**"
+      + S "-~+/*%=<>&.@|" )
 
 local OperatorWord =
-  K ( 'Operator.Word' , P "in" + P "is" + P "and" + P "or" + P "not" )
+  K ( 'Operator.Word' , P "in" + "is" + "and" + "or" + "not" )
 
 local Keyword =
   K ( 'Keyword' ,
-      P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue"
-      + P "def" + P "del" + P "elif" + P "else" + P "except" + P "exec"
-      + P "finally" + P "for" + P "from" + P "global" + P "if" + P "import"
-      + P "lambda" + P "non local" + P "pass" + P "return" + P "try"
-      + P "while" + P "with" + P "yield" + P "yield from" )
-  + K ( 'Keyword.Constant' ,P "True" + P "False" + P "None" )
+      P "as" + "assert" + "break" + "case" + "class" + "continue" + "def" +
+      "del" + "elif" + "else" + "except" + "exec" + "finally" + "for" + "from" +
+      "global" + "if" + "import" + "lambda" + "non local" + "pass" + "return" +
+      "try" + "while" + "with" + "yield" + "yield from" )
+  + K ( 'Keyword.Constant' , P "True" + "False" + "None" )
 
 local Builtin =
   K ( 'Name.Builtin' ,
-      P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool"
-    + P "bytearray" + P "bytes" + P "chr" + P "classmethod" + P "compile"
-    + P "complex" + P "delattr" + P "dict" + P "dir" + P "divmod"
-    + P "enumerate" + P "eval" + P "filter" + P "float" + P "format"
-    + P "frozenset" + P "getattr" + P "globals" + P "hasattr" + P "hash"
-    + P "hex" + P "id" + P "input" + P "int" + P "isinstance" + P "issubclass"
-    + P "iter" + P "len" + P "list" + P "locals" + P "map" + P "max"
-    + P "memoryview" + P "min" + P "next" + P "object" + P "oct" + P "open"
-    + P "ord" + P "pow" + P "print" + P "property" + P "range" + P "repr"
-    + P "reversed" + P "round" + P "set" + P "setattr" + P "slice" + P "sorted"
-    + P "staticmethod" + P "str" + P "sum" + P "super" + P "tuple" + P "type"
-    + P "vars" + P "zip" )
+      P "__import__" + "abs" + "all" + "any" + "bin" + "bool" + "bytearray" +
+      "bytes" + "chr" + "classmethod" + "compile" + "complex" + "delattr" +
+      "dict" + "dir" + "divmod" + "enumerate" + "eval" + "filter" + "float" +
+      "format" + "frozenset" + "getattr" + "globals" + "hasattr" + "hash" +
+      "hex" + "id" + "input" + "int" + "isinstance" + "issubclass" + "iter" +
+      "len" + "list" + "locals" + "map" + "max" + "memoryview" + "min" + "next"
+      + "object" + "oct" + "open" + "ord" + "pow" + "print" + "property" +
+      "range" + "repr" + "reversed" + "round" + "set" + "setattr" + "slice" +
+      "sorted" + "staticmethod" + "str" + "sum" + "super" + "tuple" + "type" +
+      "vars" + "zip" )
 
 local Exception =
   K ( 'Exception' ,
-      P "ArithmeticError" + P "AssertionError" + P "AttributeError"
-   + P "BaseException" + P "BufferError" + P "BytesWarning" + P "DeprecationWarning"
-   + P "EOFError" + P "EnvironmentError" + P "Exception" + P "FloatingPointError"
-   + P "FutureWarning" + P "GeneratorExit" + P "IOError" + P "ImportError"
-   + P "ImportWarning" + P "IndentationError" + P "IndexError" + P "KeyError"
-   + P "KeyboardInterrupt" + P "LookupError" + P "MemoryError" + P "NameError"
-   + P "NotImplementedError" + P "OSError" + P "OverflowError"
-   + P "PendingDeprecationWarning" + P "ReferenceError" + P "ResourceWarning"
-   + P "RuntimeError" + P "RuntimeWarning" + P "StopIteration"
-   + P "SyntaxError" + P "SyntaxWarning" + P "SystemError" + P "SystemExit"
-   + P "TabError" + P "TypeError" + P "UnboundLocalError" + P "UnicodeDecodeError"
-   + P "UnicodeEncodeError" + P "UnicodeError" + P "UnicodeTranslateError"
-   + P "UnicodeWarning" + P "UserWarning" + P "ValueError" + P "VMSError"
-   + P "Warning" + P "WindowsError" + P "ZeroDivisionError"
-   + P "BlockingIOError" + P "ChildProcessError" + P "ConnectionError"
-   + P "BrokenPipeError" + P "ConnectionAbortedError" + P "ConnectionRefusedError"
-   + P "ConnectionResetError" + P "FileExistsError" + P "FileNotFoundError"
-   + P "InterruptedError" + P "IsADirectoryError" + P "NotADirectoryError"
-   + P "PermissionError" + P "ProcessLookupError" + P "TimeoutError"
-   + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" )
+      P "ArithmeticError" + "AssertionError" + "AttributeError" +
+      "BaseException" + "BufferError" + "BytesWarning" + "DeprecationWarning" +
+      "EOFError" + "EnvironmentError" + "Exception" + "FloatingPointError" +
+      "FutureWarning" + "GeneratorExit" + "IOError" + "ImportError" +
+      "ImportWarning" + "IndentationError" + "IndexError" + "KeyError" +
+      "KeyboardInterrupt" + "LookupError" + "MemoryError" + "NameError" +
+      "NotImplementedError" + "OSError" + "OverflowError" +
+      "PendingDeprecationWarning" + "ReferenceError" + "ResourceWarning" +
+      "RuntimeError" + "RuntimeWarning" + "StopIteration" + "SyntaxError" +
+      "SyntaxWarning" + "SystemError" + "SystemExit" + "TabError" + "TypeError"
+      + "UnboundLocalError" + "UnicodeDecodeError" + "UnicodeEncodeError" +
+      "UnicodeError" + "UnicodeTranslateError" + "UnicodeWarning" +
+      "UserWarning" + "ValueError" + "VMSError" + "Warning" + "WindowsError" +
+      "ZeroDivisionError" + "BlockingIOError" + "ChildProcessError" +
+      "ConnectionError" + "BrokenPipeError" + "ConnectionAbortedError" +
+      "ConnectionRefusedError" + "ConnectionResetError" + "FileExistsError" +
+      "FileNotFoundError" + "InterruptedError" + "IsADirectoryError" +
+      "NotADirectoryError" + "PermissionError" + "ProcessLookupError" +
+      "TimeoutError" + "StopAsyncIteration" + "ModuleNotFoundError" +
+      "RecursionError" )
 
-local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( P "(" )
+local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q "("
 
-local Decorator = K ( 'Name.Decorator' , P "@" * letter^1  )
+local Decorator = K ( 'Name.Decorator' , P "@" * letter ^ 1  )
 local DefClass =
-  K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier )
+  K ( 'Keyword' , "class" ) * Space * K ( 'Name.Class' , identifier )
 local ImportAs =
-  K ( 'Keyword' , P "import" )
+  K ( 'Keyword' , "import" )
    * Space
-   * K ( 'Name.Namespace' ,
-         identifier * ( P "." * identifier ) ^ 0 )
+   * K ( 'Name.Namespace' , identifier * ( "." * identifier ) ^ 0 )
    * (
-       ( Space * K ( 'Keyword' , P "as" ) * Space
+       ( Space * K ( 'Keyword' , "as" ) * Space
           * K ( 'Name.Namespace' , identifier ) )
        +
-       ( SkipSpace * Q ( P "," ) * SkipSpace
+       ( SkipSpace * Q "," * SkipSpace
           * K ( 'Name.Namespace' , identifier ) ) ^ 0
      )
 local FromImport =
-  K ( 'Keyword' , P "from" )
+  K ( 'Keyword' , "from" )
     * Space * K ( 'Name.Namespace' , identifier )
-    * Space * K ( 'Keyword' , P "import" )
+    * Space * K ( 'Keyword' , "import" )
 local PercentInterpol =
   K ( 'String.Interpol' ,
       P "%"
@@ -234,161 +323,69 @@
       * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1
       * ( S "-#0 +" ) ^ 0
       * ( digit ^ 1 + P "*" ) ^ -1
-      * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1
+      * ( "." * ( digit ^ 1 + "*" ) ) ^ -1
       * ( S "HlL" ) ^ -1
       * S "sdfFeExXorgiGauc%"
     )
 local SingleShortString =
   WithStyle ( 'String.Short' ,
-         Q ( P "f'" + P "F'" )
+         Q ( P "f'" + "F'" )
          * (
-             K ( 'String.Interpol' , P "{" )
+             K ( 'String.Interpol' , "{" )
               * K ( 'Interpol.Inside' , ( 1 - S "}':" ) ^ 0  )
-              * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
-              * K ( 'String.Interpol' , P "}" )
+              * Q ( P ":" * ( 1 - S "}:'" ) ^ 0 ) ^ -1
+              * K ( 'String.Interpol' , "}" )
              +
              VisualSpace
              +
-             Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 )
+             Q ( ( P "\\'" + "{{" + "}}" + 1 - S " {}'" ) ^ 1 )
            ) ^ 0
-         * Q ( P "'" )
+         * Q "'"
        +
-         Q ( P "'" + P "r'" + P "R'" )
+         Q ( P "'" + "r'" + "R'" )
          * ( Q ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 )
              + VisualSpace
              + PercentInterpol
-             + Q ( P "%" )
+             + Q "%"
            ) ^ 0
-         * Q ( P "'" ) )
+         * Q "'" )
 
 local DoubleShortString =
   WithStyle ( 'String.Short' ,
-         Q ( P "f\"" + P "F\"" )
+         Q ( P "f\"" + "F\"" )
          * (
-             K ( 'String.Interpol' , P "{" )
+             K ( 'String.Interpol' , "{" )
                * K ( 'Interpol.Inside' , ( 1 - S "}\":" ) ^ 0 )
-               * ( K ( 'String.Interpol' , P ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1
-               * K ( 'String.Interpol' , P "}" )
+               * ( K ( 'String.Interpol' , ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1
+               * K ( 'String.Interpol' , "}" )
              +
              VisualSpace
              +
-             Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 )
+             Q ( ( P "\\\"" + "{{" + "}}" + 1 - S " {}\"" ) ^ 1 )
             ) ^ 0
-         * Q ( P "\"" )
+         * Q "\""
        +
-         Q ( P "\"" + P "r\"" + P "R\"" )
+         Q ( P "\"" + "r\"" + "R\"" )
          * ( Q ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 )
              + VisualSpace
              + PercentInterpol
-             + Q ( P "%" )
+             + Q "%"
            ) ^ 0
-         * Q ( P "\"" ) )
+         * Q "\""  )
 
 local ShortString = SingleShortString + DoubleShortString
-local balanced_braces =
-  P { "E" ,
-       E =
-           (
-             P "{" * V "E" * P "}"
-             +
-             ShortString
-             +
-             ( 1 - S "{}" )
-           ) ^ 0
-    }
-if piton_beamer
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
-    +
-      Ct ( Cc "Open"
-            * C (
-                  (
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action"
-                  )
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
-                  * P "{"
-                )
-            * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopPython:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopPython )
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopPython )
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopPython )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopPython )
-    + OneBeamerEnvironment ( "alertenv" , MainLoopPython )
-    + OneBeamerEnvironment ( "actionenv" , MainLoopPython )
-    +
-      L (
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-    +
-      L (
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-end
-DetectedCommands =
-      Ct ( Cc "Open"
-            * C ( piton.ListCommands * P "{" )
-            * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopPython:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-CleanLPEGs['python']
-      = Ct ( ( piton.ListCommands * P "{"
-                * (  balanced_braces
-                    / ( function (s) return CleanLPEGs['python']:match(s) end ) )
-                * P "}"
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat
-local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1
-local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1  )
-local EOL =
-  P "\r"
-  *
-  (
-    ( space^0 * -1 )
-    +
-    Ct (
-         Cc "EOL"
-         *
-         Ct (
-              Lc "\\__piton_end_line:"
-              * BeamerEndEnvironments
-              * BeamerBeginEnvironments
-              * PromptHastyDetection
-              * Lc "\\__piton_newline: \\__piton_begin_line:"
-              * Prompt
-            )
-       )
-  )
-  *
-  SpaceIndentation ^ 0
+local braces = Compute_braces ( ShortString )
+if piton.beamer then Beamer = Compute_Beamer ( 'python' , braces ) end
+DetectedCommands = Compute_DetectedCommands ( 'python' , braces )
+LPEG_cleaner['python'] = Compute_LPEG_cleaner ( 'python' , braces )
 local SingleLongString =
   WithStyle ( 'String.Long' ,
      ( Q ( S "fF" * P "'''" )
          * (
-             K ( 'String.Interpol' , P "{"  )
-               * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "'''" ) ^ 0  )
-               * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
-               * K ( 'String.Interpol' , P "}"  )
+             K ( 'String.Interpol' , "{" )
+               * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - "'''" ) ^ 0  )
+               * Q ( P ":" * (1 - S "}:\r" - "'''" ) ^ 0 ) ^ -1
+               * K ( 'String.Interpol' , "}"  )
              +
              Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
              +
@@ -395,7 +392,7 @@
              EOL
            ) ^ 0
        +
-         Q ( ( S "rR" ) ^ -1  * P "'''" )
+         Q ( ( S "rR" ) ^ -1  * "'''" )
          * (
              Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 )
              +
@@ -406,24 +403,24 @@
              EOL
            ) ^ 0
       )
-      * Q ( P "'''" ) )
+      * Q "'''"  )
 
 local DoubleLongString =
   WithStyle ( 'String.Long' ,
      (
-        Q ( S "fF" * P "\"\"\"" )
+        Q ( S "fF" * "\"\"\"" )
         * (
-            K ( 'String.Interpol', P "{"  )
-              * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 )
-              * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
-              * K ( 'String.Interpol' , P "}"  )
+            K ( 'String.Interpol', "{"  )
+              * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - "\"\"\"" ) ^ 0 )
+              * Q ( ":" * (1 - S "}:\r" - "\"\"\"" ) ^ 0 ) ^ -1
+              * K ( 'String.Interpol' , "}"  )
             +
-            Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 )
+            Q ( ( 1 - S "{}\"\r" - "\"\"\"" ) ^ 1 )
             +
             EOL
           ) ^ 0
       +
-        Q ( ( S "rR" ) ^ -1  * P "\"\"\"" )
+        Q ( S "rR" ^ -1  * "\"\"\"" )
         * (
             Q ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 )
             +
@@ -434,59 +431,49 @@
             EOL
           ) ^ 0
      )
-     * Q ( P "\"\"\"" )
+     * Q "\"\"\""
   )
 local LongString = SingleLongString + DoubleLongString
 local StringDoc =
-    K ( 'String.Doc' , P "r" ^ -1 * P "\"\"\"" )
-      * ( K ( 'String.Doc' , (1 - P "\"\"\"" - P "\r" ) ^ 0  ) * EOL
+    K ( 'String.Doc' , P "r" ^ -1 * "\"\"\"" )
+      * ( K ( 'String.Doc' , (1 - P "\"\"\"" - "\r" ) ^ 0  ) * EOL
           * Tab ^ 0
         ) ^ 0
-      * K ( 'String.Doc' , ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" )
-local CommentMath =
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"
-
+      * K ( 'String.Doc' , ( 1 - P "\"\"\"" - "\r" ) ^ 0 * "\"\"\"" )
 local Comment =
   WithStyle ( 'Comment' ,
-     Q ( P "#" )
-     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 )
-  * ( EOL + -1 )
-local CommentLaTeX =
-  P(piton.comment_latex)
-  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
-  * L ( ( 1 - P "\r" ) ^ 0 )
-  * Lc "}}"
-  * ( EOL + -1 )
+     Q "#" * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) -- $
+           * ( EOL + -1 )
 local expression =
   P { "E" ,
-       E = ( P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'"
-             + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\""
-             + P "{" * V "F" * P "}"
-             + P "(" * V "F" * P ")"
-             + P "[" * V "F" * P "]"
+       E = ( "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * "'"
+             + "\"" * ( P "\\\"" + 1 - S "\"\r" ) ^ 0 * "\""
+             + "{" * V "F" * "}"
+             + "(" * V "F" * ")"
+             + "[" * V "F" * "]"
              + ( 1 - S "{}()[]\r," ) ) ^ 0 ,
-       F = ( P "{" * V "F" * P "}"
-             + P "(" * V "F" * P ")"
-             + P "[" * V "F" * P "]"
+       F = (   "{" * V "F" * "}"
+             + "(" * V "F" * ")"
+             + "[" * V "F" * "]"
              + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
     }
 local Param =
   SkipSpace * ( Identifier + Q "*args" + Q "**kwargs" ) * SkipSpace
    * (
-         K ( 'InitialValues' , P "=" * expression )
-       + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter ^ 1  )
+         K ( 'InitialValues' , "=" * expression )
+       + Q ":" * SkipSpace * K ( 'Name.Type' , letter ^ 1  )
      ) ^ -1
 local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1
 local DefFunction =
-  K ( 'Keyword' , P "def" )
+  K ( 'Keyword' , "def" )
   * Space
   * K ( 'Name.Function.Internal' , identifier )
   * SkipSpace
-  * Q ( P "(" ) * Params * Q ( P ")" )
+  * Q "("  * Params * Q ")"
   * SkipSpace
-  * ( Q ( P "->" ) * SkipSpace * K ( 'Name.Type' , identifier  ) ) ^ -1
-  * K ( 'ParseAgain' , ( 1 - S ":\r" )^0  )
-  * Q ( P ":" )
+  * ( Q "->" * SkipSpace * K ( 'Name.Type' , identifier ) ) ^ -1
+  * K ( 'ParseAgain' , ( 1 - S ":\r" ) ^ 0 )
+  * Q ":"
   * ( SkipSpace
       * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
       * Tab ^ 0
@@ -494,8 +481,9 @@
       * StringDoc ^ 0 -- there may be additionnal docstrings
     ) ^ -1
 local ExceptionInConsole = Exception *  Q ( ( 1 - P "\r" ) ^ 0 ) * EOL
-local MainPython =
-       EOL
+local Main =
+       space ^ 1 * -1
+     + space ^ 0 * EOL
      + Space
      + Tab
      + Escape + EscapeMath
@@ -520,48 +508,41 @@
      + Identifier
      + Number
      + Word
-MainLoopPython =
-  (  ( space^1 * -1 )
-     + MainPython
-  ) ^ 0
-local python = P ( true )
-
-python =
+LPEG1['python'] = Main ^ 0
+LPEG2['python'] =
   Ct (
-       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
+       ( space ^ 0 * "\r" ) ^ -1
        * BeamerBeginEnvironments
        * PromptHastyDetection
        * Lc '\\__piton_begin_line:'
        * Prompt
        * SpaceIndentation ^ 0
-       * MainLoopPython
+       * LPEG1['python']
        * -1
        * Lc '\\__piton_end_line:'
      )
-languages['python'] = python
-local Delim = Q ( P "[|" + P "|]" + S "[()]" )
+local Delim = Q ( P "[|" + "|]" + S "[()]" )
 local Punct = Q ( S ",:;!" )
 local cap_identifier = R "AZ" * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0
 local Constructor = K ( 'Name.Constructor' , cap_identifier )
 local ModuleType = K ( 'Name.Type' , cap_identifier )
-local identifier =
-  ( R "az" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0
+local identifier = ( R "az" + "_" ) * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0
 local Identifier = K ( 'Identifier' , identifier )
 local expression_for_fields =
   P { "E" ,
-       E = ( P "{" * V "F" * P "}"
-             + P "(" * V "F" * P ")"
-             + P "[" * V "F" * P "]"
-             + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\""
-             + P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'"
+       E = (   "{" * V "F" * "}"
+             + "(" * V "F" * ")"
+             + "[" * V "F" * "]"
+             + "\"" * ( P "\\\"" + 1 - S "\"\r" ) ^ 0 * "\""
+             + "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * "'"
              + ( 1 - S "{}()[]\r;" ) ) ^ 0 ,
-       F = ( P "{" * V "F" * P "}"
-             + P "(" * V "F" * P ")"
-             + P "[" * V "F" * P "]"
+       F = (   "{" * V "F" * "}"
+             + "(" * V "F" * ")"
+             + "[" * V "F" * "]"
              + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
     }
 local OneFieldDefinition =
-    ( K ( 'KeyWord' , P "mutable" ) * SkipSpace ) ^ -1
+    ( K ( 'Keyword' , "mutable" ) * SkipSpace ) ^ -1
   * K ( 'Name.Field' , identifier ) * SkipSpace
   * Q ":" * SkipSpace
   * K ( 'Name.Type' , expression_for_fields )
@@ -570,7 +551,7 @@
 local OneField =
     K ( 'Name.Field' , identifier ) * SkipSpace
   * Q "=" * SkipSpace
-  * ( expression_for_fields / ( function (s) return LoopOCaml:match(s) end ) )
+  * ( expression_for_fields / ( function ( s ) return LPEG1['ocaml'] : match ( s ) end ) )
   * SkipSpace
 
 local Record =
@@ -588,7 +569,6 @@
       K ( 'Name.Module' , cap_identifier )
         * Q "."
         * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" )
-
       +
       Identifier
         * Q "."
@@ -597,135 +577,42 @@
   * ( Q "." * K ( 'Name.Field' , identifier ) ) ^ 0
 local Operator =
   K ( 'Operator' ,
-      P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":="
-      + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->"
-      + P "+." + P "-." + P "*." + P "/."
-      + S "-~+/*%=<>&@|"
-    )
+      P "!=" + "<>" + "==" + "<<" + ">>" + "<=" + ">=" + ":=" + "||" + "&&" +
+      "//" + "**" + ";;" + "::" + "->" + "+." + "-." + "*." + "/."
+      + S "-~+/*%=<>&@|" )
 
 local OperatorWord =
   K ( 'Operator.Word' ,
-      P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor"
-      + P "mod" + P "or" )
+      P "and" + "asr" + "land" + "lor" + "lsl" + "lxor" + "mod" + "or" )
 
 local Keyword =
   K ( 'Keyword' ,
-      P "assert" + P "and" + P "as" + P "begin" + P "class" + P "constraint" + P "done"
-  + P "downto" + P "do" + P "else" + P "end" + P "exception" + P "external"
-  + P "for" + P "function" + P "functor" + P "fun" + P "if"
-  + P "include" + P "inherit" + P "initializer" + P "in"  + P "lazy" + P "let"
-  + P "match" + P "method" + P "module" + P "mutable" + P "new" + P "object"
-  + P "of" + P "open" + P "private" + P "raise" + P "rec" + P "sig"
-  + P "struct" + P "then" + P "to" + P "try" + P "type"
-  + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" )
-  + K ( 'Keyword.Constant' , P "true" + P "false" )
+      P "assert" + "and" + "as" + "begin" + "class" + "constraint" + "done"
+  + "downto" + "do" + "else" + "end" + "exception" + "external" + "for" +
+  "function" + "functor" + "fun" + "if" + "include" + "inherit" + "initializer"
+  + "in"  + "lazy" + "let" + "match" + "method" + "module" + "mutable" + "new" +
+  "object" + "of" + "open" + "private" + "raise" + "rec" + "sig" + "struct" +
+  "then" + "to" + "try" + "type" + "value" + "val" + "virtual" + "when" +
+  "while" + "with" )
+  + K ( 'Keyword.Constant' , P "true" + "false" )
 
 local Builtin =
-  K ( 'Name.Builtin' , P "not" + P "incr" + P "decr" + P "fst" + P "snd" )
+  K ( 'Name.Builtin' , P "not" + "incr" + "decr" + "fst" + "snd" )
 local Exception =
   K (   'Exception' ,
-       P "Division_by_zero" + P "End_of_File" + P "Failure"
-     + P "Invalid_argument" + P "Match_failure" + P "Not_found"
-     + P "Out_of_memory" + P "Stack_overflow" + P "Sys_blocked_io"
-     + P "Sys_error" + P "Undefined_recursive_module" )
+       P "Division_by_zero" + "End_of_File" + "Failure" + "Invalid_argument" +
+       "Match_failure" + "Not_found" + "Out_of_memory" + "Stack_overflow" +
+       "Sys_blocked_io" + "Sys_error" + "Undefined_recursive_module" )
 local Char =
-  K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" )
-local balanced_braces =
-  P { "E" ,
-       E =
-           (
-             P "{" * V "E" * P "}"
-             +
-             P "\"" * ( 1 - S "\"" ) ^ 0 * P "\""  -- OCaml strings
-             +
-             ( 1 - S "{}" )
-           ) ^ 0
-    }
-if piton_beamer
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
-    +
-      Ct ( Cc "Open"
-            * C (
-                  (
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action"
-                  )
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
-                  * P "{"
-                )
-            * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopOCaml:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopOCaml )
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopOCaml )
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopOCaml )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopOCaml )
-    + OneBeamerEnvironment ( "alertenv" , MainLoopOCaml )
-    + OneBeamerEnvironment ( "actionenv" , MainLoopOCaml )
-    +
-      L (
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-    +
-      L (
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
+  K ( 'String.Short' , "'" * ( ( 1 - P "'" ) ^ 0 + "\\'" ) * "'" )
+braces = Compute_braces ( "\"" * ( 1 - S "\"" ) ^ 0 * "\"" )
+if piton.beamer then
+  Beamer = Compute_Beamer ( 'ocaml' , "\"" * ( 1 - S "\"" ) ^ 0 * "\"" )
 end
-DetectedCommands =
-      Ct ( Cc "Open"
-            * C ( piton.ListCommands * P "{" ) * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopOCaml:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-CleanLPEGs['ocaml']
-      = Ct ( ( piton.ListCommands * P "{"
-                * ( balanced_braces
-                    / ( function (s) return CleanLPEGs['ocaml']:match(s) end ) )
-                * P "}"
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat
-
-local EOL =
-  P "\r"
-  *
-  (
-    ( space^0 * -1 )
-    +
-    Ct (
-         Cc "EOL"
-         *
-         Ct (
-              Lc "\\__piton_end_line:"
-              * BeamerEndEnvironments
-              * BeamerBeginEnvironments
-              * PromptHastyDetection
-              * Lc "\\__piton_newline: \\__piton_begin_line:"
-              * Prompt
-            )
-       )
-  )
-  *
-  SpaceIndentation ^ 0
+DetectedCommands = Compute_DetectedCommands ( 'ocaml' , braces )
+LPEG_cleaner['ocaml'] = Compute_LPEG_cleaner ( 'ocaml' , braces )
 local ocaml_string =
-       Q ( P "\"" )
+       Q "\""
      * (
          VisualSpace
          +
@@ -733,14 +620,14 @@
          +
          EOL
        ) ^ 0
-     * Q ( P "\"" )
+     * Q "\""
 local String = WithStyle ( 'String.Long' , ocaml_string )
-local ext = ( R "az" + P "_" ) ^ 0
-local open = "{" * Cg(ext, 'init') * "|"
-local close = "|" * C(ext) * "}"
+local ext = ( R "az" + "_" ) ^ 0
+local open = "{" * Cg ( ext , 'init' ) * "|"
+local close = "|" * C ( ext ) * "}"
 local closeeq =
-  Cmt ( close * Cb('init'),
-        function (s, i, a, b) return a == b end )
+  Cmt ( close * Cb ( 'init' ) ,
+        function ( s , i , a , b ) return a == b end )
 local QuotedStringBis =
   WithStyle ( 'String.Long' ,
       (
@@ -750,10 +637,9 @@
         +
         EOL
       ) ^ 0  )
-
 local QuotedString =
    C ( open * ( 1 - closeeq ) ^ 0  * close ) /
-  ( function (s) return QuotedStringBis : match(s) end )
+  ( function ( s ) return QuotedStringBis : match ( s ) end )
 local Comment =
   WithStyle ( 'Comment' ,
      P {
@@ -760,22 +646,15 @@
          "A" ,
          A = Q "(*"
              * ( V "A"
-                 + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $
+                 + Q ( ( 1 - S "\r$\"" - "(*" - "*)" ) ^ 1 ) -- $
                  + ocaml_string
-                 + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $
+                 + "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * "$" -- $
                  + EOL
                ) ^ 0
              * Q "*)"
        }   )
 local balanced_parens =
-  P { "E" ,
-       E =
-           (
-             P "(" * V "E" * P ")"
-             +
-             ( 1 - S "()" )
-           ) ^ 0
-    }
+  P { "E" , E = ( "(" * V "E" * ")" + 1 - S "()" ) ^ 0 }
 local Argument =
   K ( 'Identifier' , identifier )
   + Q "(" * SkipSpace
@@ -784,16 +663,16 @@
     * K ( 'Name.Type' , balanced_parens ) * SkipSpace
     * Q ")"
 local DefFunction =
-  K ( 'Keyword' , P "let open" )
+  K ( 'Keyword' , "let open" )
    * Space
    * K ( 'Name.Module' , cap_identifier )
   +
-  K ( 'Keyword' , P "let rec" + P "let" + P "and" )
+  K ( 'Keyword' , P "let rec" + "let" + "and" )
     * Space
     * K ( 'Name.Function.Internal' , identifier )
     * Space
     * (
-        Q "=" * SkipSpace * K ( 'Keyword' , P "function" )
+        Q "=" * SkipSpace * K ( 'Keyword' , "function" )
         +
         Argument
          * ( SkipSpace * Argument ) ^ 0
@@ -804,10 +683,10 @@
            ) ^ -1
       )
 local DefModule =
-  K ( 'Keyword' , P "module" ) * Space
+  K ( 'Keyword' , "module" ) * Space
   *
     (
-          K ( 'Keyword' , P "type" ) * Space
+          K ( 'Keyword' , "type" ) * Space
         * K ( 'Name.Type' , cap_identifier )
       +
         K ( 'Name.Module' , cap_identifier ) * SkipSpace
@@ -842,11 +721,12 @@
           ) ^ -1
     )
   +
-  K ( 'Keyword' , P "include" + P "open" )
+  K ( 'Keyword' , P "include" + "open" )
   * Space * K ( 'Name.Module' , cap_identifier )
-local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) )
-MainOCaml =
-       EOL
+local TypeParameter = K ( 'TypeParameter' , "'" * alpha * # ( 1 - P "'" ) )
+local Main =
+       space ^ 1 * -1
+     + space ^ 0 * EOL
      + Space
      + Tab
      + Escape + EscapeMath
@@ -872,25 +752,17 @@
      + Number
      + Word
 
-LoopOCaml = MainOCaml ^ 0
-
-MainLoopOCaml =
-  (  ( space^1 * -1 )
-     + MainOCaml
-  ) ^ 0
-local ocaml = P ( true )
-
-ocaml =
+LPEG1['ocaml'] = Main ^ 0
+LPEG2['ocaml'] =
   Ct (
-       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
+       ( space ^ 0 * "\r" ) ^ -1
        * BeamerBeginEnvironments
-       * Lc ( '\\__piton_begin_line:' )
+       * Lc '\\__piton_begin_line:'
        * SpaceIndentation ^ 0
-       * MainLoopOCaml
+       * LPEG1['ocaml']
        * -1
-       * Lc ( '\\__piton_end_line:' )
+       * Lc '\\__piton_end_line:'
      )
-languages['ocaml'] = ocaml
 local Delim = Q ( S "{[()]}" )
 local Punct = Q ( S ",:;!" )
 local identifier = letter * alphanum ^ 0
@@ -897,176 +769,69 @@
 
 local Operator =
   K ( 'Operator' ,
-      P "!=" + P "==" + P "<<" + P ">>" + P "<=" + P ">="
-      + P "||" + P "&&" + S "-~+/*%=<>&.@|!"
-    )
+      P "!=" + "==" + "<<" + ">>" + "<=" + ">=" + "||" + "&&"
+        + S "-~+/*%=<>&.@|!" )
 
 local Keyword =
   K ( 'Keyword' ,
-      P "alignas" + P "asm" + P "auto" + P "break" + P "case" + P "catch"
-      + P "class" + P "const" + P "constexpr" + P "continue"
-      + P "decltype" + P "do" + P "else" + P "enum" + P "extern"
-      + P "for" + P "goto" + P "if" + P "nexcept" + P "private" + P "public"
-      + P "register" + P "restricted" + P "return" + P "static" + P "static_assert"
-      + P "struct" + P "switch" + P "thread_local" + P "throw" + P "try"
-      + P "typedef" + P "union" + P "using" + P "virtual" + P "volatile"
-      + P "while"
+      P "alignas" + "asm" + "auto" + "break" + "case" + "catch" + "class" +
+      "const" + "constexpr" + "continue" + "decltype" + "do" + "else" + "enum" +
+      "extern" + "for" + "goto" + "if" + "nexcept" + "private" + "public" +
+      "register" + "restricted" + "return" + "static" + "static_assert" +
+      "struct" + "switch" + "thread_local" + "throw" + "try" + "typedef" +
+      "union" + "using" + "virtual" + "volatile" + "while"
     )
-  + K ( 'Keyword.Constant' ,
-        P "default" + P "false" + P "NULL" + P "nullptr" + P "true"
-      )
+  + K ( 'Keyword.Constant' , P "default" + "false" + "NULL" + "nullptr" + "true" )
 
 local Builtin =
   K ( 'Name.Builtin' ,
-      P "alignof" + P "malloc" + P "printf" + P "scanf" + P "sizeof"
-    )
+      P "alignof" + "malloc" + "printf" + "scanf" + "sizeof" )
 
 local Type =
   K ( 'Name.Type' ,
-      P "bool" + P "char" + P "char16_t" + P "char32_t" + P "double"
-      + P "float" + P "int" + P "int8_t" + P "int16_t" + P "int32_t"
-      + P "int64_t" + P "long" + P "short" + P "signed" + P "unsigned"
-      + P "void" + P "wchar_t"
-    )
+      P "bool" + "char" + "char16_t" + "char32_t" + "double" + "float" + "int" +
+      "int8_t" + "int16_t" + "int32_t" + "int64_t" + "long" + "short" + "signed"
+      + "unsigned" + "void" + "wchar_t" )
 
 local DefFunction =
   Type
   * Space
-  * Q ( "*" ) ^ -1
+  * Q "*" ^ -1
   * K ( 'Name.Function.Internal' , identifier )
   * SkipSpace
   * # P "("
 local DefClass =
-  K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier )
-local String =
+  K ( 'Keyword' , "class" ) * Space * K ( 'Name.Class' , identifier )
+String =
   WithStyle ( 'String.Long' ,
       Q "\""
       * ( VisualSpace
           + K ( 'String.Interpol' ,
-                P "%" * ( S "difcspxXou" + P "ld" + P "li" + P "hd" + P "hi" )
+                "%" * ( S "difcspxXou" + "ld" + "li" + "hd" + "hi" )
               )
           + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 )
         ) ^ 0
       * Q "\""
     )
-local balanced_braces =
-  P { "E" ,
-       E =
-           (
-             P "{" * V "E" * P "}"
-             +
-             String
-             +
-             ( 1 - S "{}" )
-           ) ^ 0
-    }
-if piton_beamer
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
-    +
-      Ct ( Cc "Open"
-            * C (
-                  (
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action"
-                  )
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
-                  * P "{"
-                )
-            * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopC:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopC )
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopC )
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopC )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopC )
-    + OneBeamerEnvironment ( "alertenv" , MainLoopC )
-    + OneBeamerEnvironment ( "actionenv" , MainLoopC )
-    +
-      L (
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-    +
-      L (
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-end
-DetectedCommands =
-      Ct ( Cc "Open"
-            * C ( piton.ListCommands * P "{" ) * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopC:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-CleanLPEGs['c']
-      = Ct ( ( piton.ListCommands * P "{"
-                * ( balanced_braces
-                    / ( function (s) return CleanLPEGs['c']:match(s) end ) )
-                * P "}"
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat
-local EOL =
-  P "\r"
-  *
-  (
-    ( space^0 * -1 )
-    +
-    Ct (
-         Cc "EOL"
-         *
-         Ct (
-              Lc "\\__piton_end_line:"
-              * BeamerEndEnvironments
-              * BeamerBeginEnvironments
-              * PromptHastyDetection
-              * Lc "\\__piton_newline: \\__piton_begin_line:"
-              * Prompt
-            )
-       )
-  )
-  *
-  SpaceIndentation ^ 0
-local Preproc =
-  K ( 'Preproc' , P "#" * (1 - P "\r" ) ^ 0  ) * ( EOL + -1 )
-local CommentMath =
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"
-
+braces = Compute_braces ( "\"" * ( 1 - S "\"" ) ^ 0 * "\"" )
+if piton.beamer then Beamer = Compute_Beamer ( 'c' , braces ) end
+DetectedCommands = Compute_DetectedCommands ( 'c' , braces )
+LPEG_cleaner['c'] = Compute_LPEG_cleaner ( 'c' , braces )
+local Preproc = K ( 'Preproc' , "#" * ( 1 - P "\r" ) ^ 0  ) * ( EOL + -1 )
 local Comment =
   WithStyle ( 'Comment' ,
-     Q ( P "//" )
-     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 )
-  * ( EOL + -1 )
+     Q "//" * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) -- $
+            * ( EOL + -1 )
 
 local LongComment =
   WithStyle ( 'Comment' ,
-               Q ( P "/*" )
+               Q "/*"
                * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0
-               * Q ( P "*/" )
+               * Q "*/"
             ) -- $
-local CommentLaTeX =
-  P(piton.comment_latex)
-  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
-  * L ( ( 1 - P "\r" ) ^ 0 )
-  * Lc "}}"
-  * ( EOL + -1 )
-local MainC =
-       EOL
+local Main =
+       space ^ 1 * -1
+     + space ^ 0 * EOL
      + Space
      + Tab
      + Escape + EscapeMath
@@ -1081,38 +846,42 @@
      + Punct
      + DefFunction
      + DefClass
-     + Type * ( Q ( "*" ) ^ -1 + Space + Punct + Delim + EOL + -1 )
+     + Type * ( Q "*" ^ -1 + Space + Punct + Delim + EOL + -1 )
      + Keyword * ( Space + Punct + Delim + EOL + -1 )
      + Builtin * ( Space + Punct + Delim + EOL + -1 )
      + Identifier
      + Number
      + Word
-MainLoopC =
-  (  ( space^1 * -1 )
-     + MainC
-  ) ^ 0
-languageC =
+LPEG1['c'] = Main ^ 0
+LPEG2['c'] =
   Ct (
-       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
+       ( space ^ 0 * P "\r" ) ^ -1
        * BeamerBeginEnvironments
        * Lc '\\__piton_begin_line:'
        * SpaceIndentation ^ 0
-       * MainLoopC
+       * LPEG1['c']
        * -1
        * Lc '\\__piton_end_line:'
      )
-languages['c'] = languageC
+local function LuaKeyword ( name )
+return
+   Lc "{\\PitonStyle{Keyword}{"
+   * Q ( Cmt (
+               C ( identifier ) ,
+               function ( s , i , a ) return string.upper ( a ) == name end
+             )
+       )
+   * Lc "}}"
+end
 local identifier =
-  letter * ( alphanum + P "-" ) ^ 0
-  + P '"' * ( ( alphanum + space - P '"' ) ^ 1 ) * P '"'
+  letter * ( alphanum + "-" ) ^ 0
+  + '"' * ( ( alphanum + space - '"' ) ^ 1 ) * '"'
 
 local Operator =
-  K ( 'Operator' ,
-      P "=" + P "!=" + P "<>" + P ">=" + P ">" + P "<=" + P "<"  + S "*+/"
-    )
-local function Set (list)
-  local set = {}
-  for _, l in ipairs(list) do set[l] = true end
+  K ( 'Operator' , P "=" + "!=" + "<>" + ">=" + ">" + "<=" + "<"  + S "*+/" )
+local function Set ( list )
+  local set = { }
+  for _, l in ipairs ( list ) do set[l] = true end
   return set
 end
 
@@ -1151,170 +920,64 @@
         end
     end
   )
-local String =
-  K ( 'String.Long' , P "'" * ( 1 - P "'" ) ^ 1 * P "'" )
-local balanced_braces =
-  P { "E" ,
-       E =
-           (
-             P "{" * V "E" * P "}"
-             +
-             String
-             +
-             ( 1 - S "{}" )
-           ) ^ 0
-    }
-if piton_beamer
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
-    +
-      Ct ( Cc "Open"
-            * C (
-                  (
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action"
-                  )
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
-                  * P "{"
-                )
-            * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopSQL:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopSQL )
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopSQL )
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopSQL )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopSQL )
-    + OneBeamerEnvironment ( "alertenv" , MainLoopSQL )
-    + OneBeamerEnvironment ( "actionenv" , MainLoopSQL )
-    +
-      L (
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-    +
-      L (
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-end
-DetectedCommands =
-      Ct ( Cc "Open"
-            * C ( piton.ListCommands * P "{" ) * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopSQL:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-CleanLPEGs['sql']
-      = Ct ( ( piton.ListCommands * P "{"
-                * ( balanced_braces
-                    / ( function (s) return CleanLPEGs['sql']:match(s) end ) )
-                * P "}"
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat
-local EOL =
-  P "\r"
-  *
-  (
-    ( space^0 * -1 )
-    +
-    Ct (
-         Cc "EOL"
-         *
-         Ct (
-              Lc "\\__piton_end_line:"
-              * BeamerEndEnvironments
-              * BeamerBeginEnvironments
-              * Lc "\\__piton_newline: \\__piton_begin_line:"
-            )
-       )
-  )
-  *
-  SpaceIndentation ^ 0
-local CommentMath =
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"
-
+local String = K ( 'String.Long' , "'" * ( 1 - P "'" ) ^ 1 * "'" )
+braces = Compute_braces ( String )
+if piton.beamer then Beamer = Compute_Beamer ( 'sql' , braces ) end
+DetectedCommands = Compute_DetectedCommands ( 'sql' , braces )
+LPEG_cleaner['sql'] = Compute_LPEG_cleaner ( 'sql' , braces )
 local Comment =
   WithStyle ( 'Comment' ,
-     Q ( P "--" )  -- syntax of SQL92
-     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 )
+     Q "--"   -- syntax of SQL92
+     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) -- $
   * ( EOL + -1 )
 
 local LongComment =
   WithStyle ( 'Comment' ,
-               Q ( P "/*" )
+               Q "/*"
                * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0
-               * Q ( P "*/" )
+               * Q "*/"
             ) -- $
-local CommentLaTeX =
-  P(piton.comment_latex)
-  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
-  * L ( ( 1 - P "\r" ) ^ 0 )
-  * Lc "}}"
-  * ( EOL + -1 )
-local function LuaKeyword ( name )
-return
-   Lc ( "{\\PitonStyle{Keyword}{" )
-   * Q ( Cmt (
-               C ( identifier ) ,
-               function(s,i,a) return string.upper(a) == name end
-             )
-       )
-   * Lc ( "}}" )
-end
 local TableField =
-     K ( 'Name.Table' , identifier )
-     * Q ( P "." )
+       K ( 'Name.Table' , identifier )
+     * Q "."
      * K ( 'Name.Field' , identifier )
 
 local OneField =
   (
-    Q ( P "(" * ( 1 - P ")" ) ^ 0 * P ")" )
+    Q ( "(" * ( 1 - P ")" ) ^ 0 * ")" )
     +
-    K ( 'Name.Table' , identifier )
-      * Q ( P "." )
+        K ( 'Name.Table' , identifier )
+      * Q "."
       * K ( 'Name.Field' , identifier )
     +
     K ( 'Name.Field' , identifier )
   )
   * (
-      Space * LuaKeyword ( "AS" ) * Space * K ( 'Name.Field' , identifier )
+      Space * LuaKeyword "AS" * Space * K ( 'Name.Field' , identifier )
     ) ^ -1
-  * ( Space * ( LuaKeyword ( "ASC" ) + LuaKeyword ( "DESC" ) ) ) ^ -1
+  * ( Space * ( LuaKeyword "ASC" + LuaKeyword "DESC" ) ) ^ -1
 
 local OneTable =
      K ( 'Name.Table' , identifier )
    * (
        Space
-       * LuaKeyword ( "AS" )
+       * LuaKeyword "AS"
        * Space
        * K ( 'Name.Table' , identifier )
      ) ^ -1
 
 local WeCatchTableNames =
-     LuaKeyword ( "FROM" )
+     LuaKeyword "FROM"
    * ( Space + EOL )
-   * OneTable * ( SkipSpace * Q ( P "," ) * SkipSpace * OneTable ) ^ 0
+   * OneTable * ( SkipSpace * Q "," * SkipSpace * OneTable ) ^ 0
   + (
-      LuaKeyword ( "JOIN" ) + LuaKeyword ( "INTO" ) + LuaKeyword ( "UPDATE" )
-      + LuaKeyword ( "TABLE" )
+      LuaKeyword "JOIN" + LuaKeyword "INTO" + LuaKeyword "UPDATE"
+      + LuaKeyword "TABLE"
     )
     * ( Space + EOL ) * OneTable
-local MainSQL =
-       EOL
+local Main =
+       space ^ 1 * -1
+     + space ^ 0 * EOL
      + Space
      + Tab
      + Escape + EscapeMath
@@ -1330,147 +993,42 @@
      + ( TableField + Identifier ) * ( Space + Operator + Punct + Delim + EOL + -1 )
      + Number
      + Word
-MainLoopSQL =
-  (  ( space^1 * -1 )
-     + MainSQL
-  ) ^ 0
-languageSQL =
+LPEG1['sql'] = Main ^ 0
+LPEG2['sql'] =
   Ct (
-       ( ( space - P "\r" ) ^ 0 * P "\r" ) ^ -1
+       ( space ^ 0 * "\r" ) ^ -1
        * BeamerBeginEnvironments
        * Lc '\\__piton_begin_line:'
        * SpaceIndentation ^ 0
-       * MainLoopSQL
+       * LPEG1['sql']
        * -1
        * Lc '\\__piton_end_line:'
      )
-languages['sql'] = languageSQL
 local Punct = Q ( S ",:;!\\" )
 
-local CommentMath =
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"
-
 local Comment =
   WithStyle ( 'Comment' ,
-     Q ( P "#" )
-     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 )
-  * ( EOL + -1 )
+              Q "#"
+              * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 -- $
+            )
+     * ( EOL + -1 )
 
 local String =
   WithStyle ( 'String.Short' ,
-      Q "\""
-      * ( VisualSpace
-          + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 )
-        ) ^ 0
-      * Q "\""
-    )
+              Q "\""
+              * ( VisualSpace
+                  + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 )
+                ) ^ 0
+              * Q "\""
+            )
 
-local balanced_braces =
-  P { "E" ,
-       E =
-           (
-             P "{" * V "E" * P "}"
-             +
-             String
-             +
-             ( 1 - S "{}" )
-           ) ^ 0
-    }
+braces = Compute_braces ( String )
+if piton.beamer then Beamer = Compute_Beamer ( 'minimal' , braces ) end
 
-if piton_beamer
-then
-  Beamer =
-      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
-    +
-      Ct ( Cc "Open"
-            * C (
-                  (
-                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
-                    + P "\\invisible" + P "\\action"
-                  )
-                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
-                  * P "{"
-                )
-            * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopMinimal:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
-    + OneBeamerEnvironment ( "uncoverenv" , MainLoopMinimal )
-    + OneBeamerEnvironment ( "onlyenv" , MainLoopMinimal )
-    + OneBeamerEnvironment ( "visibleenv" , MainLoopMinimal )
-    + OneBeamerEnvironment ( "invisibleenv" , MainLoopMinimal )
-    + OneBeamerEnvironment ( "alertenv" , MainLoopMinimal )
-    + OneBeamerEnvironment ( "actionenv" , MainLoopMinimal )
-    +
-      L (
-          ( P "\\alt" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-    +
-      L (
-          ( P "\\temporal" )
-          * P "<" * (1 - P ">") ^ 0 * P ">"
-          * P "{"
-        )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}{" )
-      * K ( 'ParseAgain.noCR' , balanced_braces )
-      * L ( P "}" )
-end
+DetectedCommands = Compute_DetectedCommands ( 'minimal' , braces )
 
-DetectedCommands =
-      Ct ( Cc "Open"
-            * C ( piton.ListCommands * P "{" ) * Cc "}"
-         )
-       * ( balanced_braces / (function (s) return MainLoopMinimal:match(s) end ) )
-       * P "}" * Ct ( Cc "Close" )
+LPEG_cleaner['minimal'] = Compute_LPEG_cleaner ( 'minimal' , braces )
 
-CleanLPEGs['minimal']
-      = Ct ( ( piton.ListCommands * P "{"
-                * ( balanced_braces
-                    / ( function (s) return CleanLPEGs['minimal']:match(s) end ) )
-                * P "}"
-               + EscapeClean
-               +  C ( P ( 1 ) )
-              ) ^ 0 ) / table.concat
-
-local EOL =
-  P "\r"
-  *
-  (
-    ( space^0 * -1 )
-    +
-    Ct (
-         Cc "EOL"
-         *
-         Ct (
-              Lc "\\__piton_end_line:"
-              * BeamerEndEnvironments
-              * BeamerBeginEnvironments
-              * Lc "\\__piton_newline: \\__piton_begin_line:"
-            )
-       )
-  )
-  *
-  SpaceIndentation ^ 0
-
-local CommentMath =
-  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$" -- $
-
-local CommentLaTeX =
-  P(piton.comment_latex)
-  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
-  * L ( ( 1 - P "\r" ) ^ 0 )
-  * Lc "}}"
-  * ( EOL + -1 )
-
 local identifier = letter * alphanum ^ 0
 
 local Identifier = K ( 'Identifier' , identifier )
@@ -1477,8 +1035,9 @@
 
 local Delim = Q ( S "{[()]}" )
 
-local MainMinimal =
-       EOL
+local Main =
+       space ^ 1 * -1
+     + space ^ 0 * EOL
      + Space
      + Tab
      + Escape + EscapeMath
@@ -1493,68 +1052,65 @@
      + Number
      + Word
 
-MainLoopMinimal =
-  (  ( space^1 * -1 )
-     + MainMinimal
-  ) ^ 0
+LPEG1['minimal'] = Main ^ 0
 
-languageMinimal =
+LPEG2['minimal'] =
   Ct (
-       ( ( space - P "\r" ) ^ 0 * P "\r" ) ^ -1
+       ( space ^ 0 * "\r" ) ^ -1
        * BeamerBeginEnvironments
        * Lc '\\__piton_begin_line:'
        * SpaceIndentation ^ 0
-       * MainLoopMinimal
+       * LPEG1['minimal']
        * -1
        * Lc '\\__piton_end_line:'
      )
-languages['minimal'] = languageMinimal
 
-function piton.Parse(language,code)
-  local t = languages[language] : match ( code )
+function piton.Parse ( language , code )
+  local t = LPEG2[language] : match ( code )
   if t == nil
   then
-    tex.sprint("\\PitonSyntaxError")
+    tex.sprint(luatexbase.catcodetables.CatcodeTableExpl,
+               "\\__piton_error:n { syntax~error }")
     return -- to exit in force the function
   end
   local left_stack = {}
   local right_stack = {}
-  for _ , one_item in ipairs(t)
+  for _ , one_item in ipairs ( t )
   do
      if one_item[1] == "EOL"
      then
-          for _ , s in ipairs(right_stack)
-            do tex.sprint(s)
+          for _ , s in ipairs ( right_stack )
+            do tex.sprint ( s )
             end
-          for _ , s in ipairs(one_item[2])
-            do tex.tprint(s)
+          for _ , s in ipairs ( one_item[2] )
+            do tex.tprint ( s )
             end
-          for _ , s in ipairs(left_stack)
-            do tex.sprint(s)
+          for _ , s in ipairs ( left_stack )
+            do tex.sprint ( s )
             end
      else
           if one_item[1] == "Open"
           then
                tex.sprint( one_item[2] )
-               table.insert(left_stack,one_item[2])
-               table.insert(right_stack,one_item[3])
+               table.insert ( left_stack , one_item[2] )
+               table.insert ( right_stack , one_item[3] )
           else
                if one_item[1] == "Close"
                then
-                    tex.sprint( right_stack[#right_stack] )
+                    tex.sprint ( right_stack[#right_stack] )
                     left_stack[#left_stack] = nil
                     right_stack[#right_stack] = nil
                else
-                    tex.tprint(one_item)
+                    tex.tprint ( one_item )
                end
           end
      end
   end
 end
-function piton.ParseFile(language,name,first_line,last_line)
+function piton.ParseFile ( language , name , first_line , last_line )
   local s = ''
   local i = 0
-  for line in io.lines(name)
+  for line in io.lines ( name )
   do i = i + 1
      if i >= first_line
      then s = s .. '\r' .. line
@@ -1561,33 +1117,33 @@
      end
      if i >= last_line then break end
   end
-  if string.byte(s,1) == 13
-  then if string.byte(s,2) == 239
-       then if string.byte(s,3) == 187
-            then if string.byte(s,4) == 191
-                 then s = string.sub(s,5,-1)
+  if string.byte ( s , 1 ) == 13
+  then if string.byte ( s , 2 ) == 239
+       then if string.byte ( s , 3 ) == 187
+            then if string.byte ( s , 4 ) == 191
+                 then s = string.sub ( s , 5 , -1 )
                  end
             end
        end
   end
-  piton.Parse(language,s)
+  piton.Parse ( language , s )
 end
-function piton.ParseBis(language,code)
+function piton.ParseBis ( language , code )
   local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code )
-  return piton.Parse(language,s)
+  return piton.Parse ( language , s )
 end
-function piton.ParseTer(language,code)
+function piton.ParseTer ( language , code )
   local s = ( Cs ( ( P '\\__piton_breakable_space:' / ' ' + 1 ) ^ 0 ) )
             : match ( code )
-  return piton.Parse(language,s)
+  return piton.Parse ( language , s )
 end
-local function gobble(n,code)
+local function gobble ( n , code )
   if n==0
   then return code
   else
        return ( Ct (
-                     ( 1 - P "\r" ) ^ (-n)  * C ( ( 1 - P "\r" ) ^ 0 )
-                       * ( C ( P "\r" )
+                     ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 )
+                       * ( C "\r"
                        * ( 1 - P "\r" ) ^ (-n)
                        * C ( ( 1 - P "\r" ) ^ 0 )
                       ) ^ 0
@@ -1594,102 +1150,98 @@
                    ) / table.concat ) : match ( code )
   end
 end
-local function count_captures(...)
-    local acc = 0
-    for _ in ipairs({...}) do
-        acc = acc + 1
-    end
-    return acc
-end
 local AutoGobbleLPEG =
-  (
-    (
-      P " " ^ 0 * P "\r"
-      +
-      C ( P " " ) ^ 0 / count_captures * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * P "\r"
-    ) ^ 0
-    *
-    ( C ( P " " ) ^ 0 / count_captures * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1
-  ) / math.min
+      (  (
+           P " " ^ 0 * "\r"
+           +
+           Ct ( C " " ^ 0 ) / table.getn
+           * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * "\r"
+         ) ^ 0
+         * ( Ct ( C " " ^ 0 ) / table.getn
+              * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1
+       ) / math.min
 local TabsAutoGobbleLPEG =
-  (
-    (
-      P "\t" ^ 0 * P "\r"
-      +
-      C ( P " " ) ^ 0 / count_captures * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * P "\r"
-    ) ^ 0
-    *
-    ( C ( P " " ) ^ 0 / count_captures * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1
-  ) / math.min
+       (
+         (
+           P "\t" ^ 0 * "\r"
+           +
+           Ct ( C "\t" ^ 0 ) / table.getn
+           * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * "\r"
+         ) ^ 0
+         * ( Ct ( C "\t" ^ 0 ) / table.getn
+             * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1
+       ) / math.min
 local EnvGobbleLPEG =
-  ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0 * ( C ( P " " )  ^ 0 / count_captures ) * -1
-local function remove_before_cr(input_string)
-    local match_result = P("\r") : match(input_string)
-    if match_result then
-        return string.sub(input_string, match_result )
+      ( ( 1 - P "\r" ) ^ 0 * "\r" ) ^ 0
+    * Ct ( C " " ^ 0 * -1 ) / table.getn
+local function remove_before_cr ( input_string )
+    local match_result = ( P "\r" ) : match ( input_string )
+    if match_result
+    then
+        return string.sub ( input_string , match_result )
     else
         return input_string
     end
 end
-function piton.GobbleParse(language,n,code)
-  code = remove_before_cr(code)
-  if n==-1
-  then n = AutoGobbleLPEG : match(code)
-  else if n==-2
-       then n = EnvGobbleLPEG : match(code)
-       else if n==-3
-            then n = TabsAutoGobbleLPEG : match(code)
+function piton.GobbleParse ( language , n , code )
+  code = remove_before_cr ( code )
+  if n == -1
+  then n = AutoGobbleLPEG : match ( code )
+  else if n == -2
+       then n = EnvGobbleLPEG : match ( code )
+       else if n == -3
+            then n = TabsAutoGobbleLPEG : match ( code )
             end
        end
   end
-  piton.last_code = gobble(n,code)
-  piton.Parse(language,piton.last_code)
+  piton.last_code = gobble ( n , code )
+  piton.Parse ( language , piton.last_code )
   piton.last_language = language
   if piton.write ~= ''
-  then local file = assert(io.open(piton.write,piton.write_mode))
-       file:write(piton.get_last_code())
-       file:close()
+  then local file = assert ( io.open ( piton.write , piton.write_mode ) )
+       file:write ( piton.get_last_code ( ) )
+       file:close ( )
   end
 end
 function piton.get_last_code ( )
-  return CleanLPEGs[piton.last_language] : match(piton.last_code)
+  return LPEG_cleaner[piton.last_language] : match ( piton.last_code )
 end
-function piton.CountLines(code)
+function piton.CountLines ( code )
   local count = 0
   for i in code : gmatch ( "\r" ) do count = count + 1 end
-  tex.sprint(
+  tex.sprint (
       luatexbase.catcodetables.expl ,
       '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' )
 end
-function piton.CountNonEmptyLines(code)
+function piton.CountNonEmptyLines ( code )
   local count = 0
   count =
-  (  (  (  (
-            ( P " " ) ^ 0 * P "\r"
-              + ( 1 - P "\r" ) ^ 0 * C ( P "\r" )
-            ) ^ 0
-          * (1 - P "\r" ) ^ 0
-       ) / count_captures ) * -1 ) : match (code)
+     ( Ct ( ( P " " ^ 0 * "\r"
+              + ( 1 - P "\r" ) ^ 0 * C "\r" ) ^ 0
+            * ( 1 - P "\r" ) ^ 0
+            * -1
+          ) / table.getn
+     ) : match ( code )
   tex.sprint(
       luatexbase.catcodetables.expl ,
       '\\int_set:Nn \\l__piton_nb_non_empty_lines_int {' .. count .. '}' )
 end
-function piton.CountLinesFile(name)
+function piton.CountLinesFile ( name )
   local count = 0
-  io.open(name)
-  for line in io.lines(name) do count = count + 1 end
-  tex.sprint(
+  io.open ( name )
+  for line in io.lines ( name ) do count = count + 1 end
+  tex.sprint (
       luatexbase.catcodetables.expl ,
       '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' )
 end
-function piton.CountNonEmptyLinesFile(name)
+function piton.CountNonEmptyLinesFile ( name )
   local count = 0
-  for line in io.lines(name)
-  do if not ( ( ( P " " ) ^ 0 * -1 ) : match ( line ) )
+  for line in io.lines ( name )
+  do if not ( ( P " " ^ 0 * -1 ) : match ( line ) )
      then count = count + 1
      end
   end
-  tex.sprint(
+  tex.sprint (
       luatexbase.catcodetables.expl ,
       '\\int_set:Nn \\l__piton_nb_non_empty_lines_int {' .. count .. '}' )
 end
@@ -1699,12 +1251,12 @@
   local first_line = -1
   local count = 0
   local last_found = false
-  for line in io.lines(file_name)
+  for line in io.lines ( file_name )
   do if first_line == -1
-     then if string.sub(line,1,#s) == s
+     then if string.sub ( line , 1 , #s ) == s
           then first_line = count
           end
-     else if string.sub(line,1,#t) == t
+     else if string.sub ( line , 1 , #t ) == t
           then last_found = true
                break
           end
@@ -1712,14 +1264,236 @@
      count = count + 1
   end
   if first_line == -1
-  then tex.sprint("\\PitonBeginMarkerNotFound")
+  then tex.sprint ( luatexbase.catcodetables.expl ,
+                    "\\__piton_error:n { begin~marker~not~found }" )
   else if last_found == false
-       then tex.sprint("\\PitonEndMarkerNotFound")
+       then tex.sprint ( luatexbase.catcodetables.expl ,
+                         "\\__piton_error:n { end~marker~not~found }" )
        end
   end
-  tex.sprint(
+  tex.sprint (
       luatexbase.catcodetables.expl ,
       '\\int_set:Nn \\l__piton_first_line_int {' .. first_line .. ' + 2 }'
       .. '\\int_set:Nn \\l__piton_last_line_int {' .. count .. ' }' )
 end
+function piton.new_language ( lang , definition )
+  lang = string.lower ( lang )
+  local alpha , digit = lpeg.alpha , lpeg.digit
+  local letter = alpha + S "@_$" -- $
+  local other = S "+-*/<>!?:;.()@[]~^=#&\"\'\\$" -- $
+  function add_to_letter ( c )
+     if c ~= " " then letter = letter + c end
+  end
+  function add_to_digit ( c )
+     if c ~= " " then digit = digit + c end
+  end
+  local strict_braces  =
+    P { "E" ,
+        E = ( "{" * V "F" * "}" + ( 1 - S ",{}" ) ) ^ 0  ,
+        F = ( "{" * V "F" * "}" + ( 1 - S "{}" ) ) ^ 0
+      }
+  local cut_definition =
+    P { "E" ,
+        E = Ct ( V "F" * ( "," * V "F" ) ^ 0 ) ,
+        F = Ct ( space ^ 0 * C ( alpha ^ 1 ) * space ^ 0
+                * ( "=" * space ^ 0 * C ( strict_braces ) ) ^ -1 )
+      }
+  local def_table = cut_definition : match ( definition )
+  local sensitive = true
+  for _ , x in ipairs ( def_table )
+  do if x[1] == "sensitive"
+     then if x[2] == nil or ( P "true" ) : match ( x[2] )
+          then sensitive = true
+          else if ( P "false" ) : match ( x[2] ) then sensitive = false end
+          end
+     end
+     if x[1] == "alsodigit" then x[2] : gsub ( "." , add_to_digit ) end
+     if x[1] == "alsoletter" then x[2] : gsub ( "." , add_to_letter ) end
+  end
+  local Number =
+    K ( 'Number' ,
+        ( digit ^ 1 * "." * # ( 1 - P "." ) * digit ^ 0
+          + digit ^ 0 * "." * digit ^ 1
+          + digit ^ 1 )
+        * ( S "eE" * S "+-" ^ -1 * digit ^ 1 ) ^ -1
+        + digit ^ 1
+      )
+  local alphanum = letter + digit
+  local identifier = letter * alphanum ^ 0
+  local Identifier = K ( 'Identifier' , identifier )
+  local option = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]"
+  local split_clist =
+    P { "E" ,
+         E = ( "[" * ( 1 - P "]" ) ^ 0 * "]" ) ^ -1
+             * ( P "{" ) ^ 1
+             * Ct ( V "F" * ( "," * V "F" ) ^ 0 )
+             * ( P "}" ) ^ 1 * space ^ 0 ,
+         F = space ^ 0 * C ( letter * alphanum ^ 0 + other ^ 1 ) * space ^ 0
+      }
+  local function keyword_to_lpeg ( name )
+  return
+    Q ( Cmt (
+              C ( identifier ) ,
+              function(s,i,a) return string.upper(a) == string.upper(name) end
+            )
+      )
+  end
+  local Keyword = P ( false )
+  for _ , x in ipairs ( def_table )
+  do if x[1] == "morekeywords" or x[1] == "otherkeywords" then
+        local keywords = P ( false )
+        for _ , word in ipairs ( split_clist : match ( x[2] ) )
+        do if sensitive
+           then keywords = Q ( word  ) + keywords
+           else keywords = keyword_to_lpeg ( word ) + keywords
+           end
+        end
+        Keyword = Keyword +
+           Lc ( "{"
+                 ..  ( option : match ( x[2] ) or "\\PitonStyle{Keyword}" )
+                 .. "{" )
+           * keywords * Lc "}}"
+     end
+     if x[1] == "keywordsprefix" then
+       local prefix = ( ( C ( 1 - P " " ) ^ 1 ) * P " " ^ 0 ) : match ( x[2] )
+       Keyword = Keyword + K ( 'Keyword' , P ( prefix ) * alphanum ^ 0 )
+     end
+  end
+  local long_string  = P ( false )
+  local LongString = P (false )
+  local args = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]"
+               * space ^ 0
+               * ( "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" + Cc ( nil ) )
+               * space ^ 0
+               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + C ( 1 ) )
+  local central_pattern = P ( false )
+  for _ , x in ipairs ( def_table )
+  do if x[1] == "morestring" then
+       arg1 , arg2 , arg3 = args : match ( x[2] )
+       arg2 = arg2 or "\\PitonStyle{String.Long}"
+       if arg1 == "b" then
+         central_pattern = Q ( ( P ( "\\" .. arg3 )  + 1 - S ( " \r" .. arg3 ) ) ^ 1 )
+       end
+       if arg1 == "d" then
+         central_pattern = Q ( ( P ( arg3 .. arg3 )  + 1 - S ( " \r" .. arg3 ) ) ^ 1 )
+       end
+       if arg1 == "bd" then
+         central_pattern =
+           Q ( ( P ( arg3 .. arg3 ) + P ( "\\" .. arg3 ) + 1 - S ( " \r" .. arg3 ) ) ^ 1 )
+       end
+       if arg1 == "m" then
+         central_pattern =  Q ( ( P ( arg3 .. arg3 ) + 1 - S ( " \r" .. arg3 ) ) ^ 1 )
+       end
+       if arg1 == "m"
+       then prefix = P ( false )
+       else prefix = lpeg.B ( 1 - letter - ")" - "]" )
+       end
+       long_string = long_string +
+         prefix * ( Q ( arg3 ) * ( VisualSpace + central_pattern + EOL ) ^ 0 * Q ( arg3 ) )
+       LongString = LongString +
+          Ct ( Cc "Open" * Cc ( "{" ..  arg2 .. "{" ) * Cc "}}" )
+          * long_string
+          * Ct ( Cc "Close" )
+     end
+  end
 
+  local braces = Compute_braces ( String )
+  if piton.beamer then Beamer = Compute_Beamer ( lang , braces ) end
+
+  DetectedCommands = Compute_DetectedCommands ( lang , braces )
+
+  LPEG_cleaner[lang] = Compute_LPEG_cleaner ( lang , braces )
+  local Comment = P ( false )
+
+  local args = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]"
+               * space ^ 0
+               * ( "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" + Cc ( nil ) )
+               * space ^ 0
+               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + C ( 1 ) )
+               * space ^ 0
+               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + Cc ( nil ) )
+
+  for _ , x in ipairs ( def_table )
+  do if x[1] == "morecomment"
+     then local arg1 , arg2 , arg3 , arg4 = args : match ( x[2] )
+          arg2 = arg2 or "\\PitonStyle{Comment}"
+          if arg1 == "l" then
+            if arg3 == [[\#]] then arg3 = "#" end -- mandatory
+            Comment = Comment +
+                Ct ( Cc "Open"
+                     * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" )
+                     *  Q ( arg3 )
+                     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 -- $
+                * Ct ( Cc "Close" )
+                * ( EOL + -1 )
+           end
+           if arg1 == "s" then
+             Comment = Comment +
+                 Ct ( Cc "Open" * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" )
+                 * Q ( arg3 )
+                 * (
+                     CommentMath
+                     + Q ( ( 1 - P ( arg4 ) - S "$\r" ) ^ 1 ) -- $
+                     + EOL
+                   ) ^ 0
+                 * Q ( arg4 )
+                 * Ct ( Cc "Close" )
+           end
+           if arg1 == "n" then
+             Comment = Comment +
+               Ct ( Cc "Open" * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" )
+                * P { "A" ,
+                     A = Q ( arg3 )
+                         * ( V "A"
+                             + Q ( ( 1 - P ( arg3 ) - P ( arg4 )
+                                     - S "\r$\"" ) ^ 1 ) -- $
+                             + long_string
+                             +   "$" -- $
+                                 * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) --$
+                                 * "$" -- $
+                             + EOL
+                           ) ^ 0
+                         * Q ( arg4 )
+                    }
+               * Ct ( Cc "Close" )
+           end
+      end
+  end
+
+  local Delim = Q ( S "{[()]}" )
+  local Punct = Q ( S ",:;!\\'\"" )
+
+  local Main =
+         space ^ 1 * -1
+       + space ^ 0 * EOL
+       + Space
+       + Tab
+       + Escape + EscapeMath
+       + CommentLaTeX
+       + Beamer
+       + DetectedCommands
+       + Comment
+       + Delim
+       + LongString
+        -- should maybe be after the following line!
+       + Keyword * ( Space + Punct + Delim + EOL + -1 )
+       + Punct
+       + K ( 'Identifier' , letter * alphanum ^ 0 )
+       + Number
+       + Word
+
+  LPEG1[lang] = Main ^ 0
+
+  LPEG2[lang] =
+    Ct (
+         ( space ^ 0 * P "\r" ) ^ -1
+         * BeamerBeginEnvironments
+         * Lc '\\__piton_begin_line:'
+         * SpaceIndentation ^ 0
+         * LPEG1[lang]
+         * -1
+         * Lc '\\__piton_end_line:'
+       )
+
+end
+

Modified: branches/branch2023.final/Master/texmf-dist/tex/lualatex/piton/piton.sty
===================================================================
--- branches/branch2023.final/Master/texmf-dist/tex/lualatex/piton/piton.sty	2024-03-06 21:09:27 UTC (rev 70445)
+++ branches/branch2023.final/Master/texmf-dist/tex/lualatex/piton/piton.sty	2024-03-06 21:09:36 UTC (rev 70446)
@@ -19,8 +19,8 @@
 %% LaTeX version 2005/12/01 or later.
 %% -------------------------------------------
 %% 
-\def\PitonFileVersion{2.6}
-\def\PitonFileDate{2024/02/27}
+\def\PitonFileVersion{2.6a}
+\def\PitonFileDate{2024/03/06}
 
 
 \NeedsTeXFormat{LaTeX2e}
@@ -105,7 +105,8 @@
 \ProcessKeysOptions { piton / package }
 \@ifclassloaded { beamer } { \bool_gset_true:N \g__piton_beamer_bool } { }
 \@ifpackageloaded { beamerarticle } { \bool_gset_true:N \g__piton_beamer_bool } { }
-\bool_if:NT \g__piton_beamer_bool { \lua_now:n { piton_beamer = true } }
+\lua_now:n { piton = piton~or~{ } }
+\bool_if:NT \g__piton_beamer_bool { \lua_now:n { piton.beamer = true } }
 \hook_gput_code:nnn { begindocument } { . }
   {
     \@ifpackageloaded { xcolor }
@@ -160,7 +161,6 @@
   }
 \lua_now:n
   {
-    piton = piton~or { }
     piton.ListCommands = lpeg.P ( false )
     piton.last_code = ''
     piton.last_language = ''
@@ -213,9 +213,19 @@
       { \tl_put_right:Nn \l__piton_tab_tl { ~ } }
   }
 \__piton_set_tab_tl:n { 4 }
+\cs_new_protected:Npn \__piton_convert_tab_tl:
+  {
+    \hbox_set:Nn \l_tmpa_box { \l__piton_tab_tl }
+    \dim_set:Nn \l_tmpa_dim { \box_wd:N \l_tmpa_box }
+    \tl_set:Nn \l__piton_tab_tl
+      {
+        \( \mathcolor { gray }
+             { \hbox_to_wd:nn \l_tmpa_dim { \rightarrowfill } \) }
+      }
+  }
 \int_new:N \l__piton_gobble_int
 \tl_new:N \l__piton_space_tl
-\tl_set:Nn \l__piton_space_tl { ~ }
+\tl_set_eq:NN \l__piton_space_tl \nobreakspace
 \int_new:N \g__piton_indentation_int
 \cs_new_protected:Npn \__piton_an_indentation_space:
   { \int_gincr:N \g__piton_indentation_int }
@@ -288,6 +298,7 @@
         \__piton_replace_spaces:n { #1 }
         \strut \hfil
       }
+    \tl_log:n { Contenu : #1.}
     \hbox_set:Nn \l_tmpa_box
       {
         \skip_horizontal:N \l__piton_left_margin_dim
@@ -299,7 +310,7 @@
                 &&
                 \l__piton_skip_empty_lines_bool
               }
-              { \int_gincr:N \g__piton_visual_line_int}
+              { \int_gincr:N \g__piton_visual_line_int }
 
             \bool_if:nT
               {
@@ -380,9 +391,9 @@
           { \l__piton_nb_lines_int - \g__piton_line_int } > \l__piton_splittable_int
           {
             \egroup
-            \bool_if:NT \g__piton_footnote_bool { \end { savenotes } }
+            \bool_if:NT \g__piton_footnote_bool { \endsavenotes }
             \par \mode_leave_vertical:
-            \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } }
+            \bool_if:NT \g__piton_footnote_bool { \savenotes }
             \vtop \bgroup
           }
      }
@@ -584,8 +595,10 @@
 
     tab-size         .code:n            = \__piton_set_tab_tl:n { #1 } ,
     tab-size         .value_required:n  = true ,
-    show-spaces      .bool_set:N        = \l__piton_show_spaces_bool ,
-    show-spaces      .default:n         = true ,
+    show-spaces      .code:n            =
+         \bool_set_true:N \l__piton_show_spaces_bool
+         \__piton_convert_tab_tl: ,
+    show-spaces      .value_forbidden:n = true ,
     show-spaces-in-strings .code:n      = \tl_set:Nn \l__piton_space_tl { ␣ } , % U+2423
     show-spaces-in-strings .value_forbidden:n = true ,
     break-lines-in-Piton .bool_set:N    = \l__piton_break_lines_in_Piton_bool ,
@@ -689,6 +702,8 @@
           { \dim_eval:n { \g__piton_tmp_width_dim } }
       }
   }
+\NewDocumentCommand { \NewPitonLanguage } { m m }
+  { \lua_now:e { piton.new_language("#1","\lua_escape:n{#2}") } }
 \NewDocumentCommand { \piton } { }
   { \peek_meaning:NTF \bgroup \__piton_piton_standard \__piton_piton_verbatim }
 \NewDocumentCommand { \__piton_piton_standard } { m }
@@ -881,7 +896,7 @@
             \__piton_compute_width:
             \ttfamily
             \dim_zero:N \parskip
-            \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } }
+            \bool_if:NT \g__piton_footnote_bool { \savenotes }
             \str_if_empty:NTF \l__piton_path_write_str
               { \lua_now:e { piton.write = "\l__piton_write_str" } }
               {
@@ -897,7 +912,7 @@
                     \seq_gput_left:NV \g__piton_write_seq \l__piton_write_str
                   }
               }
-            \vbox \bgroup
+            \vtop \bgroup % modified 2024/03/02
             \lua_now:e
               {
                 piton.GobbleParse
@@ -904,13 +919,13 @@
                   (
                     '\l_piton_language_str' ,
                     \int_use:N \l__piton_gobble_int ,
-                    token.scan_argument()
+                    token.scan_argument ( )
                   )
               }
               { ##1 }
             \vspace { 2.5 pt }
             \egroup
-            \bool_if:NT \g__piton_footnote_bool { \end { savenotes } }
+            \bool_if:NT \g__piton_footnote_bool { \endsavenotes }
             \bool_if:NT \l__piton_width_min_bool \__piton_width_to_aux:
             \end { #1 }
             \__piton_write_aux:
@@ -936,9 +951,9 @@
     \NewPitonEnvironment { Piton } { d < > O { } }
       {
         \keys_set:nn { PitonOptions } { #2 }
-        \IfValueTF { #1 }
+        \tl_if_novalue:nTF { #1 }
+          { \begin { uncoverenv } }
           { \begin { uncoverenv } < #1 > }
-          { \begin { uncoverenv } }
       }
       { \end { uncoverenv } }
   }
@@ -1014,11 +1029,11 @@
       \int_compare:nNnT \g__piton_visual_line_int < \c_zero_int
         { \int_gzero:N \g__piton_visual_line_int }
       \mode_if_vertical:TF \mode_leave_vertical: \newline
-      \lua_now:e { piton.CountLinesFile('\l__piton_file_name_str') }
+      \lua_now:e { piton.CountLinesFile ( '\l__piton_file_name_str' ) }
       \__piton_compute_left_margin:no { CountNonEmptyLinesFile } \l__piton_file_name_str
       \__piton_compute_width:
       \ttfamily
-      \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } }
+      \bool_if:NT \g__piton_footnote_bool { \savenotes }
       \vtop \bgroup
       \lua_now:e
         {
@@ -1029,7 +1044,7 @@
            \int_use:N \l__piton_last_line_int )
         }
       \egroup
-      \bool_if:NT \g__piton_footnote_bool { \end { savenotes } }
+      \bool_if:NT \g__piton_footnote_bool { \endsavenotes }
       \bool_if:NT \l__piton_width_min_bool \__piton_width_to_aux:
     \group_end:
     \tl_if_novalue:nF { #1 }
@@ -1174,7 +1189,7 @@
 \NewDocumentCommand { \SetPitonIdentifier } { o m m }
   {
     \clist_set:Nn \l_tmpa_clist { #2 }
-    \IfNoValueTF { #1 }
+    \tl_if_novalue:nTF { #1 }
       {
         \clist_map_inline:Nn \l_tmpa_clist
           { \cs_set:cpn { pitonIdentifier _ ##1 } { #3 } }
@@ -1316,11 +1331,10 @@
   }
 \__piton_msg_new:nn { syntax~error }
   {
-    Your~code~of~the~language~"\l_piton_language_str"~is~not~syntactically~correct.\\
+    Your~code~of~the~language~"\l_piton_language_str"~is~not~
+    syntactically~correct.\\
     It~won't~be~printed~in~the~PDF~file.
   }
-\NewDocumentCommand \PitonSyntaxError { }
-  { \__piton_error:n { syntax~error } }
 \__piton_msg_new:nn { begin~marker~not~found }
   {
     Marker~not~found.\\
@@ -1336,10 +1350,6 @@
     has~not~been~found.~The~file~'\l__piton_file_name_str'~will~
     be~inserted~till~the~end.
   }
-\NewDocumentCommand \PitonBeginMarkerNotFound { }
-  { \__piton_error:n { begin~marker~not~found } }
-\NewDocumentCommand \PitonEndMarkerNotFound { }
-  { \__piton_error:n { end~marker~not~found } }
 \__piton_msg_new:nn { Unknown~file }
   {
     Unknown~file. \\
@@ -1420,7 +1430,7 @@
           end
     local my_lpeg =
       P {  "E" ,
-           E = ( V "F" * ( P "," * V "F" ) ^ 0 ) / add ,
+           E = ( V "F" * ( "," * V "F" ) ^ 0 ) / add ,
            F = space ^ 0 * ( alpha ^ 1 ) / "\\%0" * space ^ 0
         }
     function piton.addListCommands( key_value )



More information about the tex-live-commits mailing list.