我想在我的文档中添加 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 软件包newtxtext
和newtxmath
。如果您不喜欢它们提供的打字机字体,可以轻松更改它。
答案2
你的问题的第一部分并不是针对句法包。问题是,在诸如array
和tabular
和之类的环境中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}