我怎样才能逐个标记地解析标记流中的第一个单词?

我怎样才能逐个标记地解析标记流中的第一个单词?

一些编程编辑器和 IDE 以不同的方式突出显示合法和非法的变量名。我希望listings能够轻松实现这种语法检查和突出显示,但至少目前还不行。我的长期目标是实现一个兼容的解决方案listings,但目前,我正在寻找一个非常简化的问题版本。

我想解析仅由字符和空格标记组成的标记流中的第一个单词。必须这样做逐个标记,因为我必须对每个 token 执行一些检查。为此,我使用递归宏来解析流,将其保存在宏中\Word,直到.遇到 token。在那个阶段,我\Word以某种方式处理,例如用红色打印它。我定义一个单词作为不被任何空格标记打断的字符标记序列。

问题:我在这里只使用一个.标记,因为我不知道当.在流中遇到下一个空格标记(而不是标记)时,我应该在代码中更改什么才能停止递归。用控制空格(\)代替.似乎不起作用。我应该在代码中更改什么?

我赞成使用低级 TeX 命令进行解析的解决方案,但 LaTeX2e 和 LaTeX3 替代方案也引起了我的关注。

编辑:如果我似乎改变了目标,我深感抱歉,但我必须通过添加“逐个标记”的要求来澄清我的问题,这可能会使一些已经发布的答案无效。

在此处输入图片描述

\documentclass{article}

\usepackage{xcolor}

\def\ParseWordandPrint#1{%
    \if #1.%
        \textcolor{red}{\Word}\ %
    \else
        \edef\Word{\Word#1}
        \expandafter\ParseWordandPrint
    \fi%
}

\def\InitParseWordandPrint#1{%
    \def\Word{}
    \ParseWordandPrint#1%
}

\begin{document}

\InitParseWordandPrint Hello.World

\end{document}

答案1

根据您编辑的问题取消删除此内容。

使用空格分隔的参数更容易一次性抓取单词,并且然后逐个字母地迭代。(作为示例,我在这里检查它们是否是字母,最后一个例子产生了

illegal character 0
illegal character 1

要逐个字符地迭代,您必须使用空格\futurelet(或等效地\@ifnextchar),但这在您要排版的单词中不太好,因为很难不破坏字母间的字距和连字。因此,首先抓住单词更容易。

\documentclass{article}

\usepackage{xcolor}

\def\InitParseWordandPrint#1 {\check#1\relax\textcolor{red}{#1} }

\def\check#1{%
\ifx\relax#1%
\else
\ifcat a#1%
\else
\typeout{illegal character #1}%
\fi
\expandafter\check
\fi}

\begin{document}

\InitParseWordandPrint Hello World


\InitParseWordandPrint  World

Hello World

\InitParseWordandPrint  W0r1d 

\end{document}

答案2

TeX\def提供了分隔的参数文本。因此,在这种情况下,您可以使用空格作为分隔符:

在此处输入图片描述

\documentclass{article}

\usepackage{xcolor}

\def\ParseWordandPrint#1{%
    \if #1.%
        \textcolor{red}{\Word}\ %
    \else%
        \edef\Word{\Word#1}%
        \expandafter\ParseWordandPrint%
    \fi%
}

\def\InitParseWordandPrint#1{%
    \def\Word{}%
    \ParseWordandPrint#1%
}
\def\highlightfirst#1 {\textcolor{red}{#1} }

\begin{document}

\InitParseWordandPrint Hello.World

\highlightfirst Hello World.

\end{document}

答案3

使用 LaTeX3 真的很容易:

\documentclass{article}
\usepackage{xparse,xcolor}

\ExplSyntaxOn
\NewDocumentCommand{\printfirstwordincolor}{ O{red} m }
 {
  \jubobs_pfwr:nn { #1 } { #2 }
 }

\seq_new:N \l_jubobs_words_seq
\tl_new:N \l_jubobs_first_word_tl

\cs_new_protected:Npn \jubobs_pfwr:nn #1 #2
 {
  % split the input at spaces
  \seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
  % pop off the leftmost item
  \seq_pop_left:NN \l_jubobs_words_seq \l_jubobs_first_word_tl
  % print the first item in the chosen color
  \textcolor{#1}{ \l_jubobs_first_word_tl } ~ %
  % print the other items adding spaces between them
  \seq_use:Nn \l_jubobs_words_seq { ~ }
 }

\ExplSyntaxOff

\begin{document}

\printfirstwordincolor{Hello World}

\printfirstwordincolor[green]{Addio mondo crudele}

\end{document}

在此处输入图片描述


如果您还想逐个处理输入的标记,则可以对已保存的项目进行映射。假设您想将每个“d”大写:

\documentclass{article}
\usepackage{xparse,xcolor}

\ExplSyntaxOn
\NewDocumentCommand{\printfirstwordincolor}{ O{red} m }
 {
  \jubobs_pfwc:nn { #1 } { #2 }
 }

\seq_new:N \l_jubobs_words_seq
\tl_new:N \l_jubobs_first_word_tl
\bool_new:N \l_jubobs_first_item_bool

\cs_new_protected:Npn \jubobs_pfwc:nn #1 #2
 {
  \seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
  \seq_pop_left:NN \l_jubobs_words_seq \l_jubobs_first_word_tl
  \textcolor{#1}{ \l_jubobs_first_word_tl } ~ %
  \seq_use:Nn \l_jubobs_words_seq { ~ }
 }

\NewDocumentCommand{\printfirstwordincolorandcapitalizeD} { O{red} m }
 {
  \jubobs_pfwcacd:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \jubobs_pfwcacd:nn #1 #2
 {
  \seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
  \leavevmode
  \bool_set_true:N \l_jubobs_first_item_bool
  \seq_map_inline:Nn \l_jubobs_words_seq
   {
    \bool_if:NT \l_jubobs_first_item_bool
     { \c_group_begin_token \color{#1} }
    \tl_map_inline:nn { ##1 }
     {
      \peek_charcode_remove:NT d { D } ####1
     }
    \bool_if:NT \l_jubobs_first_item_bool
     { \c_group_end_token \bool_set_false:N \l_jubobs_first_item_bool }
    \c_space_tl
   }
  \unskip
 }
\ExplSyntaxOff

\begin{document}

\printfirstwordincolor{Hello World}

\printfirstwordincolorandcapitalizeD[blue]{Addio mondo crudele}

\end{document}

在此处输入图片描述

相关内容