From dc177b2cd4ed993d65860adc66d256969c1bb6ad Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Thu, 7 Mar 2024 03:01:25 +0000 Subject: CTAN sync 202403070301 --- macros/luatex/latex/piton/piton.dtx | 2337 ++++++++++++++++------------------- 1 file changed, 1054 insertions(+), 1283 deletions(-) (limited to 'macros/luatex/latex/piton/piton.dtx') diff --git a/macros/luatex/latex/piton/piton.dtx b/macros/luatex/latex/piton/piton.dtx index b7326c2d60..fb06977b46 100644 --- a/macros/luatex/latex/piton/piton.dtx +++ b/macros/luatex/latex/piton/piton.dtx @@ -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 % %<*LUA> --- Version 2.6 of 2024/02/27 +-- Version 2.6a of 2024/03/06 % %\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,7 +1744,7 @@ % 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}} @@ -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 } - { \begin { uncoverenv } < #1 > } + \tl_if_novalue:nTF { #1 } { \begin { uncoverenv } } + { \begin { uncoverenv } < #1 > } } { \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 @@ end % 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 @@ local R = lpeg.R % 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 @@ end % 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 @@ end % 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 @@ end % 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 @@ end % 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 @@ EscapeClean = P ( false ) 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 @@ 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 % \end{macrocode} % @@ -5005,7 +5027,7 @@ lpeg.locale(lpeg) % \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 @@ local space = P " " % |ç|, 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 @@ local Identifier = K ( 'Identifier' , identifier ) % \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 @@ local Number = % \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 @@ end % % \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,7 +5123,70 @@ local Delim = Q ( S "[({})]" ) % \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}. @@ -5109,67 +5194,210 @@ local VisualSpace = space * Lc "\\l_@@_space_tl" local Beamer = P ( false ) local BeamerBeginEnvironments = P ( true ) local BeamerEndEnvironments = P ( true ) -if piton_beamer -then -% \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 % \end{macrocode} % +% \bigskip +% \begin{macrocode} +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 Lua function will be used to compute the \textsc{lpeg} |Beamer| +% for each informatic language. +% \begin{macrocode} +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 -% 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. +% Now, the environments of Beamer. % \begin{macrocode} - function OneBeamerEnvironment(name,lpeg) - return + 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 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 languages = { } -local CleanLPEGs = { } +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 @@ local CleanLPEGs = { } % \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 @@ local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( % 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 @@ local Decorator = K ( 'Name.Decorator' , P "@" * letter^1 ) % 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 @@ local DefClass = % 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 @@ local ImportAs = % \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 @@ local PercentInterpol = * ( 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 @@ local SingleShortString = % \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,190 +5644,46 @@ local ShortString = SingleShortString + DoubleShortString % \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 - } -% \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 +local braces = Compute_braces ( ShortString ) +if piton.beamer then Beamer = Compute_Beamer ( 'python' , braces ) 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} -% -% +% \paragraph{The long strings} +% +% % \begin{macrocode} 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 ) + EOL ) ^ 0 + - Q ( ( S "rR" ) ^ -1 * P "'''" ) + Q ( ( S "rR" ) ^ -1 * "'''" ) * ( Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 ) + @@ -5616,25 +5694,25 @@ local SingleLongString = 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 @@ local DoubleLongString = EOL ) ^ 0 ) - * Q ( P "\"\"\"" ) + * Q "\"\"\"" ) % \end{macrocode} % @@ -5659,11 +5737,11 @@ local LongString = SingleLongString + DoubleLongString % 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 @@ local StringDoc = % 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 @@ local CommentLaTeX = % \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 expression = 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,21 +5816,21 @@ local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1 % |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 % \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 @@ local ExceptionInConsole = Exception * Q ( ( 1 - P "\r" ) ^ 0 ) * EOL % % 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 @@ local MainPython = % % 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 @@ MainLoopPython = % 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 @@ local ModuleType = K ( 'Name.Type' , cap_identifier ) % 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,22 +5951,22 @@ local Identifier = K ( 'Identifier' , identifier ) % \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} % % \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 OneFieldDefinition = 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 @@ local DotNotation = K ( 'Name.Module' , cap_identifier ) * Q "." * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" ) - + Identifier * Q "." @@ -5960,32 +6010,27 @@ local DotNotation = % \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 @@ local Builtin = % \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,134 +6048,31 @@ local Exception = % % \begin{macrocode} local Char = - K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" ) + K ( 'String.Short' , "'" * ( ( 1 - P "'" ) ^ 0 + "\\'" ) * "'" ) % \end{macrocode} % % % \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 @@ local EOL = % within the comments of OCaml. % \begin{macrocode} local ocaml_string = - Q ( P "\"" ) + Q "\"" * ( VisualSpace + @@ -6148,7 +6089,7 @@ local ocaml_string = + EOL ) ^ 0 - * Q ( P "\"" ) + * Q "\"" % \end{macrocode} % % \begin{macrocode} @@ -6167,12 +6108,12 @@ local String = WithStyle ( 'String.Long' , ocaml_string ) % 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 @@ local QuotedStringBis = + EOL ) ^ 0 ) - % \end{macrocode} % % \medskip @@ -6196,7 +6136,7 @@ local QuotedStringBis = % \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 @@ local QuotedString = % \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 @@ local Comment = "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 @@ local Comment = % % \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 @@ local Argument = % 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 @@ local DefFunction = % 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 @@ local DefModule = ) ^ -1 ) + - K ( 'Keyword' , P "include" + P "open" ) + K ( 'Keyword' , P "include" + "open" ) * Space * K ( 'Name.Module' , cap_identifier ) % \end{macrocode} % @@ -6330,7 +6263,7 @@ local DefModule = % \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 @@ local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) ) % % First, the main loop : % \begin{macrocode} -MainOCaml = - EOL +local Main = + space ^ 1 * -1 + + space ^ 0 * EOL + Space + Tab + Escape + EscapeMath @@ -6365,41 +6299,31 @@ MainOCaml = + 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 identifier = letter * alphanum ^ 0 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 @@ local DefFunction = % 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 @@ local DefClass = % \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 @@ local String = % \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 ( -% \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 +braces = Compute_braces ( "\"" * ( 1 - S "\"" ) ^ 0 * "\"" ) +if piton.beamer then Beamer = Compute_Beamer ( 'c' , braces ) 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,39 +6439,20 @@ local Preproc = % % 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 @@ -6684,8 +6460,9 @@ local CommentLaTeX = % % 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 @@ local MainC = + 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 @@ local MainC = % % 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 @@ MainLoopC = % 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} % -% \begin{macrocode} -languages['c'] = languageC -% \end{macrocode} -% % % \bigskip -% \subsubsection{The LPEG language SQL} +% \subsubsection{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} +% % \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 @@ local Operator = % 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,143 +6600,24 @@ local Identifier = % \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 ( -% \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 +braces = Compute_braces ( String ) +if piton.beamer then Beamer = Compute_Beamer ( 'sql' , braces ) 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" ) +DetectedCommands = Compute_DetectedCommands ( '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 +LPEG_cleaner['sql'] = Compute_LPEG_cleaner ( 'sql' , braces ) % \end{macrocode} % % @@ -6965,95 +6627,63 @@ local EOL = % % 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 @@ local WeCatchTableNames = % % First, the main loop : % \begin{macrocode} -local MainSQL = - EOL +local Main = + space ^ 1 * -1 + + space ^ 0 * EOL + Space + Tab + Escape + EscapeMath @@ -7082,168 +6713,56 @@ local MainSQL = % % 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 "\"" - ) - - -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 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 = - 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:" + Q "\"" + * ( VisualSpace + + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 ) + ) ^ 0 + * Q "\"" ) - ) - ) - * - SpaceIndentation ^ 0 -local CommentMath = - P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $ +braces = Compute_braces ( String ) +if piton.beamer then Beamer = Compute_Beamer ( 'minimal' , braces ) end -local CommentLaTeX = - P(piton.comment_latex) - * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" - * L ( ( 1 - P "\r" ) ^ 0 ) - * Lc "}}" - * ( EOL + -1 ) +DetectedCommands = Compute_DetectedCommands ( 'minimal' , braces ) + +LPEG_cleaner['minimal'] = Compute_LPEG_cleaner ( 'minimal' , braces ) local identifier = letter * alphanum ^ 0 @@ -7251,8 +6770,9 @@ local Identifier = K ( 'Identifier' , identifier ) local Delim = Q ( S "{[()]}" ) -local MainMinimal = - EOL +local Main = + space ^ 1 * -1 + + space ^ 0 * EOL + Space + Tab + Escape + EscapeMath @@ -7267,22 +6787,18 @@ local MainMinimal = + 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 @@ languages['minimal'] = languageMinimal % 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 @@ function piton.Parse(language,code) 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 @@ end % 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 @@ function piton.ParseFile(language,name,first_line,last_line) % \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 @@ end % 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 @@ end % 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 @@ end % 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,60 +6957,37 @@ end % \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 = - ( - ( -% \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 +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} % % \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 @@ -7502,15 +6996,17 @@ local TabsAutoGobbleLPEG = % 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,38 +7014,39 @@ end % \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 % 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,25 +7056,25 @@ end % % \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 % \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 @@ end % % \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 @@ end % % \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 @@ function piton.ComputeRange(marker_beginning,marker_end,file_name) 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 @@ function piton.ComputeRange(marker_beginning,marker_end,file_name) 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 % % \end{macrocode} % @@ -7723,7 +7536,7 @@ end % % \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 @@ end % 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} -- cgit v1.2.3