aboutsummaryrefslogtreecommitdiff
path: root/src/ical.peg
blob: 9d6d29f7d60b6323475e616312d11e5c86b084c4 (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * PEG.js grammar for iCal (http://tools.ietf.org/html/rfc5545).
 */

{
    var foldRe = /[\n][ \t]/g;
    
    while (foldRe.test(input)) {
        input = input.replace(foldRe, '');
    }
}

start
  = ContentLineList
  / "" { return []; }

ContentLineList
  = head:ContentLine tail:(LineEnd ContentLine)* {
    var result = [head], i = 0;
    for (; i < tail.length; ++i) result.push(tail[i][1]);
    return result;
  }

ContentLine
  = name:Name params:(";" Param)* ":" value:Value {
    var par = [], i = 0;
    for (i = 0; i < params.length; ++i) par.push(params[i][1]);
    return {name:name, params:par, value:value};
  }

Name
  = XName
  / IANAToken

IANAToken
  = token:([A-Za-z0-9-]+) { return token.join(""); }

XName
  = x:"X-" vendor:(VendorID "-")? tok:[A-Za-z0-9-]+ {
    if (vendor !== null) vendor = vendor[0] + '-';
    else vendor = '';
    return x + vendor + tok.join("");
  }

VendorID
  = chars:[A-Za-z0-9]+ {
    return chars.join("");
  }

Param
  = name:ParamName "=" params:ParamValueList {
    return {name:name, values:params};
  }

ParamValueList
  = head:ParamValue tail:("," ParamValue)* {
    var result = [head];
    var i = 0;
    for (i = 0; i < tail.length; ++i) result.push(tail[i][1]);
    return result;
  }

ParamName "ParamName"
  = XName
  / IANAToken

ParamValue "ParamValue"
  = QuotedString / ParamText

ParamText "ParamText"
  = chars:SAFE_CHAR* { return chars.join(""); }

Value "Value"
  = chars:VALUE_CHAR* { return chars.join(""); }

QuotedString "QuotedString"
  = '"' chars:QSAFE_CHAR* '"' { return '"' + chars.join("") + '"'; }

// Not double quote or CONTROL
QSAFE_CHAR "QSAFE_CHAR"
  = [^"\x00-\x08\x0A-\x1F\x7F]

// Any but double quote, control, ;, :, ,
SAFE_CHAR "SAFE_CHAR"
  = [^"\x00-\x08\x0A-\x1F\x7F;:,]

VALUE_CHAR "VALUE_CHAR"
  = [^\x00-\x08\x0A-\x1F\x7F]

NON_US_ASCII
  = UTF8_2
  / UTF8_3
  / UTF8_4

CONTROL
  = [\x00-\x08\x0A-\x1F\x7F]

LineEnd "LineEnd"
  = CR LF
  / LF

CR "CR"
  = "\r"

LF "LF"
  = "\n"


UTF8_Octets
  = UTF8_Char*

UTF8_Char
  = UTF8_1
  / UTF8_2
  / UTF8_3
  / UTF8_4

UTF8_1
  = [\x00-\x7F]

UTF8_2
  = [\xC2-\xDF] UTF8_Tail

UTF8_3
  = "\xE0" [\xA0-\xBF] UTF8_Tail
  / [\xE1-\xEC] UTF8_Tail2
  / "\xED" [\x80-\x9F] UTF8_Tail
  / [\xEE-\xEF] UTF8_Tail2

UTF8_4
  = "\xF0" [\x90-\xBF] UTF8_Tail2
  / [\xF1-\xF3] UTF8_Tail2 UTF8_Tail
  / "\xF4" [\x80-\x8F] UTF8_Tail2

UTF8_Tail
  = [\x80-\xBF]

UTF8_Tail2
  = UTF8_Tail UTF8_Tail