#!/usr/bin/env lua --[[-- RFC2445 parser. --]]-- local io = require "io" local ioopen = io.open local string = require "string" local stringformat = string.format local println = function (...) print (stringformat (...)) end local parse_calendar do local lpeg = require "lpeg" local lpegmatch = lpeg.match local C = lpeg.C local Cp = lpeg.Cp local Cs = lpeg.Cs local P = lpeg.P local S = lpeg.S local p_space = P" " local p_cr = P"\r" local p_lf = P"\n" local p_white_fold = S" \t" local p_white = S" \n\r\t\v" local p_eol = p_cr * p_lf + p_lf local p_noeol = P(1) - p_eol --[[-- RFC2445: Long content lines SHOULD be split into a multiple line representations using a line "folding" technique. That is, a long line can be split between any two characters by inserting a CRLF immediately followed by a single linear white space character (i.e., SPACE, US-ASCII decimal 32 or HTAB, US-ASCII decimal 9). --]]-- local p_folded_line_1 = p_noeol^1 * (p_eol / "") local p_folded_line_c = p_white_fold/"" * p_folded_line_1 local p_content_line = Cs(p_folded_line_1 * p_folded_line_c^0) * Cp() local p_skip_line = p_noeol^0 * p_eol * Cp() local parse_content_line = function (raw, pos0) local res, pos1 = lpegmatch (p_content_line, raw, pos0) return res, pos1 end local skip_line = function (raw, pos0) return lpegmatch (p_skip_line, raw, pos0) end local errline = function (pos) end parse_calendar = function (raw, pos0, consumed, nline, nskipped) if pos0 == nil then return parse_calendar (raw, 1, 0, 1) end local cline, pos1 = parse_content_line (raw, pos0) if cline == nil then pos1 = skip_line (raw, pos0) println ("[%d–%d] %d bad content line; skipping", pos0, pos1, nline) nskipped = nskipped + 1 else println ("[%d–%d] %d [%s]", pos0, pos1, nline, cline) end return parse_calendar (raw, pos1, consumed + pos1 - pos0, nline + 1, nskipped) end end local print_calendar do end local loaddata = function (fname) local fh = ioopen (fname, "r") if fh == nil then error ("could not open file " .. fname .. " for reading") end return fh:read ("*a") end local main = function (argv) if #argv ~= 1 then error "pass me a file name, I insist!" end local raw = loaddata (argv [1]) return parse_calendar (raw) end return main (arg)