Refinement of list manipulation question

This code simply splits at the symbols and the integers, and joins the relevant parts.

splitAt[list_,pat_]:=Module[{pos=Flatten@Position[list,pat]},MapThread[list[[#1;;#2]]&,{pos,Append[Rest@pos-1,-1]}]];
Flatten[Function[u,Prepend[#,First@u]&/@splitAt[u,_Integer]]/@splitAt[testList,_?(#==Abc||#==Def&)],1]
(*{{Abc, 2, f, g}, {Abc, 1, h}, {Def, 2, j, k}, {Def, 1, w, z, y}}*)

list = {Abc, d, e, 2, f, g, 1, h, Def, q, 2, j, k, 1, w, z, y};

Here's something more readable:

Join @@ SequenceCases[
  list
, { head : Abc | Def
  , Except[_Integer] ...
  , rest : Except[Abc | Def] ..
  } :> Flatten /@ Thread[{head, Split[{rest}, Not@IntegerQ[#2] &]}]
]

Consider the following approach, which is going to sequentially build the output, by treating the entries in the input list in an appropriate way, depending on their position relative to flag Def.

(Please note that if you are interested in the code of this answer you can skip all the commenting and go straight to the end of this answer.)

First, we need to obtain the positions of the flag Def and the integers in the input list, respectively.

{{fpos}} = Position[list, Def]
ipos = Position[list, _Integer]

Evaluating the code above with our testList as input returns

{{9}}
{{4}, {7}, {11}, {14}}

(please note that fpos evaluates to 9, not {{9}}).

Next, we are going to create two sub-lists of indexes, namely a sub-list with the indexes of integer entries in the input list that are located before the flag (in this list, we will include the position of the Def flag, too) and a sub-list of indexes of integer entries in the input list that are located after the flag.

pos1 = Cases[ipos, {n_} :> n /; n < fpos]
If[fpos - 1 > Last[pos1], pos1 = Flatten[{pos1, fpos}]]

pos2 = Cases[ipos, {n_} :> n /; n > fpos]

Evaluating this, yields

{4, 7}
{4, 7, 9}
{11, 14}

(The second line in the code segment above, is used to identify the case where there are intervening symbols between the last integer before the Def flag and he flag itself-as is the case with the testList input list).

The following step, entails assembling the core of the output list out of the index lists pos1 and pos2.

res11 = Apply[Take[list, Flatten[{##} + {0, -1}]] &, Partition[pos1, 2, 1], 1]

res21 = Apply[Take[list, Flatten[{##} + {0, -1}]] &, Partition[pos2, 2, 1], 1]
res22 = Drop[list, Last[pos2 - 1]]

Both res11 and res21 compose the core of the output sub-lists as does res22, which is introduced to tackle the last admissible integer entry in the input list; Partition[<positions>,2,1] supplies the input for Takeing the appropriate parts of the input list.

Evaluating the code, produces

{{2, f, g}, {1, h}}

{{2, j, k}}
{1, w, z, y}

Essentially, the transformation of input to output is complete; the only thing left is to format the output sub-lists appropriately, namely to insert the Abc and Def markers as intended.

res1 = Apply[{Abc, ##} &, Flatten[{res11}, 1], 1]
res2 = Apply[{Def, ##} &, Flatten[{res21, {res22}}, 1], 1]

Flatten[{res1, res2}, 1]

Evaluation of this last segment of code returns

{{Abc, 2, f, g}, {Abc, 1, h}}

{{Def, 2, j, k}, {Def, 1, w, z, y}}

and, what is effectively the requested output

{{Abc, 2, f, g}, {Abc, 1, h}, {Def, 2, j, k}, {Def, 1, w, z, y}}

Having said that-on a personal note-I have come to realize that when I need to resort to similar sequential treatment of output, it is highly likely that I could have reorganized my code in a different way, to begin with. It might not be the case here (obviously, I don't know) but I'm pretty sure that, at some level and to a certain extent, Mathematica / Wolfram Language can produce structured output with a lot less trouble.


All the code bundled in a Module:

f[list_] := Module[{fpos, ipos, pos1, pos2, res11, res21, res22, res1, res2},

  {{fpos}} = Position[list, Def];
  ipos = Position[list, _Integer];

  pos1 = Cases[ipos, {n_} :> n /; n < fpos]; 
  If[fpos - 1 > Last[pos1], pos1 = Flatten[{pos1, fpos}]];

  pos2 = Cases[ipos, {n_} :> n /; n > fpos];


  res11 = Apply[Take[list, Flatten[{##} + {0, -1}]] &, Partition[pos1, 2, 1],1];

  res21 = Apply[Take[list, Flatten[{##} + {0, -1}]] &, Partition[pos2, 2, 1],1]; 
  res22 = Drop[list, Last[pos2 - 1]];

  res1 = Apply[{Abc, ##} &, Flatten[{res11}, 1], 1];
  res2 = Apply[{Def, ##} &, Flatten[{res21, {res22}}, 1], 1];

  Flatten[{res1, res2}, 1]

]

and evaluating

f[testList] == desiredList

should return True.