///|
pub(all) struct DicEntry {
word : String
flags : String
morph : String
}
///|
pub(all) struct Dictionary {
declared_count : Int
entries : Array[DicEntry]
index : Map[String, Array[DicEntry]]
}
///|
pub suberror DicParseError {
EmptyDictionary
InvalidHeader(String)
}
///|
fn parse_decimal_count(text : String) -> Int? {
let value = text.trim()
if value.is_empty() {
return None
}
let mut result = 0
for c in value {
if !c.is_ascii_digit() {
return None
}
result = result * 10 + c.to_int() - '0'.to_int()
}
Some(result)
}
///|
fn split_at_first_space(text : StringView) -> (String, String) {
match text.find_by(c => c.is_whitespace()) {
Some(index) =>
(
text.view(end_offset=index).to_owned(),
text.view(start_offset=index + 1).trim().to_owned(),
)
None => (text.trim().to_owned(), "")
}
}
///|
pub fn parse_dic_entry(line : String) -> DicEntry? {
let value = line.trim().replace_all(old="\\/", new="\u{FDE1}")
if value == "/" {
return Some({ word: "/", flags: "", morph: "", })
}
if value == "/" {
return Some({ word: "/", flags: "", morph: "", })
}
if value.is_empty() {
return None
}
match value.split_once("/") {
Some((word, suffix)) => {
if word.is_empty() {
return None
}
let (flags, morph) = split_at_first_space(suffix)
Some({
word: word.to_owned().replace_all(old="\u{FDE1}", new="/"),
flags,
morph,
})
}
None => {
let morph_index = match value.find(" ph:") {
Some(index) => Some((index, 1))
None =>
match value.find("\t") {
Some(index) => Some((index, 1))
None => None
}
}
match morph_index {
Some((index, offset)) => {
let word = value.view(end_offset=index).trim().to_owned()
let morph = value.view(start_offset=index + offset).trim().to_owned()
if word.is_empty() {
None
} else {
Some({
word: word.replace_all(old="\u{FDE1}", new="/"),
flags: "",
morph,
})
}
}
None =>
Some({
word: value.replace_all(old="\u{FDE1}", new="/").to_owned(),
flags: "",
morph: "",
})
}
}
}
}
///|
pub fn parse_dic(text : String) -> Result[Dictionary, DicParseError] {
let lines = strip_bom(text).split("\n").collect()
let mut header_index = -1
let mut header = ""
for i in 0.. !item.is_empty())
.collect()
if header_parts.length() == 0 {
return Err(InvalidHeader(header))
}
let declared_count = match parse_decimal_count(header_parts[0].to_owned()) {
Some(count) => count
None => return Err(InvalidHeader(header))
}
let entries : Array[DicEntry] = []
let index : Map[String, Array[DicEntry]] = Map([])
for i in (header_index + 1).. {
entries.push(entry)
match index.get(entry.word) {
Some(bucket) => bucket.push(entry)
None => index.set(entry.word, [entry])
}
}
None => ()
}
}
Ok({ declared_count, entries, index, })
}
///|
pub fn Dictionary::has_word(self : Dictionary, word : String) -> Bool {
let mut found = false
for entry in self.entries {
if entry.word == word {
found = true
break
}
}
found
}