From 93838985e29fdfb11937db920f08b87435c83c2d Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Fri, 3 Sep 2010 12:20:43 +0200 Subject: fixed a serious bug in list nesting --- rst_context.lua | 2 +- rst_parser.lua | 88 ++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 67 insertions(+), 23 deletions(-) diff --git a/rst_context.lua b/rst_context.lua index 8131505..40dd719 100644 --- a/rst_context.lua +++ b/rst_context.lua @@ -227,7 +227,7 @@ local enumeration_types = { local stripme = S"()." local dontstrip = 1 - stripme -local itemstripper = stripme^0 * C(dontstrip) * stripme^0 +local itemstripper = stripme^0 * C(dontstrip^1) * stripme^0 local function parse_itemstring(str) local setup = [[\setupitemize[]] -- string.match is slightly faster than string.find diff --git a/rst_parser.lua b/rst_parser.lua index eb5e6b8..14d23ff 100644 --- a/rst_parser.lua +++ b/rst_parser.lua @@ -23,6 +23,7 @@ local eol = P"\n" local tracklists = {} tracklists.depth = 0 tracklists.bullets = {} -- mapping bullet forms to depth +tracklists.bullets.max = 0 tracklists.lastbullet = "" n = 0 @@ -47,6 +48,32 @@ 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" + c.Alpha = R"AZ" + 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 + tracklists.conversion = con +end + local parser = P{ [1] = V"document", @@ -83,23 +110,22 @@ local parser = P{ -- the next rule handles enumerations as well bullet_list = V"bullet_init" - * (V"bullet_list" - + V"bullet_continue")^0 + --* (V"bullet_list" + --+ V"bullet_continue")^0 + * (V"bullet_continue" + + V"bullet_list")^0 * V"bullet_stop" * Cmt(Cc(nil), function (s, i) local t = tracklists print("[close]>", t.depth) + t.bullets[t.depth] = nil -- “pop” t.depth = t.depth - 1 return true end), bullet_stop = Cs(Cc("")) / rst.stopitemize, - bullet_init = V"eol"^0 - * V"bullet_first" - * V"bullet_itemrest", - - bullet_indent = V"space"^0 * V"bullet_expr" * V"space"^1, + bullet_init = V"eol"^0 * V"bullet_first" * V"bullet_itemrest", bullet_first = #Cmt(V"bullet_indent", function (s, i, bullet) local t = tracklists @@ -108,18 +134,21 @@ local parser = P{ print("[first]>", t.depth, (t.depth == 0 and n_spaces == 1) or - (t.depth > 0 and n_spaces > 1), bullet, oldbullet) + (t.depth > 0 and n_spaces > 1), bullet, oldbullet, + t.conversion(bullet)) if t.depth == 0 and n_spaces == 1 then -- first level - t.depth = 1 + t.depth = 1 -- “push” t.bullets[1] = bullet t.lastbullet = bullet + t.bullets.max = t.bullets.max < t.depth and t.depth or t.bullets.max return true - elseif t.depth > 0 and n_spaces > 1 then -- sublist (of sublist)^0 + elseif t.depth > 0 and n_spaces > 1 then -- sublist (of sublist)^0 if n_spaces >= utf.len(oldbullet) then t.depth = t.depth + 1 t.bullets[t.depth] = bullet t.lastbullet = bullet + t.bullets.max = t.bullets.max < t.depth and t.depth or t.bullets.max return true end end @@ -128,37 +157,50 @@ local parser = P{ --* V"bullet_indent" / rst.startitemize, * Cs(V"bullet_indent") / rst.startitemize, + bullet_indent = V"space"^0 * V"bullet_expr" * V"space"^1, + bullet_cont = Cmt(V"bullet_indent", function (s, i, bullet) local t = tracklists print("[contin]>>", t.depth, bullet == t.bullets[t.depth], bullet, - t.bullets[t.depth]) - return t.bullets[t.depth] == bullet + t.bullets[t.depth], + t.conversion(t.lastbullet), + t.conversion(bullet) + ) + + if utf.len(t.bullets[t.depth]) ~= utf.len(bullet) then + return false + elseif t.bullets[t.depth] == bullet then + return true + elseif t.conversion(t.lastbullet) == t.conversion(bullet) then -- same type + return true + end + return true + --return t.bullets[t.depth] == bullet end) / "", -- ^^^^^ -- otherwise returns the value of V"bullet_indent", not sure why … - bullet_continue = V"eol"^0 + bullet_continue = V"eol"^0 -- ^-1 * V"bullet_cont" * V"bullet_itemrest", bullet_itemrest = Cs(V"bullet_rest" -- first line * ((V"bullet_match" * V"bullet_rest")^0 -- any successive lines * (V"eol" - * (V"bullet_match" * (V"bullet_rest" - V"bullet_expr"))^1)^0)) + * (V"bullet_match" * (V"bullet_rest" - V"bullet_indent"))^1)^0)) / rst.bullet_item, -- ^^^^^^^^^^^^^ -- otherwise matches bullet_first bullet_expr = V"bullet_char" - + (V"number_char" * V"dot") + (P"(" * V"number_char" * P")") - + V"number_char" * P")" - + V"number_char" * #V"space", - - bullet_char = S"*+-" + P"•" + P"‣" + P"⁃", + + (V"number_char" * P")") + + (V"number_char" * V"dot") * #V"space" + + (V"number_char" * #V"space") + , number_char = V"roman_numeral" + V"Roman_numeral" @@ -169,8 +211,8 @@ local parser = P{ bullet_rest = Cs((1 - V"eol")^1 * V"eol"), -- rest of one line - bullet_next = C(V"space"^1), - bullet_match = Cmt(V"bullet_next", function (s, i, this) + bullet_next = V"space"^1, + bullet_match = #Cmt(V"bullet_next", function (s, i, this) local t = tracklists print("[match]>>>", t.depth, @@ -411,6 +453,8 @@ local parser = P{ adornment_char = S[[!"#$%&'()*+,-./:;<=>?@[]^_`{|}~]] + P[[\\]], + bullet_char = S"*+-" + P"•" + P"‣" + P"⁃", + digit = R"09", roman_numeral = S"ivxlcdm"^1, Roman_numeral = S"IVXLCDM"^1, @@ -426,7 +470,7 @@ f:close() print(parser:match(testdata)) print(">>>Last used char>: " ..tracklists.lastbullet.." <<<<") -print(">>>Max list nestin>: "..#tracklists.bullets .." <<<<") +print(">>>Max list nestin>: "..tracklists.bullets.max .." <<<<") --for i,j in next, rst.collected_references do --print (string.format("== %7s => %s <=", i,j)) -- cgit v1.2.3