77 lines
2.5 KiB
Text
77 lines
2.5 KiB
Text
# nest.ludic - a line bracketed inside another (bytes 29 .. 30 round it: a game's txt_key / txt_line, a
|
|
# key's line in another's hole or glued to words): each bracket made into its text first, outermost in, then
|
|
# the whole. A line wholly inside one bracket is made already, and not looked up again as English;
|
|
# a key whole takes this path only through its arguments, which keyed() has unescaped by then
|
|
export const I18N_OPEN: int = 29
|
|
export const I18N_CLOSE: int = 30
|
|
|
|
export function kx_nested(s: string) -> bool {
|
|
let p: string = s
|
|
for i in 0 .. len(p) { if p[i] == I18N_OPEN or p[i] == I18N_CLOSE { return true } }
|
|
return false
|
|
}
|
|
|
|
# what L does with such a line: made once per distinct line in this language, kept with the keys
|
|
function kx_nest_line(i18n_st: mut I18nState, s: string) -> string {
|
|
if i18n_st.kc == null { kc_clear(i18n_st) }
|
|
let ci = Dict.get_or(i18n_st.kc, s, -1)
|
|
if ci >= 0 { return i18n_st.kc_out[ci] }
|
|
let q: string = s
|
|
var r = kx_flat(i18n_st, s)
|
|
if not (q[0] == I18N_OPEN and q[len(q) - 1] == I18N_CLOSE) { r = L(i18n_st, r) }
|
|
if Dict.size(i18n_st.kc) >= CACHE_MAX { kc_clear(i18n_st) }
|
|
@alloc_ok("a line with a line inside it, made into text: kept, up to CACHE_MAX")
|
|
Dict.set(i18n_st.kc, s, len(i18n_st.kc_out))
|
|
@alloc_ok("a line with a line inside it: as above")
|
|
push(i18n_st.kc_out, r)
|
|
return r
|
|
}
|
|
|
|
# each outermost bracket made into its text (what is inside is made the same way, by L), then any
|
|
# bracket left without a partner taken out
|
|
@alloc_ok("a line with a line inside it (a cache miss): once per distinct line")
|
|
function kx_flat(i18n_st: mut I18nState, s: string) -> string {
|
|
let p: string = s
|
|
var r = ""
|
|
var seg = 0
|
|
var i = 0
|
|
while i < len(p) {
|
|
let c = kx_close(p, i)
|
|
if p[i] == I18N_OPEN and c > i {
|
|
r = r + s[seg..i] + L(i18n_st, s[i + 1..c])
|
|
seg = c + 1
|
|
i = c + 1
|
|
} else {
|
|
i += 1
|
|
}
|
|
}
|
|
return kx_strip(r + s[seg..len(p)])
|
|
}
|
|
|
|
# where the bracket opening at i closes, or -1 when it never does
|
|
function kx_close(p: string, i: int) -> int {
|
|
var depth = 0
|
|
for j in i .. len(p) {
|
|
if p[j] == I18N_OPEN { depth += 1 }
|
|
if p[j] == I18N_CLOSE {
|
|
depth -= 1
|
|
if depth == 0 { return j }
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
# a close with no open before it (or an open with no close): no stray byte drawn
|
|
@alloc_ok("as above")
|
|
function kx_strip(s: string) -> string {
|
|
let p: string = s
|
|
var r = ""
|
|
var seg = 0
|
|
for i in 0 .. len(p) {
|
|
if p[i] == I18N_OPEN or p[i] == I18N_CLOSE {
|
|
r = r + s[seg..i]
|
|
seg = i + 1
|
|
}
|
|
}
|
|
return r + s[seg..len(p)]
|
|
}
|