vcard.lua 3.3KB

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