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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
inspect = require "inspect.lua"
function raise_error(...)
local arg = {...}
local description = "a luaprogtable package exception occured:\n" .. table.concat(arg, ", ")
tex.error(description)
error(description)
end
local _spacer = lpeg.S(" \t\f\v\n\r")
local _non_spacer = 1 - _spacer
local _stripper = _spacer^0 * lpeg.C((_spacer^0 * _non_spacer^1)^0)
function _lpt_strip(s)
return s and lpeg.match(_stripper,s) or ""
end
function _lpt_split(s, sep)
sep = lpeg.P(sep)
local elem = lpeg.C((1 - sep)^0)
local p = lpeg.Ct(elem * (sep * elem)^0) -- make a table capture
return lpeg.match(p, s)
end
function _lpt_tonumber(s)
local n = tonumber(s)
if n == nil then
raise_error(string.format("'{%s}' is not a valid number expression", s))
end
return n
end
function _lpt_parse_index_expr(expr)
local expr = _lpt_strip(expr)
local parts = _lpt_split(expr, ",")
local ret = {}
for i=1,#parts do
local subexpr = _lpt_strip(parts[i])
if subexpr:len() == 0 then
raise_error(string.format("empty field in index expression '%s'", expr))
end
local colon_pos = subexpr:find(":")
local str_l = ""
local str_r = ""
if colon_pos == nil then
str_l = subexpr
str_r = subexpr
else
local subsubexpr = _lpt_split(subexpr, ":")
str_l = _lpt_strip(subsubexpr[1])
str_r = _lpt_strip(subsubexpr[2])
if str_l:len() == 0 then
str_l = "1"
end
if str_r:len() == 0 then
str_r = "-1"
end
end
local n_l = _lpt_tonumber(str_l)
local n_r = _lpt_tonumber(str_r)
table.insert(ret, {n_l, n_r})
end
return ret
end
function _lpt_parse_shape(shape_expr)
local shape_expr = _lpt_strip(shape_expr)
local parts = _lpt_split(shape_expr, ",")
if #parts ~= 2 then
raise_error(string.format("invalid shape: '%s'", shape_expr))
end
local shape1 = _lpt_tonumber(parts[1])
local shape2 = _lpt_tonumber(parts[2])
if shape1 < 1 or shape2 < 1 then
raise_error(string.format("invalid shape: '%s'", shape_expr))
end
return {shape1, shape2}
end
function table.slice(tbl, first, last, step)
local sliced = {}
for i = first or 1, last or #tbl, step or 1 do
sliced[#sliced+1] = tbl[i]
end
return sliced
end
function table.find(tbl, item, index)
for i=index or 1, #tbl do
local tbl_item = tbl[i]
if tbl_item == item then
return i
end
end
return nil
end
|