Commits

Anonymous committed a535e3b

new parser; also revised data structure

Comments (0)

Files changed (2)

 ========================================================================
                               Whose fault?
 ========================================================================
-|rstcontext| was written by Philipp Gesang, ``megas.kapaneus`` at
-``gmail`` dot ``com`` (find me on BitBucket_).
+The Bibelstellen module was written by Philipp Gesang,
+``megas.kapaneus`` at ``gmail`` dot ``com`` (find me on BitBucket_).
 
 ========================================================================
                                 Can I …?

tex/context/third/bstellen/bibelstellen.lua

 --  DESCRIPTION:  typeset bible quotations automagically
 -- REQUIREMENTS:  context mkiv
 --       AUTHOR:  Philipp Gesang (Phg), <megas.kapaneus@gmail.com>
---      VERSION:  hg tip, rev20+
---      CREATED:  13/10/10 01:15:28 CEST
+--      VERSION:  hg tip, rev21+
+--     MODIFIED:  2012-06-02 15:04:40+0200
 ------------------------------------------------------------------------
 --
 
-require "lpeg"
-require "unicode"
+local lpeg    = require "lpeg"
+local unicode = require "unicode"
 
-local C, Ct, P, S, V = lpeg.C, lpeg.Ct, lpeg.P, lpeg.S, lpeg.V
-local lpegmatch      = lpeg.match
+local verbose = false
+
+local     P,      R,      S,      V
+   = lpeg.P, lpeg.R, lpeg.S, lpeg.V
+local    C,      Cf,      Cg,      Cs,      Ct
+  = lpeg.C, lpeg.Cf, lpeg.Cg, lpeg.Cs, lpeg.Ct
+local lpegmatch         = lpeg.match
 
 local contextframed       = context.framed
 local contextpage         = context.page
 local utflower      = unicode.utf8.lower
 
 local warn = function (...)
-    local args = { ... }
-    iowrite("*t-bs*>")
-    for i=1, #args do
-        iowrite(" " .. args[i])
+    if verbose then
+        local args = { ... }
+        iowrite("*t-bs*>")
+        for i=1, #args do
+            iowrite(" " .. args[i])
+        end
+        iowrite"\n"
     end
-    iowrite"\n"
     return 0
 end
 
 
 
 local string_of_file = function (fname)
-    local h = assert(ioopen(fname, "r"), "Not a file: " .. fname)
-    local result = h:read"*all"
-    h:close()
-    if stringmatch(result, "^\239\187\191") then
-        --- utf8 BOM is evil
-        return stringsub(result, 4)
+    local h = ioopen(fname, "r")
+    if h then
+        local result = h:read"*all"
+        h:close()
+        if stringmatch(result, "^\239\187\191") then
+            --- utf8 BOM is evil
+            return stringsub(result, 4)
+        end
+        return result
     end
-    return result
+    warn("File not found: “%s”.", fname)
+    return nil
 end
 
 ------------------------------------------------------------------------
 end
 
 ------------------------------------------------------------------------
--- stellen input parser
+-- old input parser
 ------------------------------------------------------------------------
 local b_parser = P{
     [1] = "file",
 ------------------------------------------------------------------------
 
 local get_data = function (filename)
-    local files = {}
+    local files
     if stringmatch(filename, ",") then
         -- multiple files
         files = stringexplode(filename, ",+")
 
     for _,file in next, files do
         warn("Processing file " .. file)
-        local data = string_of_file(file)
-        lpegmatch(b_parser, data)
+        local raw = string_of_file(file)
+        if raw then
+            lpegmatch(b_parser, raw)
+        end
     end
 
     return 0
 end
 
 ------------------------------------------------------------------------
+--                           refined parser
+------------------------------------------------------------------------
+local get_data
+do
+    --- some terminals first
+    local dash             = P"-"
+    local colon            = P":"
+    local semicolon        = P";"
+    local eol              = P"\n\r" + P"\r\n" + P"\r" + P"\n" / " " -- you never know
+    local eof              = -P(1)
+    local space            = P" "
+    local tabs             = S"\t\v"
+    local whitespace       = (space + tabs)
+    local kv_sep           = whitespace^0 * colon * whitespace^0
+    local blank_line       = whitespace^0 * eol
+    local rest_of_line     = (1 - eol)^0  * eol
+    local comment_line     = semicolon^1 * rest_of_line    -- ignored
+    local blank_or_comment = blank_line + comment_line
+    local key_char         = R("az", "AZ") + dash
+    local key              = C(key_char^1)
+    local separator        = blank_or_comment^0
+                           * whitespace^0 * dash^1 * whitespace^0
+                           * eol
+                           * blank_or_comment^0
+    local non_blank_line   = -#blank_or_comment * rest_of_line
+    local dbg = function (...)
+        local args = { ... }
+        io.write"=>"
+        io.write(args[1])
+        if args[2] then
+            for i=2, #args do
+                io.write(" <> ")
+                io.write(args[i])
+            end
+        end
+        io.write"\n"
+        return ...
+    end
+    --- grammar
+    local stellen_parser = P{
+        "blocks",
+        --"assignments",
+        blocks      = separator^-1
+                    * Ct(V"block"
+                       * (separator * V"block")^0)
+                    * separator^-1
+                    --* eof
+                    ,
+        block       = blank_or_comment^0 * V"assignments",
+        assignments = Cf(Ct"" * Cg(V"kv_pair")^1, rawset),
+        kv_pair     = key -- capture implicit
+                    * kv_sep
+                    * V"value"
+                    * blank_or_comment^0
+                    ,
+        value       = Cs(non_blank_line^1), -- substitutes eols with spaces
+    }
+    get_data = function (filename)
+        local files
+        if stringmatch(filename, ",") then
+            -- multiple files
+            files = stringexplode(filename, ",+")
+        else
+            files = { filename }
+        end
+
+        for _,file in next, files do
+            warn("Processing file " .. file)
+            local raw = string_of_file(file)
+            print">>>>>>>>>>>>>>>>>>>>>>>>>>>"
+            if raw then
+                local data = lpegmatch(stellen_parser, raw)
+                table.print(data)
+                td.stellen.data = data
+            end
+        end
+        return 0
+    end
+end
+
+------------------------------------------------------------------------
 -- typesetting routines
 ------------------------------------------------------------------------
 
     local tdsk = td.stellen.keywords
     local tdsd = td.stellen.data
     local tdsp = td.stellen.parameters
+    --table.print(tdsd)
     contextstartcolumns({
         n        = tdsp.columns,
         distance = "0mm"