Files
AzooKeyKanaKanjiConverter/Sources/KanaKanjiConverterModule/DicdataStore/JapaneseNumber.swift
2023-07-23 00:34:27 +09:00

448 lines
14 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// extension JapaneseNumber.swift
// Keyboard
//
// Created by ensan on 2020/09/17.
// Copyright © 2020 ensan. All rights reserved.
//
import Foundation
private enum JapaneseNumber {
case , , , , , , , , ,
case , , , , ,
case
case
var isNumber: Bool {
[., ., ., ., ., ., ., ., ., ., .].contains(self)
}
var isNotNumber: Bool {
[., ., ., ., ., ., ., .].contains(self)
}
var toRoman: String {
switch self {
case .:
return "1"
case .:
return "2"
case .:
return "3"
case .:
return "4"
case .:
return "5"
case .:
return "6"
case .:
return "7"
case .:
return "8"
case .:
return "9"
case .:
return "0"
default:
return ""
}
}
var maxDigit: Int? {
switch self {
case .:
return 1
case .:
return 2
case .:
return 3
case .:
return 4
default:
return nil
}
}
var toKanji: String {
switch self {
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
case .:
return ""
}
}
}
private enum Number {
case Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine
var character: Character {
switch self {
case .Zero:
return "0"
case .One:
return "1"
case .Two:
return "2"
case .Three:
return "3"
case .Four:
return "4"
case .Five:
return "5"
case .Six:
return "6"
case .Seven:
return "7"
case .Eight:
return "8"
case .Nine:
return "9"
}
}
}
extension DicdataStore {
private func parseLiteral(input: some StringProtocol) -> [JapaneseNumber] {
var chars = input.makeIterator()
var tokens: [JapaneseNumber] = []
func judge(char: Character) {
if char == ""{
if let char = chars.next(), char == "" || char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
} else if char == ""{
tokens.append(.)
} else if char == ""{
tokens.append(.)
} else if char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next() {
if char == ""{
tokens.append(.)
} else {
tokens.append(.)
judge(char: char)
}
} else {
tokens.append(.)
}
} else if char == ""{
if let char = chars.next(), char == ""{
if let char = chars.next(), char == "" || char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next() {
if char == ""{
tokens.append(.)
} else if char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else if char == ""{
tokens.append(.)
} else if char == ""{
if let char = chars.next(), char == "" || char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next() {
if char == ""{
tokens.append(.)
} else if char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else if char == ""{
if let char = chars.next(), char == "" || char == ""{
tokens.append(.)
} else {
tokens.append(.)
return
}
} else {
tokens.append(.)
return
}
}
while let char = chars.next() {
judge(char: char)
}
tokens.append(.)
return tokens
}
private func parseTokens(tokens: [JapaneseNumber]) -> [(Number, Number, Number, Number)] {
var maxDigits: Int?
var result: [(Number, Number, Number, Number)] = []
var stack: (Number, Number, Number, Number) = (.Zero, .Zero, .Zero, .Zero)
var tokens = tokens.makeIterator()
var curnum: Number?
while let token = tokens.next() {
switch token {
case .:
if curnum != nil {return []}
curnum = .One
case .:
if curnum != nil {return []}
curnum = .Two
case .:
if curnum != nil {return []}
curnum = .Three
case .:
if curnum != nil {return []}
curnum = .Four
case .:
if curnum != nil {return []}
curnum = .Five
case .:
if curnum != nil {return []}
curnum = .Six
case .:
if curnum != nil {return []}
curnum = .Seven
case .:
if curnum != nil {return []}
curnum = .Eight
case .:
if curnum != nil {return []}
curnum = .Nine
case .:
if curnum != nil {return []}
curnum = .Zero
case .:
stack.2 = curnum ?? .One
curnum = nil
case .:
stack.1 = curnum ?? .One
curnum = nil
case .:
stack.0 = curnum ?? .One
curnum = nil
case ., ., ., .:
stack.3 = curnum ?? .Zero
if let maxDigit = maxDigits {
if maxDigit <= token.maxDigit! {
return []
}
result[maxDigit - token.maxDigit!] = stack
} else {
maxDigits = token.maxDigit!
result = [(Number, Number, Number, Number)].init(repeating: (.Zero, .Zero, .Zero, .Zero), count: maxDigits!)
result[0] = stack
}
curnum = nil
stack = (.Zero, .Zero, .Zero, .Zero)
case .:
break
}
}
return result
}
func getJapaneseNumberDicdata(head: String) -> [DicdataElement] {
let tokens = parseLiteral(input: head)
if !tokens.allSatisfy({$0 != .}) {
return []
}
let kanji = tokens.map {$0.toKanji}.joined()
let roman: String
if tokens.allSatisfy({$0.isNumber}) {
roman = tokens.map {$0.toRoman}.joined()
} else if tokens.allSatisfy({$0.isNotNumber}) {
return []
} else {
let result = parseTokens(tokens: tokens)
if result.isEmpty {
return []
}
var chars: [Character] = []
for stack in result {
if chars.isEmpty {
if stack.0 != .Zero {
chars.append(contentsOf: [stack.0.character, stack.1.character, stack.2.character, stack.3.character])
} else if stack.1 != .Zero {
chars.append(contentsOf: [stack.1.character, stack.2.character, stack.3.character])
} else if stack.2 != .Zero {
chars.append(contentsOf: [stack.2.character, stack.3.character])
} else if stack.3 != .Zero {
chars.append(stack.3.character)
} else {
return []
}
} else {
chars.append(contentsOf: [stack.0.character, stack.1.character, stack.2.character, stack.3.character])
}
}
roman = String(chars)
}
return [
DicdataElement(word: kanji, ruby: head, cid: CIDData..cid, mid: MIDData..mid, value: -17 + PValue(head.count) / 3),
DicdataElement(word: roman, ruby: head, cid: CIDData..cid, mid: MIDData..mid, value: -16 + 4 / PValue(roman.count))
]
}
}