You say there are three possibilities for the value which a parameter can have.
Parameters and ⟨parameter text⟩ of a macro definition are means for denoting how at the time of expanding the macro in question macro arguments are to be gathered from the token stream and processed.
Macro arguments in turn are combinations of tokens.
The term "value" is sort of ambiguous:
Do you mean that there are exactly three different combinations of
tokens that could be gathered as macro-argument?
Or does expansion/evaluation as a TeX-⟨number⟩ play a rôle, also?
Do two arguments have the same "value" also in case they do not consist of the same combination of tokens but of different combinations of tokens with an equal amount of tokens and for every possible k the k-th tokens having the same \meaning
, i.e., something like:
\let\One=1
\let\Two=2
argument 1: 1\Two
argument 2: \One2
In case it is just about different combinations of tokens, and expansion/evaluation and equality of meanings of different tokens do not play a rôle, and none of the possible combinations contains special tokens like curly braces or hashes (explicit character tokens of category code 1 or 2 or 6), forking can be implemented by means of delimited arguments where parts of the argument-delimiters are formed by the combinations of tokens that are possible. No curly braces and no hashes because these kinds of tokens cannot be components of delimiters of delimited arguments.
\documentclass{article}
\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
{\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%% If e-TeX-extensions are available, you can do:
%\newcommand\UD@CheckWhetherNull[1]{%
% \romannumeral0\if\relax\detokenize{#1}\relax
% \@firstoftwo{\expandafter\expandafter\expandafter}{} \expandafter\@firstoftwo
% \else
% \@firstoftwo{\expandafter\expandafter\expandafter}{} \expandafter\@secondoftwo
% \fi
%}%
%%-----------------------------------------------------------------------------
%% Check whether argument contains ! not nested in braces:
%%.............................................................................
\@ifdefinable\UD@gobbletoExclam{\long\def\UD@gobbletoExclam#1!{}}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoExclam#1!}%
}%
\newcommand\Test[3]{%
\UD@CheckWhetherNoExclam{#1}{%
\ForkParameterOne!#1!1!{Argument 1 est vide.}%
!!#1!{Argument 1 est \'egal à 1.}%
!!1!{Argument 1 n'est pas vide, n'est pas egal à 1, et est sans ``!''.}%
!!!!%
}{Argument 1 n'est pas vide, n'est pas egal à 1, et est avec ``!''.} %
\UD@CheckWhetherNoExclam{#2}{%
\ForkParameterTwo!#2!v!h!{Argument 2 est vide.}%
!!#2!h!{Argument 2 est \'egal à v.}%
!!v!#2!{Argument 2 est \'egal à h.}%
!!v!h!{Argument 2 n'est pas vide, ni est egal à v, ni est egal à h, et est sans ``!''.}%
!!!!%
}{Argument 2 n'est pas vide, ni est egal à v, ni est egal à h, et est avec ``!''.} %
\UD@CheckWhetherNoExclam{#3}{%
\ForkParameterThree!#3!{Argument 3 est vide.}%
!!{Argument 3 n'est pas vide et est sans ``!''.}%
!!!!%
}{Argument 3 n'est pas vide et est avec ``!''.}%
}%
\@ifdefinable\ForkParameterOne{%
\long\def\ForkParameterOne#1!!1!#2#3!!!!{#2}%
}%
\@ifdefinable\ForkParameterTwo{%
\long\def\ForkParameterTwo#1!!v!h!#2#3!!!!{#2}%
}%
\@ifdefinable\ForkParameterThree{%
\long\def\ForkParameterThree#1!!#2#3!!!!{#2}%
}%
\makeatother
\parindent=0ex
\parskip=\bigskipamount
\begin{document}
\verb|\Test{1}{v}{}| $\to$\\ \Test{1}{v}{}
\verb|\Test{1}{h}{}| $\to$\\ \Test{1}{h}{}
\verb|\Test{}{}{}| $\to$\\ \Test{}{}{}
\verb|\Test{X}{Y}{Z}| $\to$\\ \Test{X}{Y}{Z}
\verb|\Test{!}{!}{!}| $\to$\\ \Test{!}{!}{!}
\verb|\Test{1a}{vb}{}| $\to$\\ \Test{1a}{vb}{}
\end{document}

If you need the result of the evaluation as a token-sequence, e.g., within expansion-contexts, you can add a bit of exchanging arguments and \romannumeral0
-expansion:
\documentclass{article}
\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
{\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%% If e-TeX-extensions are available, you can do:
%\newcommand\UD@CheckWhetherNull[1]{%
% \romannumeral0\ifx\relax\detokenize{#1}\relax
% \@firstoftwo{\expandafter\expandafter\expandafter}{} \expandafter\@firstoftwo
% \else
% \@firstoftwo{\expandafter\expandafter\expandafter}{} \expandafter\@secondoftwo
% \fi
%}%
%%-----------------------------------------------------------------------------
%% Exchanging two arguments:
%%.............................................................................
\newcommand\UD@Exchange[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% Check whether argument contains ! not nested in braces:
%%.............................................................................
\@ifdefinable\UD@gobbletoExclam{\long\def\UD@gobbletoExclam#1!{}}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoExclam#1!}%
}%
%%-----------------------------------------------------------------------------
%% \Test. The result is delivered after two expansion-steps/after two "hits"
%% with \expandafter.
%%.............................................................................
\newcommand\Test[3]{%
\romannumeral0%
\expandafter\UD@Exchange\expandafter{%
\romannumeral0%
\UD@CheckWhetherNoExclam{#3}{%
\ForkParameterThree!#3!{ Argument 3 est vide.}%
!!{ Argument 3 n'est pas vide et est sans ``!''.}%
!!!!%
}{ Argument 3 n'est pas vide et est avec ``!''.} %
}{%
\expandafter\UD@Exchange\expandafter{%
\romannumeral0%
\UD@CheckWhetherNoExclam{#2}{%
\ForkParameterTwo!#2!v!h!{ Argument 2 est vide.}%
!!#2!h!{ Argument 2 est \'egal à v.}%
!!v!#2!{ Argument 2 est \'egal à h.}%
!!v!h!{ Argument 2 n'est pas vide, ni est egal à v, ni est egal à h, et est sans ``!''.}%
!!!!%
}{ Argument 2 n'est pas vide, ni est egal à v, ni est egal à h, et est avec ``!''.} %
}{%
\expandafter\UD@Exchange\expandafter{%
\romannumeral0%
\UD@CheckWhetherNoExclam{#1}{%
\ForkParameterOne!#1!1!{ Argument 1 est vide.}%
!!#1!{ Argument 1 est \'egal à 1.}%
!!1!{ Argument 1 n'est pas vide, n'est pas egal à 1, et est sans ``!''.}%
!!!!%
}{ Argument 1 n'est pas vide, n'est pas egal à 1, et est avec ``!''.} %
}{ }%
}%
}%
}%
\@ifdefinable\ForkParameterOne{%
\long\def\ForkParameterOne#1!!1!#2#3!!!!{#2}%
}%
\@ifdefinable\ForkParameterTwo{%
\long\def\ForkParameterTwo#1!!v!h!#2#3!!!!{#2}%
}%
\@ifdefinable\ForkParameterThree{%
\long\def\ForkParameterThree#1!!#2#3!!!!{#2}%
}%
\makeatother
\parindent=0ex
\parskip=0ex
\topsep=0ex
\partopsep=0ex
\begin{document}
% adjust gap between top-margin and 1st line of text
\hbox{}%
\kern-\headheight
\kern-\headsep
\kern-1in
\kern-\topmargin
\kern-\baselineskip
\kern-\topskip
\kern\ht\strutbox
\kern.5cm
\enlargethispage{.5cm}%
%--------------------------
\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{1}{v}{}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{1}{v}{}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%
\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null
\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{1}{h}{}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{1}{h}{}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%
\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null
\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{}{}{}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{}{}{}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%
\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null
\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{X}{Y}{Z}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{X}{Y}{Z}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%
\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null
\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{!}{!}{!}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{!}{!}{!}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%
\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null
\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{1a}{vb}{}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
\Test{1a}{vb}{}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%
\end{document}

\ifblank
or\ifstrempty
inetoolbox
?ifthen
-package and use it like:\ifthenelse{\equal{#1}{}}{it's empty}{it's not empty}