toki-pona-translator/translator.nim

79 lines
2.3 KiB
Nim

import re, sequtils, sets, strutils
import elvis, zero_functional
import dictionary, words
type
Context = ref object
seenNouns: HashSet[string]
let
sentenceSeparator = re"(?<=[.?!])\s+"
ignoredChars = re"[^A-Za-z\s]"
sentenceStructure = rex"""^
# subject
(?:(mi|sina|mi\smute|sina\smute)|(.+?)\sli)
# predicate
\s(.+?)
# direct object
(?:\se\s(.+?))?
$"""
proc translateNounPhrase(phrase: string, context: Context, form: NounForm): string =
for noun in nouns --> filter(phrase.startsWith(it.tp)):
let
nounTranslated = noun[form]
rest = phrase[noun.tp.len..^1]
restTranslated = rest
article = if noun.article and form in {nfSg, nfSgAcc}:
if noun.tp in context.seenNouns:
"the"
else:
context.seenNouns.incl(noun.tp)
"a"
else:
""
return [article, restTranslated, nounTranslated]
.filterIt(?it)
.join(" ")
phrase
proc translateVerbPhrase(phrase: string, context: Context, form: VerbForm, transitive: bool): string =
let verbs = transitive ? verbsTr ! verbsIn
for verb in verbs --> filter(phrase.startsWith(it.tp)):
let
verbTranslated = verb[form]
rest = phrase[verb.tp.len..^1]
restTranslated = rest
return [restTranslated, verbTranslated]
.filterIt(?it)
.join(" ")
phrase
proc translateSentence(sentence: string, context: Context): string =
let sentence = sentence.replace(ignoredChars, "")
if sentence =~ sentenceStructure:
let
subject = matches[0] ?: matches[1]
predicate = matches[2]
directObject = matches[3]
subjectTranslated = subject.translateNounPhrase(context, nfSg)
predicateForm = case subject
of "mi": vf1S
of "mi mute", "sina", "sina mute": vfPl
else: vf3S
predicateTranslated = predicate.translateVerbPhrase(context, predicateForm, directObject != "")
directObjectTranslated = directObject.translateNounPhrase(context, nfSgAcc)
result = [subjectTranslated, predicateTranslated, directObjectTranslated]
.filterIt(?it)
.join(" ")
.capitalizeAscii
result.add "."
else:
result = sentence
proc translate*(text: string): string =
let context = Context()
text.split(sentenceSeparator)
.mapIt(it.translateSentence(context))
.join(" ")