"""
    pygments.lexers.berry
    ~~~~~~~~~~~~~~~~~~~~~

    Lexer for Berry.

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

from pygments.lexer import RegexLexer, words, include, bygroups
from pygments.token import Comment, Whitespace, Operator, Keyword, Name, \
    String, Number, Punctuation

__all__ = ['BerryLexer']


class BerryLexer(RegexLexer):
    """
    For `berry <http://github.com/berry-lang/berry>`_ source code.

    .. versionadded:: 2.12.0
    """
    name = 'Berry'
    aliases = ['berry', 'be']
    filenames = ['*.be']
    mimetypes = ['text/x-berry', 'application/x-berry']

    _name = r'\b[^\W\d]\w*'

    tokens = {
        'root': [
            include('whitespace'),
            include('numbers'),
            include('keywords'),
            (rf'(def)(\s+)({_name})',
             bygroups(Keyword.Declaration, Whitespace, Name.Function)),
            (rf'\b(class)(\s+)({_name})',
             bygroups(Keyword.Declaration, Whitespace, Name.Class)),
            (rf'\b(import)(\s+)({_name})',
             bygroups(Keyword.Namespace, Whitespace, Name.Namespace)),
            include('expr')
        ],
        'expr': [
            (r'[^\S\n]+', Whitespace),
            (r'\.\.|[~!%^&*+=|?:<>/-]', Operator),
            (r'[(){}\[\],.;]', Punctuation),
            include('controls'),
            include('builtins'),
            include('funccall'),
            include('member'),
            include('name'),
            include('strings')
        ],
        'whitespace': [
            (r'\s+', Whitespace),
            (r'#-(.|\n)*?-#', Comment.Multiline),
            (r'#.*?$', Comment.Single)
        ],
        'keywords': [
            (words((
                'as', 'break', 'continue', 'import', 'static', 'self', 'super'),
                suffix=r'\b'), Keyword.Reserved),
            (r'(true|false|nil)\b', Keyword.Constant),
            (r'(var|def)\b', Keyword.Declaration)
        ],
        'controls': [
            (words((
                'if', 'elif', 'else', 'for', 'while', 'do', 'end', 'break',
                'continue', 'return', 'try', 'except', 'raise'),
                suffix=r'\b'), Keyword)
        ],
        'builtins': [
            (words((
                'assert', 'bool', 'input', 'classname', 'classof', 'number', 'real',
                'bytes', 'compile', 'map', 'list', 'int', 'isinstance', 'print',
                'range', 'str', 'super', 'module', 'size', 'issubclass', 'open',
                'file', 'type', 'call'),
                suffix=r'\b'), Name.Builtin)
        ],
        'numbers': [
            (r'0[xX][a-fA-F0-9]+', Number.Hex),
            (r'-?\d+', Number.Integer),
            (r'(-?\d+\.?|\.\d)\d*([eE][+-]?\d+)?', Number.Float)
        ],
        'name': [
            (_name, Name)
        ],
        'funccall': [
            (rf'{_name}(?=\s*\()', Name.Function, '#pop')
        ],
        'member': [
            (rf'(?<=\.){_name}\b(?!\()', Name.Attribute, '#pop')
        ],
        'strings': [
            (r'"([^\\]|\\.)*?"', String.Double, '#pop'),
            (r'\'([^\\]|\\.)*?\'', String.Single, '#pop')
        ]
    }
