Code Review
add tag
निरंजन
The `expex` package provides two macros named `\gla` and `\glb` with which linguists typeset linguistic examples. See the following example.

```
\documentclass{article}
\usepackage{expex}
\usepackage{fontspec}
\newfontfamily\ipafont[%
  StylisticSet={05},%
  Renderer={Harfbuzz}%
]{NewCM10-Regular.otf}
\lingset{everygla={\ipafont}}

\begin{document}
\ex
\begingl
\gla kʰup maɳs-ə ahe-t̪//
\glb many person-\textsc{pl} be.\textsc{prs}-\textsc{pl}//
\glft There are many people.//
\endgl
\xe
\end{document}
```

I am yet to figure out how the `expex` package actually typesets these words in a tabular-like format and what is the optimal way of doing it in modern ways, but that's a different question-post altogether. I wanted to develop a functionality with which I can count the number of dashes and equals in `\gla` and `\glb`. It always has to be equal and not just equal in the total number, but the number of individual signs should also be equal. We often commit mistakes and give mismatching signs in `\gla` and `\glb` while writing which is a serious problem, hence I wanted to develop an error mechanism for this and came up with some code. It needs to be reviewed. The following are the logical possibilities I could think of with which my mechanism has to deal.

```
\documentclass{article}
\usepackage{linguistix}

\begin{document}
\section{Equal number cases}

\pex
\a\begingl
\gla abcd-efgh=ijkl=mnop//
\glb abcd-efgh=ijkl=mnop//
\glft abcd//
\endgl
\xe

\pex
\a\begingl
\gla abcd-efgh=ijkl=mnop//
\glb abcd=efgh=ijkl=mnop//
\glft abcd//
\endgl
\xe

\pex
\a\begingl
\gla abcd-efgh=ijkl=mnop//
\glb abcd-efgh-ijkl=mnop//
\glft abcd//
\endgl
\xe

\section{Unequal number cases}

\pex
\a\begingl
\gla abcd-efgh=ijkl=mnop//
\glb abcd-efgh=ijklmnop//
\glft abcd//
\endgl
\xe

\pex
\a\begingl
\gla abcd-efgh=ijkl=mnop//
\glb abcd-efgh=ijkl=mnop=//
\glft abcd//
\endgl
\xe

\pex
\a\begingl
\gla abcd-efgh=ijkl=mnop//
\glb abcdefgh=ijkl=mnop//
\glft abcd//
\endgl
\xe

\pex
\a\begingl
\gla abcd-efgh=ijkl=mnop//
\glb abcd-efgh-ijkl=mnop=//
\glft abcd//
\endgl
\xe

\pex
\a\begingl
\gla abcd-efgh=ijkl=mnop//
\glb abcd-efgh=ijkl-mnop-//
\glft abcd//
\endgl
\xe
\end{document}
```

and the following is the code for giving errors.

```
\ExplSyntaxOn
\int_new:N \l__lng_tmpa_int
\NewDocumentCommand { \lng@count } { s m m o }{
  \IfBooleanTF {#1}
  { \lng_count:nVn {#2}  #3  {#4} }
  { \lng_count:nnn {#2} {#3} {#4} }
}
\cs_new_protected:Nn \lng_count:nnn {
  \regex_count:nnN {#1} {#2} \l__lng_tmpa_int
  \IfValueTF {#3}
  { \int_set_eq:NN #3 \l__lng_tmpa_int }
  { \int_to_arabic:n { \l__lng_tmpa_int } }
}
\cs_generate_variant:Nn \lng_count:nn { nV }
\ExplSyntaxOff
\newcount\lng@gla@dashes
\newcount\lng@gla@equals
\newcount\lng@glb@dashes
\newcount\lng@glb@equals
\newcount\lng@gla@dsneqs
\newcount\lng@glb@dsneqs
\newcount\lng@cnt@checks
\newif\iflng@glpreamble@used
\lng@glpreamble@usedfalse
\newif\iflng@nlevel
\providecommand{\@thirdofthree}[3]{3}
\NewDocumentCommand{ \begingl }{ O{glstyle=wrap} }{%
  \begingroup
  \NewDocumentCommand{ \gla }{ u{//} }{%
    \iflng@glpreamble@used
      \sbox\lng@tmpexbox{%
        \hspace{\lng@numoffset}%
        \lng@exnoformat
        \hspace{\lng@labeloffset}%
        \lng@labelformat
        \hspace{\lng@textoffset}%
      }%
      \settowidth{\w@lng@tmpexbox}{%
        \usebox{\lng@tmpexbox}%
      }%
      \noindent
      \hspace{\w@lng@tmpexbox}%
    \fi
    \lng@count{-}{##1}[\lng@gla@dashes]%
    \lng@count{=}{##1}[\lng@gla@equals]%
    \lng@count{[-=]}{##1}[\lng@gla@dsneqs]%
    ##1%
    \NewDocumentCommand{ \glb }{ u{//} }{%
      \sbox\lng@tmpexbox{%
        \hspace{\lng@numoffset}%
        \lng@exnoformat
        \hspace{\lng@labeloffset}%
        \lng@labelformat
        \hspace{\lng@textoffset}%
      }%
      \settowidth{\w@lng@tmpexbox}{%
        \usebox{\lng@tmpexbox}%
      }%
      \noindent
      \hspace{\w@lng@tmpexbox}%
      ####1%
      \lng@count{-}{####1}[\lng@glb@dashes]%
      \lng@count{=}{####1}[\lng@glb@equals]%
      \lng@count{[-=]}{####1}[\lng@glb@dsneqs]%
      \ifnum\lng@gla@dsneqs=\lng@glb@dsneqs\relax
        \ifnum\lng@gla@dashes>\lng@glb@dashes\relax
          % \gla -==//
          % \gla ===//
          \PackageError{linguistix}%
          {%
            Found less dashes and more equals in the gloss%
            \MessageBreak
            than in the transcription%
          }%
          {%
            Unbalanced number of dashes and/or equals in one
            of your examples. Please%
            \MessageBreak
            correct the code.%
          }%
        \else
          \ifnum\lng@gla@dashes=\lng@glb@dashes\relax
            % \gla -==//
            % \glb -==//
            % The only case where the user have glossed
            % without errors, hence this is silent.
          \else
            % \gla -==//
            % \glb --=//
            \PackageError{linguistix}%
            {%
              Found more dashes and less equals in the gloss%
              \MessageBreak
              than in the transcription%
            }%
            {%
              Unbalanced number of dashes and/or equals in
              one of your examples. Please%
              \MessageBreak
              correct the code.%
            }%
          \fi
        \fi
      \else
        \ifnum\lng@gla@dashes=\lng@glb@dashes\relax
          \ifnum\lng@gla@equals>\lng@glb@equals\relax
            % \gla -==//
            % \glb -=//
            \PackageError{linguistix}%
            {%
              Found less equals in the gloss than in the%
              \MessageBreak
              transcription%
            }%
            {%
              Unbalanced number of dashes and/or equals in
              one of your examples. Please%
              \MessageBreak
              correct the code.%
            }%
          \else
            % \gla -==//
            % \glb -===//
            \PackageError{linguistix}%
            {%
              Found more equals in the gloss than in the%
              \MessageBreak
              transcription%
            }%
            {%
              Unbalanced number of dashes and/or equals in one
              of your examples. Please%
              \MessageBreak
              correct the code.%
            }%
          \fi
        \fi
        \ifnum\lng@gla@equals=\lng@glb@equals\relax
          \ifnum\lng@gla@dashes>\lng@glb@dashes\relax
            % \gla -==//
            % \glb ==//
            \PackageError{linguistix}%
            {%
              Found less dashes in the gloss than in the%
              \MessageBreak
              transcription%
            }{}%
          \else
            % \gla -==//
            % \glb --==//
            \PackageError{linguistix}%
            {%
              Found more dashes in the gloss than in the
              transcription%
            }{}%
          \fi
        \fi
        % Here we have unbalanced number of the total
        % dashes and equals used in \gla and \glb. We have
        % produced errors where one of dashes or equals
        % were equal in number. Now we check if both of
        % them are unequal.
        \ifnum
          \ifnum\lng@gla@dashes=\lng@glb@dashes\@sptoken
            % \gla-dashes=\gla-dashes
            \ifnum\lng@gla@equals=\lng@glb@equals\@sptoken
              % \gla-equals=\glb-equals
              1% Print 1 when true
            \else
              0% Print 0 when false
            \fi
          \else
            0% Print 0 when false
          \fi
          =%
          1\@sptoken
          \expandafter\@firstoftwo
        \else
          \expandafter\@secondoftwo
        \fi
        {}%
        {%
          \ifnum\lng@gla@dashes>\lng@glb@dashes\relax
            % \gla --//
            % \gla -//
            \PackageError{linguistix}%
            {%
              Found less dashes in the gloss than in the
              transcription%
            }{}%
          \else
            % \gla -//
            % \gla --//
            \PackageError{linguistix}%
            {%
              Found more dashes in the gloss than in the
              transcription%
            }{}%
          \fi
          \ifnum\lng@gla@equals>\lng@glb@equals\relax
            % \gla ==//
            % \gla =//
            \PackageError{linguistix}%
            {%
              Found less equals in the gloss than in the
              transcription%
            }{}%
          \else
            % \gla =//
            % \gla ==//
            \PackageError{linguistix}%
            {%
              Found more equals in the gloss than in the
              transcription%
            }{}%
          \fi
        }%
      \fi
      \par
    }%\glc
  \par
  }%
  \NewDocumentCommand{ \glft }{ u{//} }{%
    \vspace{\lng@aboveglftskip}%
    \sbox\lng@tmpexbox{%
      \hspace{\lng@numoffset}%
      \lng@exnoformat
      \hspace{\lng@labeloffset}%
      \lng@labelformat
      \hspace{\lng@textoffset}%
    }%
    \settowidth{\w@lng@tmpexbox}{%
      \usebox{\lng@tmpexbox}%
    }%
    \noindent
    \hspace{\w@lng@tmpexbox}%
    ##1%
  }%
  \NewDocumentCommand{ \endgl }{  }{%
    \endgroup
  }%
}
```

As I have said already, this doesn't produce the exact thing. Not even a near one, but I specifically want to hear comments about the error-mechanism I have tried to implement. Can it be improved? Are there any logical possibilities which I have missed? Are there any results which should be avoided by the mechanism I have built?
Top Answer
Skillmon
I didn't test this, and I certainly have mixed up "gloss" and "transcription", but I'd just do something like the following (I removed some unused `\newcount` and `\newif`, so don't blindly copy this, I have no idea what you need -- also I fixed your `\@thirdofthree` definition here, and dropped the unnecessary box assignment to measure the width):

```
\ExplSyntaxOn
\int_new:N \l__lng_tmpa_int
\NewDocumentCommand { \lng@count } { s m m o }{
  \IfBooleanTF {#1}
  { \lng_count:nVn {#2}  #3  {#4} }
  { \lng_count:nnn {#2} {#3} {#4} }
}
\cs_new_protected:Nn \lng_count:nnn {
  \regex_count:nnN {#1} {#2} \l__lng_tmpa_int
  \IfValueTF {#3}
  { \int_set_eq:NN #3 \l__lng_tmpa_int }
  { \int_to_arabic:n { \l__lng_tmpa_int } }
}
\cs_generate_variant:Nn \lng_count:nn { nV }
\ExplSyntaxOff
\newcount\lng@gla@dashes
\newcount\lng@gla@equals
\newcount\lng@glb@dashes
\newcount\lng@glb@equals
\newif\iflng@glpreamble@used
\lng@glpreamble@usedfalse
\providecommand{\@thirdofthree}[3]{#3}
\NewDocumentCommand{ \begingl }{ O{glstyle=wrap} }{%
  \begingroup
  \NewDocumentCommand{ \gla }{ u{//} }{%
    \iflng@glpreamble@used
      \settowidth{\w@lng@tmpexbox}{%
        \hspace{\lng@numoffset}%
        \lng@exnoformat
        \hspace{\lng@labeloffset}%
        \lng@labelformat
        \hspace{\lng@textoffset}%
      }%
      \noindent
      \hspace{\w@lng@tmpexbox}%
    \fi
    \lng@count{-}{##1}[\lng@gla@dashes]%
    \lng@count{=}{##1}[\lng@gla@equals]%
    ##1%
    \NewDocumentCommand{ \glb }{ u{//} }{%
      \settowidth{\w@lng@tmpexbox}{%
        \hspace{\lng@numoffset}%
        \lng@exnoformat
        \hspace{\lng@labeloffset}%
        \lng@labelformat
        \hspace{\lng@textoffset}%
      }%
      \noindent
      \hspace{\w@lng@tmpexbox}%
      ####1%
      \lng@count{-}{####1}[\lng@glb@dashes]%
      \lng@count{=}{####1}[\lng@glb@equals]%
      \ifnum\lng@gla@dashes>\lng@glb@dashes
        \PackageError{linguistix}
          {More dashes in gloss than in transcription}
          {}%
      \fi
      \ifnum\lng@gla@dashes<\lng@glb@dashes
        \PackageError{linguistix}
          {Fewer dashes in gloss than in transcription}
          {}%
      \fi
      \ifnum\lng@gla@equals>\lng@glb@equals
        \PackageError{linguistix}
          {More equals in gloss than in transcription}
          {}%
      \fi
      \ifnum\lng@gla@equals<\lng@glb@equals
        \PackageError{linguistix}
          {Fewer equals in gloss than in transcription}
          {}%
      \fi
      \par
    }%\glc
  \par
  }%
  \NewDocumentCommand{ \glft }{ u{//} }{%
    \vspace{\lng@aboveglftskip}%
    \settowidth{\w@lng@tmpexbox}{%
      \hspace{\lng@numoffset}%
      \lng@exnoformat
      \hspace{\lng@labeloffset}%
      \lng@labelformat
      \hspace{\lng@textoffset}%
    }%
    \noindent
    \hspace{\w@lng@tmpexbox}%
    ##1%
  }%
  \NewDocumentCommand{ \endgl }{  }{%
    \endgroup
  }%
}
```

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.