Skip to content

Instantly share code, notes, and snippets.

@kmaed
Created October 11, 2012 18:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kmaed/3874502 to your computer and use it in GitHub Desktop.
Save kmaed/3874502 to your computer and use it in GitHub Desktop.
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
Copy link
Author

kmaed commented Oct 11, 2012

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