I would probably use instrrev...since it counts from the end of the line...so it would be easier...I think.
my formula would be something like:
local stringvar temp := {table.field};
shared stringvar zip;
shared stringvar state;
shared stringvar city;
local numbervar index;
index := instrrev(temp, " ");
zip = mid(temp, index +1);
temp := left(temp, index -1);
index := instrrev(temp, " ");
state: = mid(temp, index + 1);
city := left(temp, index - 1);
depending on puntuation, you might want to do a replace for the comma and or trim to remove white space.
basically it is looking for th first space from the end of the string, which is the zip, then it trims off from before the space. then repeats for the state, and whatever is left is the city, this way you don't have to worry about cities with 1 or more spaces in them.
HTH