From bd95a21d2b31a5fab1b4cc7c2b0334823fb3a3e9 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 20 May 2013 02:00:00 +0200 Subject: beta 2013.05.20 02:00 --- tex/context/base/math-tag.lua | 690 +++++++++++++++++++++--------------------- 1 file changed, 345 insertions(+), 345 deletions(-) (limited to 'tex/context/base/math-tag.lua') diff --git a/tex/context/base/math-tag.lua b/tex/context/base/math-tag.lua index 3dafaaa2f..ab5902dd4 100644 --- a/tex/context/base/math-tag.lua +++ b/tex/context/base/math-tag.lua @@ -1,345 +1,345 @@ -if not modules then modules = { } end modules ['math-tag'] = { - version = 1.001, - comment = "companion to math-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- use lpeg matchers - -local find, match = string.find, string.match -local insert, remove = table.insert, table.remove - -local attributes, nodes = attributes, nodes - -local set_attributes = nodes.setattributes -local traverse_nodes = node.traverse - -local nodecodes = nodes.nodecodes - -local math_noad_code = nodecodes.noad -- attr nucleus sub sup -local math_accent_code = nodecodes.accent -- attr nucleus sub sup accent -local math_radical_code = nodecodes.radical -- attr nucleus sub sup left degree -local math_fraction_code = nodecodes.fraction -- attr nucleus sub sup left right -local math_box_code = nodecodes.subbox -- attr list -local math_sub_code = nodecodes.submlist -- attr list -local math_char_code = nodecodes.mathchar -- attr fam char -local math_textchar_code = nodecodes.mathtextchar -- attr fam char -local math_delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char -local math_style_code = nodecodes.style -- attr style -local math_choice_code = nodecodes.choice -- attr display text script scriptscript -local math_fence_code = nodecodes.fence -- attr subtype - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glyph_code = nodecodes.glyph -local glue_code = nodecodes.glue - -local a_tagged = attributes.private('tagged') -local a_exportstatus = attributes.private('exportstatus') -local a_mathcategory = attributes.private('mathcategory') -local a_mathmode = attributes.private('mathmode') - -local tags = structures.tags - -local start_tagged = tags.start -local restart_tagged = tags.restart -local stop_tagged = tags.stop -local taglist = tags.taglist - -local chardata = characters.data - -local getmathcode = tex.getmathcode -local mathcodes = mathematics.codes -local ordinary_code = mathcodes.ordinary -local variable_code = mathcodes.variable - -local process - -local function processsubsup(start) - -- At some point we might need to add an attribute signaling the - -- super- and subscripts because TeX and MathML use a different - -- order. - local nucleus, sup, sub = start.nucleus, start.sup, start.sub - if sub then - if sup then - start[a_tagged] = start_tagged("msubsup") - process(nucleus) - process(sub) - process(sup) - stop_tagged() - else - start[a_tagged] = start_tagged("msub") - process(nucleus) - process(sub) - stop_tagged() - end - elseif sup then - start[a_tagged] = start_tagged("msup") - process(nucleus) - process(sup) - stop_tagged() - else - process(nucleus) - end -end - --- todo: check function here and keep attribute the same - --- todo: variants -> original - -local actionstack = { } - -process = function(start) -- we cannot use the processor as we have no finalizers (yet) - while start do - local id = start.id - if id == math_char_code then - local char = start.char - -- check for code - local a = start[a_mathcategory] - if a then - a = { detail = a } - end - local code = getmathcode(char) - if code then - code = code[1] - end - local tag - if code == ordinary_code or code == variable_code then - local ch = chardata[char] - local mc = ch and ch.mathclass - if mc == "number" then - tag = "mn" - elseif mc == "variable" or not mc then -- variable is default - tag = "mi" - else - tag = "mo" - end - else - tag = "mo" - end - start[a_tagged] = start_tagged(tag,a) - stop_tagged() - break -- okay? - elseif id == math_textchar_code then - -- check for code - local a = start[a_mathcategory] - if a then - start[a_tagged] = start_tagged("ms",{ detail = a }) - else - start[a_tagged] = start_tagged("ms") - end - stop_tagged() - break - elseif id == math_delim_code then - -- check for code - start[a_tagged] = start_tagged("mo") - stop_tagged() - break - elseif id == math_style_code then - -- has a next - elseif id == math_noad_code then - processsubsup(start) - elseif id == math_box_code or id == hlist_code or id == vlist_code then - -- keep an eye on math_box_code and see what ends up in there - local attr = start[a_tagged] - local last = attr and taglist[attr] - if last and find(last[#last],"formulacaption[:%-]") then - -- leave alone, will nicely move to the outer level - else - local text = start_tagged("mtext") - start[a_tagged] = text - local list = start.list - if not list then - -- empty list - elseif not attr then - -- box comes from strange place - set_attributes(list,a_tagged,text) - else - -- Beware, the first node in list is the actual list so we definitely - -- need to nest. This approach is a hack, maybe I'll make a proper - -- nesting feature to deal with this at another level. Here we just - -- fake structure by enforcing the inner one. - local tagdata = taglist[attr] - local common = #tagdata + 1 - local function runner(list) -- quite inefficient - local cache = { } -- we can have nested unboxed mess so best local to runner - for n in traverse_nodes(list) do - local id = n.id - local aa = n[a_tagged] - if aa then - local ac = cache[aa] - if not ac then - local tagdata = taglist[aa] - local extra = #tagdata - if common <= extra then - for i=common,extra do - ac = restart_tagged(tagdata[i]) -- can be made faster - end - for i=common,extra do - stop_tagged() -- can be made faster - end - else - ac = text - end - cache[aa] = ac - end - n[a_tagged] = ac - else - n[a_tagged] = text - end - if id == hlist_code or id == vlist_code then - runner(n.list) - end - end - end - runner(list) - end - stop_tagged() - end - elseif id == math_sub_code then - local list = start.list - if list then - local attr = start[a_tagged] - local last = attr and taglist[attr] - local action = last and match(last[#last],"maction:(.-)%-") - if action and action ~= "" then - if actionstack[#actionstack] == action then - start[a_tagged] = start_tagged("mrow") - process(list) - stop_tagged() - else - insert(actionstack,action) - start[a_tagged] = start_tagged("mrow",{ detail = action }) - process(list) - stop_tagged() - remove(actionstack) - end - else - start[a_tagged] = start_tagged("mrow") - process(list) - stop_tagged() - end - end - elseif id == math_fraction_code then - local num, denom, left, right = start.num, start.denom, start.left, start.right - if left then - left[a_tagged] = start_tagged("mo") - process(left) - stop_tagged() - end - start[a_tagged] = start_tagged("mfrac") - process(num) - process(denom) - stop_tagged() - if right then - right[a_tagged] = start_tagged("mo") - process(right) - stop_tagged() - end - elseif id == math_choice_code then - local display, text, script, scriptscript = start.display, start.text, start.script, start.scriptscript - if display then - process(display) - end - if text then - process(text) - end - if script then - process(script) - end - if scriptscript then - process(scriptscript) - end - elseif id == math_fence_code then - local delim = start.delim - local subtype = start.subtype - if subtype == 1 then - -- left - start[a_tagged] = start_tagged("mfenced") - if delim then - start[a_tagged] = start_tagged("mleft") - process(delim) - stop_tagged() - end - elseif subtype == 2 then - -- middle - if delim then - start[a_tagged] = start_tagged("mmiddle") - process(delim) - stop_tagged() - end - elseif subtype == 3 then - if delim then - start[a_tagged] = start_tagged("mright") - process(delim) - stop_tagged() - end - stop_tagged() - else - -- can't happen - end - elseif id == math_radical_code then - local left, degree = start.left, start.degree - if left then - start_tagged("") - process(left) -- root symbol, ignored - stop_tagged() - end - if degree then -- not good enough, can be empty mlist - start[a_tagged] = start_tagged("mroot") - processsubsup(start) - process(degree) - stop_tagged() - else - start[a_tagged] = start_tagged("msqrt") - processsubsup(start) - stop_tagged() - end - elseif id == math_accent_code then - local accent, bot_accent = start.accent, start.bot_accent - if bot_accent then - if accent then - start[a_tagged] = start_tagged("munderover",{ detail = "accent" }) - processsubsup(start) - process(bot_accent) - process(accent) - stop_tagged() - else - start[a_tagged] = start_tagged("munder",{ detail = "accent" }) - processsubsup(start) - process(bot_accent) - stop_tagged() - end - elseif accent then - start[a_tagged] = start_tagged("mover",{ detail = "accent" }) - processsubsup(start) - process(accent) - stop_tagged() - else - processsubsup(start) - end - elseif id == glue_code then - start[a_tagged] = start_tagged("mspace") - stop_tagged() - else - start[a_tagged] = start_tagged("merror", { detail = nodecodes[i] }) - stop_tagged() - end - start = start.next - end -end - -function noads.handlers.tags(head,style,penalties) - local v_math = start_tagged("math") - local v_mrow = start_tagged("mrow") - local v_mode = head[a_mathmode] - head[a_tagged] = v_math - head[a_tagged] = v_mrow - tags.setattributehash(v_math,"mode",v_mode == 1 and "display" or "inline") - process(head) - stop_tagged() - stop_tagged() - return true -end +if not modules then modules = { } end modules ['math-tag'] = { + version = 1.001, + comment = "companion to math-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- use lpeg matchers + +local find, match = string.find, string.match +local insert, remove = table.insert, table.remove + +local attributes, nodes = attributes, nodes + +local set_attributes = nodes.setattributes +local traverse_nodes = node.traverse + +local nodecodes = nodes.nodecodes + +local math_noad_code = nodecodes.noad -- attr nucleus sub sup +local math_accent_code = nodecodes.accent -- attr nucleus sub sup accent +local math_radical_code = nodecodes.radical -- attr nucleus sub sup left degree +local math_fraction_code = nodecodes.fraction -- attr nucleus sub sup left right +local math_box_code = nodecodes.subbox -- attr list +local math_sub_code = nodecodes.submlist -- attr list +local math_char_code = nodecodes.mathchar -- attr fam char +local math_textchar_code = nodecodes.mathtextchar -- attr fam char +local math_delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char +local math_style_code = nodecodes.style -- attr style +local math_choice_code = nodecodes.choice -- attr display text script scriptscript +local math_fence_code = nodecodes.fence -- attr subtype + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph +local glue_code = nodecodes.glue + +local a_tagged = attributes.private('tagged') +local a_exportstatus = attributes.private('exportstatus') +local a_mathcategory = attributes.private('mathcategory') +local a_mathmode = attributes.private('mathmode') + +local tags = structures.tags + +local start_tagged = tags.start +local restart_tagged = tags.restart +local stop_tagged = tags.stop +local taglist = tags.taglist + +local chardata = characters.data + +local getmathcode = tex.getmathcode +local mathcodes = mathematics.codes +local ordinary_code = mathcodes.ordinary +local variable_code = mathcodes.variable + +local process + +local function processsubsup(start) + -- At some point we might need to add an attribute signaling the + -- super- and subscripts because TeX and MathML use a different + -- order. + local nucleus, sup, sub = start.nucleus, start.sup, start.sub + if sub then + if sup then + start[a_tagged] = start_tagged("msubsup") + process(nucleus) + process(sub) + process(sup) + stop_tagged() + else + start[a_tagged] = start_tagged("msub") + process(nucleus) + process(sub) + stop_tagged() + end + elseif sup then + start[a_tagged] = start_tagged("msup") + process(nucleus) + process(sup) + stop_tagged() + else + process(nucleus) + end +end + +-- todo: check function here and keep attribute the same + +-- todo: variants -> original + +local actionstack = { } + +process = function(start) -- we cannot use the processor as we have no finalizers (yet) + while start do + local id = start.id + if id == math_char_code then + local char = start.char + -- check for code + local a = start[a_mathcategory] + if a then + a = { detail = a } + end + local code = getmathcode(char) + if code then + code = code[1] + end + local tag + if code == ordinary_code or code == variable_code then + local ch = chardata[char] + local mc = ch and ch.mathclass + if mc == "number" then + tag = "mn" + elseif mc == "variable" or not mc then -- variable is default + tag = "mi" + else + tag = "mo" + end + else + tag = "mo" + end + start[a_tagged] = start_tagged(tag,a) + stop_tagged() + break -- okay? + elseif id == math_textchar_code then + -- check for code + local a = start[a_mathcategory] + if a then + start[a_tagged] = start_tagged("ms",{ detail = a }) + else + start[a_tagged] = start_tagged("ms") + end + stop_tagged() + break + elseif id == math_delim_code then + -- check for code + start[a_tagged] = start_tagged("mo") + stop_tagged() + break + elseif id == math_style_code then + -- has a next + elseif id == math_noad_code then + processsubsup(start) + elseif id == math_box_code or id == hlist_code or id == vlist_code then + -- keep an eye on math_box_code and see what ends up in there + local attr = start[a_tagged] + local last = attr and taglist[attr] + if last and find(last[#last],"formulacaption[:%-]") then + -- leave alone, will nicely move to the outer level + else + local text = start_tagged("mtext") + start[a_tagged] = text + local list = start.list + if not list then + -- empty list + elseif not attr then + -- box comes from strange place + set_attributes(list,a_tagged,text) + else + -- Beware, the first node in list is the actual list so we definitely + -- need to nest. This approach is a hack, maybe I'll make a proper + -- nesting feature to deal with this at another level. Here we just + -- fake structure by enforcing the inner one. + local tagdata = taglist[attr] + local common = #tagdata + 1 + local function runner(list) -- quite inefficient + local cache = { } -- we can have nested unboxed mess so best local to runner + for n in traverse_nodes(list) do + local id = n.id + local aa = n[a_tagged] + if aa then + local ac = cache[aa] + if not ac then + local tagdata = taglist[aa] + local extra = #tagdata + if common <= extra then + for i=common,extra do + ac = restart_tagged(tagdata[i]) -- can be made faster + end + for i=common,extra do + stop_tagged() -- can be made faster + end + else + ac = text + end + cache[aa] = ac + end + n[a_tagged] = ac + else + n[a_tagged] = text + end + if id == hlist_code or id == vlist_code then + runner(n.list) + end + end + end + runner(list) + end + stop_tagged() + end + elseif id == math_sub_code then + local list = start.list + if list then + local attr = start[a_tagged] + local last = attr and taglist[attr] + local action = last and match(last[#last],"maction:(.-)%-") + if action and action ~= "" then + if actionstack[#actionstack] == action then + start[a_tagged] = start_tagged("mrow") + process(list) + stop_tagged() + else + insert(actionstack,action) + start[a_tagged] = start_tagged("mrow",{ detail = action }) + process(list) + stop_tagged() + remove(actionstack) + end + else + start[a_tagged] = start_tagged("mrow") + process(list) + stop_tagged() + end + end + elseif id == math_fraction_code then + local num, denom, left, right = start.num, start.denom, start.left, start.right + if left then + left[a_tagged] = start_tagged("mo") + process(left) + stop_tagged() + end + start[a_tagged] = start_tagged("mfrac") + process(num) + process(denom) + stop_tagged() + if right then + right[a_tagged] = start_tagged("mo") + process(right) + stop_tagged() + end + elseif id == math_choice_code then + local display, text, script, scriptscript = start.display, start.text, start.script, start.scriptscript + if display then + process(display) + end + if text then + process(text) + end + if script then + process(script) + end + if scriptscript then + process(scriptscript) + end + elseif id == math_fence_code then + local delim = start.delim + local subtype = start.subtype + if subtype == 1 then + -- left + start[a_tagged] = start_tagged("mfenced") + if delim then + start[a_tagged] = start_tagged("mleft") + process(delim) + stop_tagged() + end + elseif subtype == 2 then + -- middle + if delim then + start[a_tagged] = start_tagged("mmiddle") + process(delim) + stop_tagged() + end + elseif subtype == 3 then + if delim then + start[a_tagged] = start_tagged("mright") + process(delim) + stop_tagged() + end + stop_tagged() + else + -- can't happen + end + elseif id == math_radical_code then + local left, degree = start.left, start.degree + if left then + start_tagged("") + process(left) -- root symbol, ignored + stop_tagged() + end + if degree then -- not good enough, can be empty mlist + start[a_tagged] = start_tagged("mroot") + processsubsup(start) + process(degree) + stop_tagged() + else + start[a_tagged] = start_tagged("msqrt") + processsubsup(start) + stop_tagged() + end + elseif id == math_accent_code then + local accent, bot_accent = start.accent, start.bot_accent + if bot_accent then + if accent then + start[a_tagged] = start_tagged("munderover",{ detail = "accent" }) + processsubsup(start) + process(bot_accent) + process(accent) + stop_tagged() + else + start[a_tagged] = start_tagged("munder",{ detail = "accent" }) + processsubsup(start) + process(bot_accent) + stop_tagged() + end + elseif accent then + start[a_tagged] = start_tagged("mover",{ detail = "accent" }) + processsubsup(start) + process(accent) + stop_tagged() + else + processsubsup(start) + end + elseif id == glue_code then + start[a_tagged] = start_tagged("mspace") + stop_tagged() + else + start[a_tagged] = start_tagged("merror", { detail = nodecodes[i] }) + stop_tagged() + end + start = start.next + end +end + +function noads.handlers.tags(head,style,penalties) + local v_math = start_tagged("math") + local v_mrow = start_tagged("mrow") + local v_mode = head[a_mathmode] + head[a_tagged] = v_math + head[a_tagged] = v_mrow + tags.setattributehash(v_math,"mode",v_mode == 1 and "display" or "inline") + process(head) + stop_tagged() + stop_tagged() + return true +end -- cgit v1.2.3