1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#!/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)
|