Hi,
I am trying to implement the algorithm outlined at https://tools.ietf.org/html/rfc3986#section-5.2.4
(Two other implementations are at [1] and [2])
The following function is my work in progress. It seems, all goes fine, till the last `else`, which is commented with `(: E :)`. I hit the tail recursion barrier and I do not see why.
The function may not (yet) make sense, since I am still experimenting.
`local:remove-dot-segments("/a/b/c/./../../g",[])`
``` (:~ Remove dot segments from a URI path component according to RFC 3986 Section 5.2.4 @param $path the path component of an URL @param $out an empty (!) array @return the path component with the relative part (dot segments) removed and resolved to the absolute path. @see https://tools.ietf.org/html/rfc3986#section-5.2.4 :) declare function local:remove-dot-segments( $path as xs:string, $out as array(*)) as item()* { concat("in: ", $path, " out: ", string-join(array:flatten($out))), if (not(contains($path, "."))) then $path else if (string-length($path) > 0) then (: A :) if (substring($path,1,3) = "../") then local:remove-dot-segments(substring($path, 4), $out) else if (substring($path, 1, 2) = "./") then local:remove-dot-segments(substring($path, 3), $out) else (: B :) if (substring($path,1,3) = "/./") then local:remove-dot-segments(concat("/", substring($path, 4)), $out) else if (substring($path, 1, 2) = "/.") then local:remove-dot-segments(concat("/", substring($path, 3)), $out) else (: C :) if (substring($path, 1, 4) = "/../") then let $ret := array:remove($out, array:size($out)) return local:remove-dot-segments(concat("/", substring($path, 5)), $ret) else if (substring($path, 1, 3) = "/..") then let $ret := array:remove($out, array:size($out)) return local:remove-dot-segments(concat("/", substring($path, 4)), $ret) else (: D :) if ($path = ".." or $path = ".") then local:remove-dot-segments(concat(substring((), 4), ""), $out) else (: E :) let $ret := if (starts-with($path, "/")) then array:append($out, concat("/", substring-before(substring($path,2), "/"))) else array:append($out, substring-before(substring($path,1), "/")) return local:remove-dot-segments($path, $ret) else $path };
```
Sorry for throwing such a big function at you, but I do not find the place, where the stack overflow gets triggered. It does not happen, if I return an empty sequence at `else (: E :)`. If I replace that part (after `else (: E :)`) with `local:remove-dot-segments($path, $out)` I get the stack overflow as well, which is, what confuses me the most.
[1]https://github.com/ariutta/remove-dot-segments/blob/master/index.js [2] https://gist.github.com/rdlowrey/5f56cc540099de9d5006