diff --git a/luamml-convert.lua b/luamml-convert.lua index 380865c..79b7994 100644 --- a/luamml-convert.lua +++ b/luamml-convert.lua @@ -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 diff --git a/luamml-pdf.sty b/luamml-pdf.sty new file mode 100644 index 0000000..7f1d751 --- /dev/null +++ b/luamml-pdf.sty @@ -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} diff --git a/pdfmml-logreader.lua b/pdfmml-logreader.lua index d211d56..384345a 100644 --- a/pdfmml-logreader.lua +++ b/pdfmml-logreader.lua @@ -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 diff --git a/pdfmml-showlists.lua b/pdfmml-showlists.lua index 1338946..012046a 100644 --- a/pdfmml-showlists.lua +++ b/pdfmml-showlists.lua @@ -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) @@ -106,13 +115,31 @@ function parse_list(lines, i, prefix) end last = mathchoice else - print(line, prefix, i) - print('unknown noad ' .. line:sub(#prefix+1)) - i = i + 1 + 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)) + i = i + 1 + 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 diff --git a/showlists_test.lua b/pdfmml.lua similarity index 88% rename from showlists_test.lua rename to pdfmml.lua index d5849a3..bf20c51 100755 --- a/showlists_test.lua +++ b/pdfmml.lua @@ -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))