""" pygments.lexers.dns ~~~~~~~~~~~~~~~~~~~ Pygments lexers for DNS :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re from pygments.token import Comment, Operator, Keyword, Name, String, \ Number, Punctuation, Whitespace, Literal from pygments.lexer import RegexLexer, bygroups, include __all__ = ['DnsZoneLexer'] CLASSES = [ "IN", "CS", "CH", "HS", ] CLASSES_RE = "(" + "|".join(CLASSES) + ')' class DnsZoneLexer(RegexLexer): """ Lexer for DNS zone file .. versionadded:: 2.16 """ flags = re.MULTILINE name = 'Zone' aliases = ['zone'] filenames = [ "*.zone" ] url = "https://datatracker.ietf.org/doc/html/rfc1035" mimetypes = ['text/dns'] tokens = { 'root': [ # Empty/comment line: (r'([ \t]*)(;.*)(\n)', bygroups(Whitespace, Comment.Single, Whitespace)), # Special directives: (r'^\$ORIGIN\b', Keyword, 'values'), (r'^\$TTL\b', Keyword, 'values'), (r'^\$INCLUDE\b', Comment.Preproc, 'include'), # TODO, $GENERATE https://bind9.readthedocs.io/en/v9.18.14/chapter3.html#soa-rr (r'^\$[A-Z]+\b', Keyword, 'values'), # Records: # [] [] [] (r'^(@)([ \t]+)(?:([0-9]+[smhdw]?)([ \t]+))?(?:' + CLASSES_RE + "([ \t]+))?([A-Z]+)([ \t]+)", bygroups(Operator, Whitespace, Number.Integer, Whitespace, Name.Class, Whitespace, Keyword.Type, Whitespace), "values"), (r'^([^ \t\n]*)([ \t]+)(?:([0-9]+[smhdw]?)([ \t]+))?(?:' + CLASSES_RE + "([ \t]+))?([A-Z]+)([ \t]+)", bygroups(Name, Whitespace, Number.Integer, Whitespace, Name.Class, Whitespace, Keyword.Type, Whitespace), "values"), # [] [] [] (r'^(Operator)([ \t]+)(?:' + CLASSES_RE + "([ \t]+))?(?:([0-9]+[smhdw]?)([ \t]+))?([A-Z]+)([ \t]+)", bygroups(Name, Whitespace, Number.Integer, Whitespace, Name.Class, Whitespace, Keyword.Type, Whitespace), "values"), (r'^([^ \t\n]*)([ \t]+)(?:' + CLASSES_RE + "([ \t]+))?(?:([0-9]+[smhdw]?)([ \t]+))?([A-Z]+)([ \t]+)", bygroups(Name, Whitespace, Number.Integer, Whitespace, Name.Class, Whitespace, Keyword.Type, Whitespace), "values"), ], # Parsing values: 'values': [ (r'\n', Whitespace, "#pop"), (r'\(', Punctuation, 'nested'), include('simple-values'), ], # Parsing nested values (...): 'nested': [ (r'\)', Punctuation, "#pop"), include('simple-values'), ], # Parsing values: 'simple-values': [ (r'(;.*)(\n)', bygroups(Comment.Single, Whitespace)), (r'[ \t]+', Whitespace), (r"@\b", Operator), ('"', String, 'string'), (r'[0-9]+[smhdw]?$', Number.Integer), (r'([0-9]+[smhdw]?)([ \t]+)', bygroups(Number.Integer, Whitespace)), (r'\S+', Literal), ], 'include': [ (r'([ \t]+)([^ \t\n]+)([ \t]+)([-\._a-zA-Z]+)([ \t]+)(;.*)?$', bygroups(Whitespace, Comment.PreprocFile, Whitespace, Name, Whitespace, Comment.Single), '#pop'), (r'([ \t]+)([^ \t\n]+)([ \t\n]+)$', bygroups(Whitespace, Comment.PreprocFile, Whitespace), '#pop'), ], "string": [ (r'\\"', String), (r'"', String, "#pop"), (r'[^"]+', String), ] } def analyse_text(text): return text.startswith("$ORIGIN")