7

I want to add an EBNF grammar to my document and following the answers here and here, it seems that the most popular package for this is syntax.

However, in the documentation it is not clear how to support constructs such as optional items enclosed in square brackets on multiple lines. I tried to use both [ and \[ directly but both do not work inside the \begin{grammar} block. Inserting [ after a \\ outputs an error, while \[ puts the line centered and adds a lot of vertical space before and after it.

Is there a proper way to include optional items in EBNF using syntax?

I would also like to change the font to use typewriter font throughout, and not have this continuous changing of typewriter and normal font. Not sure what is the right way to achieve this. The syntax documentation is a bit confusing in this regard.

I've included a minimal example below where I have the first rule including the [ which works, but it is on the same line, the second rule including a line break, which works, but does not start with [, while the third one which includes both, and reports a strange error 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}

I would like to know what is the right way to put the optional parameter on the new line with the [ and how to change the font of BNF grammars to typewriter font throughout. (Not the rest of the document of course).

  • Please provide a minimal example document demonstrating the issue. That will make it much easier for people to help you. – cfr Jan 18 '16 at 0:56
  • Have you see this question? – cfr Jan 18 '16 at 0:59
  • @cfr Yes I did, it is linked from the one I referred to in my question. There is no mention of square brackets there either (or of setting the font). – jbx Jan 18 '16 at 1:03
  • Maybe the stuff below helps? I think the documentation assumes you know how NFSS works. If you do, it tells you enough. If you don't, it provides no clue as to what to look up to figure it out. (NFSS = New Font Selection Scheme which is basically how LaTeX-2e thinks about all things font.) – cfr Jan 18 '16 at 1:56
6
+50

You can exploit \new@ifnextchar from 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}

With this trick, \\ will consider a following [ to introduce the optional argument only if no space intervenes.

I've used cfr's code for changing the font. The packages newtxtext and newtxmath are recommended for Times with math fonts support. If you don't like the typewriter font they provide, it's easy to change it.

enter image description here

  • Thanks for your input. For some reason my system cannot find the newtxtext and newtxmath. (It is set to download packages automatically of course, and I did a Synchronize on the MikTeX Package Manager just in case.) Do I need to change repository to a more updated one or something? Also what is the xpatch package being used for? (I left it out and the solution seems to work just the same) – jbx Jan 19 '16 at 11:51
  • @jbx Those packages are just a suggestion for how to replace \usepackage{times}. Possibly your document loads etoolbox, perhaps via biblatex, so \pretocmd is already defined without needing xpatch. – egreg Jan 19 '16 at 11:55
  • Yes I already use biblatex and etoolbox in fact. What could be the reason why those 2 fonts are not working? I tried to change my repository to another CTAN mirror, with version 14-Jan-16 but still the same problem. (The PDF doesn't even generate when I put those packages) – jbx Jan 19 '16 at 12:02
  • @jbx I'm no expert with MiKTeX. Try looking for newtx in the package listing. In general, I suggest to do a full install of a TeX system: it's much easier to manage. – egreg Jan 19 '16 at 12:04
  • Yes in package manager I can see newtx also saying 'Installed on 2016-01-19' so I presume it's today after I included it in my tex file. I suspect it might be related to tex.stackexchange.com/questions/287033/newtx-wont-load . Maybe I should try updating my MikTeX installation, it is over 2 years old I think. – jbx Jan 19 '16 at 12:08
5

The first part of your question is not specific to the syntax package. The problem is that in environments such as array and tabular and grammar, \\ directly followed by an opening square bracket is assumed to introduce an adjustment to vertical spacing. And a space beforehand doesn't prevent the next relevant token counting as the [. You don't want an adjustment, but that's just like an adjustment of zero, I think, so you can say \\[0pt] [<d>] and everything should work OK. Alternatively, you could define a special command to create the square brackets or write \\{} in place of \\[0pt] if that's better.

Note that times is long deprecated and ought not be used. I've used tgtermes here, but there are other options if you don't like this particular choice.

\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}

square brackets

The documentation does say something about changing the fonts (page 10) but it rather assumes that you know how to do this in the general case.

The commands it lists as affecting the appearance of different typeset elements are

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

So, to change these, we need the origiinal definitions. The manual provides this for the first two:

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

The \normalfont is setting the font to the default family for the document (usually serif). The \itshape sets the italic. If we want to use the typewriter family instead of serif, we can say

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

If we wanted the upright shape, we could say

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

We don't need to change the right one because it doesn't affect the font. The default definitions for the remaining 4 commands are as follows:

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

This changes the font but it already changes it to typewriter, so nothing to worry about here.

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

These don't affect the font, so nothing to do here either.

So, the one change of command yields this result in place of the original above:

all typewriter

Complete code:

\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}
  • Thanks for the suggestion of tgtermes. Any ideas how to make the grammar part in typewriter font instead of times / tgtermes? (the times part is for the normal document text). – jbx Jan 18 '16 at 1:55
  • @jbx Please see edit. I posted it 1 min before you posted you comment.... ;) – cfr Jan 18 '16 at 1:57
  • Thanks trying it out. Is there a way to avoid that [0pt] on each line? I have a grammar which has lots of new lines in it and it is going to become quite polluted. I guess I will have to stick with it if there is no other way. – jbx Jan 18 '16 at 2:00
  • @jbx The other thing you could do would be to define a command to produce the square bracket. Or you can say \\{} if that's better than \\[0pt]. You have to somehow change the token stream so that TeX does not see \\[ and expect a number next. I don't think it would be a good idea to try to alter the way TeX reads the stream because that may be important 'behind the scenes' here even if you don't explicitly rely on it in your code. – cfr Jan 18 '16 at 2:07
  • ok thanks. I will work with it like that for now. On another note, I am using package courier too for listings and these kinds of things. Is that also outdated? Where can I get some info on the latest up to date fonts to use? – jbx Jan 18 '16 at 2:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.