summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/lua-uni-algos/lua-uni-parse.lua
blob: a264a2573e31622a9e57ada7f814ce9f68de661e (plain)
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
-- lua-uni-parse.lua
-- Copyright 2020 Marcel Krüger
--
-- This work may be distributed and/or modified under the
-- conditions of the LaTeX Project Public License, either version 1.3
-- of this license or (at your option) any later version.
-- The latest version of this license is in
--   http://www.latex-project.org/lppl.txt
-- and version 1.3 or later is part of all distributions of LaTeX
-- version 2005/12/01 or later.
--
-- This work has the LPPL maintenance status `maintained'.
-- 
-- The Current Maintainer of this work is Marcel Krüger

-- Just a simple helper module to make UCD parsing more readable

local lpeg = lpeg or require'lpeg'
local R = lpeg.R
local tonumber = tonumber

local codepoint = lpeg.R('09', 'AF')^4 / function(c) return tonumber(c, 16) end
local sep = lpeg.P' '^0 * ';' * lpeg.P' '^0
local codepoint_range = codepoint * ('..' * codepoint + lpeg.Cc(false))
local ignore_line = (1-lpeg.P'\n')^0 * '\n'
local eol = lpeg.S' \t'^0 * ('#' * ignore_line + '\n')
local ignored = (1-lpeg.S';#\n')^0
local number = lpeg.R'09'^1 / tonumber

local function fields(first, ...)
  if first == ignore_line then
    assert(select('#', ...) == 0)
    return ignore_line
  end
  local tail = select('#', ...) == 0 and eol or sep * fields(...)
  return first * tail
end

local function multiset(table, key1, key2, value)
  for key = key1,(key2 or key1) do
    table[key] = value
  end
  return table
end

local function parse_uni_file(filename, patt, func, ...)
  if func then
    return parse_uni_file(filename, lpeg.Cf(lpeg.Ct'' * patt^0 * -1, func), nil, ...)
  end
  local resolved = kpse.find_file(filename .. '.txt')
  if not resolved then
    error(string.format("Unable to find Unicode datafile %q", filename))
  end
  local f = assert(io.open(resolved))
  local data = f:read'*a'
  f:close()
  return lpeg.match(patt, data, 1, ...)
end

return {
  codepoint = codepoint,
  codepoint_range = codepoint_range,
  ignore_line = ignore_line,
  ignore_field = ignored,
  eol = eol,
  sep = sep,
  number = number,
  fields = fields,
  multiset = multiset,
  parse_file = parse_uni_file,
}