我想创建一个显示上下文无关语法的环境。具体来说,我希望能够编写
\begin{syntax*}
Propositions & A,B & p \mid \lnot A \mid A \land B \mid A \lor B \\
Contexts & \Gamma & \cdot \mid \Gamma, A
\end{syntax*}
产生以下输出。
align*
通过与的和aligned
环境类比amsmath
,我也希望有一个syntaxed
环境,以便在需要时可以将构造放置在其他数学环境内。
为了与环境保持一致amsmath
,我考虑将上述代码处理成:
\begin{alignat*}{2}
\text{\scshape propositions} &\quad& A,B &\Coloneqq p \mid \lnot A \mid A \land B \mid A \lor B \\
\text{\scshape contexts} && \Gamma &\Coloneqq \cdot \mid \Gamma, A
\end{alignat*}
我如何检测&
标记并分别抓取环境的每个单元?
这是一个示例文档。
\documentclass{article}
\usepackage{amsmath}
\usepackage{mathtools}
\begin{document}
\begin{alignat*}{2}
\text{\scshape propositions} &\quad& A,B &\Coloneqq p \mid \lnot A \mid A \land B \mid A \lor B \\
\text{\scshape contexts} && \Gamma &\Coloneqq \cdot \mid \Gamma, A
\end{alignat*}
\begin{syntax*}
Propositions & A,B & p \mid \lnot A \mid A \land B \mid A \lor B \\
Contexts & \Gamma & \cdot \mid \Gamma, A
\end{syntax*}
\end{document}
答案1
使用array
:
\documentclass{article}
\usepackage{amsmath,mathtools,array}
\newenvironment{syntax}
{%
\renewcommand{\arraystretch}{1.5}%
\begin{array}{ @{} >{$\scshape}r<{$} @{\quad} r @{{}\Coloneqq{}} l @{} }
}
{\end{array}}
\begin{document}
\begin{equation*}
\begin{syntax}
Propositions & A,B & p \mid \lnot A \mid A \land B \mid A \lor B \\
Contexts & \Gamma & \cdot \mid \Gamma, A
\end{syntax}
\end{equation*}
\end{document}
答案2
\documentclass{article}
\usepackage{array}
\newenvironment{syntax*}
{\center
\begin{tabular}{@{}>\scshape r@{\quad}>$r<$@{}>{${}\mathrel{::=}}l<$@{}}}
{\end{tabular}\endcenter}
\begin{document}
\begin{syntax*}
Propositions & A,B & p \mid \lnot A \mid A \land B \mid A \lor B \\
Contexts & \Gamma & \cdot \mid \Gamma, A
\end{syntax*}
\end{document}
答案3
这是您的语法环境的一个版本(为了简单起见,我省略了星号):
这用于environ
收集环境的主体,然后将其拆分多次。通过滥用全局集合操作,代码归结为:
\documentclass{article}
\usepackage{amsmath}
\usepackage{mathtools}
\usepackage{environ}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new:Npn \syntax_format:n #1 { \text{\scshape \tl_lower_case:n { #1 } } }
\cs_new:Npn \syntax_process:n #1
{
\begin{alignat*}{2}
\seq_set_split:Nnn \l_tmpa_seq { \\ } { #1 }
\seq_map_inline:Nn \l_tmpa_seq
{
\seq_gset_split:Nnn \l_tmpb_seq { & } { ##1 }
\syntax_format:n { \seq_item:Nn \l_tmpb_seq { 1 } }
&\quad&
\seq_item:Nn \l_tmpb_seq { 2 } &\Coloneqq
\seq_item:Nn \l_tmpb_seq { 3 }\\
}
\end{alignat*}
}
\cs_generate_variant:Nn \syntax_process:n { V }
\NewEnviron{syntax}{
\syntax_process:V \BODY
}
\ExplSyntaxOff
\begin{document}
\begin{alignat*}{2}
\text{\scshape propositions} &\quad& A,B &\Coloneqq p \mid \lnot A \mid A \land B \mid A \lor B \\
\text{\scshape contexts} && \Gamma &\Coloneqq \cdot \mid \Gamma, A
\end{alignat*}
\begin{syntax}
Propositions & A,B & p \mid \lnot A \mid A \land B \mid A \lor B \\
Contexts & \Gamma & \cdot \mid \Gamma, A
\end{syntax}
\end{document}
答案4
我稍微修改了 egreg 的解决方案。最重要的是,我在最后一列恢复到\arraystretch
,1
这样array
出现在那里的 s 就不会受到影响。
\RequirePackage { array }
\RequirePackage { collcell }
\RequirePackage { textcase }
\cs_new_protected:Npn \__syntax_text:n #1
{ \text { \scshape \MakeTextLowercase {#1} } }
\NewDocumentEnvironment { syntax* } { }
{ \__syntax_star_begin: }
{ \__syntax_star_end: }
\cs_new_protected:Npn \__syntax_star_begin:
{
\group_begin:
\use:c { equation* }
\cs_set:Npn \arraystretch { 1.5 }
\use:c { array }
{
@{}
>{ \collectcell \__syntax_text:n }
r
<{ \endcollectcell }
@{ \quad }
r
@{ {} \Coloneqq {} }
>{ \renewcommand\arraystretch{1} }
l
@{}
}
}
\cs_new_protected:Npn \__syntax_star_end:
{
\use:c { endarray }
\use:c { endequation* }
\group_end:
}
再次感谢 egreg 的帮助!