Я снова играл с Haskell и реализовал простую программу замены текста, которая заменяет все согласные c в тексте cВc, то есть вставив букву «о» между:
> robber_simple "abcdef"
"abobcocdodefof"
Это довольно просто реализовать:
robber_simple :: [Char] -> [Char]
robber_simple [] = []
robber_simple (x:xs)
| x `elem` monophthongs = x:(robber_simple xs)
| otherwise = x:'o':x:(robber_simple xs)
where -- vowels represented by one character, or monograph
monophthongs :: [Char]
monophthongs = "aeiouy"
Однако во многих языках, например, в немецком, есть мультиграфы, которые могут действовать как гласные или согласные, такие как «uh» («uhr») или «sch» («schokolade»).
Итак, я реализовал более сложную программу, которая выполняет базовый просмотр, чтобы выяснить, является ли, скажем, ‘s’, которое мы читаем в настоящее время, действительно частью «sch». Но я не доволен этим 🙂
import Data.List
robber :: [Char] -> [Char]
robber xs = robber' xs [] where
robber' :: [Char] -> [Char] -> [Char]
-- Read first character into backlog
robber' (x:xs) [] = robber' xs [x]
-- Nonempty prefix, new input can either form a multigraph prefix or end one.
robber' (x:xs) (p:ps)
-- Current character with existing prefix forms a prefix of a multigraph
| token `elem` (prefixes multigraph_consonant) = robber' xs token
| token `elem` (prefixes multigraph_vowel) = robber' xs token
-- The current token makes it clear that we aren't reading a multigraph
| otherwise = (robber' [] (p:ps)) ++ (robber' (x:xs) [])
where token = (p:ps) ++ [x]
-- No input, consume characters in backlog.
robber' [] pref
-- Either this forms a multigraph...
| pref `elem` multigraph_consonant = pref ++ 'o':pref
| pref `elem` multigraph_vowel = pref
-- ... or not.
| otherwise = robber_simple pref
-- consonant phoneme made up of multiple characters
multigraph_consonant :: [[Char]]
multigraph_consonant = ["sch", "ch", "sc"]
-- same for vowels
multigraph_vowel :: [[Char]]
multigraph_vowel = ["ei", "uh"]
prefixes :: [[a]] -> [[a]]
prefixes xs = concat $ map prefix xs
prefix :: [a] -> [[a]]
prefix = inits
Стратегия синтаксического анализа / токенизации, которую я использую, заключается в том, чтобы читать символы и сохранять их в бэклоге до тех пор, пока не появится символ (или конец ввода), который определяет, что текущий бэклог можно рассматривать как одну единицу. То есть это либо полная монография (например, «щ»), либо определенно не префикс монографии («с»).
В таком случае я заменяю отставание Икс либо с x++'o':x или оставьте его, в зависимости от того, гласная это или согласная.
Наконец, я продолжаю синтаксический анализ оставшейся части строки.
Любые предложения приветствуются!
