summaryrefslogtreecommitdiff
path: root/tex/context/base/chem-ini.lua
blob: 192953ec9830d0894f6f233ded6b5aa1462bf1a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
if not modules then modules = { } end modules ['chem-ini'] = {
    version   = 1.001,
    comment   = "companion to chem-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local format = string.format
local lpegmatch = lpeg.match

local P, R, V, Cc, Cs = lpeg.P, lpeg.R, lpeg.V, lpeg.Cc, lpeg.Cs

local trace_molecules = false  trackers.register("chemistry.molecules",  function(v) trace_molecules = v end)

local report_chemistry = logs.reporter("chemistry")

local context = context

chemistry       = chemistry or { }
local chemistry = chemistry

--[[
<p>The next code is an adaptation of code from Wolfgang Schuster
as posted on the mailing list. This version supports nested
braces and unbraced integers as scripts. We could consider
spaces as terminals for them but first let collect a bunch
of input then.</p>
]]--

-- some lpeg, maybe i'll make an syst-lpg module

local lowercase   = R("az")
local uppercase   = R("AZ")
local backslash   = P("\\")
local csname      = backslash * P(1) * (1-backslash)^0
local plus        = P("+") / "\\textplus "
local minus       = P("-") / "\\textminus "
local digit       = R("09")
local sign        = plus + minus
local cardinal    = digit^1
local integer     = sign^0 * cardinal

local leftbrace   = P("{")
local rightbrace  = P("}")
local nobrace     = 1 - (leftbrace + rightbrace)
local nested      = P { leftbrace * (csname + sign + nobrace + V(1))^0 * rightbrace }
local any         = P(1)

local subscript   = P("_")
local superscript = P("^")
local somescript  = subscript + superscript

local content     = Cs(csname + nested + sign + any)

-- could be made more efficient

local lowhigh    = Cc("\\lohi{%s}{%s}") * subscript   * content * superscript * content / format
local highlow    = Cc("\\hilo{%s}{%s}") * superscript * content * subscript   * content / format
local low        = Cc("\\low{%s}")      * subscript   * content                         / format
local high       = Cc("\\high{%s}")     * superscript * content                         / format
local justtext   = (1 - somescript)^1
local parser     = Cs((csname + lowhigh + highlow + low + high + sign + any)^0)

chemistry.moleculeparser = parser -- can be used to avoid functioncall

function chemistry.molecule(str)
    return lpegmatch(parser,str)
end

function commands.molecule(str)
    if trace_molecules then
        local rep = lpegmatch(parser,str)
        report_chemistry("molecule %s => %s",str,rep)
        context(rep)
    else
        context(lpegmatch(parser,str))
    end
end