diff options
-rw-r--r-- | rst_helpers.lua | 111 | ||||
-rw-r--r-- | rst_parser.lua | 124 |
2 files changed, 119 insertions, 116 deletions
diff --git a/rst_helpers.lua b/rst_helpers.lua index a635996..b30370a 100644 --- a/rst_helpers.lua +++ b/rst_helpers.lua @@ -590,5 +590,116 @@ function helpers.table.simple(raw) return rows end +helpers.list = {} + +do + local c = {} + c.roman = S"ivxlcdm"^1 + c.Roman = S"IVXLCDM"^1 + c.alpha = R"az" - P"i" + c.Alpha = R"AZ" - P"I" + c.digit = R"09"^1 + c.auto = P"#" + + local stripme = S" ()." + local dontstrip = 1 - stripme + local itemstripper = stripme^0 * C(dontstrip^1) * stripme^0 + + local con = function (str) + --print("This is it: >"..str.."<") + str = itemstripper:match(str) + for conv, pat in next, c do + if pat:match(str) then + return conv + end + end + return false + end + helpers.list.conversion = con + + local rnums = { + i = 1, + v = 5, + x = 10, + l = 50, + c = 100, + d = 500, + m = 1000, + } + + local function roman_to_arab (str) + local n = 1 + local curr, succ + local max_three = { } + local value = 0 + while n <= #str do + if curr and curr == max_three[#max_three] then + if #max_three >= 3 then + return "Not a number" + else + max_three[#max_three+1] = curr + end + else + max_three = { curr } + end + + curr = rnums[str:sub(n,n)] + + n = n + 1 + succ = str:sub(n,n) + + if succ and succ ~= "" then + succ = rnums[succ] + if curr < succ then + --n = n + 1 + --value = value + succ - curr + value = value - curr + else + value = value + curr + end + else + value = value + curr + end + end + return value + end + helpers.list.roman_to_arab = roman_to_arab + + local suc = function (str, old) + str, old = itemstripper:match(str), itemstripper:match(old) + local n_str, n_old = tonumber(str), tonumber(old) + if n_str and n_old then -- arabic numeral + return n_str == n_old + 1 + end + + local con_str, con_old = con(str), con(old) + if con_str == "alpha" or + con_str == "Alpha" then + return str:byte() == old:byte() + 1 + else -- “I'm a Roman!” - “A woman?” - “No, *Roman*! - Au!” - “So your father was a woman?” + if not (str:lower() == str or + str:upper() == str) then -- uneven cased --> fail + return false + end + + + local trc = state.roman_cache + n_str = trc[str] or nil + n_old = trc[old] or nil + if not n_str then + n_str = roman_to_arab(str:lower()) + trc[str] = n_str + end + if not n_old then + n_old = roman_to_arab(old:lower()) + trc[old] = n_old + end + --print(n_str, n_old, n_str == n_old + 1 ) + return n_str == n_old + 1 + end + end + helpers.list.successor = suc +end + return helpers diff --git a/rst_parser.lua b/rst_parser.lua index b3e5f27..13f3a2d 100644 --- a/rst_parser.lua +++ b/rst_parser.lua @@ -88,115 +88,6 @@ local utfchar = P{ -- from l-lpeg.lua, modified to use as grammar } -do - local c = {} - c.roman = S"ivxlcdm"^1 - c.Roman = S"IVXLCDM"^1 - c.alpha = R"az" - P"i" - c.Alpha = R"AZ" - P"I" - c.digit = R"09"^1 - c.auto = P"#" - - local stripme = S" ()." - local dontstrip = 1 - stripme - local itemstripper = stripme^0 * C(dontstrip^1) * stripme^0 - - local con = function (str) - --print("This is it: >"..str.."<") - str = itemstripper:match(str) - for conv, pat in next, c do - if pat:match(str) then - return conv - end - end - return false - end - state.conversion = con - - local rnums = { - i = 1, - v = 5, - x = 10, - l = 50, - c = 100, - d = 500, - m = 1000, - } - - local function roman_to_arab (str) - local n = 1 - local curr, succ - local max_three = { } - local value = 0 - while n <= #str do - if curr and curr == max_three[#max_three] then - if #max_three >= 3 then - return "Not a number" - else - max_three[#max_three+1] = curr - end - else - max_three = { curr } - end - - curr = rnums[str:sub(n,n)] - - n = n + 1 - succ = str:sub(n,n) - - if succ and succ ~= "" then - succ = rnums[succ] - if curr < succ then - --n = n + 1 - --value = value + succ - curr - value = value - curr - else - value = value + curr - end - else - value = value + curr - end - end - return value - end - state.roman_to_arab = roman_to_arab - - local suc = function (str, old) - str, old = itemstripper:match(str), itemstripper:match(old) - local n_str, n_old = tonumber(str), tonumber(old) - if n_str and n_old then -- arabic numeral - return n_str == n_old + 1 - end - - local con_str, con_old = con(str), con(old) - if con_str == "alpha" or - con_str == "Alpha" then - return str:byte() == old:byte() + 1 - else -- “I'm a Roman!” - “A woman?” - “No, *Roman*! - Au!” - “So your father was a woman?” - if not (str:lower() == str or - str:upper() == str) then -- uneven cased --> fail - return false - end - - - local trc = state.roman_cache - n_str = trc[str] or nil - n_old = trc[old] or nil - if not n_str then - n_str = roman_to_arab(str:lower()) - trc[str] = n_str - end - if not n_old then - n_old = roman_to_arab(old:lower()) - trc[old] = n_old - end - --print(n_str, n_old, n_str == n_old + 1 ) - return n_str == n_old + 1 - end - - end - state.successor = suc -end local parser = P{ [1] = V"document", @@ -872,7 +763,7 @@ local parser = P{ (t.depth > 0 and n_spaces > 1), bullet, oldbullet, - t.conversion(bullet)) + helpers.list.conversion(bullet)) if t.depth == 0 and n_spaces == 1 then -- first level t.depth = 1 -- “push” @@ -898,23 +789,24 @@ local parser = P{ bullet_cont = Cmt(V"bullet_indent", function (s, i, bullet) local t = state + local conversion = helpers.list.conversion warn("conti", t.depth, bullet == t.bullets[t.depth], bullet, t.bullets[t.depth], t.lastbullets[t.depth], - t.conversion(t.lastbullet), - t.conversion(bullet) + conversion(t.lastbullet), + conversion(bullet) ) if utf.len(t.bullets[t.depth]) ~= utf.len(bullet) then return false - elseif not t.conversion(bullet) and t.bullets[t.depth] == bullet then + elseif not conversion(bullet) and t.bullets[t.depth] == bullet then return true - elseif t.conversion(t.lastbullet) == t.conversion(bullet) then -- same type - local autoconv = t.conversion(bullet) == "auto" - local successor = t.successor(bullet, t.lastbullet) + elseif conversion(t.lastbullet) == conversion(bullet) then -- same type + local autoconv = conversion(bullet) == "auto" + local successor = helpers.list.successor(bullet, t.lastbullet) t.lastbullet = bullet return autoconv or successor end |