2021-05-31 12:42:51 +02:00
|
|
|
local l = lpeg or require'lpeg'
|
|
|
|
|
|
|
|
local line = (1-l.P'\n')^0 * '\n'
|
|
|
|
|
2021-06-27 04:30:49 +02:00
|
|
|
local id = l.R'09'^1/tonumber
|
2021-06-06 06:23:13 +02:00
|
|
|
local non_final_list_block = (l.C((1-l.P'\n')^1) * '\n' - '### ' + '\n')^0
|
2021-05-31 12:42:51 +02:00
|
|
|
local math_lists_block = l.Ct('### ' * l.Cg(l.C'display' * ' ', 'display')^-1 * 'math mode entered at line ' * l.Cg(l.R'09'^1 / tonumber, 'line') * '\n'
|
2021-06-01 22:29:48 +02:00
|
|
|
* non_final_list_block)^1
|
|
|
|
local generic_list_block = '### ' * (line - 'current page:') * non_final_list_block
|
2021-06-26 19:49:28 +02:00
|
|
|
local luamml_block = l.Cg('LUAMML_FORMULA_BEGIN:' * id * ':' * l.Ct(
|
2021-06-27 00:43:30 +02:00
|
|
|
l.Cg(id, 'flag') * ':' * l.Cg((1-l.S':\n')^0, 'tag') * ':' * l.Cg((1-l.P'\n')^1, 'label')^-1 * l.P'\n'^1
|
2021-06-26 19:49:28 +02:00
|
|
|
|
|
|
|
* (math_lists_block + generic_list_block/0)^0
|
2021-06-01 22:29:48 +02:00
|
|
|
* (line - 'LUAMML_FORMULA_END\n')^0
|
|
|
|
* 'LUAMML_FORMULA_END\n') * l.Cc'groups')
|
|
|
|
|
|
|
|
local luamml_mark = l.Cg('LUAMML_MARK:' * id * ':' * l.Cs((1 - l.P'\n' + l.Cg('\n' * l.Cc'' - '\nLUAMML_MARK_END\n'))^0) * '\nLUAMML_MARK_END\n' * l.Cc'marks')
|
|
|
|
|
2021-06-03 17:28:22 +02:00
|
|
|
local function add(a, b) return a + b end
|
|
|
|
local count_block = '### ' * line * l.Cf(l.Cc(0) * (('\\' * l.Cc(1))^-1 * line - '### ')^0, add)
|
2021-06-27 05:39:42 +02:00
|
|
|
local luamml_precount = l.Cg('LUAMML_COUNT:' * id * l.P'\n'^1
|
|
|
|
* count_block * l.Cc'precount')
|
|
|
|
|
|
|
|
local luamml_postcount = l.Cg('LUAMML_COUNT_END:' * id * l.P'\n'^1
|
|
|
|
* count_block * l.Cc'postcount')
|
2021-06-03 17:28:22 +02:00
|
|
|
|
2021-06-03 17:06:01 +02:00
|
|
|
local luamml_instruction = l.Cg('LUAMML_INSTRUCTION:' * l.Cc(nil) * l.C((1 - l.P'\n')^0) * '\n' * l.Cc'instructions')
|
|
|
|
|
2021-06-01 22:29:48 +02:00
|
|
|
local function multi_table_set(t, key, value, table)
|
2021-06-03 17:06:01 +02:00
|
|
|
table = t[table]
|
|
|
|
table[key or #table + 1] = value
|
2021-06-01 22:29:48 +02:00
|
|
|
return t
|
|
|
|
end
|
2021-06-03 17:06:01 +02:00
|
|
|
local log_file = l.Cf(l.Ct(l.Cg(l.Ct'', 'groups')
|
2021-06-27 05:39:42 +02:00
|
|
|
* l.Cg(l.Ct'', 'precount')
|
|
|
|
* l.Cg(l.Ct'', 'postcount')
|
2021-06-03 17:06:01 +02:00
|
|
|
* l.Cg(l.Ct'', 'marks')
|
|
|
|
* l.Cg(l.Ct'', 'instructions'))
|
2021-06-27 05:39:42 +02:00
|
|
|
* (luamml_block + luamml_mark + luamml_instruction + luamml_precount + luamml_postcount + line)^0,
|
2021-06-03 17:06:01 +02:00
|
|
|
multi_table_set)
|
2021-05-31 12:42:51 +02:00
|
|
|
|
|
|
|
return function(filename)
|
|
|
|
local f
|
|
|
|
if filename and filename ~= '-' then
|
|
|
|
local msg f, msg = assert(io.open(filename, 'r'))
|
|
|
|
if not f then return f, msg end
|
|
|
|
end
|
|
|
|
local content = (f or io.stdin):read'a'
|
|
|
|
if f then f:close() end
|
|
|
|
-- The following does *not* end with * -1 since we want to allow the last line to not end with \n.
|
|
|
|
-- In that case we ignore the last line, but that's safe since the last line never contains our markers.
|
2021-06-27 05:39:42 +02:00
|
|
|
local parsed = assert(log_file:match(content))
|
|
|
|
local precount, postcount, count = parsed.precount, parsed.postcount, {}
|
|
|
|
for id, pre in next, precount do
|
|
|
|
local post = assert(postcount[id], 'Unbalanced count')
|
|
|
|
count[id], postcount[id] = post-pre, nil
|
|
|
|
end
|
|
|
|
assert(not next(postcount), 'Unbalanced count')
|
|
|
|
parsed.precount, parsed.postcount, parsed.count = nil, nil, count
|
|
|
|
return parsed
|
2021-05-31 12:42:51 +02:00
|
|
|
end
|