是否有可能计算令牌列表中令牌的数量?
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\tl_new:N \tobi_list_tl
\tl_set:Nn \tobi_list_tl {foo~bar~baz}
\begin{document}
'\tl_use:N \tobi_list_tl'~contains~?~spaces.
\end{document}
在排版音节和韵律符号的宏中,我需要计算标记列表中的空格数。
\cs_new_protected:Npn \tobi_metrics:nn #1 #2
{
\tl_set:Nn \l_tobi_words_tl { #2 }
% change spaces into -\q_tobi_space_marker-
\tl_replace_all:Nnn \l_tobi_words_tl { ~ } { - \q_tobi_space_marker - }
% split the (modified) second argument at -
\seq_set_split:NnV \l_tobi_syllables_seq { - } \l_tobi_words_tl
% split the first argument "at nothing"
\seq_set_split:Nnn \l_tobi_measures_seq { } { #1 }
% AT THIS POINT I WANT TO KNOW THE NUMBER OF SPACES <---------
% IN \l_tobi_words OR THE NUMBER OF \q_tobi_space_marker <------------
% IN \l_tobi_syllables_seq <---------
\int_zero:N \l_tobi_process_int
\seq_map_inline:Nn \l_tobi_syllables_seq
{
\int_incr:N \l_tobi_process_int
\tl_if_eq:nnTF { ##1 } { \q_tobi_space_marker }
{% we had a space, step back the counter and issue a space
\int_add:Nn \l_tobi_process_int { -1 }
\c_space_token
}
{% print the syllable with the metric marker
\tobi_print_syllable:n { ##1 }
}
}
}
看https://tex.stackexchange.com/a/124531/4918。
我需要数字来检查列表中是否有足够的符号可以与音节结合,这是我迄今为止的测试:
\int_compare:nT
{
\seq_count:N \l_@@_syllables_seq - 1 != \seq_count:N \l_@@_symbols_seq
}
{
ERROR
}
必须-1
用空格数替换。
也许我应该添加一些关于用法的信息。这将是宏的一部分
\metrics{_ u u _ _ _ | _ _ u u _ _ _ }
{flos ve-te-ris vi-ni | meis na-ri-bus ob-iec-tust}
第一个参数是一个空格分隔的度量符号列表(通过缩写访问,如u
或_
),第二个列表包含带连字符的单词。我需要检查每个音节是否有一个符号,但\seq_count:
在这里不起作用,因为第二个列表中的空格被特殊处理。测试必须是
# of symbols = # of syllables
lengt of symbol list = lengthh of syllablelist – # of spaces
这是完整处理宏的最新版本:
\cs_new_protected:Npn \__metrix_metrics:nn #1 #2
{
\tl_set:Nn \l__metrix_words_tl { #2 }
\tl_replace_all:Nnn \l__metrix_words_tl { ~ } { - \q__metrix_space_marker - }
\seq_set_split:NnV \l__metrix_syllables_seq { - } \l__metrix_words_tl
\seq_set_split:Nnn \l__metrix_symbols_seq { ~ } { #1 }
\int_zero:N \l__metrix_process_int
\seq_map_inline:Nn \l__metrix_syllables_seq
{
\tl_if_eq:nnT { ##1 } { \q__metrix_space_marker }
{ \int_incr:N \l__metrix_process_int }
}
\int_compare:nTF
{
\seq_count:N \l__metrix_syllables_seq -
\seq_count:N \l__metrix_symbols_seq = \l__metrix_process_int
}
{
\int_zero:N \l__metrix_process_int
\seq_map_inline:Nn \l__metrix_syllables_seq
{
\int_incr:N \l__metrix_process_int
\tl_if_eq:nnTF { ##1 } { \q__metrix_space_marker }
{
\int_add:Nn \l__metrix_process_int { -1 }
\c_space_token
}
{
\str_case:nnn { ##1 }
{
{ | } { \__metrix_l_break: }
{ || } { \__metrix_ll_break: }
}
{
\__metrix_print_syllable:n { ##1 }
}
}
}
}
{
\__metrix_error_msg:n { Numbers~of~symbols~and~syllables~mismatch. }
}
}
除了当一个或两个列表以空格结尾时,每个方法都可以工作,因此如果可以在开始处理列表之前从右侧剪切所有空格,那就太好了。
答案1
您可以通过多种方式来实现。
第一种方法(映射音节序列)
%%% Code to add for checking the syllables and the measures are the same number
\int_zero:N \l_tobi_process_int
\seq_map_inline:Nn \l_tobi_syllables_seq
{
\tl_if_eq:nnT { ##1 } { \q_tobi_space_marker }
{ \int_incr:N \l_tobi_process_int }
}
\int_compare:nF
{
\seq_count:N \l_tobi_syllables_seq -
\seq_count:N \l_tobi_measures_seq = \l_tobi_process_int
}
{ ERROR! }
%%% End of code to add
第二种方式(直接计数)
这需要l3regex
:
\RequirePackage{l3regex}
\cs_generate_variant:Nn \regex_count:nnN { nV }
%%% Code to add for checking the syllables and the measures are the same number
\regex_count:nVN { \c{q_tobi_space_marker} } \l_tobi_words_tl \l_tobi_process_int
\int_compare:nF
{
\seq_count:N \l_tobi_syllables_seq -
\seq_count:N \l_tobi_measures_seq = \l_tobi_process_int
}
{ ERROR! }
%%% End of code to add
答案2
也许最简单的解决方案是使用标准 TeX 分隔参数方法。由于我们用空格分隔,因此这比平常稍微棘手一些:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\tl_new:N \tobi_list_tl
\tl_set:Nn \tobi_list_tl {foo~bar~baz}
\use:x
{
\cs_new:Npn \exp_not:N \tl_count_spaces:n ##1
{
\exp_not:N \int_eval:n
{
-1 \exp_not:N \__tl_count_spaces:w ##1 ~
\exp_not:N \q_recursion_tail \c_space_tl
\exp_not:N \q_recursion_stop
}
}
}
\cs_new:Npn \__tl_count_spaces:w #1 ~
{
\quark_if_recursion_tail_stop:n {#1}
+1
\__tl_count_spaces:w
}
\cs_generate_variant:Nn \tl_count_spaces:n { V }
\begin{document}
'\tl_use:N \tobi_list_tl'~contains~\tl_count_spaces:V \tobi_list_tl \c_space_tlspaces.
\end{document}
您可以使用两部分方法,用于\seq_set_split:Nnn
存储在空格上分割的令牌列表,然后\seq_count:N
获取值。