h = object.new
op_escape = [ "!" : "_bang",
"*" : "_star",
"-" : "_minus",
"+" : "_plus",
"|" : "_or",
"&" : "_and",
"@" : "_at",
"~" : "_tilde",
"^" : "_up",
"/" : "_forward",
"\\" : "_back",
"?" : "_question",
"<" : "_less",
">" : "_greater",
"=" : "_equal",
"%" : "_percent",
"_" : "_under",
"$" : "_dollar" ]
escape_op = { input |
input.sub "[!?*+^@/\\><$_%%|&=~-]", { o |
op_escape[o]
}
}
kw_escape = /\A(and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\Z/i
escape_keyword = { input |
input.sub kw_escape, { m | "_" + m }
}
h.escape_identifier = { identifier |
escape_keyword(escape_op(identifier))
}
unescape_ops = ["bang" : "!",
"star" : "*",
"minus" : "-",
"plus" : "+",
"or" : "|" ,
"and" : "&",
"at" : "@",
"tilde" : "~",
"up" : "^",
"forward" : "/",
"back" : "\\",
"question" : "?",
"less" : "<",
"greater" : ">",
"notequal" : "!=",
"equal" : "=",
"percent" : "%",
"under" : "_",
"dollar" : "$" ]
op_unescape = /_(bang|star|minus|plus|or|and|at|tilde|up|forward|back|question|less|greater|equal|percent|under|dollar)/
unescape_op = { input |
input.sub op_unescape, { m | unescape_ops[m] }
}
kw_unescape = /__(and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)/
unescape_keyword = { input |
input.sub kw_unescape, { m | m }
}
h.unescape_identifier = { identifier |
unescape_op(unescape_keyword(identifier))
}
h.escape_string = { str |
str.sub("\n", '\n')
}
h.lift_string = { str, var, type = :simple |
lifted_id = my.lifted_string_index[str]
null? lifted_id
{
true? type == :simple
{ my.liftable_strings << "symbol:new('#{str}')" }
{ my.liftable_strings << "symbol:new(\"#{str}\")" }
lifted_id = my.liftable_strings.length
my.lifted_string_index[str] = lifted_id
}
set_result var, "_lifted_strings[#{lifted_id}]", type: :string
}
h.lifted_strings = {
list = [r(null, "local _lifted_strings = {")]
o = my
my.liftable_strings.each { str |
list << o.r(null, "#{str}," )
}
list << r(null, "}")
list
}
export h, :string_helper