-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathCodepage.hs
84 lines (70 loc) · 4.88 KB
/
Codepage.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
-- Implementation of the Husk code page
module Codepage where
import Data.Word
import Data.List
-- The Husk code page: 256 characters, each representing one byte
codepage :: String
codepage = "¤½↕↑↓↔←→∟¦\n¡¿‼…‰†‡√≤≥±∂∫∞≈≠≡⌐¬÷×" ++
" !\"#$%&'()*+,-./0123456789:;<=>?" ++
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" ++
"`abcdefghijklmnopqrstuvwxyz{|}~·" ++
"₀₁₂₃₄₅₆₇₈₉⌈⌉⌊⌋ΓΔΘΛΞΠΣΦΨΩαβγδεζηθ" ++
"λμξπρςστφχψω⁰¹²³⁴⁵⁶⁷⁸⁹¢£€¥ƒ´▲▼►◄" ++
"§ȦḂĊḊĖḞĠḢİĿṀṄȮṖṘṠṪẆẊẎŻȧḃċḋėḟġḣıȷ" ++
"ŀṁṅȯṗṙṡṫẇẋẏż¨ÄËÏÖÜŸØäëïöüÿø◊□¶«»"
-- A short ASCII alias for each non-ASCII char in the code page
aliases :: [(Char, String)]
aliases = [('¤', "cur"), ('½', "hlf"), ('↕', "ud"), ('↑', "up"), ('↓', "dow"), ('↔', "lr"), ('←', "lft"), ('→', "rgt"),
('∟', "ang"), ('¦', "bar"), ('¡', "exc"), ('¿', "que"), ('‼', "dex"), ('…', "ell"), ('‰', "ppm"),
('†', "dag"), ('‡', "ddg"), ('√', "srd"), ('≤', "leq"), ('≥', "geq"), ('±', "pm"), ('∂', "ptl"), ('∫', "int"),
('∞', "inf"), ('≈', "apx"), ('≠', "neq"), ('≡', "cng"), ('⌐', "gen"), ('¬', "neg"), ('÷', "div"), ('×', "eks"),
('·', "blt"),
('₀', "nul"), ('₁', "one"), ('₂', "two"), ('₃', "tre"), ('₄', "for"), ('₅', "fiv"), ('₆', "six"), ('₇', "sev"),
('₈', "ate"), ('₉', "nin"), ('⌈', "lce"), ('⌉', "rce"), ('⌊', "lfl"), ('⌋', "rfl"), ('Γ', "Gam"), ('Δ', "Del"),
('Θ', "The"), ('Λ', "Lam"), ('Ξ', "Xi"), ('Π', "Pi"), ('Σ', "Sig"), ('Φ', "Phi"), ('Ψ', "Psi"), ('Ω', "Ohm"),
('α', "alp"), ('β', "bet"), ('γ', "gam"), ('δ', "del"), ('ε', "eps"), ('ζ', "zet"), ('η', "eta"), ('θ', "the"),
('λ', "lam"), ('μ', "mu"), ('ξ', "xi"), ('π', "pi"), ('ρ', "rho"), ('ς', "sig"), ('σ', "sjg"), ('τ', "tau"),
('φ', "phi"), ('χ', "chi"), ('ψ', "psi"), ('ω', "ohm"), ('⁰', "Nul"), ('¹', "One"), ('²', "Two"), ('³', "Tre"),
('⁴', "For"), ('⁵', "Fiv"), ('⁶', "Six"), ('⁷', "Sev"), ('⁸', "Ate"), ('⁹', "Nin"), ('¢', "cnt"), ('£', "gbp"),
('€', "eur"), ('¥', "yen"), ('ƒ', "fl"), ('´', "acu"), ('▲', "top"), ('▼', "bot"), ('►', "est"), ('◄', "wst"),
('§', "sec"), ('Ȧ', "dA"), ('Ḃ', "dB"), ('Ċ', "dC"), ('Ḋ', "dD"), ('Ė', "dE"), ('Ḟ', "dF"), ('Ġ', "dG"),
('Ḣ', "dH"), ('İ', "dI"), ('Ŀ', "dL"), ('Ṁ', "dM"), ('Ṅ', "dN"), ('Ȯ', "dO"), ('Ṗ', "dP"), ('Ṙ', "dR"),
('Ṡ', "dS"), ('Ṫ', "dT"), ('Ẇ', "dW"), ('Ẋ', "dX"), ('Ẏ', "dY"), ('Ż', "dZ"), ('ȧ', "da"), ('ḃ', "db"),
('ċ', "dc"), ('ḋ', "dd"), ('ė', "de"), ('ḟ', "df"), ('ġ', "dg"), ('ḣ', "dh"), ('ı', "di"), ('ȷ', "dj"),
('ŀ', "dl"), ('ṁ', "dm"), ('ṅ', "dn"), ('ȯ', "do"), ('ṗ', "dp"), ('ṙ', "dr"), ('ṡ', "ds"), ('ṫ', "dt"),
('ẇ', "dw"), ('ẋ', "dx"), ('ẏ', "dy"), ('ż', "dz"), ('¨', "die"), ('Ä', "DA"), ('Ë', "DE"), ('Ï', "DI"),
('Ö', "DO"), ('Ü', "DU"), ('Ÿ', "DY"), ('Ø', "sO"), ('ä', "Da"), ('ë', "De"), ('ï', "Di"), ('ö', "Do"),
('ü', "Du"), ('ÿ', "Dy"), ('ø', "so"), ('◊', "loz"), ('□', "squ"), ('¶', "pgf"), ('«', "ll"), ('»', "rr")]
-- Convert a list of bytes into a string using the code page
getCommands :: [Word8] -> String
getCommands = map $ (codepage !!) . fromEnum
-- Get the position of a character in the code page
findByte :: Char -> Int
findByte byte | Just ix <- elemIndex byte codepage = ix
| otherwise = error "Bad byte"
-- Convert a program to list of bytes
getBytes :: String -> [Word8]
getBytes = map $ toEnum . findByte
-- Get the alias of a character
getAlias :: Char -> String
getAlias c | Just str <- lookup c aliases = '\\' : str ++ "\\"
| c == '\\' = "\\\\"
| otherwise = [c]
-- Convert terse program to verbose program
toAliases :: String -> String
toAliases = concatMap getAlias
-- Get the character of an alias
fromAlias :: String -> Maybe Char
fromAlias "" = Just '\\'
fromAlias str = lookup str $ map (\(a,b) -> (b,a)) aliases
-- Convert verbose program to terse program
parseAliases :: String -> Either String String
parseAliases ('\\':str) = do
let (alias, rest) = break (== '\\') str
char = case (rest, fromAlias alias) of
([], _) -> Left $ "Parse error (missing \\): " ++ alias
(_ : rest, Just c) -> Right c
(_, Nothing) -> Left $ "No character with alias " ++ alias
(:) <$> char <*> parseAliases (drop 1 rest)
parseAliases (char : str) = (char :) <$> parseAliases str
parseAliases "" = Right ""