parser: Split the input into multiple blocks

parent d6fa02fb
......@@ -57,4 +57,34 @@ function parse_block(block)
return result
Split text into blocks separated by at least one empty line.
Returns an iterator.
function split_blocks(string)
local pos = 0 -- 0 is the last one we /don't/ want.
-- Get the next block (an iterator)
local function next_block()
if not pos then return end
pos = pos + 1 -- Move /after/ the last char of the previous separator
local bstart, bend = string:find("\n\n+", pos)
-- Omit the first character of the separator from the result
if bstart then bstart = bstart - 1 end
-- It's OK to call with nil ‒ we take the rest of the string
local block = string:sub(pos, bstart)
pos = bend
return block
-- Filter out empty results
local function filter_empty()
local result = next_block()
-- Just retry as long as the block are empty
while result and result:len() == 0 do
result = next_block()
return result
return filter_empty
return _M
......@@ -49,3 +49,44 @@ val2: value 2]]))
assert_error(function() B.parse_block("xyz") end)
assert_error(function() B.parse_block(" ") end)
Call the B.split_blocks on inputs. Then go in through the iterator
returned and in the outputs table in tandem, checking the things match.
local function blocks_check(input, outputs)
local exp_i, exp_v = next(outputs)
for b in B.split_blocks(input) do
assert_equal(exp_v, b)
exp_i, exp_v = next(outputs, exp_i)
-- Nothing left.
-- Tests for the split_blocks function.
function test_split_blocks()
-- Just splitting into blocks
blocks_check([[block 1
next line
another line
block 2
multi line]], {[[block 1
next line
another line]], [[block 2
multi line]]})
-- More than one empty line (should not produce extra empty block)
blocks_check([[block 1
block 2]], {'block 1', 'block 2'})
-- Few empty lines at the end - should not produce an empty block
blocks_check([[block 1
block 2
]], {'block 1', 'block 2'})
-- Few empty lines at the beginning - should not produce an empty block
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment