为了给宏指定看似无穷无尽的参数,我只想提供一个#1
,其中#1
是一个包含一堆的字符串具体的字符。例如
\mymacro{1jq4PK2/62Bb/-krkR/...}
然后,我想#1
按顺序逐个字符进行解析,并根据字符执行某些操作。如上例所示,字符可以是数字0...9
、字母a...z
和A...Z
(因此条件应区分大小写)或符号-
、、/
...
这里的重点是创建一个使用chessfss
使用排版棋盘或任意形状FEN 符号。符号-
表示空白格,数字表示空格(上面没有棋子),/
表示下一等级,字母表示棋子的颜色(通过大写)和类型(通过特定字母)。
代码由skak
包裹仅限于固定的 8 阶(或文件)棋盘。具体而言,skak
规定\InitBoard
定义为
\def\InitBoard(#1/#2/#3/#4/#5/#6/#7/#8){%
%<code>
}
其中 8 个参数中的每一个都以非常“嵌套的方式”进行处理(为了简洁起见,我跳过了一些中间步骤):
\def\FenConvert#1{%
\EqStr{8}{#1}%
{EEEEEEEE}%
{\EqStr{7}{#1}%
{EEEEEEE}%
{\EqStr{6}{#1}%
{EEEEEE}%
{\EqStr{5}{#1}%
{EEEEE}%
{\EqStr{4}{#1}%
{EEEE}%
{\EqStr{3}{#1}%
{EEE}%
{\EqStr{2}{#1}%
{EE}%
{\EqStr{1}{#1}%
{E}%
{#1}}}}}}}}}
\def\ParseFenRank#1{\ParseFenRankA(#1Z)}
\def\ParseFenRankA(#1#2){%
\EqStr{Z}{#1}%
{}%
{\FenConvert{#1}\ParseFenRankA(#2)}}
我希望避免这种情况,因为它不是完全读者友好的,而且有点不吸引人,而是使用一些“case语句”,在其中我逐个条件化宏参数中的字符。boolexpr
包裹提供了这样的switch
环境,但我不确定如何扩展它以按照我想要的方式工作。
答案1
tikz-timing
我已经在我的和collcell
包中实现了这样的字符或标记解析器ydoc
。它们都可以在https://bitbucket.org/martin_scharrer/当然还有 CTAN。基本上,您可以使用\futurelet
或宏参数(#1
)来读取下一个标记或字符并相应地分支,然后递归调用输入集合宏。
我collcell
添加了一个用于标记的 case 语句,可以将其更改为采用字符。当前语法是:
\cc@case
<token>{<code>}
<token>{<code>}
<token>{<code>}
<token>{<code>}
\endcc@case
在使用之前读取令牌的位置\futurelet\collect@cell@lettoken\next
。请参阅case 语句的源代码更多细节。
我一ydoc
开始用了一个大\ifcase
语句,但后来把它改成了查找表类似功能:每个输入字符都有一个宏定义,例如\@namedef{mypkg@char@<char>}{<code for this character>}
,然后解析器宏只需要读取下一个字符并使用\@nameuse{mypkg@char@#1}
(或\csname
直接使用)。只要您没有任何特殊标记,如{
,和空格,这就可以正常工作。否则您需要先}
使用\futurelet
/来检查这些。\@ifnextchar
也可以始终使用带有 和 的标记\futurelet
来\meaning
构建宏名称,即\@nameuse{mypkg@char@\meaning\@let@token}
。这适用于所有标记,无论是普通标记还是特殊标记。然后,处理程序宏应从输入流中删除该标记。
基于此的简单逐字符解析器如下所示:
\documentclass{article}
\makeatletter
\newcommand\mymacro[1]{%
\@mymacro#1\@nnil
}
\def\@mymacro#1{%
\ifx\@nnil#1\relax\else
\@nameuse{mymacro@char@#1\expandafter}%
\fi
}
\def\defcharcode#1{%
\@namedef{mymacro@char@#1}%
}
\defcharcode{1}{%
(1)
\@mymacro
}
\defcharcode{j}{%
(j)
\@mymacro
}
\defcharcode{q}#1{% reads further character!
(q#1)
\@mymacro
}
\defcharcode{.}{%
(.)
\@mymacro
}
\makeatother
\begin{document}
\mymacro{1jq4...}
\end{document}
这将打印:(1) (j) (q4) (.) (.) (.)
。
递归调用被放置在每个字符处理程序中,以便它之后没有任何内容,以便它可以在需要时读取进一步的输入字符。