ordinal selection asks the lexicon, and declines a half hour (V-522)
Group 1 of the sweep listed cmd/mavend/ordinal.go, and it was still
picking a position by stem prefix: {"перв", 1}, {"втор", 2}. The lexicon
already carries every form with its position and "последний" as -1, up to
twelve rather than five, so parseOrdinal reads that instead. "вторым" and
"седьмую" were missed before and now land.
A wider set opens one hole the stems did not have. Russian names a half
hour with the genitive ordinal of the hour it is entering, so "в половине
восьмого" would read as the eighth thing she read out. The forms of
"половина" move into the lexicon as half_hour, where the clock rewrite in
internal/router/halfpast.go and this refusal read one copy, and
parseOrdinal skips an ordinal standing behind one.
Six new parseOrdinal cases. cmd/mavend, internal/router, internal/lexicon
and internal/calendar all pass.
This commit is contained in:
@@ -63,7 +63,7 @@ func mustLoad() lexiconFile {
|
||||
for _, name := range []string{
|
||||
"interrogatives", "capture_verbs", "narrative_requests", "cardinals", "ordinals",
|
||||
"day_offsets", "weekdays", "months_genitive", "hours_spoken",
|
||||
"not_place_after_v", "parts_of_day", "reminder_verbs",
|
||||
"not_place_after_v", "parts_of_day", "reminder_verbs", "half_hour",
|
||||
} {
|
||||
s, ok := f.Sets[name]
|
||||
if !ok || (len(s.Words) == 0 && len(s.Values) == 0) {
|
||||
@@ -112,6 +112,23 @@ func PartsOfDay() []string { return words("parts_of_day") }
|
||||
// ReminderVerbs returns the imperatives that open a reminder.
|
||||
func ReminderVerbs() []string { return words("reminder_verbs") }
|
||||
|
||||
// HalfHourWords returns those forms, for a caller folding every time word into
|
||||
// one set rather than asking about one word.
|
||||
func HalfHourWords() []string { return words("half_hour") }
|
||||
|
||||
// IsHalfHour reports whether a word introduces a spoken half hour, so the
|
||||
// ordinal after it is an hour rather than a position. One caller reads that
|
||||
// ordinal as the hour and another has to decline it; both ask here.
|
||||
func IsHalfHour(word string) bool {
|
||||
w := norm(word)
|
||||
for _, h := range ru.Sets["half_hour"].Words {
|
||||
if w == h {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Cardinal reports the value of a spoken number word. The word is compared
|
||||
// lowercased and trimmed, because it arrives from a tokenizer that may not have
|
||||
// done either.
|
||||
|
||||
@@ -166,6 +166,13 @@
|
||||
"напомни", "напомните", "напомнить", "напоминай",
|
||||
"remind"
|
||||
]
|
||||
},
|
||||
"half_hour": {
|
||||
"note": "The forms of \"половина\" that introduce a spoken half hour: \"в половине восьмого\", \"к половине\", the bare \"пол\" of \"полвосьмого\". The set matters to two callers and for opposite reasons (V-522). The clock rewrite reads the ordinal after one of these as the hour being entered, and the ordinal-selection turn has to REFUSE that ordinal, because \"в половине восьмого\" names a time and not the eighth thing she read out.",
|
||||
"words": [
|
||||
"половина", "половине", "половину", "половины", "пол",
|
||||
"half"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,9 @@ import (
|
||||
// had one and added when it did not, because the stub scans for "в" before a
|
||||
// clock and the contracted "полвосьмого" carries no preposition at all.
|
||||
|
||||
// halfWords — the forms of "половина" a spoken time uses. "в половине",
|
||||
// "половина", "к половине", "полвосьмого". Closed and tiny; the ordinal beside
|
||||
// them is what carries the hour, and that comes from the lexicon.
|
||||
var halfWords = map[string]bool{
|
||||
"половина": true, "половине": true, "половину": true, "половины": true,
|
||||
"пол": true, "half": true,
|
||||
}
|
||||
// The forms of "половина" a spoken time uses are a closed class and live in the
|
||||
// lexicon as half_hour, because the ordinal-selection turn has to decline the
|
||||
// same ordinal this file reads (V-522). Ask lexicon.IsHalfHour.
|
||||
|
||||
// minutesTo — the words that name the minutes in a "без X" hour. "четверти" is
|
||||
// the only one that is not a number; the rest are cardinals and are read as
|
||||
@@ -74,7 +70,7 @@ func halfPastAt(toks []string, i int) (hour, width int, ok bool) {
|
||||
return h, 1, true
|
||||
}
|
||||
}
|
||||
if !halfWords[head] || i+1 >= len(toks) {
|
||||
if !lexicon.IsHalfHour(head) || i+1 >= len(toks) {
|
||||
return 0, 0, false
|
||||
}
|
||||
h, ok := enteredHour(cleanWord(toks[i+1]))
|
||||
|
||||
@@ -129,7 +129,7 @@ func buildTimeMarkers() map[string]bool {
|
||||
m[w] = true
|
||||
}
|
||||
}
|
||||
for w := range halfWords {
|
||||
for _, w := range lexicon.HalfHourWords() {
|
||||
m[w] = true
|
||||
}
|
||||
for w := range minutesTo {
|
||||
|
||||
Reference in New Issue
Block a user