79 lines
2.3 KiB
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(" ")
|