/*
Language: Elixir
Author: Josh Adams <josh@isotope11.com>
Description: language definition for Elixir source code files (.ex and .exs).  Based on ruby language support.
Category: functional
Website: https://elixir-lang.org
*/
/** @type LanguageFn */
function elixir(hljs) {
    const regex = hljs.regex;
    const ELIXIR_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_.]*(!|\\?)?';
    const ELIXIR_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?';
    const KEYWORDS = [
        "after",
        "alias",
        "and",
        "case",
        "catch",
        "cond",
        "defstruct",
        "defguard",
        "do",
        "else",
        "end",
        "fn",
        "for",
        "if",
        "import",
        "in",
        "not",
        "or",
        "quote",
        "raise",
        "receive",
        "require",
        "reraise",
        "rescue",
        "try",
        "unless",
        "unquote",
        "unquote_splicing",
        "use",
        "when",
        "with|0"
    ];
    const LITERALS = [
        "false",
        "nil",
        "true"
    ];
    const KWS = {
        $pattern: ELIXIR_IDENT_RE,
        keyword: KEYWORDS,
        literal: LITERALS
    };
    const SUBST = {
        className: 'subst',
        begin: /#\{/,
        end: /\}/,
        keywords: KWS
    };
    const NUMBER = {
        className: 'number',
        begin: '(\\b0o[0-7_]+)|(\\b0b[01_]+)|(\\b0x[0-9a-fA-F_]+)|(-?\\b[0-9][0-9_]*(\\.[0-9_]+([eE][-+]?[0-9]+)?)?)',
        relevance: 0
    };
    // TODO: could be tightened
    // https://elixir-lang.readthedocs.io/en/latest/intro/18.html
    // but you also need to include closing delemeters in the escape list per
    // individual sigil mode from what I can tell,
    // ie: \} might or might not be an escape depending on the sigil used
    const ESCAPES_RE = /\\[\s\S]/;
    // const ESCAPES_RE = /\\["'\\abdefnrstv0]/;
    const BACKSLASH_ESCAPE = {
        match: ESCAPES_RE,
        scope: "char.escape",
        relevance: 0
    };
    const SIGIL_DELIMITERS = '[/|([{<"\']';
    const SIGIL_DELIMITER_MODES = [
        {
            begin: /"/,
            end: /"/
        },
        {
            begin: /'/,
            end: /'/
        },
        {
            begin: /\//,
            end: /\//
        },
        {
            begin: /\|/,
            end: /\|/
        },
        {
            begin: /\(/,
            end: /\)/
        },
        {
            begin: /\[/,
            end: /\]/
        },
        {
            begin: /\{/,
            end: /\}/
        },
        {
            begin: /</,
            end: />/
        }
    ];
    const escapeSigilEnd = (end) => {
        return {
            scope: "char.escape",
            begin: regex.concat(/\\/, end),
            relevance: 0
        };
    };
    const LOWERCASE_SIGIL = {
        className: 'string',
        begin: '~[a-z]' + '(?=' + SIGIL_DELIMITERS + ')',
        contains: SIGIL_DELIMITER_MODES.map(x => hljs.inherit(x, { contains: [
                escapeSigilEnd(x.end),
                BACKSLASH_ESCAPE,
                SUBST
            ] }))
    };
    const UPCASE_SIGIL = {
        className: 'string',
        begin: '~[A-Z]' + '(?=' + SIGIL_DELIMITERS + ')',
        contains: SIGIL_DELIMITER_MODES.map(x => hljs.inherit(x, { contains: [escapeSigilEnd(x.end)] }))
    };
    const REGEX_SIGIL = {
        className: 'regex',
        variants: [
            {
                begin: '~r' + '(?=' + SIGIL_DELIMITERS + ')',
                contains: SIGIL_DELIMITER_MODES.map(x => hljs.inherit(x, {
                    end: regex.concat(x.end, /[uismxfU]{0,7}/),
                    contains: [
                        escapeSigilEnd(x.end),
                        BACKSLASH_ESCAPE,
                        SUBST
                    ]
                }))
            },
            {
                begin: '~R' + '(?=' + SIGIL_DELIMITERS + ')',
                contains: SIGIL_DELIMITER_MODES.map(x => hljs.inherit(x, {
                    end: regex.concat(x.end, /[uismxfU]{0,7}/),
                    contains: [escapeSigilEnd(x.end)]
                }))
            }
        ]
    };
    const STRING = {
        className: 'string',
        contains: [
            hljs.BACKSLASH_ESCAPE,
            SUBST
        ],
        variants: [
            {
                begin: /"""/,
                end: /"""/
            },
            {
                begin: /'''/,
                end: /'''/
            },
            {
                begin: /~S"""/,
                end: /"""/,
                contains: [] // override default
            },
            {
                begin: /~S"/,
                end: /"/,
                contains: [] // override default
            },
            {
                begin: /~S'''/,
                end: /'''/,
                contains: [] // override default
            },
            {
                begin: /~S'/,
                end: /'/,
                contains: [] // override default
            },
            {
                begin: /'/,
                end: /'/
            },
            {
                begin: /"/,
                end: /"/
            }
        ]
    };
    const FUNCTION = {
        className: 'function',
        beginKeywords: 'def defp defmacro defmacrop',
        end: /\B\b/, // the mode is ended by the title
        contains: [
            hljs.inherit(hljs.TITLE_MODE, {
                begin: ELIXIR_IDENT_RE,
                endsParent: true
            })
        ]
    };
    const CLASS = hljs.inherit(FUNCTION, {
        className: 'class',
        beginKeywords: 'defimpl defmodule defprotocol defrecord',
        end: /\bdo\b|$|;/
    });
    const ELIXIR_DEFAULT_CONTAINS = [
        STRING,
        REGEX_SIGIL,
        UPCASE_SIGIL,
        LOWERCASE_SIGIL,
        hljs.HASH_COMMENT_MODE,
        CLASS,
        FUNCTION,
        { begin: '::' },
        {
            className: 'symbol',
            begin: ':(?![\\s:])',
            contains: [
                STRING,
                { begin: ELIXIR_METHOD_RE }
            ],
            relevance: 0
        },
        {
            className: 'symbol',
            begin: ELIXIR_IDENT_RE + ':(?!:)',
            relevance: 0
        },
        {
            className: 'title.class',
            begin: /(\b[A-Z][a-zA-Z0-9_]+)/,
            relevance: 0
        },
        NUMBER,
        {
            className: 'variable',
            begin: '(\\$\\W)|((\\$|@@?)(\\w+))'
        }
        // -> has been removed, capnproto always uses this grammar construct
    ];
    SUBST.contains = ELIXIR_DEFAULT_CONTAINS;
    return {
        name: 'Elixir',
        aliases: [
            'ex',
            'exs'
        ],
        keywords: KWS,
        contains: ELIXIR_DEFAULT_CONTAINS
    };
}
export { elixir as default };
//# sourceMappingURL=elixir.js.map