如何逐一解析令牌流中的第一個單字?

如何逐一解析令牌流中的第一個單字?

一些程式編輯器和 IDE 以不同的方式突出顯示合法和非法變數名稱。我希望listings能夠輕鬆地允許進行此類語法檢查和突出顯示,但至少目前還沒有。我的長期目標是實現一個相容的解決方案,listings但目前,我正在研究問題的一個非常簡化的版本。

我想解析僅由字元和空格標記組成的標記流中的第一個單字。這是必須要做的一個又一個令牌不過,因為我必須對每個令牌執行一些檢查。為此,我使用遞歸巨集來解析流,將其保存在\Word巨集中,直到.遇到令牌。在那個階段,我會\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}

在此輸入影像描述

相關內容