diff options
author | Taco Hoekwater <taco@elvenkind.com> | 2009-08-23 11:11:32 +0000 |
---|---|---|
committer | Taco Hoekwater <taco@elvenkind.com> | 2009-08-23 11:11:32 +0000 |
commit | 8fc3039c82d48605b5ca8b2eda3f4fdd755681e1 (patch) | |
tree | 3cd9bbdd599bc4d1ac0409e167fee2136e4c0ec9 /Master/texmf-dist/tex/context/base/x-calcmath.lua | |
parent | 850fc99b7cd3ae7a20065531fe866ff7bae642ec (diff) |
this is context 2009.08.19 17:10
git-svn-id: svn://tug.org/texlive/trunk@14827 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/x-calcmath.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/x-calcmath.lua | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/x-calcmath.lua b/Master/texmf-dist/tex/context/base/x-calcmath.lua new file mode 100644 index 00000000000..fcb6b7470a6 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/x-calcmath.lua @@ -0,0 +1,334 @@ +if not modules then modules = { } end modules ['x-calcmath'] = { + version = 1.001, + comment = "companion to x-calcmath.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local format, lower, upper, gsub = string.format, string.lower, string.upper, string.gsub + +tex = tex or { } + +texsprint = tex.sprint or function(catcodes,str) print(str) end + +calcmath = { } + +local list_1 = { + "median", "min", "max", "round", "ln", "log", + "sin", "cos", "tan", "sinh", "cosh", "tanh" +} +local list_2 = { + "int", "sum", "prod" +} +local list_3 = { + "f", "g" +} +local list_4 = { + "pi", "inf" +} + +local list_1_1 = { } +local list_2_1 = { } +local list_2_2 = { } +local list_2_3 = { } +local list_4_1 = { } + +local frozen = false + +local function freeze() + for k=1,#list_1 do + local v = list_1[k] + list_1_1[v] = "\\".. upper(v) .." " + end + for k=1,#list_2 do + local v = list_2[k] + list_2_1[v .. "%((.-),(.-),(.-)%)"] = "\\" .. upper(v) .. "^{%1}_{%2}{%3}" + list_2_2[v .. "%((.-),(.-)%)"] = "\\" .. upper(v) .. "^{%1}{%2}" + list_2_3[v .. "%((.-)%)"] = "\\" .. upper(v) .. "{%1}" + end + for k=1,#list_4 do + local v = list_4[k] + list_4_1[v] = "\\" .. upper(v) + end + frozen = true +end + +local entities = { + ['gt'] = '>', + ['lt'] = '<', +} + +local symbols = { + ["<="] = "\\LE ", + [">="] = "\\GE ", + ["=<"] = "\\LE ", + ["=>"] = "\\GE ", + ["=="] = "\\EQ ", + ["<" ] = "\\LT ", + [">" ] = "\\GT ", + ["="] = "\\EQ ", +} + +local function nsub(str,tag,pre,post) + return (str:gsub(tag .. "(%b())", function(body) + return pre .. nsub(body:sub(2,-2),tag,pre,post) .. post + end)) +end + +function calcmath.totex(str,mode) + if not frozen then freeze() end + local n = 0 + -- crap + str = str:gsub("%s+" , ' ') + -- xml + str = str:gsub("&(.-);", entities) + -- ...E... + str = str:gsub("([%-%+]?[%d%.%+%-]+)E([%-%+]?[%d%.]+)", "{\\SCINOT{%1}{%2}}") + -- ^-.. + str = str:gsub( "%^([%-%+]*%d+)", "^{%1}") + -- ^(...) + str = nsub(str, "%^", "^{", "}") + -- 1/x^2 + repeat + str, n = str:gsub("([%d%w%.]+)/([%d%w%.]+%^{[%d%w%.]+})", "\\frac{%1}{%2}") + until n == 0 + -- todo: autoparenthesis + -- int(a,b,c) + for k, v in next, list_2_1 do + repeat str, n = str:gsub(k,v) until n == 0 + end + -- int(a,b) + for k, v in next, list_2_2 do + repeat str, n = str:gsub(k, v) until n == 0 + end + -- int(a) + for k, v in next, list_2_3 do + repeat str, n = str:gsub(k, v) until n == 0 + end + -- sin(x) => {\\sin(x)} + for k, v in next, list_1_1 do + repeat str, n = str:gsub(k, v) until n == 0 + end + -- mean + str = nsub(str, "mean", "\\OVERLINE{", "}") + -- (1+x)/(1+x) => \\FRAC{1+x}{1+x} + repeat + str, n = str:gsub("(%b())/(%b())", function(a,b) + return "\\FRAC{" .. a:sub(2,-2) .. "}{" .. b:sub(2,-2) .. "}" + end ) + until n == 0 + -- (1+x)/x => \\FRAC{1+x}{x} + repeat + str, n = str:gsub("(%b())/([%+%-]?[%.%d%w]+)", function(a,b) + return "\\FRAC{" .. a:sub(2,-2) .. "}{" .. b .. "}" + end ) + until n == 0 + -- 1/(1+x) => \\FRAC{1}{1+x} + repeat + str, n = str:gsub("([%.%d%w]+)/(%b())", function(a,b) + return "\\FRAC{" .. a .. "}{" .. b:sub(2,-2) .. "}" + end ) + until n == 0 + -- 1/x => \\FRAC{1}{x} + repeat + str, n = str:gsub("([%.%d%w]+)/([%+%-]?[%.%d%w]+)", "\\FRAC{%1}{%2}") + until n == 0 + -- times + str = str:gsub("%*", " ") + -- symbols -- we can use a table substitution here + str = str:gsub("([<>=][<>=]*)", symbols) + -- functions + str = nsub(str, "sqrt", "\\SQRT{", "}") + str = nsub(str, "exp", "e^{", "}") + str = nsub(str, "abs", "\\left|", "\\right|") + -- d/D + str = nsub(str, "D", "{\\FRAC{\\MBOX{d}}{\\MBOX{d}x}{(", ")}}") + str = str:gsub("D([xy])", "\\FRAC{{\\RM d}%1}{{\\RM d}x}") + -- f/g + for k,v in next, list_3 do -- todo : prepare k,v + str = nsub(str, "D"..v,"{\\RM "..v.."}^{\\PRIME}(",")") + str = nsub(str, v,"{\\RM "..v.."}(",")") + end + -- more symbols + for k,v in next, list_4_1 do + str = str:gsub(k, v) + end + -- parenthesis (optional) + if mode == 2 then + str = str:gsub("%(", "\\left\(") + str = str:gsub("%)", "\\right\)") + end + -- csnames + str = str:gsub("(\\[A-Z]+)", lower) + -- trace +--~ print(str) + -- report + return str +end + +function calcmath.tex(str,mode) + texsprint(tex.texcatcodes,calcmath.totex(str)) +end + +function calcmath.xml(id,mode) + local str = lxml.id(id).dt[1] + texsprint(tex.texcatcodes,calcmath.totex(str,mode)) +end + +-- work in progress ... lpeg variant + +if false then + + -- todo: + + -- maybe rewrite to current lpeg, i.e. string replacement and no Cc's + + -- table approach we have now is less efficient but more flexible + + -- D \frac {\rm d} {{\rm d}x} + -- Dx Dy \frac {{\rm d}y} {{\rm d}x} + -- Df Dg {\rm f}^{\prime} + -- f() g() {\rm f}() + + -- valid utf8 + + local S, P, R, C, V, Cc, Ct = lpeg.S, lpeg.P, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Ct + + local space = S(" \n\r\t")^0 + local number_x = P("-")^-1 * R("09")^1 + local real_x = P("-")^-1 * R("09")^1 * S(".")^1 * R("09")^1 + local number = Cc("number") * C(number_x) * space + local real = Cc("real") * C(real_x) * space + local float = Cc("float") * C(real_x) * lpeg.P("E") * lpeg.C(number_x) * space + local identifier = Cc("identifier") * C(R("az","AZ")^1) * space + local compareop = P("<") + P("=") + P(">") + P(">=") + P("<=") + P(">") + P("<") + local factorop = Cc("factor") * C(S("+-^,") + compareop ) * space + local termop = Cc("term") * C(S("*/")) * space + local constant = Cc("constant") * C(P("pi") + lpeg.P("inf")) * space + local functionop = Cc("function") * C(R("az")^1) * space + local open = P("(") * space + local close = P(")") * space + + local grammar = P { + "expression", + expression = Ct(V("factor" ) * (factorop * V("factor" ))^0), + factor = Ct(V("term" ) * (termop * V("term" ))^0), + term = Ct( + float + real + number + + (open * V("expression") * close) + + (functionop * open * V("expression") * close) + + constant + identifier + ), + } + + local parser = space * grammar * -1 + + function totex(t) + if t then + local one, two, three = t[1], t[2], t[3] + if one == "number" then + return two + elseif one == "real" then + return two + elseif one == "float" then + return format("\\scinot{%s}{%s}", two, three) + elseif one == "identifier" then + return format(" %s ", two) + elseif one == "constant" then + return format("\\%s ", two) + elseif one == "function" then + if two == "sqrt" then + return format("\\sqrt{%s}", totex(three)) + elseif two == "exp" then + return format(" e^{%s}", totex(three)) + elseif two == "abs" then + return format("\\left|%s\\right|", totex(three)) + elseif two == "mean" then + return format("\\overline{%s}", totex(three)) + elseif two == "int" or two == "prod" or two == "sum" then --brrr, we need to parse better for ,, + local tt = three + if #tt == 1 then + return format("\\%s{%s}", two ,totex(tt[1])) + elseif #tt == 4 then + return format("\\%s^{%s}{%s}", two ,totex(tt[1]), totex(tt[4])) + elseif #tt == 7 then + return format("\\%s^{%s}_{%s}{%s}", two ,totex(tt[1]), totex(tt[4]), totex(tt[7])) + end + elseif #two == 1 then + return format("%s(%s)", two, totex(three)) + else + return format("\\%s(%s)", two, totex(three)) + end + elseif one == "factor" then + if two == '^' then + return format("^{%s}%s",totex(three), (#t>3 and totex({unpack(t,4,#t)})) or "") + else + if two == ">=" then + two = "\\ge " + elseif two == "<=" then + two = "\\le " + elseif two == ">" then + two = "> " + elseif two == "<" then + two = "< " + end + return format("%s%s%s", two, totex(three), (#t>3 and totex({unpack(t,4,#t)})) or "") + end + elseif one == "term" then + if two == '/' then + if #t > 4 then + return format("\\frac{%s}{%s}", totex(three), totex({unpack(t,4,#t)})) + else + return format("\\frac{%s}{%s}", totex(three), totex(t[4])) + end + elseif two == '*' then + local times = "\\times " + return format("%s%s%s", times, totex(three), (#t>3 and totex({unpack(t,4,#t)})) or "") + else + return format("%s%s%s", two, totex(three), (#t>3 and totex({unpack(t,4,#t)})) or "") + end + elseif two == "factor" then + if three == '^' then + return format("%s^{%s}", totex(one), totex(t[4])) + else + if two == ">=" then + two = "\\ge " + elseif two == "<=" then + two = "\\le " + elseif two == ">" then + two = "> " + elseif two == "<" then + two = "< " + end + return format("%s%s", totex(one), (#t>1 and totex({unpack(t,2,#t)})) or "") + end + elseif two == "term" then + if three == '/' then + return format("\\frac{%s}{%s}", totex(one), (#t>3 and totex({unpack(t,4,#t)})) or "") + else + return format("%s%s", totex(one), (#t>1 and totex({unpack(t,2,#t)})) or "") + end + else + return totex(one) + end + end + return "" + end + + calcmath = { } + + function calcmath.parse(str) + return parser:match(str) + end + + function calcmath.tex(str) + str = totex(parser:match(str)) + print(str) + return (str == "" and "[error]") or str + end + +end + +--~ compareop = Cc("compare") * C(P("<") + P("=") + P(">") + P(">=") + P("<=") + P(">")/">" + P("<")/"<") * space +--~ comparison = Ct(V("expression") * (compareop * V("expression"))^0), |