diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx | 163 |
1 files changed, 94 insertions, 69 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx index 755d9020d82..f0cdec7ffbb 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx @@ -36,7 +36,7 @@ % %<*driver> \documentclass[full]{l3doc} -\GetIdInfo$Id: l3fp-parse.dtx 4728 2014-05-04 13:25:37Z joseph $ +\GetIdInfo$Id: l3fp-parse.dtx 4975 2014-05-31 19:26:32Z bruno $ {L3 Floating-point expression parsing} \begin{document} \DocInput{\jobname.dtx} @@ -474,7 +474,7 @@ % \begin{itemize} % \item % \item If the next token is a control sequence, it could be the -% end-marker \cs{s_@@_mark}, which has the lowest precedence, and +% special marker \cs{s_@@_mark}, and % otherwise it is a case of juxtaposing numbers, such as % |2\c_three|, with an implied multiplication. % \item If the next token is a letter, it is also a case of @@ -1646,7 +1646,7 @@ \if_catcode:w \scan_stop: \exp_not:N #1 \if_meaning:w \scan_stop: #1 \if_int_compare:w - \pdftex_strcmp:D { \s_@@ } { \exp_not:N #1 } = \c_zero + \__str_if_eq_x:nn { \s_@@ } { \exp_not:N #1 } = \c_zero 0 \__msg_kernel_expandable_error:nnn { kernel } { fp-after-e } { floating~point~ } @@ -1659,7 +1659,7 @@ \fi: \else: \if_int_compare:w - \pdftex_strcmp:D { \__int_value:w #1 } { \tex_the:D #1 } + \__str_if_eq_x:nn { \__int_value:w #1 } { \tex_the:D #1 } = \c_zero \__int_value:w #1 \else: @@ -2039,8 +2039,12 @@ % Start a \tn{romannumeral} expansion so that \cs{@@_parse:n} expands % in two steps. The \cs{@@_parse_operand:Nw} function will perform % computations until reaching an operation with precedence -% \cs{c_minus_one} or less. Then stop the initial expansion with -% \cs{c_zero}. +% \cs{c_minus_one} or less, namely, the end of the expression. The +% marker \cs{s_@@_mark} indicates that the next token is an already +% parsed version of an infix operator, and \cs{@@_parse_infix_end:N} +% has infinitely negative precedence. Finally, clean up a +% (well-defined) set of extra tokens and stop the initial expansion +% with \cs{c_zero}. % \begin{macrocode} \cs_new:Npn \@@_parse:n #1 { @@ -2048,11 +2052,12 @@ \exp_after:wN \@@_parse_after:ww \tex_romannumeral:D \@@_parse_operand:Nw \c_minus_one - \@@_parse_expand:w #1 \s_@@_mark + \@@_parse_expand:w #1 + \s_@@_mark \@@_parse_infix_end:N \s_@@_stop } \cs_new:Npn \@@_parse_after:ww - #1@ \@@_parse_infix_end:N \s_@@_mark \s_@@_stop + #1@ \@@_parse_infix_end:N \s_@@_stop { \c_zero #1 } % \end{macrocode} % \end{macro} @@ -2111,10 +2116,10 @@ { \if_catcode:w \scan_stop: \exp_not:N #2 \if_int_compare:w - \pdftex_strcmp:D { \s_@@_mark } { \exp_not:N #2 } + \__str_if_eq_x:nn { \s_@@_mark } { \exp_not:N #2 } = \c_zero \exp_after:wN \exp_after:wN - \exp_after:wN \@@_parse_infix_end:N + \exp_after:wN \@@_parse_infix_mark:NNN \else: \exp_after:wN \exp_after:wN \exp_after:wN \@@_parse_infix_juxtapose:N @@ -2158,6 +2163,16 @@ % % \subsubsection{Closing parentheses and commas} % +% \begin{macro}[aux, EXP]{\@@_parse_infix_mark:NNN} +% As an infix operator, \cs{s_@@_mark} means that the next +% token~(|#3|) has already gone through \cs{@@_parse_infix:NN} and +% should be provided the precedence~|#1|. The scan mark~|#2| is +% discarded. +% \begin{macrocode} +\cs_new:Npn \@@_parse_infix_mark:NNN #1#2#3 { #3 #1 } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[aux, EXP]{\@@_parse_infix_end:N} % This one is a little bit odd: force every previous operator to end, % regardless of the precedence. @@ -2571,41 +2586,56 @@ % \subsection{Candidate: defining new \pkg{l3fp} functions} % % \begin{macro}[EXP]{\fp_function:Nw} -% This relies on the definition of the null character as a prefix -% operator with very specific semantics. +% Parse the argument of the function~|#1| using +% \cs{@@_parse_operand:Nw} with a precedence of~$16$, and pass the +% function and argument to \cs{@@_function_apply:nw}. % \begin{macrocode} -\group_begin: - \char_set_catcode_other:N \^^@ - \cs_new:Npn \fp_function:Nw #1 { ^^@ ; { \exp_after:wN #1 } } -\group_end: +\cs_new:Npn \fp_function:Nw #1 + { + \exp_after:wN \@@_function_apply:nw + \exp_after:wN #1 + \tex_romannumeral:D + \@@_parse_operand:Nw \c_sixteen \@@_parse_expand:w + } % \end{macrocode} % \end{macro} % % \begin{macro}{\fp_new_function:Npn} +% \begin{macro}[aux]{\@@_new_function:NNnnn, \@@_new_function:Ncfnn} % \begin{macro}[aux]{\@@_function_args:Nwn} -% This relies on the definition of the null character as a prefix -% operator with very specific semantics. -% \begin{macrocode} -\group_begin: - \char_set_catcode_other:N \^^@ - \cs_new_protected:Npn \fp_new_function:Npn #1#2# - { - \cs_new:Npx #1 - { - ^^@ ; - { - \exp_not:N \exp_after:wN - \exp_not:N \@@_function_args:Nwn - \exp_not:N \exp_after:wN - \exp_not:c { @@_user_ \cs_to_str:N #1 } - \exp_not:N \__int_value:w - \int_eval:n { \tl_count:n {#2} / \c_two } - \exp_not:N \exp_after:wN ; - } - } - \cs_new:cpn { @@_user_ \cs_to_str:N #1 } #2 - } -\group_end: +% Save the code provided by the user in the control sequence +% |\__fp_user_#1|. Define |#1| to call \cs{@@_function_apply:nw} +% after parsing one operand using \cs{@@_parse_operand:Nw} with +% precedence~$16$. The auxiliary \cs{@@_function_args:Nwn} receives +% the user function and the number of arguments (half of the number of +% tokens in the parameter text~|#2|), followed by the operand (as a +% token list of floating points). It checks the number of arguments, +% and applies the user function to the arguments (without the outer +% brace group). +% \begin{macrocode} +\cs_new_protected:Npn \fp_new_function:Npn #1#2# + { + \@@_new_function:Ncfnn #1 + { @@_user_ \cs_to_str:N #1 } + { \int_eval:n { \tl_count:n {#2} / \c_two } } + {#2} + } +\cs_new_protected:Npn \@@_new_function:NNnnn #1#2#3#4#5 + { + \cs_new_nopar:Npn #1 + { + \exp_after:wN \@@_function_apply:nw \exp_after:wN + { + \exp_after:wN \@@_function_args:Nwn + \exp_after:wN #2 + \__int_value:w #3 \exp_after:wN ; \exp_after:wN + } + \tex_romannumeral:D + \@@_parse_operand:Nw \c_sixteen \@@_parse_expand:w + } + \cs_new:Npn #2 #4 {#5} + } +\cs_generate_variant:Nn \@@_new_function:NNnnn { Ncf } \cs_new:Npn \@@_function_args:Nwn #1#2; #3 { \int_compare:nNnTF { \tl_count:n {#3} } = {#2} @@ -2619,49 +2649,44 @@ % \end{macrocode} % \end{macro} % \end{macro} -% -% \begingroup\catcode`\^^@=12\relax % ^^A hack -% \begin{macro}[EXP, aux]{\@@_parse_prefix_^^@:Nw} -% \begin{macrocode} -\group_begin: - \char_set_catcode_other:N \^^@ - \cs_new:cpn { @@_parse_prefix_ ^^@ :Nw } #1 ; #2 - { - \exp_after:wN \@@_function_apply:NnwN - \exp_after:wN #1 - \exp_after:wN { #2 \exp_after:wN } - \tex_romannumeral:D - \@@_parse_operand:Nw \c_sixteen \@@_parse_expand:w - } -\group_end: -% \end{macrocode} % \end{macro} -% \endgroup % % \begin{macro}[aux, EXP] % { -% \@@_function_apply:NnwN, +% \@@_function_apply:nw, % \@@_function_store:wwNwnn, % \@@_function_store_end:wnnn % } -% \begin{macrocode} -\cs_new:Npn \@@_function_apply:NnwN #1#2#3@#4 - { - \exp_after:wN \@@_exp_after_array_f:w - \tex_romannumeral:D -`0 - \@@_function_store:wwNwnn #3 - \s_@@_mark \@@_function_store:wwNwnn ; - \s_@@_mark \@@_function_store_end:wnnn - \s_@@_stop { } { } {#2} - \s_@@_stop - #4 #1 +% The auxiliary \cs{@@_function_apply:nw} is called after parsing an +% operand, so it receives some code~|#1|, then the operand ending +% with~|@|, then a function such as \cs{@@_parse_infix_+:N} (but not +% always of this form, see comparisons for instance). Package the +% operand (an array) into a token list with floating point items: this +% is the role of \cs{@@_function_store:wwNwnn} and +% \cs{@@_function_store_end:wnnn}. Then apply \cs{@@_parse:n} to the +% code~|#1| followed by a brace group with this token list. This +% results in a floating point result, which will correctly be parsed +% as the next operand of whatever was looking for one. The trailing +% \cs{s_@@_mark} is used as a special infix operator to indicate that +% the next token has already gone through \cs{@@_parse_infix:NN}. +% \begin{macrocode} +\cs_new:Npn \@@_function_apply:nw #1#2 @ + { + \@@_parse:n + { + \@@_function_store:wwNwnn #2 + \s_@@_mark \@@_function_store:wwNwnn ; + \s_@@_mark \@@_function_store_end:wnnn + \s_@@_stop { } { } {#1} + } + \s_@@_mark } \cs_new:Npn \@@_function_store:wwNwnn #1; #2 \s_@@_mark #3#4 \s_@@_stop #5#6 { #3 #2 \s_@@_mark #3#4 \s_@@_stop { #5 #6 } { { #1; } } } \cs_new:Npn \@@_function_store_end:wnnn #1 \s_@@_stop #2#3#4 - { \@@_parse:n { #4 {#2} } } + { #4 {#2} } % \end{macrocode} % \end{macro} % |