"""
    pygments.lexers.yang
    ~~~~~~~~~~~~~~~~~~~~

    Lexer for the YANG 1.1 modeling language. See :rfc:`7950`.

    :copyright: Copyright 2006-2021 by the Pygments team, see AUTHORS.
    :license: BSD, see LICENSE for details.
"""

from pygments.lexer import RegexLexer
from pygments.lexer import bygroups
from pygments.lexer import words
from pygments.token import Comment
from pygments.token import Name
from pygments.token import Number
from pygments.token import String
from pygments.token import Text
from pygments.token import Token

__all__ = ['YangLexer']

class YangLexer(RegexLexer):
    """
    Lexer for `YANG <https://tools.ietf.org/html/rfc7950/>`_, based on RFC7950

    .. versionadded:: 2.7
    """
    name = 'YANG'
    aliases = ['yang']
    filenames = ['*.yang']
    mimetypes = ['application/yang']

    #Keywords from RFC7950 ; oriented at BNF style
    TOP_STMTS_KEYWORDS = ("module", "submodule")
    MODULE_HEADER_STMT_KEYWORDS = ("belongs-to", "namespace", "prefix", "yang-version")
    META_STMT_KEYWORDS = ("contact", "description", "organization",
                          "reference", "revision")
    LINKAGE_STMTS_KEYWORDS = ("import", "include", "revision-date")
    BODY_STMT_KEYWORDS = ("action", "argument", "augment", "deviation",
                          "extension", "feature", "grouping", "identity",
                          "if-feature", "input", "notification", "output",
                          "rpc", "typedef")
    DATA_DEF_STMT_KEYWORDS = ("anydata", "anyxml", "case", "choice",
                              "config", "container", "deviate", "leaf",
                              "leaf-list", "list", "must", "presence",
                              "refine", "uses", "when")
    TYPE_STMT_KEYWORDS = ("base", "bit", "default", "enum", "error-app-tag",
                          "error-message", "fraction-digits", "length",
                          "max-elements", "min-elements", "modifier",
                          "ordered-by", "path", "pattern", "position",
                          "range", "require-instance", "status", "type",
                          "units", "value", "yin-element")
    LIST_STMT_KEYWORDS = ("key", "mandatory", "unique")

    #RFC7950 other keywords
    CONSTANTS_KEYWORDS = ("add", "current", "delete", "deprecated", "false",
                          "invert-match", "max", "min", "not-supported",
                          "obsolete", "replace", "true", "unbounded", "user")

    #RFC7950 Built-In Types
    TYPES = ("binary", "bits", "boolean", "decimal64", "empty", "enumeration",
             "identityref", "instance-identifier", "int16", "int32", "int64",
             "int8", "leafref", "string", "uint16", "uint32", "uint64",
             "uint8", "union")

    suffix_re_pattern = r'(?=[^\w\-:])'

    tokens = {
        'comments': [
            (r'[^*/]', Comment),
            (r'/\*', Comment, '#push'),
            (r'\*/', Comment, '#pop'),
            (r'[*/]', Comment),
        ],
        "root": [
            (r'\s+', Text.Whitespace),
            (r'[{};]+', Token.Punctuation),
            (r'(?<![\-\w])(and|or|not|\+|\.)(?![\-\w])', Token.Operator),

            (r'"(?:\\"|[^"])*?"', String.Double),
            (r"'(?:\\'|[^'])*?'", String.Single),

            (r'/\*', Comment, 'comments'),
            (r'//.*?$', Comment),

            #match BNF stmt for `node-identifier` with [ prefix ":"]
            (r'(?:^|(?<=[\s{};]))([\w.-]+)(:)([\w.-]+)(?=[\s{};])',
             bygroups(Name.Namespace, Token.Punctuation, Name.Variable)),

            #match BNF stmt `date-arg-str`
            (r'([0-9]{4}\-[0-9]{2}\-[0-9]{2})(?=[\s{};])', Name.Label),
            (r'([0-9]+\.[0-9]+)(?=[\s{};])', Number.Float),
            (r'([0-9]+)(?=[\s{};])', Number.Integer),

            (words(TOP_STMTS_KEYWORDS, suffix=suffix_re_pattern), Token.Keyword),
            (words(MODULE_HEADER_STMT_KEYWORDS, suffix=suffix_re_pattern), Token.Keyword),
            (words(META_STMT_KEYWORDS, suffix=suffix_re_pattern), Token.Keyword),
            (words(LINKAGE_STMTS_KEYWORDS, suffix=suffix_re_pattern), Token.Keyword),
            (words(BODY_STMT_KEYWORDS, suffix=suffix_re_pattern), Token.Keyword),
            (words(DATA_DEF_STMT_KEYWORDS, suffix=suffix_re_pattern), Token.Keyword),
            (words(TYPE_STMT_KEYWORDS, suffix=suffix_re_pattern), Token.Keyword),
            (words(LIST_STMT_KEYWORDS, suffix=suffix_re_pattern), Token.Keyword),
            (words(TYPES, suffix=suffix_re_pattern), Name.Class),
            (words(CONSTANTS_KEYWORDS, suffix=suffix_re_pattern), Name.Class),

            (r'[^;{}\s\'"]+', Name.Variable),
        ]
    }
