我想将自己的文档类编写为一个文学程序,并尽可能少地使用依赖树,作为测试我的能力的练习。
我通过分解参数实现了稳定的 foreach 循环,但同样尝试解析日历失败。
\def\@pointer{\@pointer}
\long\def\@iterate#1#2#3,{
\def\cell{#3}
\ifx\cell\@pointer
\let\next=\relax
\else
\def#1{#3}
#2
\def\next{\@iterate{#1}{#2}}
\fi
\next
}
\long\gdef\foreach#1in#2#3%
{\@iterate{#1}{#3}#2,\@pointer,}
\def\@testOccidental#1 #2, #3{
\def\subject{#1}
\foreach \month in {January,February,March,April,May,June,July,August,October,September,November,December}{
\ifx\subject\month
#1 #2, #3 (Occidental Solar)
\fi
}
}
\def\checkCalendar#1{
\def\subject{#1}
\@testOccidental\subject
}
\checkCalendar{\today}
答案1
问题标题提出了一个无法回答的问题,关于如何(一般来说)编写解析器,但仅限于发布的代码
\catcode`\@=11
\def\@pointer{\@pointer}
\long\def\@iterate#1#2#3,{
\def\cell{#3}
\ifx\cell\@pointer
\let\next=\relax
\else
\def#1{#3}
#2
\def\next{\@iterate{#1}{#2}}
\fi
\next
}
\long\gdef\foreach#1in#2#3%
{\@iterate{#1}{#3}#2,\@pointer,}
X\foreach \z in {a,b,c,d}{[\z]}X
\bye
循环有效,但会给输出增加很多空间
从定义过程中删除空格标记
\catcode`\@=11
\def\@pointer{\@pointer}
\long\def\@iterate#1#2#3,{%
\def\cell{#3}%
\ifx\cell\@pointer
\let\next=\relax
\else
\def#1{#3}%
#2%
\def\next{\@iterate{#1}{#2}}%
\fi
\next
}
\long\gdef\foreach#1in#2#3%
{\@iterate{#1}{#3}#2,\@pointer,}
X\foreach \z in {a,b,c,d}{[\z]}X
\bye
猜测日历示例的意图更加困难。
\def\@testOccidental#1 #2, #3{
定义一个接受三个参数的命令,第一个参数由空格分隔,第二个参数由逗号和空格分隔,第三个参数为未分隔的{..}
参数。
您只能在一个地方使用它,因为\@testOccidental\subject
那里只有一个标记并且没有空格或逗号分隔符。由 so\subject
定义始终为 false,(并且对于循环变量来说是一个坏名称,因为它是当前月份数字的 TeX 原语)\def\subject{\today}
\ifx\subject\month
\month
尝试猜测几个月来循环的目的,也许是这样的:
\catcode`\@=11
\def\@pointer{\@pointer}
\long\def\@iterate#1#2#3,{%
\def\cell{#3}%
\ifx\cell\@pointer
\let\next=\relax
\else
\def#1{#3}%
#2%
\def\next{\@iterate{#1}{#2}}%
\fi
\next
}
\long\gdef\foreach#1in#2#3%
{\@iterate{#1}{#3}#2,\@pointer,}
X\foreach \z in {a,b,c,d}{[\z]}X
\def\@testOccidental#1 #2, #3\relax{%
\def\subject{#1}%
\foreach \xmonth in {January,February,March,April,May,June,July,August,October,September,November,December}{%
\ifx\subject\xmonth
#1 #2, #3 (Occidental Solar)\par
\else
not \xmonth\par % just for debugging
\fi
}%
}
\def\checkCalendar#1{%
\@testOccidental#1\relax
}
\checkCalendar{June 7, 2019}
\bye