# Syntax issue with optional argument inside optional argument

The following source gives the expected results, as shown:

\documentclass[12pt]{article}

\usepackage{amsmath}
\usepackage{xstring}

\usepackage[refpage,nocfg]{nomencl}
\renewcommand*{\pagedeclaration}[1]{\unskip, #1}

\newcommand{\nom}[4][]{%
\IfStrEqCase{#1}{%
{logic}{\nomenclature[a#4]{#2}{#3}}%
{set}{\nomenclature[e#4]{#2}{#3}}%
}%
%[\nomenclature[z#4]{#2}{#3}]%
}

\makenomenclature

\begin{document}

\nom[logic]{$p\implies q$}{if $p$ then $q$}{1}
\nom[set]{$x \in A$}{$x$ is an element of $A$}{1}

\printnomenclature[0.75in]

\end{document}


But if the comment sign is removed from the beginning of the line

%[\nomenclature[z#4]{#2}{#3}]%


then I'm getting strange results for output—extra insertions in body of the document output:

What's wrong with my syntax? I thought that

[\nomenclature[z#4]{#2}{#3}]


would constitute the "other-cases code" for the entire \IfStrEqCase construction.

Note: This is an extract. In the actual document, I have several nomenclature "groups" defined by means of \nomgroup, each group with its own header. The optional (1st) argument of the command \nom will indicate the group to which that \nomenclature item belongs.

[\nomenclature[z#4]{#2}{#3}]


has a ] inside (after #4), so that finishes the argument, and the rest is just text that is inserted in the document.

Solution: enclose it in braces:

 [{\nomenclature[z #4]{#2}{#3}}]%


You cannot nest optional arguments (that come in catcode-12-brackets) like mandatory arguments (that come in catcode-1-opening braces and catcode-2-closing-braces).

Optional arguments are handled as delimited arguments with opening brackets and closing brackets as argument-delimiters.
When nesting optional arguments, (La)TeX' delimited argument-mechanism doesn't "know" how to match opening and closing brackets correctly.

If you wish to nest optional arguments within optional arguments, make sure to wrap the content of entire optional arguments into an additional pair of braces. When optional arguments are wrapped into a pair of braces, these braces get silently removed by LaTeX before further processing these optional arguments. So these braces are not harmful.

E.g.,

\documentclass[12pt]{article}

\newcommand\Foo[2][Optional]{%
This is Foo' s optional:\parbox[t]{.6\textwidth}{(\\#1\\)}\\%
This is Foo's mandatory:\parbox[t]{.6\textwidth}{(\\#2\\)}%
}

\newcommand\Bar[2][Optional]{%
This is Bar's optional:(#1)\\%
This is Bar's mandatory:(#2)%
}

\begin{document}

\noindent
% This works because \Foo's optional argument is nested into an
\Foo[{\Bar[BarOptional]{BarMandatory}}]{FooMandatory}

% This does not work as (La)TeX' delimited argument-mechanism doesn't
% "know" how to match opening and closing brackets correctly:
% \Foo[\Bar[BarOptional]{BarMandatory}]{FooMandatory}

\end{document}


Only after having obtained this knowledge, it is obvious that

\newcommand{\nom}[4][]{%
\IfStrEqCase{#1}{%
{logic}{\nomenclature[a#4]{#2}{#3}}%
{set}{\nomenclature[e#4]{#2}{#3}}%
}%
[\nomenclature[z#4]{#2}{#3}]%
}


should be changed to:

\newcommand{\nom}[4][]{%
\IfStrEqCase{#1}{%
{logic}{\nomenclature[a#4]{#2}{#3}}%
{set}{\nomenclature[e#4]{#2}{#3}}%
}%
[{\nomenclature[z#4]{#2}{#3}}]%
}


Your entire example becomes something like:

\documentclass[12pt]{article}

%\IfFileExists{\jobname.nlo}%
%             {\immediate\write18{makeindex \jobname.nlo -s nomencl.ist -o \jobname.nls}}%
%             {}

\usepackage{amsmath}
\usepackage{xstring}

\usepackage[refpage,nocfg]{nomencl}
\renewcommand*{\pagedeclaration}[1]{\unskip, #1}

\newcommand{\nom}[4][]{%
\IfStrEqCase{#1}{%
{logic}{\nomenclature[a#4]{#2}{#3}}%
{set}{\nomenclature[e#4]{#2}{#3}}%
}%
[{\nomenclature[z#4]{#2}{#3}}]%
}

\makenomenclature

\begin{document}

Some text for ensuring that \LaTeX' output-routine comes into action.\\
Otherwise .nlo-files do not get generated.

\nom[logic]{$p\implies q$}{if $p$ then $q$}{1}
\nom[set]{$x \in A$}{$x$ is an element of $A$}{1}
\nom{$x =y$}{$x$ and $y$ are different designators for the same item of cognizance}{1}

\printnomenclature%[0.75in]

\end{document}