g | x | w | all
Bytes Lang Time Link
169Python3250819T190651ZAjax1234
131Retina 0.8.2211001T161139ZNeil
059K ngn/k210915T093807Zchrispsn
04605AB1E210914T093940ZKevin Cr
032Stax210914T035747ZRazetime
092JavaScript Node.js210914T021845Ztsh
033Jelly210915T001941ZJonathan
183Scala210914T231435Zuser
126Python 3.8 prerelease210914T032109Zgsitcia

Python3, 169 bytes

import re
def f(s):
 a,*b=[i.split(';')for i in re.findall('[\d;]+',s)]
 for i in b:a=[j if j.isdigit()else(i.pop(0)if i else'')for j in a]+i
 return f"f[{';'.join(a)}]"

Try it online!

Retina 0.8.2, 131 bytes

(f.(\d;)*(;(\d;)*)*)(;[^]]*].(?<-3>;)*(?(3)^))(\d);?
$1$6$5
}`\[\]

}`(f(.(\d|((?=;)))(?=[];]))*);?(].(?<-4>;)*)([^]]+)?
$1$#6$*;$6

Try it online! Explanation: Uses .NET balancing groups to shuffle arguments into slots. The first two lines shuffle arguments from the second application into free slots in the first. The middle two lines delete an empty application resulting from the first two lines. The last two lines append trailing arguments or slots from the second application to the first, however the test assumes that there are no arguments left to shuffle or empty applications, which is why an extra loop is needed.

K (ngn/k), 65 59 bytes

{"f[",|x,|y/{.![a*+\a:~#'x;x],(1+!#y)!y}/y\'-1_'1_z\}."];["

Thanks to ngn for cutting 4 bytes here and here.

Try it online!

K (k9 2021.09.01), 54 bytes

{"f[",|x,|y/{!?(?x*+\x!:~#'x),?+\y!1}/y\'1_z\x_}."];["

05AB1E, 46 bytes

¦¤¡¨ε¦';¡}Å»U0ìD_OXg-(©di®Å0«}0X.;}θ';ý0K"f[ÿ]

05AB1E is not the right language for this challenge.. :/

Try it online or verify all test cases.

Explanation:

Step 1: Transform the input to something more usable: Try it online.

¦                  # Remove the leading "f" from the (implicit) input-string
 ¤                 # Get its last character "]" (without popping)
  ¡                # Split it on this "]"
   ¨               # Remove the trailing empty item
    ε              # Map over each inner string
     ¦             #  Remove the leading character (the "[")
      ';¡         '#  Split it on ";"
    }              # Close the map

We now have a list of lists of digits and empty strings.

Step 2: Reduce this list of lists according to the challenge: Try it online.

Å»                 # Cumulative left-reduce (which unfortunately keeps track of steps):
  U                #  Pop and store the current list in variable `X`
   0ì              #  Prepend a 0 before each item in the result-string
                   #  (so all empty strings become 0s)
   D_O             #  Get the amount of 0s in this list (duplicate; ==0; sum)
      Xg           #  Push the length of the current list `X`
        s-         #  Subtract the amount of 0s from this length
          ©        #  Store it in variable `®` (without popping)
           di    } #  Pop, and if this value is >= 0:
             ®Å0   #   Push a list with `®` amount of 0s
                «  #   And append this to the result-list
    0X.;           #  Then replace each zero ("0","00","000",etc.) in this list one by
                   #  one with the values from list `X`
 }θ                # And after the cumulative left-reduce, pop and keep the last list

Step 3: Format this resulting list to a format similar as the input:

';ý               '# Join the list with ";" delimiter
   0K              # Remove all 0s from the string
     "f[ÿ]        "# Push string "f[ÿ]", where `ÿ` is automatically replaced with the
                   # string
                   # (after which the result is output implicitly)

Stax, 37 34 32 bytes

Ñgí⌡²☼☺≈AU▀≤L♠╫$U∩─.ù·○╓╥ò±E♦τèZ

Run and debug it

-2 reducing splitting code

Explanation

2t1T.][/  {';/m{s{c{c{B}z?}?ms+k';*:}'fs+
2t1T.][/                                  get all argument bodies
          {';/m                           split all on semicolons
               {s{c{c{B}z?}?ms+k          reduce by:
                s                          swap with prev
                 {c{c{B}z?}?m              map elements in prev to:
                  c{      }?                if non-empty, leave elem as is
                    c{B}z?                  else remove first element of next and push
                                            (pushes [] if empty)
                             s+           append the rest elements
                                ';*       join with semicolons
                                   :}     put in square brackets
                                     'fs+ prepend 'f'   

Stax, 37 bytes

Ö☺τσj↔₧♂√V{▐9,=☺|╢Δ‼$≥ä₧ÿºÉ/♂y╩▲S╞♫┘{

Run and debug it

uses an assign at index builtin, slightly longer.

JavaScript (Node.js), 92 bytes

v=>v.match(/(?<=[[;])\d*|\[/g).map(g=n=>1/n?o[++i]?g(n):o[i]=n:i=-1,o=[])&&`f[${o.join`;`}]`

Try it online!

-1 byte by Arnauld.

Jelly, 33 bytes

ṣ”[Ṗ€ṣ€”;VṆ€k$ḟ0;ɗ"Ẏɗ/j”;ḟ0Ø[j”f;

A monadic Link that accepts a list of characters and yields a list of characters.

Try it online!

How?

ṣ”[Ṗ€ṣ€”;VṆ€k$ḟ0;ɗ"Ẏɗ/j”;ḟ0Ø[j”f; - Link: list of characters, S
ṣ”[                               - split (S) at '['
   Ṗ€                             - pop (i.e. remove ']' from) each
     ṣ€”;                         - split each at ';'
         V                        - evaluate as Jelly code
                                     -> list of projections with zeros at empty slots
                     /            - reduce by:
                    ɗ             -   last three links as a dyad, f(P, Q):
             $                    -     last two links as a monad, f(P):
          Ṇ€                      -       logical NOT each
            k                     -       partition (P) after truthy indices (of that)
                                            -> P split after each empty slot
                  "               -     zip (across [t in that] and [q in Q]) with:
                 ɗ                -       last three links as a dyad, f(t, q):
               0                  -         zero
              ḟ                   -         (t) filter discard (zeros)
                ;                 -         concatenate (q)
                   Ẏ              -     tighten (to a flat list)
                      j”;         - join with ';'
                         ḟ0       - filter discard zeros
                           Ø[j    - "[]" join (that)
                              ”f; - 'f' concatenate (that)

Scala, 183 bytes

_.drop(2).init split "\\]\\["map(_ split ";")reduce{(p,q)=>val(b,a)=((q,q take 0)/:p){case((q,p),x)=>if(q.size<1|x!="")(q,p:+x)else(q drop 1,p++q.take(1))}
a++b}mkString("f[",";","]")

Try it in Scastie!

A pretty horrible solution, but I'll work on it later. Explanation coming soon.

_                  //The input
 .drop(2)          //Drop the "f["
 .init             //Drop the "]" at the very end
  split "\\]\\["   //Split the projections up
  map(_ split ";") //Split each projection into its parts
  reduce{ (p, q) => //Reduce the projections by this function, which does the real work
   val(b,a)=((q,q take 0)/:p){case((q,p),x)=>if(q.size<1|x!="")(q,p:+x)else(q drop 1,p++q.take(1))}
a++b}mkString("f[",";","]")

Python 3.8 (pre-release), 126 bytes

lambda s,D=[]:f'f[{";".join([D:=[j or next(i,"")for j in D]+[*i]for k in s[2:-1].split("][")if(i:=iter(k.split(";")))]*0+D)}]'

Try it online!

Ungolfed:

def f(s):
  D=[]
  for k in s[2:-1].split(']['):
    i = iter(k.split(';')) # next projection
    D = [j or next(i,'') for j in D] # replace empty slots with arguments from i
    D += [*i] # add the rest of i
  return 'f['+';'.join(D)+']'