如何在语法包中的新行中包含 EBNF 方括号并将字体设置为打字机?

如何在语法包中的新行中包含 EBNF 方括号并将字体设置为打字机?

我想在我的文档中添加 EBNF 语法,并遵循以下答案这里这里,似乎最受欢迎的包是syntax

但是,文档中没有明确说明如何支持多行中方括号内的可选项等结构。我尝试直接使用和,[\[两者都无法在\begin{grammar}块内工作。[在 a 之后插入\\会输出错误,而 while\[会使行居中并在其前后添加大量垂直空间。

是否有适当的方法在 EBNF 中使用包含可选项syntax

我还想将字体改为始终使用打字机字体,而不是不断更改打字机字体和普通字体。不确定实现此目的的正确方法是什么。语法文档在这方面有点令人困惑。

我在下面提供了一个最小的例子,其中第一条规则包括 ,它[可以工作,但它在同一行;第二条规则包括一个换行符,它可以工作,但不以 开头[;而第三条规则包括两者,并报告一个奇怪的错误Missing number, treated as zero

\documentclass[]{article}

\usepackage{times}
\usepackage{syntax}

\begin{document}

\begin{grammar}

<a> ::= "a" [<b>]

<b> ::= "b" \\ <c>

%this does not work
<c> ::= "c" \\ [<d>]

\end{grammar}

\end{document}

我想知道将可选参数放在新行上的正确方法是什么,[以及如何将 BNF 语法的字体始终更改为打字机字体。(当然不是文档的其余部分)。

答案1

您可以\new@ifnextchar从以下位置进行利用amsmath

\documentclass[]{article}

\usepackage{amsmath}
\usepackage{newtxtext,newtxmath}

\usepackage{syntax}
\usepackage{xpatch}

\makeatletter
\pretocmd{\grammar}{\let\@ifnextchar\new@ifnextchar}{}{}
\makeatother
\renewcommand{\syntleft}{$\langle$\normalfont\ttfamily}

\begin{document}

\begin{grammar}

<a> ::= "a" [<b>]

<b> ::= "b" \\ <c>

<c> ::= "c" \\ [<d>]

\end{grammar}

\end{document}

使用此技巧,只有在没有空格介入的情况下\\才会考虑[引入可选参数。

我使用了 cfr 的代码来更改字体。建议使用支持数学字体的 Times 软件包newtxtextnewtxmath。如果您不喜欢它们提供的打字机字体,可以轻松更改它。

在此处输入图片描述

答案2

你的问题的第一部分并不是针对句法包。问题是,在诸如arraytabular和之类的环境中grammar\\直接跟在左方括号后面会被认为会调整垂直间距。而且前面的空格不会阻止将下一个相关标记计为[。您不希望进行调整,但我认为这就像调整为零一样,因此您可以说\\[0pt] [<d>],一切都应该正常工作。或者,您可以定义一个特殊命令来创建方括号,或者如果这样更好的话,可以\\{}代替写。\\[0pt]

注意早已被弃用,不应使用。我用过白蚁这里,但如果您不喜欢这个特定的选择,还有其他选择。

\documentclass{article}
\usepackage{tgtermes}
\usepackage{syntax}
\begin{document}
\begin{grammar}

  <a> ::= "a" [<b>]

  <b> ::= "b" \\ <c>

  % this works
  <c> ::= "c" \\[0pt] [<d>]
  % or this
%  <c> ::= "c" \\{} [<d>]

\end{grammar}
\end{document}

方括号

文档确实提到了有关更改字体(第 10 页)的内容,但它假设您知道在一般情况下如何执行此操作。

它列出的影响不同排版元素外观的命令是

\syntleft
\syntright
\ulitleft
\ulitright
\litleft
\litright

因此,要更改这些,我们需要原始定义。手册为前两个提供了此定义:

\newcommand{\syntleft}{$\langle$\normalfont\itshape}
\newcommand{\syntright}{$\rangle$}

\normalfont字体设置为文档的默认系列(通常是衬线字体)。设置\itshape斜体。如果我们想使用打字机系列而不是衬线字体,我们可以说

\renewcommand{\syntleft}{$\langle$\normalfont\ttfamily\itshape}

如果我们想要直立的形状,我们可以说

\renewcommand{\syntleft}{$\langle$\normalfont\ttfamily}

右边的我们不用改,因为不影响字体,其余4个命令默认定义如下:

\newcommand{\ulitleft}{\normalfont\ttfamily\syn@ttspace\frenchspacing}

这会改变字体,但它已经将其更改为打字机字体,因此无需担心。

\newcommand{\ulitright}{}
\newcommand{\litleft}{`\bgroup\ulitleft}
\newcommand{\litright}{\ulitright\egroup'}

这些不会影响字体,所以这里也无事可做。

因此,只需更改一次命令即可得到此结果,取代上面的原始结果:

所有打字机

完整代码:

\documentclass{article}
\usepackage{tgtermes}
\usepackage{syntax}
\renewcommand{\syntleft}{$\langle$\normalfont\ttfamily\itshape}
% \newcommand{\syntright}{$\rangle$}
% \newcommand{\ulitleft}{\normalfont\ttfamily\syn@ttspace\frenchspacing}
% \newcommand{\ulitright}{}
% \newcommand{\litleft}{`\bgroup\ulitleft}
% \newcommand{\litright}{\ulitright\egroup'}
\begin{document}
\begin{grammar}

  <a> ::= "a" [<b>]

  <b> ::= "b" \\ <c>

  % this works
  <c> ::= "c" \\[0pt] [<d>]
  % or this
%  <c> ::= "c" \\{} [<d>]

\end{grammar}
\end{document}

相关内容