Instantly share code, notes, and snippets.

Embed
What would you like to do?
2012/09/17 の解答
\documentclass[a4paper]{article}
\begin{document}
\makeatletter
%% \length{<token list>}
% <token list> に含まれるトークンの数の * に展開される.完全展開可能.
\def\length#1{\len@begin#1{\len@end}}
%% \len@begin<token list>{
% { までのトークン列を取ってきて \len@count に渡す.
% 残りは \len@ifend に.
\def\len@begin#1#{\len@count{#1\len@count@end}\len@ifend}
%% \len@ifend{<token list>}
% もし <token list> が \len@end なら終端なので終わり.
% そうでなければ2つの括弧分の ** を出して <token list> は \length に渡し,
% 残りを処理する.
\def\len@ifend#1{%
\ifx\len@end#1\empty
\else
**\length{#1}\expandafter\len@begin
\fi}
%% \len@count{<token list>}
% { が含まれない <token list> 中のトークンの数の * に展開される.
% <token list> が \len@count@end だったら終わり.
% そうでなければ * を1つ出して,<token list> の先頭のトークンを1つ取り除く.
\def\len@count#1{%
\ifx\len@count@end#1%
\expandafter\@gobble
\else
*\expandafter\len@count@gobble
\fi{#1}}
%% \len@count@gobble{<token list>}
% <token list> の先頭のトークンを1つ取り除く.
% まず,<token list> の先頭がスペースかどうかを判定する.
% 一旦 \len@count@eat で判定後に残されたトークン列を取り除き,
% その後分岐する.
\edef\len@count@gobble#1{%
\unexpanded{\expandafter\len@count@eat
\ifx}\space#1%
\unexpanded{\expandafter\len@count@rmsp
\else
\len@count@end\expandafter\len@count@rmtop
\fi}{#1}}
%% \len@count@eat<token list>\len@count@end
% <token list> を除去する.
\def\len@count@eat#1\len@count@end{}
%% \len@count@rmsp{<token list>}
% <token list> の先頭のスペースを取り除き,残りのトークンを数える.
\def\len@count@rmsp#1{\expandafter\len@count\expandafter{\len@rmsp#1}}
%% \len@count@rmtop{<token list>}
% <token list> の先頭の非スペーストークンを取り除き,残りのトークンを数える.
\def\len@count@rmtop#1{\expandafter\len@count\expandafter{\@gobble#1}}
%% \len@rmsp<space>
% スペース文字を1つ取り除く.
\expandafter\def\expandafter\len@rmsp\space{}
%% 終端のトークンと異世界の \makeatother.
\def\len@end{\len@end}
\def\len@count@end{\len@count@end}
\makeatother
\def\check{\ifx\result\checkstr OK\else NG\fi}
\edef\result{\length{ \a {b\cd ef{g} }\h }}
\def\checkstr{*************}
\check
\edef\result{\length{{ }{ {}} {}}}
\def\checkstr{***********}
\check
\escapechar=-1
\edef\result{\length{\expandafter\expandafter\expandafter}}
\escapechar=`\\
\def\checkstr{***}
\check
\edef\result{\expandafter\length\expandafter{\csname ?TeX\endcsname}}
\def\checkstr{*}
\check
\edef\result{\length{{>>+<+<-}}}
\def\checkstr{*********}
\check
\edef\next{\noexpand\length{a\space\space\space b}}
\edef\result{\next}
\def\checkstr{*****}
\check
\end{document}
@kmaed

This comment has been minimized.

Copy link
Owner Author

kmaed commented Oct 11, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment