# splits a string into parts with nested structures
# ie ( () () (( ) ())) ()  ( ())  is split into its main groups '( () () (( ) ()))','()','( ())'
  function(string_nested_split code open close)
    string(LENGTH "${code}" len)
    math(EXPR len "${len} -1")
    set(openings 0)
    set(last_index 0)
    set(result)
    foreach(i RANGE 0 ${len})
      string_char_at( "${i}" "${code}")
      ans(c)
      #message("char ${i}: ${c}")
      if("${c}_" STREQUAL "${open}_")
        if("${openings}" EQUAL 0)
          math(EXPR start "${last_index}")
          math(EXPR end "${i}")
          string_slice("${code}" "${start}" "${end}")
          ans(part)
       #   message("part ${part} ${start} ${end}")
          list(APPEND result "${part}")
          math(EXPR last_index "${i}+1")
        endif()
        math(EXPR openings "${openings} + 1")
      elseif("${c}_" STREQUAL "${close}_")
        math(EXPR openings "${openings} -1")
        if("${openings}" EQUAL 0)
          math(EXPR start "${last_index}")
          math(EXPR end "${i}")
          string_slice("${code}" "${start}" "${end}")
          ans(part)
        #  message("part ${part} ${start} ${end}")
          list(APPEND result "${open}${part}${close}")
          math(EXPR last_index "${i}+1")
        endif()
      endif()
    #  message("openings ${openings}")

    endforeach()
    string_slice("${code}" "${last_index}" -1)
    ans(last_part)
    string_isempty("${last_part}")
    ans(isempty)
    if(NOT isempty)
      list(APPEND result "${last_part}")
    endif()
    #message("asd ${result}")
    return_ref(result)

  endfunction()