Support annotations while parsing pdfTeX log
This commit is contained in:
parent
a782003db4
commit
d6b2747171
@ -505,7 +505,6 @@ function nodes_to_table(head, cur_style)
|
||||
local props = properties[n]
|
||||
local mathml_core = props and props.mathml_core
|
||||
local mathml_table = props and (props.mathml_table or mathml_core)
|
||||
print(mathml_table)
|
||||
if mathml_table ~= nil then
|
||||
new_node, new_core = mathml_table, mathml_core
|
||||
elseif id == noad_t then
|
||||
|
94
luamml-pdf.sty
Normal file
94
luamml-pdf.sty
Normal file
@ -0,0 +1,94 @@
|
||||
\ProvidesExplPackage {luamml-pdf} {2021-05-31} {0.0.1-alpha}
|
||||
{MathML generation for L̶u̶a̶pdfLaTeX}
|
||||
|
||||
\cs_new:Npn \__luamml_pdf_showlists: {
|
||||
\group_begin:
|
||||
\int_set:Nn \l_tmpa_int { \tex_interactionmode:D }
|
||||
\int_set:Nn \tex_interactionmode:D { 0 }
|
||||
\int_set:Nn \tex_showboxdepth:D { \c_max_int }
|
||||
\int_set:Nn \tex_showboxbreadth:D { \c_max_int }
|
||||
\tex_showlists:D
|
||||
\int_set:Nn \tex_interactionmode:D { \l_tmpa_int }
|
||||
\group_end:
|
||||
}
|
||||
|
||||
\int_new:N \g__luamml_formula_id_int
|
||||
\cs_new_protected:Npn \luamml_pdf_write: {
|
||||
\int_gincr:N \g__luamml_formula_id_int
|
||||
\iow_log:x {
|
||||
LUAMML_FORMULA_BEGIN:
|
||||
\int_use:N \g__luamml_formula_id_int
|
||||
}
|
||||
\__luamml_pdf_showlists:
|
||||
\iow_log:x {
|
||||
LUAMML_FORMULA_END
|
||||
}
|
||||
}
|
||||
|
||||
\cs_new:Npn \luamml_pdf_last_formula: {
|
||||
\int_use:N \g__luamml_formula_id_int
|
||||
}
|
||||
|
||||
\cs_generate_variant:Nn \tl_to_str:n { e }
|
||||
|
||||
% annotate parameters
|
||||
% #1 number of top level nodes to be annotated
|
||||
% #2 annotation
|
||||
% #3 nodes to be annotated
|
||||
\int_new:N \g__luamml_annotation_id_int
|
||||
\cs_new_protected:Npn \luamml_pdf_annotate:nnn #1#2#3 {
|
||||
\int_gincr:N \g__luamml_annotation_id_int
|
||||
\iow_shipout_x:Nx \c_log_iow {
|
||||
\tl_to_str:e {
|
||||
LUAMML_MARK:
|
||||
\int_use:N \g__luamml_annotation_id_int
|
||||
:
|
||||
count = \int_eval:n {#1},
|
||||
#2
|
||||
}
|
||||
\exp_not:N \iow_newline:
|
||||
LUAMML_MARK_END
|
||||
}
|
||||
#3
|
||||
}
|
||||
|
||||
% annotate parameters
|
||||
% #1 annotation
|
||||
% #2 nodes to be annotated
|
||||
% THIS VERSION IS SIGNIFICANTLY SLOWER
|
||||
\cs_new_protected:Npn \luamml_pdf_annotate:nn #1#2 {
|
||||
\int_gincr:N \g__luamml_annotation_id_int
|
||||
\iow_write:Nx \c_log_iow {
|
||||
LUAMML_COUNT_BEGIN:
|
||||
\int_use:N \g__luamml_annotation_id_int
|
||||
}
|
||||
\__luamml_pdf_showlists:
|
||||
\iow_shipout:Nx \c_log_iow {
|
||||
LUAMML_MARK:
|
||||
\int_use:N \g__luamml_annotation_id_int
|
||||
:
|
||||
#1
|
||||
}
|
||||
#2
|
||||
\iow_write:Nx \c_log_iow {
|
||||
LUAMML_COUNT_END:
|
||||
\int_use:N \g__luamml_annotation_id_int
|
||||
}
|
||||
\__luamml_pdf_showlists:
|
||||
}
|
||||
|
||||
\endinput
|
||||
|
||||
\cs_new:Npn \__luamml_patch_package:nn #1 #2 {
|
||||
\@ifpackageloaded {#1} {#2} {
|
||||
\hook_gput_code:nnn {package/after/#1} {luamml} {#2}
|
||||
}
|
||||
}
|
||||
\cs_new:Npn \__luamml_patch_package:n #1 {
|
||||
\__luamml_patch_package:nn {#1} {
|
||||
\RequirePackage { luamml-patches-#1 }
|
||||
}
|
||||
}
|
||||
\RequirePackage { luamml-patches-kernel }
|
||||
\__luamml_patch_package:n {amsmath}
|
||||
\__luamml_patch_package:n {array}
|
@ -2,15 +2,23 @@ local l = lpeg or require'lpeg'
|
||||
|
||||
local line = (1-l.P'\n')^0 * '\n'
|
||||
|
||||
local list_block = (l.C(l.S'\\._^/ps' * (1-l.P'\n')^0)^-1 * '\n')^0
|
||||
local id = l.R'09'/tonumber
|
||||
local non_final_list_block = (l.C((1-l.P'\n')^0) * '\n' - '### ')^0
|
||||
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'
|
||||
* list_block)^1
|
||||
local generic_list_block = '### ' * line * list_block
|
||||
local luamml_block = l.Ct('LUAMML_META_BEGIN\n\n'
|
||||
* (math_lists_block + generic_list_block/0)^0
|
||||
* (line - 'LUAMML_META_END\n')^0
|
||||
* 'LUAMML_META_END\n')
|
||||
local log_file = l.Ct((luamml_block + line)^0)
|
||||
* non_final_list_block)^1
|
||||
local generic_list_block = '### ' * (line - 'current page:') * non_final_list_block
|
||||
local luamml_block = l.Cg('LUAMML_FORMULA_BEGIN:' * id * l.P'\n'^1 * l.Ct(
|
||||
(math_lists_block + generic_list_block/0)^0
|
||||
* (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')
|
||||
|
||||
local function multi_table_set(t, key, value, table)
|
||||
assert(t[table])[key] = value
|
||||
return t
|
||||
end
|
||||
local log_file = l.Cf(l.Ct(l.Cg(l.Ct'', 'groups') * l.Cg(l.Ct'', 'marks')) * (luamml_block + luamml_mark + line)^0, multi_table_set)
|
||||
|
||||
return function(filename)
|
||||
local f
|
||||
|
@ -1,3 +1,7 @@
|
||||
require'pdfmml-emulate-node'
|
||||
|
||||
local properties = node.get_properties_table()
|
||||
|
||||
local l = lpeg or require'lpeg'
|
||||
local hex_digit = l.R('09', 'af')
|
||||
local function hex_to_int(s) return tonumber(s, 16) end
|
||||
@ -22,12 +26,12 @@ local math_char = l.Ct('\\fam' * l.Cg(l.R'09'^1 / tonumber, 'fam') * ' ' * l.Cg(
|
||||
local simple_noad = l.Ct(
|
||||
'\\math' * l.Cg(
|
||||
'ord' * l.Cc(0)
|
||||
+ 'open' * l.Cc(6)
|
||||
+ 'op\\limits' * l.Cc(2)
|
||||
+ 'op\\nolimits' * l.Cc(3)
|
||||
+ 'op' * l.Cc(1)
|
||||
+ 'bin' * l.Cc(4)
|
||||
+ 'rel' * l.Cc(5)
|
||||
+ 'open' * l.Cc(6)
|
||||
+ 'close' * l.Cc(7)
|
||||
+ 'punct' * l.Cc(8)
|
||||
+ 'inner' * l.Cc(9)
|
||||
@ -60,6 +64,8 @@ local fraction_noad = l.Ct('\\fraction, thickness '
|
||||
|
||||
local mathchoice_noad = l.Ct('\\mathchoice' * l.Cg(l.Cc'choice', 'id') * -1)
|
||||
|
||||
local mark_whatsit = '\\write-{LUAMML_MARK:' * (l.R'09'/tonumber) * ':'
|
||||
|
||||
local parse_list
|
||||
local function parse_kernel(lines, i, prefix)
|
||||
local line = lines[i]
|
||||
@ -69,11 +75,14 @@ local function parse_kernel(lines, i, prefix)
|
||||
result, i = parse_list(lines, i, prefix)
|
||||
return {list = result, id = 'sub_mlist'}, i
|
||||
end
|
||||
function parse_list(lines, i, prefix)
|
||||
function parse_list(lines, i, prefix, marks)
|
||||
i = i or 1
|
||||
prefix = prefix or ''
|
||||
local head, last
|
||||
local mark_environment = {}
|
||||
local current_mark, current_count, current_offset
|
||||
while true do
|
||||
local skip
|
||||
local line = lines[i]
|
||||
if not line or line:sub(1, #prefix) ~= prefix then break end
|
||||
local simple = simple_noad:match(line, #prefix+1)
|
||||
@ -105,6 +114,13 @@ function parse_list(lines, i, prefix)
|
||||
mathchoice.prev, last.next = last, mathchoice
|
||||
end
|
||||
last = mathchoice
|
||||
else
|
||||
skip = true
|
||||
local mark = mark_whatsit:match(line)
|
||||
if mark then
|
||||
local mark_table = assert(load('return {' .. assert(marks[mark], 'Undefined mark encountered') .. '}', nil, 't', mark_environment))()
|
||||
current_mark, current_count, current_offset = mark_table, mark_table.count or 1, mark_table.offset or 1
|
||||
i = i + 1
|
||||
else
|
||||
print(line, prefix, i)
|
||||
print('unknown noad ' .. line:sub(#prefix+1))
|
||||
@ -112,7 +128,18 @@ function parse_list(lines, i, prefix)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not head then head = last end
|
||||
if not skip and current_mark then
|
||||
current_count = current_count - 1
|
||||
current_offset = current_offset - 1
|
||||
if current_offset == 0 then
|
||||
properties[current_mark.nucleus and last.nucleus or last] = {mathml_core = current_mark.core}
|
||||
else
|
||||
properties[last] = {mathml_core = false}
|
||||
end
|
||||
if current_count == 0 then current_mark = nil end
|
||||
end
|
||||
end
|
||||
return head, i
|
||||
end
|
||||
|
@ -17,9 +17,9 @@ end
|
||||
local math_lists = assert(parse_log(arg[1]))
|
||||
|
||||
local out_stream = arg[2] and arg[2] ~= '-' and assert(io.open(arg[2], 'w')) or io.stdout
|
||||
for i, block in ipairs(math_lists) do
|
||||
for i, block in ipairs(math_lists.groups) do
|
||||
block = block[1]
|
||||
local parsed = parse_showlists(block)
|
||||
local parsed = parse_showlists(block, nil, nil, math_lists.marks)
|
||||
local style = block.display and 0 or 2
|
||||
out_stream:write(
|
||||
to_xml(convert.make_root(convert.process(parsed, style), style))
|
Loading…
Reference in New Issue
Block a user