# What is causing (and how can I fix) "Misplaced \cr" and "Misplaced alignment tab" errors in an array environment when trying to compile my .dtx?

I created a small package to help me typeset various tidbits in papers for a specific domain of theoretical computer science that I sometimes work in. So far, it has been working well, but I decided that I wanted to introduce auto-growing brackets since I can sometimes end up with a whole bunch of nested brackets being displayed. To do this, I introduced use of the 'perfectcut' package. Or tried to.

For full reference, you can find the pre-perfectcut implementation here, and the attempt at a new implementation here. The only substantive difference between the two is changing the definitions of cpfunc, cpsend and cprecv, and introducing the new cpsystems@functorparens and cpsystems@msgbraces commands to back said new definitions.

The problem is, with just these changes (and, best as I can tell, the modification to cpfunc was the only one that actually caused these problems), is that now when I try to re-compile my .dtx file (using the command pdflatex cpsystems.dtx), I get a whole bunch of "Misplaced \cr" and "Misplaced alignment tab &" errors. E.g., the very first ones look like:

! Misplaced \cr.
\reserved@c ->\ifnum 0={}\fi \cr

l.310 ...func{p}{h(R) \cpfunc{p}{h(F)p(P)}}}~c(W)}

?
! Misplaced alignment tab character &.

l.310 ...func{p}{h(R) \cpfunc{p}{h(F)p(P)}}}~c(W)}


In the full-blown file, these such errors start at line 310, with more being reported at lines 315, 370 and 375 (though the latter two are actually a repeat of the earlier two, for documentation reasons). Going by discussions of these errors that I could turn up, such as this TeXOverflow question, or this Overleaf help page, I surmise that the errors are probably not occurring there, but likely on the line above. Either way, though, I can't work out what the issue really is.

The lines in question are using a package command, which in turn uses an array environment, to present something. On the previous line, I have included a line break. I have checked, and am fairly certain I have specified the correct number of & characters on those lines to get everything to fit together, and I didn't see any errors previously.

I have done my best to create an example that reproduces the errors, which is below, though it is still awfully long (I wasn't sure what else I could remove without mucking something up):

% \iffalse meta-comment
% !TEX program  = pdfLaTeX
%
% \fi
% \iffalse
%%cpsystems LaTeX package
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{cpsystems.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{cpsystems}
%<*package>
[2020/07/16 v0.14 Package to aid in typesetting cP systems
rulesets, following Nicolescu's standard style]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{cpsystems}[2020/07/16 v0.14]
\usepackage{fancyvrb}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
%\OnlyDescription %Leave this commented out unless you have read the Doc documentation and know what you're doing
\begin{document}
\DocInput{cpsystems-autogrow-bracks-mwe.dtx}
\PrintIndex
\PrintChanges
\end{document}
%</driver>
% \fi
%
%   \begin{cpruleset}
%       \cprule{s_1}{\cpfunc{v}{v(R)Y}}{1}{s_2}{\cpfunc{s}{r(R)~u(Y)~
%       \cpfunc{p}{h(R)p()}}~c(\lambda)}
%
%       \cprule{s_2}{\cpfunc{s}{r(R)~u() \\ & \cpfunc{p}{h(F)p(P)} \\ & c(C)}}
%       {+}{s_3}{\cpfunc{z}{\cpfunc{p}{h(R) \cpfunc{p}{h(F)p(P)}}}~c(W)}
%
%       \cprule{s_2}{}{+}{s_2}{\cpfunc{s}{r(R)~u(Z) \\
%       & & & & \cpfunc{p}{h(T) \cpfunc{p}{h(F) p(P)}}
%       \\ & & & & c(CW)}}
%
%       \cprule{s_2}{s(\_)}{+}{s_2}{}
%
%   \end{cpruleset}
% \StopEventually{\PrintIndex}
% \iffalse
%<*package>
% \fi
%
% \iffalse
%
% \fi
%
% \subsection{Preamble}
%
%    \begin{macrocode}
%

\RequirePackage{array}
\RequirePackage{framed}
\RequirePackage{changepage}
\RequirePackage{amsmath}
\RequirePackage{trimspaces}
\RequirePackage{newfloat}
\RequirePackage{perfectcut}

\newcounter{cpsystems@RuleNum}
%
%    \begin{macrocode}
\newenvironment{cpruleset}
\renewcommand{\arraystretch}{1.0}$\begin{array}{lllllr}} {\end{array}$\end{adjustwidth}\end{framed}}
%    \end{macrocode}
%
% % \begin{macro}{\cprule}
%    \begin{macrocode}
\newcommand{\cprule}[5]{
\refstepcounter{cpsystems@RuleNum}
\cpsystems@basecprule{#1}{#2}{#3}{#4}{#5}{(\arabic{cpsystems@RuleNum})}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cpfunc}
% Command for declaring a cP~systems functor.
% The first argument is the symbol for the functor itself, and the second argument is the objects contained inside the functor.
%    \begin{macrocode}
\newcommand{\cpfunc}[2]{
\trim@spaces@noexp{#1\cpsystems@functorparens{#2}}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cpsystems@basecprule}
% For writing out rules inside a |cpruleset| environment.
% Required arguments are, in order, beginning state name; LHS of rule; the label to be applied to the arrow; the ending state name; the RHS of the rule.
%    \begin{macrocode}
\newcommand{\cpsystems@basecprule}[6]{
\trim@spaces@noexp{#1 & #2 & \rightarrow_{#3} & #4 & #5 & #6\\}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\cpsystems@functorparens}
% To ensure that brackets resize themselves automatically in functors.
%    \begin{macrocode}
\newcommand{\cpsystems@functorparens}[1]{
\perfectunary{IncreaseHeight}(){#1}
}
%    \end{macrocode}
% \end{macro}
%
% \iffalse
%</package>
% \fi
%
% \Finale
%


In case versions matter, I am using MikTex to run this, and it seems to be reporting its version as 20.6.29. AmsMath is version 2.17e. The 'tools' package doesn't have a listed version in the MikTex console but is dated with 'Tue Feb 4 10:11:41 2020'.

Can you see what the problem is? I imagine it is probably some trivial issue of a misplaced character or something, but I have been unable to figure this out. (I'm also open to suggestions on other aspects of the package if someone is keen enough :) )

EDIT: I began to wonder if the perfectcut package actually had anything to do with this problem, and I'm not sure that it does in actuality. To test this, I removed the \RequirePackage{perfectcut} line and modified the definition of cpsystems@cpfunctorparens to simply (#1). I still get the exact same error. Leaving perfectcut in, but changing the cpruleset block to just:

\begin{cpruleset}
\cpfunc{a}{\cpfunc{b}{\cpfunc{c}{d}}}
\end{cpruleset}


gives me exactly the expected behaviour. That said, I did also try to exclude the requirepackage line for perfectcut, but continue using perfectunary to define cpfunc, and didn't seem to experience any errors with it, so I'm not 100% sure I was doing everything correctly. Does anybody have any suggestions on what I should do to test this further to determine the problem precisely?

I came back to this today, and I seem to have found the problem. It was, in fact, two-fold. Firstly, I wasn't using the perfectunary environment correctly. For some daft reason, I wasn't using including all necessary curly braces. I.e. the definition was

\newcommand{\cpsystems@functorparens}[1]{
\perfectunary{IncreaseHeight}(){#1}
}


but should have been

\newcommand{\cpsystems@functorparens}[1]{
\perfectunary{IncreaseHeight}{(}{)}{#1}
}


Secondly, it appears that the perfectcut macros (or, at least, perfectunary) don't play nicely with linebreaks inside itself. In a couple of places in the documentation inside the .dtx file for the package, I had linebreaks inside cpfunc macros. The use of perfectunary seems to break these and cause the errors I was seeing. I tried changing them from \\ to \linebreak based on what I read here and here, which helped, but not totally. The errors stopped complaining about misplaced \crs but swapped to complaining about misplaced &s. Removing the &s got rid of the errors, but now there doesn't seem to be any sort of line breaking at all going on inside either cpfunc or cprule` macros. Currently, that is a lower priority for me than auto-growing brackets, so it is a trade-off I have made for now. Hopefully, I will stumble across a way to get that back.

You can find the results of all this at the GitHub repo under release v0.15 if you are interested.