summaryrefslogtreecommitdiff
path: root/cal.lua
blob: 6dd2c6bc1d386fddc10114b7c3b2a3db6834f406 (plain)
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)