local function partial(f,x) return function(...) return f(x,...) end end local function kv_syntax(block,line) local k,v = line:match"^([a-z0-9_-]+)%s*=%s*(.*)$" assert(k,"syntax error in kv line: "..line) k = k:gsub("-","_") block[k]=v end local function tuple_syntax(pattern) return function(block,line) local matches = {line:match(pattern)} assert(matches[1], "syntax error in tuple line: "..line) table.insert(block, matches) end end local schema = { pylon = kv_syntax, bus = tuple_syntax"^(%S+)%s+(%S+)$", } local function parse_file(file) local blocks = {} for k in pairs(schema) do blocks[k] = {} end local line_handler = function() error("line outside of block") end for line in file:lines() do line = line:gsub("#.*$",""):gsub("^%s*",""):gsub("%s*$","") if line == '' then goto next end local block_type, block_name = line:match"%[%s*(%S+)%s+(%S+)%s*%]" if block_type then local blocks_of_this_type = assert(blocks[block_type],"no such block type "..block_type) local block = {} blocks_of_this_type[block_name] = block line_handler = partial(schema[block_type], block) else line_handler(line) end ::next:: end return blocks end return {parse=parse_file}