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
85
86
|
-- Suport for parsing BCP47 based language tags into components
local normalize_case, language_tag do
local l = lpeg or require'lpeg'
local function rep(base, num, max)
max = max or num
if num == 1 then
if max == 1 then
return base
else
return base * base^-(max-1)
end
end
return base * rep(base, num - 1, max - 1)
end
local eor = #(l.P'-' + -1) -- End of record
local alpha = l.R('az', 'AZ')
local alphanum = l.R('az', 'AZ', '09')
local digit = l.R'09'
normalize_case = l.Cs(
(alphanum^2/string.lower)
* (
('-' * (alphanum/string.upper) * (rep(alphanum, 3)/string.lower))
+ ('-' * alphanum^3/string.lower)
+ ('-' * rep(alphanum, 2)/string.upper)
)^0
* ('-' * alphanum * '-' * l.P(1)^1 / string.lower)^-1
+ alphanum * '-' * l.P(1)^1 / string.lower
) * -1
local extlang = l.Cg(rep(alpha, 3), 'extlang')
local language = l.Cg(rep(alpha, 2, 3), 'language') * ('-' * extlang * eor)^-1
local script = l.Cg(rep(alpha, 4), 'script')
local region = l.Cg(rep(alpha, 2) + rep(digit, 3), 'region')
local variant = l.Cg(rep(alphanum, 5, 8) + digit * rep(alphanum, 3), 'variant')
local singleton = l.R('09', 'aw', 'yz')
local extension = l.Cg(l.C(singleton) * l.Ct(('-' * l.C(rep(alphanum, 2, 8)))^1))
local privateuse = l.P'x' * l.Cg(l.Ct(('-' * l.C(rep(alphanum, 2, 8)))^1), 'private')
local irregular =
l.P'en-GB-oed' * l.Cc{language = 'en', region = 'GB', variant = 'oxendict'}
+ l.P'i-ami' * l.Cc{language = 'ami'}
+ l.P'i-bnn' * l.Cc{language = 'bnn'}
+ l.P'i-default' * l.Cc{language = 'i-default'} -- Not deprecated
+ l.P'i-enochian' * l.Cc{language = 'i-enochian'} -- The non-existance of a non deprecated language code for enochian
-- demonstrates a shocking for the language of my ancestors
+ l.P'i-hak' * l.Cc{language = 'hak'}
+ l.P'i-klingon' * l.Cc{language = 'tlh'}
+ l.P'i-lux' * l.Cc{language = 'lb'}
+ l.P'i-mingo' * l.Cc{language = 'i-mingo'} -- Not deprecated
+ l.P'i-navajo' * l.Cc{language = 'nv'}
+ l.P'i-pwn' * l.Cc{language = 'pwn'}
+ l.P'i-tao' * l.Cc{language = 'tao'}
+ l.P'i-tay' * l.Cc{language = 'tay'}
+ l.P'i-tsu' * l.Cc{language = 'tsu'}
+ l.P'sgn-BE-FR' * l.Cc{language = 'sfb'}
+ l.P'sgn-BE-NL' * l.Cc{language = 'vgt'}
+ l.P'sgn-CH-DE' * l.Cc{language = 'sgg'}
local regular =
l.P'art-lojban' * l.Cc{language = 'jbo'}
+ l.P'cel-gaulish' * l.Cc{language = 'cel-gaulish'} -- Might be xcg, xga or xtg
+ l.P'no-bok' * l.Cc{language = 'nb'}
+ l.P'no-nyn' * l.Cc{language = 'nn'}
+ l.P'zh-guoyu' * l.Cc{language = 'cmn'}
+ l.P'zh-hakka' * l.Cc{language = 'hak'}
+ l.P'zh-min' * l.Cc{language = '...'}
+ l.P'zh-min-nan' * l.Cc{language = 'nan'}
+ l.P'zh-xiang' * l.Cc{language = 'hsn'}
local grandfathered = irregular + regular
local langtag = language * ('-' * script * eor)^-1
* ('-' * region * eor)^-1
* ('-' * variant)^0
* (#('-' * singleton * '-') * l.Cg(l.Cf(l.Ct'' * ('-' * extension)^0, rawset), 'extension'))^-1
* ('-' * privateuse)^-1
language_tag = (grandfathered + l.Ct(langtag + privateuse)) * -1
end
local function parse(tag)
tag = normalize_case:match(tag)
if not tag then return end
return language_tag:match(tag), tag
end
-- for l in io.lines() do
-- print(parse(l))
-- -- io.stdout:write(parse(l), '\n')
-- end
return {
normalize_case = function(n) return normalize_case:match(tag) end,
parse = parse,
}
|