diff options
Diffstat (limited to 'tex/context/base/x-calcmath.lua')
-rw-r--r-- | tex/context/base/x-calcmath.lua | 724 |
1 files changed, 362 insertions, 362 deletions
diff --git a/tex/context/base/x-calcmath.lua b/tex/context/base/x-calcmath.lua index 1394f3450..631cd613b 100644 --- a/tex/context/base/x-calcmath.lua +++ b/tex/context/base/x-calcmath.lua @@ -1,362 +1,362 @@ -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" -} - --- this really needs to be redone - -local format, lower, upper, gsub, sub = string.format, string.lower, string.upper, string.gsub, string.sub -local concat = table.concat -local lpegmatch = lpeg.match - -local calcmath = { } -local moduledata = moduledata or { } -moduledata.calcmath = 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 (gsub(str,tag .. "(%b())", function(body) - return pre .. nsub(sub(body,2,-2),tag,pre,post) .. post - end)) -end - -local function totex(str,mode) - if not frozen then freeze() end - local n = 0 - -- crap - str = gsub(str,"%s+",' ') - -- xml - str = gsub(str,"&(.-);",entities) - -- ...E... - str = gsub(str,"([%-%+]?[%d%.%+%-]+)E([%-%+]?[%d%.]+)", "{\\SCINOT{%1}{%2}}") - -- ^-.. - str = gsub(str,"%^([%-%+]*%d+)", "^{%1}") - -- ^(...) - str = nsub(str,"%^", "^{", "}") - -- 1/x^2 - repeat - str, n = gsub(str,"([%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 = gsub(str,k,v) until n == 0 - end - -- int(a,b) - for k, v in next, list_2_2 do - repeat str, n = gsub(str,k,v) until n == 0 - end - -- int(a) - for k, v in next, list_2_3 do - repeat str, n = gsub(str,k,v) until n == 0 - end - -- sin(x) => {\\sin(x)} - for k, v in next, list_1_1 do - repeat str, n = gsub(str,k,v) until n == 0 - end - -- mean - str = nsub(str, "mean", "\\OVERLINE{", "}") - -- (1+x)/(1+x) => \\FRAC{1+x}{1+x} - repeat - str, n = gsub(str,"(%b())/(%b())", function(a,b) - return "\\FRAC{" .. sub(a,2,-2) .. "}{" .. sub(b,2,-2) .. "}" - end ) - until n == 0 - -- (1+x)/x => \\FRAC{1+x}{x} - repeat - str, n = gsub(str,"(%b())/([%+%-]?[%.%d%w]+)", function(a,b) - return "\\FRAC{" .. sub(a,2,-2) .. "}{" .. b .. "}" - end ) - until n == 0 - -- 1/(1+x) => \\FRAC{1}{1+x} - repeat - str, n = gsub(str,"([%.%d%w]+)/(%b())", function(a,b) - return "\\FRAC{" .. a .. "}{" .. sub(b,2,-2) .. "}" - end ) - until n == 0 - -- 1/x => \\FRAC{1}{x} - repeat - str, n = gsub(str,"([%.%d%w]+)/([%+%-]?[%.%d%w]+)", "\\FRAC{%1}{%2}") - until n == 0 - -- times - str = gsub(str,"%*", " ") - -- symbols -- we can use a table substitution here - str = gsub(str,"([<>=][<>=]*)", 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 = gsub(str,"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 = gsub(str,k,v) - end - -- parenthesis (optional) - if mode == 2 then - str = gsub(str,"%(", "\\left(") - str = gsub(str,"%)", "\\right)") - end - -- csnames - str = gsub(str,"(\\[A-Z]+)", lower) - -- report - return str -end - -calcmath.totex = totex - -function calcmath.tex(str,mode) - context(totex(str)) -end - -function calcmath.xml(id,mode) - context(totex(lxml.id(id).dt[1],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 integer = P("-")^-1 * R("09")^1 - local realpart = P("-")^-1 * R("09")^1 * S(".")^1 * R("09")^1 - local number = Cc("number") * C(integer) * space - local real = Cc("real") * C(realpart) * space - local float = Cc("float") * C(realpart) * lpeg.P("E") * lpeg.C(integer) * space - local identifier = Cc("identifier") * C(R("az","AZ")) * space - local compareop = Cc("compare") * C(P("<") + P("=") + P(">") + P(">=") + P("<=") + P(">") + P("<")) * space - local factorop = Cc("factor") * C(S("+-^_,")) * 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+compareop) * V("factor"))^0), - factor = Ct(V("term") * (termop * V("term"))^0), - term = Ct( - float + real + number + - (open * V("expression") * close) + - (functionop * open * (V("expression") * (P(",") * V("expression"))^0) * close) + - (functionop * V("term")) + - constant + identifier - ), - } - - local parser = space * grammar * -1 - - local function has_factor(t) - for i=1,#t do - if t[i] == "factor" then - return true - end - end - end - - -- can be sped up if needed ... - - function totex(t) - if t then - local one = t[1] - if type(one) == "string" then - local two, three = t[2], t[3] - if one == "number" then - context(two) - elseif one == "real" then - context(two) - elseif one == "float" then - context("\\scinot{",two,"}{",three,"}") - elseif one == "identifier" then - context(two) - elseif one == "constant" then - context("\\"..two) - elseif one == "function" then - if two == "sqrt" then - context("\\sqrt{") - totex(three) - context("}") - elseif two == "exp" then - context(" e^{") - totex(three) - context("}") - elseif two == "abs" then - context("\\left|") - totex(three) - context("\\right|") - elseif two == "mean" then - context("\\overline{") - totex(three) - context("}") - elseif two == "int" or two == "prod" or two == "sum" then - local four, five = t[4], t[5] - if five then - context("\\"..two.."^{") -- context[two]("{") - totex(three) - context("}_{") - totex(four) - context("}") - totex(five) - elseif four then - context("\\"..two.."^{") - totex(three) - context("}") - totex(four) - elseif three then - context("\\"..two.." ") -- " " not needed - totex(three) - else - context("\\"..two) - end - else - context("\\"..two.."(") - totex(three) - context(")") - end - end - else - local nt = #t - local hasfactor = has_factor(t) - if hasfactor then - context("\\left(") - end - totex(one) - for i=2,nt,3 do - local what, how, rest = t[i], t[i+1], t[i+2] - if what == "factor" then - if how == '^' or how == "_" then - context(how) - context("{") - totex(rest) - context("}") - else - context(how) - totex(rest) - end - elseif what == "term" then - if how == '/' then - context("\\frac{") - totex(rest) - context("}{") - totex(t[i+3] or "") - context("}") - elseif how == '*' then - context("\\times") - totex(rest) - else - context(how) - totex(three) - end - elseif what == "compare" then - if two == ">=" then - context("\\ge") - elseif two == "<=" then - context("\\le") - elseif two == ">" then - context(">") - elseif two == "<" then - context("<") - end - totex(three) - end - end - if hasfactor then - context("\\right)") - end - end - end - end - - calcmath = { } - - function calcmath.parse(str) - return lpegmatch(parser,str) - end - - function calcmath.tex(str) - str = totex(lpegmatch(parser,str)) - return (str == "" and "[error]") or str - end - -end +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"
+}
+
+-- this really needs to be redone
+
+local format, lower, upper, gsub, sub = string.format, string.lower, string.upper, string.gsub, string.sub
+local concat = table.concat
+local lpegmatch = lpeg.match
+
+local calcmath = { }
+local moduledata = moduledata or { }
+moduledata.calcmath = 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 (gsub(str,tag .. "(%b())", function(body)
+ return pre .. nsub(sub(body,2,-2),tag,pre,post) .. post
+ end))
+end
+
+local function totex(str,mode)
+ if not frozen then freeze() end
+ local n = 0
+ -- crap
+ str = gsub(str,"%s+",' ')
+ -- xml
+ str = gsub(str,"&(.-);",entities)
+ -- ...E...
+ str = gsub(str,"([%-%+]?[%d%.%+%-]+)E([%-%+]?[%d%.]+)", "{\\SCINOT{%1}{%2}}")
+ -- ^-..
+ str = gsub(str,"%^([%-%+]*%d+)", "^{%1}")
+ -- ^(...)
+ str = nsub(str,"%^", "^{", "}")
+ -- 1/x^2
+ repeat
+ str, n = gsub(str,"([%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 = gsub(str,k,v) until n == 0
+ end
+ -- int(a,b)
+ for k, v in next, list_2_2 do
+ repeat str, n = gsub(str,k,v) until n == 0
+ end
+ -- int(a)
+ for k, v in next, list_2_3 do
+ repeat str, n = gsub(str,k,v) until n == 0
+ end
+ -- sin(x) => {\\sin(x)}
+ for k, v in next, list_1_1 do
+ repeat str, n = gsub(str,k,v) until n == 0
+ end
+ -- mean
+ str = nsub(str, "mean", "\\OVERLINE{", "}")
+ -- (1+x)/(1+x) => \\FRAC{1+x}{1+x}
+ repeat
+ str, n = gsub(str,"(%b())/(%b())", function(a,b)
+ return "\\FRAC{" .. sub(a,2,-2) .. "}{" .. sub(b,2,-2) .. "}"
+ end )
+ until n == 0
+ -- (1+x)/x => \\FRAC{1+x}{x}
+ repeat
+ str, n = gsub(str,"(%b())/([%+%-]?[%.%d%w]+)", function(a,b)
+ return "\\FRAC{" .. sub(a,2,-2) .. "}{" .. b .. "}"
+ end )
+ until n == 0
+ -- 1/(1+x) => \\FRAC{1}{1+x}
+ repeat
+ str, n = gsub(str,"([%.%d%w]+)/(%b())", function(a,b)
+ return "\\FRAC{" .. a .. "}{" .. sub(b,2,-2) .. "}"
+ end )
+ until n == 0
+ -- 1/x => \\FRAC{1}{x}
+ repeat
+ str, n = gsub(str,"([%.%d%w]+)/([%+%-]?[%.%d%w]+)", "\\FRAC{%1}{%2}")
+ until n == 0
+ -- times
+ str = gsub(str,"%*", " ")
+ -- symbols -- we can use a table substitution here
+ str = gsub(str,"([<>=][<>=]*)", 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 = gsub(str,"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 = gsub(str,k,v)
+ end
+ -- parenthesis (optional)
+ if mode == 2 then
+ str = gsub(str,"%(", "\\left(")
+ str = gsub(str,"%)", "\\right)")
+ end
+ -- csnames
+ str = gsub(str,"(\\[A-Z]+)", lower)
+ -- report
+ return str
+end
+
+calcmath.totex = totex
+
+function calcmath.tex(str,mode)
+ context(totex(str))
+end
+
+function calcmath.xml(id,mode)
+ context(totex(lxml.id(id).dt[1],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 integer = P("-")^-1 * R("09")^1
+ local realpart = P("-")^-1 * R("09")^1 * S(".")^1 * R("09")^1
+ local number = Cc("number") * C(integer) * space
+ local real = Cc("real") * C(realpart) * space
+ local float = Cc("float") * C(realpart) * lpeg.P("E") * lpeg.C(integer) * space
+ local identifier = Cc("identifier") * C(R("az","AZ")) * space
+ local compareop = Cc("compare") * C(P("<") + P("=") + P(">") + P(">=") + P("<=") + P(">") + P("<")) * space
+ local factorop = Cc("factor") * C(S("+-^_,")) * 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+compareop) * V("factor"))^0),
+ factor = Ct(V("term") * (termop * V("term"))^0),
+ term = Ct(
+ float + real + number +
+ (open * V("expression") * close) +
+ (functionop * open * (V("expression") * (P(",") * V("expression"))^0) * close) +
+ (functionop * V("term")) +
+ constant + identifier
+ ),
+ }
+
+ local parser = space * grammar * -1
+
+ local function has_factor(t)
+ for i=1,#t do
+ if t[i] == "factor" then
+ return true
+ end
+ end
+ end
+
+ -- can be sped up if needed ...
+
+ function totex(t)
+ if t then
+ local one = t[1]
+ if type(one) == "string" then
+ local two, three = t[2], t[3]
+ if one == "number" then
+ context(two)
+ elseif one == "real" then
+ context(two)
+ elseif one == "float" then
+ context("\\scinot{",two,"}{",three,"}")
+ elseif one == "identifier" then
+ context(two)
+ elseif one == "constant" then
+ context("\\"..two)
+ elseif one == "function" then
+ if two == "sqrt" then
+ context("\\sqrt{")
+ totex(three)
+ context("}")
+ elseif two == "exp" then
+ context(" e^{")
+ totex(three)
+ context("}")
+ elseif two == "abs" then
+ context("\\left|")
+ totex(three)
+ context("\\right|")
+ elseif two == "mean" then
+ context("\\overline{")
+ totex(three)
+ context("}")
+ elseif two == "int" or two == "prod" or two == "sum" then
+ local four, five = t[4], t[5]
+ if five then
+ context("\\"..two.."^{") -- context[two]("{")
+ totex(three)
+ context("}_{")
+ totex(four)
+ context("}")
+ totex(five)
+ elseif four then
+ context("\\"..two.."^{")
+ totex(three)
+ context("}")
+ totex(four)
+ elseif three then
+ context("\\"..two.." ") -- " " not needed
+ totex(three)
+ else
+ context("\\"..two)
+ end
+ else
+ context("\\"..two.."(")
+ totex(three)
+ context(")")
+ end
+ end
+ else
+ local nt = #t
+ local hasfactor = has_factor(t)
+ if hasfactor then
+ context("\\left(")
+ end
+ totex(one)
+ for i=2,nt,3 do
+ local what, how, rest = t[i], t[i+1], t[i+2]
+ if what == "factor" then
+ if how == '^' or how == "_" then
+ context(how)
+ context("{")
+ totex(rest)
+ context("}")
+ else
+ context(how)
+ totex(rest)
+ end
+ elseif what == "term" then
+ if how == '/' then
+ context("\\frac{")
+ totex(rest)
+ context("}{")
+ totex(t[i+3] or "")
+ context("}")
+ elseif how == '*' then
+ context("\\times")
+ totex(rest)
+ else
+ context(how)
+ totex(three)
+ end
+ elseif what == "compare" then
+ if two == ">=" then
+ context("\\ge")
+ elseif two == "<=" then
+ context("\\le")
+ elseif two == ">" then
+ context(">")
+ elseif two == "<" then
+ context("<")
+ end
+ totex(three)
+ end
+ end
+ if hasfactor then
+ context("\\right)")
+ end
+ end
+ end
+ end
+
+ calcmath = { }
+
+ function calcmath.parse(str)
+ return lpegmatch(parser,str)
+ end
+
+ function calcmath.tex(str)
+ str = totex(lpegmatch(parser,str))
+ return (str == "" and "[error]") or str
+ end
+
+end
|