varnish.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. """
  2. pygments.lexers.varnish
  3. ~~~~~~~~~~~~~~~~~~~~~~~
  4. Lexers for Varnish configuration
  5. :copyright: Copyright 2006-2021 by the Pygments team, see AUTHORS.
  6. :license: BSD, see LICENSE for details.
  7. """
  8. from pygments.lexer import RegexLexer, include, bygroups, using, this, \
  9. inherit, words
  10. from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
  11. Number, Punctuation, Literal
  12. __all__ = ['VCLLexer', 'VCLSnippetLexer']
  13. class VCLLexer(RegexLexer):
  14. """
  15. For Varnish Configuration Language (VCL).
  16. .. versionadded:: 2.2
  17. """
  18. name = 'VCL'
  19. aliases = ['vcl']
  20. filenames = ['*.vcl']
  21. mimetypes = ['text/x-vclsrc']
  22. def analyse_text(text):
  23. # If the very first line is 'vcl 4.0;' it's pretty much guaranteed
  24. # that this is VCL
  25. if text.startswith('vcl 4.0;'):
  26. return 1.0
  27. # Skip over comments and blank lines
  28. # This is accurate enough that returning 0.9 is reasonable.
  29. # Almost no VCL files start without some comments.
  30. elif '\nvcl 4.0;' in text[:1000]:
  31. return 0.9
  32. tokens = {
  33. 'probe': [
  34. include('whitespace'),
  35. include('comments'),
  36. (r'(\.\w+)(\s*=\s*)([^;]*)(;)',
  37. bygroups(Name.Attribute, Operator, using(this), Punctuation)),
  38. (r'\}', Punctuation, '#pop'),
  39. ],
  40. 'acl': [
  41. include('whitespace'),
  42. include('comments'),
  43. (r'[!/]+', Operator),
  44. (r';', Punctuation),
  45. (r'\d+', Number),
  46. (r'\}', Punctuation, '#pop'),
  47. ],
  48. 'backend': [
  49. include('whitespace'),
  50. (r'(\.probe)(\s*=\s*)(\w+)(;)',
  51. bygroups(Name.Attribute, Operator, Name.Variable.Global, Punctuation)),
  52. (r'(\.probe)(\s*=\s*)(\{)',
  53. bygroups(Name.Attribute, Operator, Punctuation), 'probe'),
  54. (r'(\.\w+\b)(\s*=\s*)([^;\s]*)(\s*;)',
  55. bygroups(Name.Attribute, Operator, using(this), Punctuation)),
  56. (r'\{', Punctuation, '#push'),
  57. (r'\}', Punctuation, '#pop'),
  58. ],
  59. 'statements': [
  60. (r'(\d\.)?\d+[sdwhmy]', Literal.Date),
  61. (r'(\d\.)?\d+ms', Literal.Date),
  62. (r'(vcl_pass|vcl_hash|vcl_hit|vcl_init|vcl_backend_fetch|vcl_pipe|'
  63. r'vcl_backend_response|vcl_synth|vcl_deliver|vcl_backend_error|'
  64. r'vcl_fini|vcl_recv|vcl_purge|vcl_miss)\b', Name.Function),
  65. (r'(pipe|retry|hash|synth|deliver|purge|abandon|lookup|pass|fail|ok|'
  66. r'miss|fetch|restart)\b', Name.Constant),
  67. (r'(beresp|obj|resp|req|req_top|bereq)\.http\.[a-zA-Z_-]+\b', Name.Variable),
  68. (words((
  69. 'obj.status', 'req.hash_always_miss', 'beresp.backend', 'req.esi_level',
  70. 'req.can_gzip', 'beresp.ttl', 'obj.uncacheable', 'req.ttl', 'obj.hits',
  71. 'client.identity', 'req.hash_ignore_busy', 'obj.reason', 'req.xid',
  72. 'req_top.proto', 'beresp.age', 'obj.proto', 'obj.age', 'local.ip',
  73. 'beresp.uncacheable', 'req.method', 'beresp.backend.ip', 'now',
  74. 'obj.grace', 'req.restarts', 'beresp.keep', 'req.proto', 'resp.proto',
  75. 'bereq.xid', 'bereq.between_bytes_timeout', 'req.esi',
  76. 'bereq.first_byte_timeout', 'bereq.method', 'bereq.connect_timeout',
  77. 'beresp.do_gzip', 'resp.status', 'beresp.do_gunzip',
  78. 'beresp.storage_hint', 'resp.is_streaming', 'beresp.do_stream',
  79. 'req_top.method', 'bereq.backend', 'beresp.backend.name', 'beresp.status',
  80. 'req.url', 'obj.keep', 'obj.ttl', 'beresp.reason', 'bereq.retries',
  81. 'resp.reason', 'bereq.url', 'beresp.do_esi', 'beresp.proto', 'client.ip',
  82. 'bereq.proto', 'server.hostname', 'remote.ip', 'req.backend_hint',
  83. 'server.identity', 'req_top.url', 'beresp.grace', 'beresp.was_304',
  84. 'server.ip', 'bereq.uncacheable'), suffix=r'\b'),
  85. Name.Variable),
  86. (r'[!%&+*\-,/<.}{>=|~]+', Operator),
  87. (r'[();]', Punctuation),
  88. (r'[,]+', Punctuation),
  89. (words(('hash_data', 'regsub', 'regsuball', 'if', 'else',
  90. 'elsif', 'elif', 'synth', 'synthetic', 'ban',
  91. 'return', 'set', 'unset', 'import', 'include', 'new',
  92. 'rollback', 'call'), suffix=r'\b'),
  93. Keyword),
  94. (r'storage\.\w+\.\w+\b', Name.Variable),
  95. (words(('true', 'false')), Name.Builtin),
  96. (r'\d+\b', Number),
  97. (r'(backend)(\s+\w+)(\s*\{)',
  98. bygroups(Keyword, Name.Variable.Global, Punctuation), 'backend'),
  99. (r'(probe\s)(\s*\w+\s)(\{)',
  100. bygroups(Keyword, Name.Variable.Global, Punctuation), 'probe'),
  101. (r'(acl\s)(\s*\w+\s)(\{)',
  102. bygroups(Keyword, Name.Variable.Global, Punctuation), 'acl'),
  103. (r'(vcl )(4.0)(;)$',
  104. bygroups(Keyword.Reserved, Name.Constant, Punctuation)),
  105. (r'(sub\s+)([a-zA-Z]\w*)(\s*\{)',
  106. bygroups(Keyword, Name.Function, Punctuation)),
  107. (r'([a-zA-Z_]\w*)'
  108. r'(\.)'
  109. r'([a-zA-Z_]\w*)'
  110. r'(\s*\(.*\))',
  111. bygroups(Name.Function, Punctuation, Name.Function, using(this))),
  112. (r'[a-zA-Z_]\w*', Name),
  113. ],
  114. 'comment': [
  115. (r'[^*/]+', Comment.Multiline),
  116. (r'/\*', Comment.Multiline, '#push'),
  117. (r'\*/', Comment.Multiline, '#pop'),
  118. (r'[*/]', Comment.Multiline),
  119. ],
  120. 'comments': [
  121. (r'#.*$', Comment),
  122. (r'/\*', Comment.Multiline, 'comment'),
  123. (r'//.*$', Comment),
  124. ],
  125. 'string': [
  126. (r'"', String, '#pop'),
  127. (r'[^"\n]+', String), # all other characters
  128. ],
  129. 'multistring': [
  130. (r'[^"}]', String),
  131. (r'"\}', String, '#pop'),
  132. (r'["}]', String),
  133. ],
  134. 'whitespace': [
  135. (r'L?"', String, 'string'),
  136. (r'\{"', String, 'multistring'),
  137. (r'\n', Text),
  138. (r'\s+', Text),
  139. (r'\\\n', Text), # line continuation
  140. ],
  141. 'root': [
  142. include('whitespace'),
  143. include('comments'),
  144. include('statements'),
  145. (r'\s+', Text),
  146. ],
  147. }
  148. class VCLSnippetLexer(VCLLexer):
  149. """
  150. For Varnish Configuration Language snippets.
  151. .. versionadded:: 2.2
  152. """
  153. name = 'VCLSnippets'
  154. aliases = ['vclsnippets', 'vclsnippet']
  155. mimetypes = ['text/x-vclsnippet']
  156. filenames = []
  157. def analyse_text(text):
  158. # override method inherited from VCLLexer
  159. return 0
  160. tokens = {
  161. 'snippetspre': [
  162. (r'\.\.\.+', Comment),
  163. (r'(bereq|req|req_top|resp|beresp|obj|client|server|local|remote|'
  164. r'storage)($|\.\*)', Name.Variable),
  165. ],
  166. 'snippetspost': [
  167. (r'(backend)\b', Keyword.Reserved),
  168. ],
  169. 'root': [
  170. include('snippetspre'),
  171. inherit,
  172. include('snippetspost'),
  173. ],
  174. }