C string parser criticism
Major remark of the code as whole: for some reason you write the unreadable version of array access *(arr+i) all over the place. Don't do that! This makes your code look needlessly obscure and hard to read. Instead use the much more readable arr[i].

Your compare is just a naive implementation of strchr. It would be much more efficient to use strchr.

Don't write while loops when you can write for loops, the latter is easier to read and often optimizes better too.

There is no point in const qualifying parameters passed by value - it only confuses the caller. Though this is a bit subjective and coding style.

The &quot;correct naive&quot; implementation of strchr would rather look like this:
  static const char* compare (char value, const char *parse)
  {
    for(size_t i=0; parse[i] != '\0'; i++)
    {
      if(parse[i] == value)
      {
        return &amp;parse[i];
      }
    }
    return NULL;
  }


Since you don't use the above version but just return 1 or 0, you end up calling compare over and over on the same data, which is inefficient. If you had a version returning a pointer or index, you could continue searching from that location at next iteration, instead of starting over.

You can get rid of the &quot;on error goto&quot; pattern and leave all clean-up to a wrapper function. It's a bit more readable and you don't have to suffer the old &quot;goto considered harmful&quot; debate yet again:
  size_t parse_string (/* params */)  // wrapper function
  {
    // declare all resources potentially needing clean-up here:
    char **temp_matrix = NULL;  
    ...

    bool ok;
    ok = actual_function (/* params */); // the algorithm, private static inline

    if(!ok)
    {
      if(temp_matrix != NULL)  // the clean-up code from your FAIL0 label here
      ...
    }
  }

Upon failure, &quot;actual_function&quot; just return false; and then the wrapper function can worry about clean-up.
(For more intricate scenarios like some opaque struct allocated by your lib, you can move the whole clean-up code into yet another public &quot;destructor&quot; function.)

Generally, more than 2 levels of indirection is bad practice, but your scenario here is one of the very few cases where three *** is actually motivated. However, char *** const means that the outer-most pointer is const-qualified, which is just weird. The caller doesn't care if you change that local variable internally or not, it just serves to confuse the user. Again, just drop const of parameters passed by value. In this case the char*** passed by value.

Don't name your variables with identifiers used by C++ keywords, functions, libraries etc. Like string. Even if you never intend to use the code with C++, many IDE use same code formatting and color coding for C and C++, like this site for example.