varnish.py 7.1 KB

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