if not modules then modules = { } end modules ['bibl-bib'] = { version = 1.001, comment = "this module is the basis for the lxml-* ones", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } --[[ldx--
This is a prelude to integrated bibliography support. This file just loads bibtex files and converts them to xml so that the we access the content in a convenient way. Actually handling the data takes place elsewhere.
--ldx]]-- local lower, format = string.lower, string.format local next = next bibtex = bibtex or { } bibtex.size = 0 bibtex.definitions = 0 bibtex.shortcuts = 0 local shortcuts = { } local data = { } local entries local function do_shortcut(tag,key,value) bibtex.shortcuts = bibtex.shortcuts + 1 if lower(tag) == "@string" then shortcuts[key] = value end end local function do_definition(tag,key,tab) -- maybe check entries here (saves memory) if not entries or entries[key] then bibtex.definitions = bibtex.definitions + 1 local t = { } for i=1,#tab,2 do t[tab[i]] = tab[i+1] end local p = data[tag] if not p then data[tag] = { [key] = t } else p[key] = t end end end local function resolve(s) return shortcuts[s] or "" end local percent = lpeg.P("%") local start = lpeg.P("@") local comma = lpeg.P(",") local hash = lpeg.P("#") local escape = lpeg.P("\\") local single = lpeg.P("'") local double = lpeg.P('"') local left = lpeg.P('{') local right = lpeg.P('}') local both = left + right local lineending = lpeg.S("\n\r") local space = lpeg.S(" \t\n\r\f") local spacing = space^0 local equal = lpeg.P("=") local collapsed = (space^1)/ " " local function add(a,b) if b then return a..b else return a end end local keyword = lpeg.C((lpeg.R("az","AZ","09") + lpeg.S("@_:-"))^1) -- lpeg.C((1-space)^1) local s_quoted = ((escape*single) + collapsed + (1-single))^0 local d_quoted = ((escape*double) + collapsed + (1-double))^0 local balanced = lpeg.P { [1] = ((escape * (left+right)) + (1 - (left+right)) + lpeg.V(2))^0, [2] = left * lpeg.V(1) * right } local s_value = (single/"") * s_quoted * (single/"") local d_value = (double/"") * d_quoted * (double/"") local b_value = (left /"") * balanced * (right /"") local r_value = keyword/resolve local somevalue = s_value + d_value + b_value + r_value local value = lpeg.Cs((somevalue * ((spacing * hash * spacing)/"" * somevalue)^0)) local assignment = spacing * keyword * spacing * equal * spacing * value * spacing local shortcut = keyword * spacing * left * spacing * (assignment * comma^0)^0 * spacing * right local definition = keyword * spacing * left * spacing * keyword * comma * lpeg.Ct((assignment * comma^0)^0) * spacing * right local comment = keyword * spacing * left * (1-right)^0 * spacing * right local forget = percent^1 * (1-lineending)^0 -- todo \% local grammar = (space + forget + shortcut/do_shortcut + definition/do_definition + comment + 1)^0 function bibtex.convert(session,content) statistics.starttiming(bibtex) data, shortcuts, entries = session.data, session.shortcuts, session.entries -- session.size = session.size + #content bibtex.size = bibtex.size + #content grammar:match(content or "") statistics.stoptiming(bibtex) end function bibtex.load(session,filename) local filename = resolvers.find_file(filename,"bib") if filename ~= "" then bibtex.convert(session,io.loaddata(filename) or "") end end function bibtex.new() return { data = { }, shortcuts = { }, xml = xml.convert("\n