aboutsummaryrefslogblamecommitdiffstats
path: root/test/readme.lua
blob: 17f831283f7a9e47fc757f74dd8ef4148cfecf34 (plain) (tree)



















































































































                                                                                         
local lpeg = require 'lpeg'
local test = require 'test'
local io = require 'io'

local format = string.format
local pack = table.pack
local concat = table.concat

local readme_parser
do
	local P = lpeg.P
	local Ct = lpeg.Ct
	local C = lpeg.C
	local Cc = lpeg.Cc

	local sp = P(' ')
	local eq = P('=')
	local nl = P('\n')
	local div = P(' -- returns ')
	local non_nl = P(1)-nl

	local example = Ct(Cc('example') * C(((P(1)-(div+nl))^1)) * div * C(non_nl^1))
	local assign_left = P('local ')^-1 * C(((P(1)-((sp^0 * eq)+nl))^1))
	local assign_mid = sp^1 * eq * sp^1
	local assign_right = C(non_nl^1)
	local assignment = Ct(Cc('assignment') * assign_left * assign_mid * assign_right)
	local indented_line = sp^2 * (example + assignment)
	local anyline = non_nl^0
	local line = indented_line + anyline

	readme_parser = Ct((line * nl)^0 * line^-1 * -1)
end

local env = {
	tostring = tostring,
	require = require,
}

local function run(name, code)
	local f = assert(load(code, name, 't', env))
	local ret = pack(pcall(f))
	if ret[1] then
		return ret
	else
		print()
		print('code:', code)
		print('error:', ret[2])
		print()
		return { true, nil, n=3 }
	end
end

local function run_example(name, code)
	return run(name, format('return %s', code))
end

local function pack2str(t)
	local new = {}
	local n = t.n
	for i=2,n do
		local v = t[i]
		local vt = type(v)
		if vt == 'nil' then
			new[i] = 'nil'
		else
			new[i] = format('%s "%s"', vt, v)
		end
	end
	return concat(new, ', ', 2, n)
end

local function compare_packs(a, b)
	local n = a.n
	if n ~= b.n then return false end
	for i=1,n do
		local va = a[i]
		local vb = b[i]
		local vat = type(va)
		local vbt = type(vb)
		if vat ~= vbt then return false end
		if va ~= vb then return false end
	end
	return true
end

local function hdl_assignment(line)
	local code = format('%s = %s', line[2], line[3])
	run('assignment', code)
end

local function hdl_example(line)
	local t1 = line[2]
	local t2 = line[3]
	local r1 = run_example('left side', t1)
	local r2 = run_example('right side', t2)
	local errmsg = format('"%s" returns %s, not %s', t1, pack2str(r1), pack2str(r2))
	assert(compare_packs(r1, r2), errmsg)
end

local handlers = {
	assignment = hdl_assignment,
	example = hdl_example,
}

local function readme_test()
	local data = assert(io.open('README.rst', 'r')):read('*a')
	local lines = assert(readme_parser:match(data))
	for i=1,#lines do
		local line = lines[i]
		local kind = line[1]
		local handler = handlers[kind]
		handler(line)
	end
end

return test.new(readme_test)