///|
fn encoder_ascii_is_vowel(code : UInt16) -> Bool {
code == 65 ||
code == 69 ||
code == 73 ||
code == 79 ||
code == 85 ||
code == 89
}
///|
fn ascii_starts_with_at(input : String, index : Int, pattern : String) -> Bool {
if index < 0 || index + pattern.length() > input.length() {
return false
}
for i = 0; i < pattern.length(); i = i + 1 {
if input[index + i] != pattern[i] {
return false
}
}
true
}
///|
fn ascii_ends_with(input : String, suffix : String) -> Bool {
ascii_starts_with_at(input, input.length() - suffix.length(), suffix)
}
///|
fn ascii_slice(input : String, start : Int, end : Int) -> String {
let from = if start < 0 {
0
} else if start > input.length() {
input.length()
} else {
start
}
let until = if end < from {
from
} else if end > input.length() {
input.length()
} else {
end
}
let mut output = ""
for i = from; i < until; i = i + 1 {
output = output + input[i].unsafe_to_char().to_string()
}
output
}
///|
fn append_bounded(output : String, fragment : String, maximum : Int) -> String {
if maximum <= 0 {
return ""
}
let mut bounded = ascii_slice(output, 0, maximum)
for i = 0; i < fragment.length() && bounded.length() < maximum; i = i + 1 {
bounded = bounded + fragment[i].unsafe_to_char().to_string()
}
bounded
}
///|
priv struct RuleCursor {
input : String
index : Int
output : String
maximum : Int
}
///|
fn RuleCursor::new(input : String, maximum : Int) -> RuleCursor {
{ input, index: 0, output: "", maximum }
}
///|
fn RuleCursor::remaining(self : RuleCursor) -> Int {
self.input.length() - self.index
}
///|
fn RuleCursor::peek(self : RuleCursor, offset : Int) -> UInt16 {
let position = self.index + offset
if position < 0 || position >= self.input.length() {
0
} else {
self.input[position]
}
}
///|
fn RuleCursor::advance(self : RuleCursor, amount : Int) -> RuleCursor {
let requested = if amount < 0 { self.index } else { self.index + amount }
let next_index = if requested > self.input.length() {
self.input.length()
} else {
requested
}
{
input: self.input,
index: next_index,
output: self.output,
maximum: self.maximum,
}
}
///|
fn RuleCursor::append(self : RuleCursor, fragment : String) -> RuleCursor {
{
input: self.input,
index: self.index,
output: append_bounded(self.output, fragment, self.maximum),
maximum: self.maximum,
}
}