|
@@ -0,0 +1,85 @@
|
|
1
|
+-- Copyright (c) 2015 Piotr Orzechowski [drzewo.org]. See LICENSE.
|
|
2
|
+-- vCard 2.1, 3.0 and 4.0 LPeg lexer.
|
|
3
|
+
|
|
4
|
+local l = require('lexer')
|
|
5
|
+local token, word_match = l.token, l.word_match
|
|
6
|
+local P, R, S = lpeg.P, lpeg.R, lpeg.S
|
|
7
|
+
|
|
8
|
+local M = {_NAME = 'vcard'}
|
|
9
|
+
|
|
10
|
+-- Whitespace.
|
|
11
|
+local ws = token(l.WHITESPACE, l.space^1)
|
|
12
|
+
|
|
13
|
+-- Required properties.
|
|
14
|
+local required_property = token(l.KEYWORD, word_match({
|
|
15
|
+ 'BEGIN', 'END', 'FN', 'N' --[[ Not required in v4.0. ]], 'VERSION'
|
|
16
|
+}, nil, true)) * #P(':')
|
|
17
|
+
|
|
18
|
+-- Supported properties.
|
|
19
|
+local supported_property = token(l.TYPE, word_match({
|
|
20
|
+ 'ADR', 'AGENT' --[[ Not supported in v4.0. ]], 'ANNIVERSARY' --[[ Supported in v4.0 only. ]],
|
|
21
|
+ 'BDAY', 'CALADRURI' --[[ Supported in v4.0 only. ]], 'CALURI' --[[ Supported in v4.0 only. ]],
|
|
22
|
+ 'CATEGORIES', 'CLASS' --[[ Supported in v3.0 only. ]],
|
|
23
|
+ 'CLIENTPIDMAP' --[[ Supported in v4.0 only. ]], 'EMAIL', 'END',
|
|
24
|
+ 'FBURL' --[[ Supported in v4.0 only. ]], 'GENDER' --[[ Supported in v4.0 only. ]], 'GEO',
|
|
25
|
+ 'IMPP' --[[ Not supported in v2.1. ]], 'KEY', 'KIND' --[[ Supported in v4.0 only. ]],
|
|
26
|
+ 'LABEL' --[[ Not supported in v4.0. ]], 'LANG' --[[ Supported in v4.0 only. ]], 'LOGO',
|
|
27
|
+ 'MAILER' --[[ Not supported in v4.0. ]], 'MEMBER' --[[ Supported in v4.0 only. ]],
|
|
28
|
+ 'NAME' --[[ Supported in v3.0 only. ]], 'NICKNAME' --[[ Not supported in v2.1. ]], 'NOTE', 'ORG',
|
|
29
|
+ 'PHOTO', 'PRODID' --[[ Not supported in v2.1. ]], 'PROFILE' --[[ Not supported in v4.0. ]],
|
|
30
|
+ 'RELATED' --[[ Supported in v4.0 only. ]], 'REV', 'ROLE',
|
|
31
|
+ 'SORT-STRING' --[[ Not supported in v4.0. ]], 'SOUND', 'SOURCE', 'TEL', 'TITLE', 'TZ', 'UID',
|
|
32
|
+ 'URL', 'XML' --[[ Supported in v4.0 only. ]]
|
|
33
|
+}, nil, true)) * #S(':;')
|
|
34
|
+
|
|
35
|
+local identifier = l.alpha^1 * l.digit^0 * (P('-') * l.alnum^1)^0
|
|
36
|
+
|
|
37
|
+-- Extension.
|
|
38
|
+local extension = token(l.TYPE, l.starts_line(S('xX') * P('-') * identifier * #S(':;')))
|
|
39
|
+
|
|
40
|
+-- Parameter.
|
|
41
|
+local parameter = token(l.IDENTIFIER, l.starts_line(identifier * #S(':='))) +
|
|
42
|
+ token(l.STRING, identifier) * #S(':=')
|
|
43
|
+
|
|
44
|
+-- Operators.
|
|
45
|
+local operator = token(l.OPERATOR, S('.:;='))
|
|
46
|
+
|
|
47
|
+-- Group and property.
|
|
48
|
+local group_sequence = token(l.CONSTANT, l.starts_line(identifier)) * token(l.OPERATOR, P('.')) *
|
|
49
|
+ (required_property + supported_property +
|
|
50
|
+ l.token(l.TYPE, S('xX') * P('-') * identifier) * #S(':;'))
|
|
51
|
+-- Begin vCard, end vCard.
|
|
52
|
+local begin_sequence = token(l.KEYWORD, P('BEGIN')) * token(l.OPERATOR, P(':')) *
|
|
53
|
+ token(l.COMMENT, P('VCARD'))
|
|
54
|
+local end_sequence = token(l.KEYWORD, P('END')) * token(l.OPERATOR, P(':')) *
|
|
55
|
+ token(l.COMMENT, P('VCARD'))
|
|
56
|
+
|
|
57
|
+-- vCard version (in v3.0 and v4.0 must appear immediately after BEGIN:VCARD).
|
|
58
|
+local version_sequence = token(l.KEYWORD, P('VERSION')) * token(l.OPERATOR, P(':')) *
|
|
59
|
+ token(l.CONSTANT, l.digit^1 * (P('.') * l.digit^1)^-1)
|
|
60
|
+
|
|
61
|
+-- Data.
|
|
62
|
+local data = token(l.IDENTIFIER, l.any)
|
|
63
|
+
|
|
64
|
+-- Rules.
|
|
65
|
+M._rules = {
|
|
66
|
+ {'whitespace', ws},
|
|
67
|
+ {'begin_sequence', begin_sequence},
|
|
68
|
+ {'end_sequence', end_sequence},
|
|
69
|
+ {'version_sequence', version_sequence},
|
|
70
|
+ {'group_sequence', group_sequence},
|
|
71
|
+ {'required_property', required_property},
|
|
72
|
+ {'supported_property', supported_property},
|
|
73
|
+ {'extension', extension},
|
|
74
|
+ {'parameter', parameter},
|
|
75
|
+ {'operator', operator},
|
|
76
|
+ {'data', data},
|
|
77
|
+}
|
|
78
|
+
|
|
79
|
+-- Folding.
|
|
80
|
+M._foldsymbols = {
|
|
81
|
+ _patterns = {'BEGIN', 'END'},
|
|
82
|
+ [l.KEYWORD] = {['BEGIN'] = 1, ['END'] = -1}
|
|
83
|
+}
|
|
84
|
+
|
|
85
|
+return M
|