Here's a rough draft for a solution. I believe this can be cleaned up a bit, but here's what I've come up with so far:
\documentclass{article}
\usepackage{forarray}
\makeatletter
\def\@demo@query{\relax}%%
\newcounter{@demo@level@cnt}
\newcommand{\demo}[1]{\@demo#1\@demo@query\@nil\@demo@follow@up}
\def\@demo#1\@nil{%%
\stepcounter{@demo@level@cnt}%%
\begin{itemize}
\ForEach{.}{\item \thislevelitem}{#1}%%
}
\def\@demo@follow@up{%%
\@ifnextchar\@demo@query
{\@demo@close}
{\@demo@continue}}
\def\@demo@continue{%%
\@demo@close
\ifnum\the@demo@level@cnt>0 %%
\item
\fi
}
\def\@demo@close{%%
\end{itemize}%%
\addtocounter{@demo@level@cnt}{-1}%%
}
\makeatother
\begin{document}
\demo
{
1.
\demo
{
21.
22
}
3.4
}
\rule{\textwidth}{0.4pt}
\demo
{
1.
\demo
{
21.
22
}}
\rule{\textwidth}{0.4pt}
\demo
{
1.
\demo
{
21.
22
}
}
\end{document}
The key is creating some wrapper code to get around the wrapper code introduced by forarray
. Hence
\@demo#1\@demo@query\@nil\@demo@follow@up
The last command
\@demo@follow@up
will be followed by
\@demo@query
only if there is no further code to examine.
To assist in seeing what's happening
consider the following moot code:
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\makeatletter
\newcommand\demo[1]{\@demo#1?\@nil!}
\def\@demo#1\@nil{[\another{#1}]}
\def\another#1{<<#1>>}
\makeatother
\begin{document}
\ttfamily
\demo{1.\demo{21.22}3.4}\par
\demo{1.\demo{21.22}}
\end{document}
The macro \another
wraps its arguments with <<
and >>
in a manner similar to what forarray
s macros do. The question mark plays the role of \@demo@query
and the exclamation point that of \@demo@follow@up
. As in the real solution above, !
only precedes ?
when there is no continuation code for \ForEach
to consider.

.
before the3
, how is it that you're going to distinguish between a continuation of a paragraph after a list and a new list entry for the outer list?\demo
macro throw out an\item
. But, this approach has its own problems such as with\demo{1. \demo{21. 22}}
where you wouldn't want an spurious\item
showing up.forarray
package; so, I don't know whether the macros it provides are expandable or not. If expandability is not an issue, you could use\@ifnextchar
to test the next character to see whether or not to toss out an extra\item
. If no one has posted their own solution to this later tonight, then I'll write up something that might work for you, but it won't be for several more hours.\newcommand\demo[1]{\@demo#1\@something}
And then you can later use\futurelet
to grab the token after the next and then run a test on whether you have two adjacent\@something
. Now, if\@something
is not defined as a macro, then that will just result in an error. Nevertheless, that's the main thrust of the idea for this naive approach.