# -*- coding: utf-8 -*-
"""
    pygments.lexers.slash
    ~~~~~~~~~~~~~~~~~~~~~

    Lexer for the `Slash <https://github.com/arturadib/Slash-A>`_ programming
    language.

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

from pygments.lexer import ExtendedRegexLexer, bygroups, DelegatingLexer
from pygments.token import Name, Number, String, Comment, Punctuation, \
    Other, Keyword, Operator, Whitespace

__all__ = ['SlashLexer']


class SlashLanguageLexer(ExtendedRegexLexer):
    _nkw = r'(?=[^a-zA-Z_0-9])'

    def move_state(new_state):
        return ("#pop", new_state)

    def right_angle_bracket(lexer, match, ctx):
        if len(ctx.stack) > 1 and ctx.stack[-2] == "string":
            ctx.stack.pop()
        yield match.start(), String.Interpol, u"}"
        ctx.pos = match.end()
        pass

    tokens = {
        "root": [
            (r"<%=",        Comment.Preproc,    move_state("slash")),
            (r"<%!!",       Comment.Preproc,    move_state("slash")),
            (r"<%#.*?%>",   Comment.Multiline),
            (r"<%",         Comment.Preproc,    move_state("slash")),
            (r".|\n",       Other),
        ],
        "string": [
            (r"\\",         String.Escape,      move_state("string_e")),
            (r"\"",         String,             move_state("slash")),
            (r"#\{",        String.Interpol,    "slash"),
            (r'.|\n',       String),
        ],
        "string_e": [
            (r'n',                  String.Escape,      move_state("string")),
            (r't',                  String.Escape,      move_state("string")),
            (r'r',                  String.Escape,      move_state("string")),
            (r'e',                  String.Escape,      move_state("string")),
            (r'x[a-fA-F0-9]{2}',    String.Escape,      move_state("string")),
            (r'.',                  String.Escape,      move_state("string")),
        ],
        "regexp": [
            (r'}[a-z]*',            String.Regex,       move_state("slash")),
            (r'\\(.|\n)',           String.Regex),
            (r'{',                  String.Regex,       "regexp_r"),
            (r'.|\n',               String.Regex),
        ],
        "regexp_r": [
            (r'}[a-z]*',            String.Regex,       "#pop"),
            (r'\\(.|\n)',           String.Regex),
            (r'{',                  String.Regex,       "regexp_r"),
        ],
        "slash": [
            (r"%>",                     Comment.Preproc,    move_state("root")),
            (r"\"",                     String,             move_state("string")),
            (r"'[a-zA-Z0-9_]+",         String),
            (r'%r{',                    String.Regex,       move_state("regexp")),
            (r'/\*.*?\*/',              Comment.Multiline),
            (r"(#|//).*?\n",            Comment.Single),
            (r'-?[0-9]+e[+-]?[0-9]+',   Number.Float),
            (r'-?[0-9]+\.[0-9]+(e[+-]?[0-9]+)?', Number.Float),
            (r'-?[0-9]+',               Number.Integer),
            (r'nil'+_nkw,               Name.Builtin),
            (r'true'+_nkw,              Name.Builtin),
            (r'false'+_nkw,             Name.Builtin),
            (r'self'+_nkw,              Name.Builtin),
            (r'(class)(\s+)([A-Z][a-zA-Z0-9_\']*)',
                bygroups(Keyword, Whitespace, Name.Class)),
            (r'class'+_nkw,             Keyword),
            (r'extends'+_nkw,           Keyword),
            (r'(def)(\s+)(self)(\s*)(\.)(\s*)([a-z_][a-zA-Z0-9_\']*=?|<<|>>|==|<=>|<=|<|>=|>|\+|-(self)?|~(self)?|\*|/|%|^|&&|&|\||\[\]=?)',
                bygroups(Keyword, Whitespace, Name.Builtin, Whitespace, Punctuation, Whitespace, Name.Function)),
            (r'(def)(\s+)([a-z_][a-zA-Z0-9_\']*=?|<<|>>|==|<=>|<=|<|>=|>|\+|-(self)?|~(self)?|\*|/|%|^|&&|&|\||\[\]=?)',
                bygroups(Keyword, Whitespace, Name.Function)),
            (r'def'+_nkw,               Keyword),
            (r'if'+_nkw,                Keyword),
            (r'elsif'+_nkw,             Keyword),
            (r'else'+_nkw,              Keyword),
            (r'unless'+_nkw,            Keyword),
            (r'for'+_nkw,               Keyword),
            (r'in'+_nkw,                Keyword),
            (r'while'+_nkw,             Keyword),
            (r'until'+_nkw,             Keyword),
            (r'and'+_nkw,               Keyword),
            (r'or'+_nkw,                Keyword),
            (r'not'+_nkw,               Keyword),
            (r'lambda'+_nkw,            Keyword),
            (r'try'+_nkw,               Keyword),
            (r'catch'+_nkw,             Keyword),
            (r'return'+_nkw,            Keyword),
            (r'next'+_nkw,              Keyword),
            (r'last'+_nkw,              Keyword),
            (r'throw'+_nkw,             Keyword),
            (r'use'+_nkw,               Keyword),
            (r'switch'+_nkw,            Keyword),
            (r'\\',                     Keyword),
            (r'λ',                      Keyword),
            (r'__FILE__'+_nkw,          Name.Builtin.Pseudo),
            (r'__LINE__'+_nkw,          Name.Builtin.Pseudo),
            (r'[A-Z][a-zA-Z0-9_\']*'+_nkw, Name.Constant),
            (r'[a-z_][a-zA-Z0-9_\']*'+_nkw, Name),
            (r'@[a-z_][a-zA-Z0-9_\']*'+_nkw, Name.Variable.Instance),
            (r'@@[a-z_][a-zA-Z0-9_\']*'+_nkw, Name.Variable.Class),
            (r'\(',                     Punctuation),
            (r'\)',                     Punctuation),
            (r'\[',                     Punctuation),
            (r'\]',                     Punctuation),
            (r'\{',                     Punctuation),
            (r'\}',                     right_angle_bracket),
            (r';',                      Punctuation),
            (r',',                      Punctuation),
            (r'<<=',                    Operator),
            (r'>>=',                    Operator),
            (r'<<',                     Operator),
            (r'>>',                     Operator),
            (r'==',                     Operator),
            (r'!=',                     Operator),
            (r'=>',                     Operator),
            (r'=',                      Operator),
            (r'<=>',                    Operator),
            (r'<=',                     Operator),
            (r'>=',                     Operator),
            (r'<',                      Operator),
            (r'>',                      Operator),
            (r'\+\+',                   Operator),
            (r'\+=',                    Operator),
            (r'-=',                     Operator),
            (r'\*\*=',                  Operator),
            (r'\*=',                    Operator),
            (r'\*\*',                   Operator),
            (r'\*',                     Operator),
            (r'/=',                     Operator),
            (r'\+',                     Operator),
            (r'-',                      Operator),
            (r'/',                      Operator),
            (r'%=',                     Operator),
            (r'%',                      Operator),
            (r'^=',                     Operator),
            (r'&&=',                    Operator),
            (r'&=',                     Operator),
            (r'&&',                     Operator),
            (r'&',                      Operator),
            (r'\|\|=',                  Operator),
            (r'\|=',                    Operator),
            (r'\|\|',                   Operator),
            (r'\|',                     Operator),
            (r'!',                      Operator),
            (r'\.\.\.',                 Operator),
            (r'\.\.',                   Operator),
            (r'\.',                     Operator),
            (r'::',                     Operator),
            (r':',                      Operator),
            (r'(\s|\n)+',               Whitespace),
            (r'[a-z_][a-zA-Z0-9_\']*',  Name.Variable),
        ],
    }


class SlashLexer(DelegatingLexer):
    """
    Lexer for the Slash programming language.

    .. versionadded:: 2.4
    """

    name = 'Slash'
    aliases = ['slash']
    filenames = ['*.sl']

    def __init__(self, **options):
        from pygments.lexers.web import HtmlLexer
        super(SlashLexer, self).__init__(HtmlLexer, SlashLanguageLexer, **options)
