# How do I format a regular expression in math mode?

I want to display some regular expression, like the following, in LaTeX math mode.

$(F+(A+I*)*)|(F*(A+I*)+)E$


However, the spacing is all wrong, because TeX formats + and * as binary operators, rather than as postfix ones. I would expect that the postfix operators would appear close to the preceding operand, and, in cases where the successor element is an operand, they would introduce some additional space to prevent the appearance's ambiguity.

An example formatted in the way I'd like it to be appears below. I have marked with red the places where additional spacing is unwanted and with green places where additional spacing is required. However, I'd be open to other formatting suggestions from typography experts.

Is there a way to handle this without adding manual spacing commands?

It would be possible to set up +*? to act automatically as postfix, but how easy it is depends a bit if they also need their normal definitions within the same document or same expression.

Probably simplest is to set up simple commands for the postfix versions for example:

\documentclass{article}

\makeatletter

\def\+{\@postfix+}
\def\*{\@postfix*}
\def\?{\@postfix?}

\def\@postfix#1{{#1}\@ifnextchar){}{\;}}

\makeatother
\begin{document}

$(F+(A+I*)*)|(F*(A+I*)+)E$

$(F\+(A\+I\*)\*)|(F\*(A\+I\*)\+)E$

\end{document}

• The problem is too much space before the operator. I could correct this with a negative space, but the problem occurs only in some cases (e.g. it does not occur when the next element is a bracket), so I would have to reverse-engineer TeXs operator spacing in order to know where to use the modified versions. – Diomidis Spinellis Jul 25 '12 at 11:32
• the {} in my definitions prevents that (makes the character be set as a mathord rather than a mathbin. I added a thin space afterwards as tex doesn't have a primitive postfix operator class. if you omitted the \, you would get the same spacing as egreg's answer. – David Carlisle Jul 25 '12 at 11:41
• Nice! This should give a better presentation than a considering the operators mathord. Will try it out. – Diomidis Spinellis Jul 25 '12 at 11:54
• The result looks better than egreg's answer in the "F+I" case, but worse when formatting "I*)", because there is an unneeded space before the bracket. It turns out this is an interesting problem. – Diomidis Spinellis Jul 25 '12 at 11:59
• It depends how hard you want to try. TeX doesn't have a built-in postfix class so you can't just set mathclass as you would to mathop for a prefix operator. You could define \+ and friends to look ahead to the next character, take its mathcode and then add spacing or not. Or I wonder if you could be sneaky and typeset the thing in reverse using prefix operators and \mathop but then reverse the display back to postscript using etex bidirectional features. Hmmmmm – David Carlisle Jul 25 '12 at 12:25

I suggest to mark up regular expressions, so that you can do whatever change you want with them. Here's a possibility:

\documentclass{article}

\newcommand{\regex}[1]{\ensuremath{
\begingroup
\makeord{+}
\makeord{*}
\makeord{?}
#1
\endgroup
}}

\makeatletter
\newcommand{\makeord}[1]{
\@tempcnta=\mathcode#1
\divide\@tempcnta by "1000
\multiply\@tempcnta by "1000
\mathcode#1=\numexpr\the\mathcode#1-\@tempcnta\relax
}
\makeatother

\begin{document}
$\regex{(F+(A+I*)*)|(F*(A+I*)+)E}$
\end{document}


You can also use \regex directly in text mode.

The "magic" \makeord macro strips off from a character its type as math atom: a mathcode is a 15 bit number; the three most significant digits tell TeX what kind of atom and 0 corresponds to "ordinary". So we do

n - (n mod 4096)

where n is the mathcode of the character and assign this as the mathcode: the character which is printed is the same, but treated as an ordinary symbol as far as spacing is concerned.

An alternative way that adds the desired spacing is with

\newcommand{\makeord}[1]{
\edef\@tempa{\the\mathcode#1 }
\begingroup\lccode~=#1
\lowercase{\endgroup\edef~}{\mathpunct{\mathchar\@tempa}}
\mathcode#1="8000
}


which, with the same regex as before, produces

However this won't work for things such as

A*?


because a space would be inserted between * and ?.

The trick here is to consider +, * and ?` as punctuation symbols.

• I assume I also need to add \makeatother after the newcommand, right? – Diomidis Spinellis Jul 25 '12 at 11:39
• I am going with this. Ideally, there should be some additional space after an operator when it appears before another letter, as in "A+ I", but not when it appears before a closing bracket, as in "I*)". – Diomidis Spinellis Jul 25 '12 at 12:02
• @DiomidisSpinellis Can you add to your question a complete specification of the spacings you need? – egreg Jul 25 '12 at 12:19
• Added. Sorry for being vague initially, but the complications of what I wanted appeared when I read the answers. – Diomidis Spinellis Jul 25 '12 at 12:59