import hljs from 'highlight.js';

/**
 * @name Lox
 * @author jaacko-torus <jaacko.torus@gmail.com> (https://github.com/jaacko-torus)
 * @website http://craftinginterpreters.com/
 * @license MIT
 */
const regex = hljs.regex;
const IDENT_RE = "[A-Za-z][0-9A-Za-z]*";
const LANGUAGE_KEYWORDS = [
    "class",
    "else",
    "for",
    "function",
    "if",
    "print",
    "return",
    "var",
    "while",
];
const LITERALS = [
    "false",
    "nil",
    "true",
];
const BUILT_IN_VARIABLES = [
    "super",
    "this",
];
const KEYWORDS = {
    $pattern: IDENT_RE,
    keyword: LANGUAGE_KEYWORDS,
    literal: LITERALS,
    "variable.language": BUILT_IN_VARIABLES
};
const NUMBER = {
    scope: "number",
    variants: [
        { begin: "[\\d]+" },
        { begin: "\\d+(\.\\d+)?" },
    ],
    relevance: 0
};
const PARAMS_CONTAINS = [
    hljs.C_LINE_COMMENT_MODE,
    // eat recursive parens in sub expressions
    {
        begin: /\(/,
        end: /\)/,
        keywords: KEYWORDS,
        contains: ["self", hljs.C_LINE_COMMENT_MODE]
    }
];
const PARAMS = {
    scope: "params",
    begin: /\(/,
    end: /\)/,
    excludeBegin: true,
    excludeEnd: true,
    keywords: KEYWORDS,
    contains: PARAMS_CONTAINS
};
const CLASS_OR_EXTENDS = {
    variants: [
        // class Car < Vehicle
        {
            match: [
                /class/,
                /\s+/,
                IDENT_RE,
                /\s+/,
                /</,
                /\s+/,
            ],
            scope: {
                1: "keyword",
                3: "title.class",
                5: "keyword",
                7: "title.class.inherited"
            }
        },
        // class Car
        {
            match: [
                /class/,
                /\s+/,
                IDENT_RE
            ],
            scope: {
                1: "keyword",
                3: "title.class"
            }
        },
    ]
};
const FUNCTION_DEFINITION = {
    variants: [
        {
            match: [
                /function/,
                /\s+/,
                IDENT_RE,
                /(?=\s*\()/
            ]
        },
    ],
    scope: {
        1: "keyword",
        3: "title.function"
    },
    label: "func.def",
    contains: [PARAMS],
    illegal: /%/
};
const UPPER_CASE_CONSTANT = {
    relevance: 0,
    match: /\b[A-Z][A-Z0-9]+\b/,
    scope: "variable.constant"
};
function noneOf(list) {
    return regex.concat("(?!", list.join("|"), ")");
}
const FUNCTION_CALL = {
    match: regex.concat(/\b/, noneOf(["super"]), IDENT_RE, regex.lookahead(/\(/)),
    scope: "title.function",
    relevance: 0
};
const PROPERTY_ACCESS = {
    begin: regex.concat(/\./, regex.lookahead(regex.concat(IDENT_RE, /(?![0-9A-Za-z(])/))),
    end: IDENT_RE,
    excludeBegin: true,
    scope: "property",
    relevance: 0
};
/**
 * @name Lox
 * @param {HLJSApi} hljs
 * @website http://craftinginterpreters.com/
 */
function lox(hljs) {
    return {
        name: "Lox",
        aliases: ["lox"],
        keywords: KEYWORDS,
        illegal: /#(?![$_A-z])/,
        contains: [
            hljs.QUOTE_STRING_MODE,
            hljs.C_LINE_COMMENT_MODE,
            NUMBER,
            {
                begin: "(" + hljs.RE_STARTERS_RE + "|\\b(return)\\b)\\s*",
                keywords: "return",
                relevance: 0,
                contains: [
                    hljs.C_LINE_COMMENT_MODE,
                    hljs.REGEXP_MODE,
                    {
                        begin: /,/,
                        relevance: 0
                    },
                    {
                        match: /\s+/,
                        relevance: 0
                    },
                ],
            },
            FUNCTION_DEFINITION,
            {
                // prevent this from getting swallowed up by function since they appear "function like"
                beginKeywords: "while if for"
            },
            {
                // we have to count the parens to make sure we actually have the correct
                // bounding ( ).  There could be any number of sub-expressions inside
                // also surrounded by parens.
                begin: "\\b(?!function)" + hljs.UNDERSCORE_IDENT_RE +
                    "\\(" + // first parens
                    "[^()]*(\\(" +
                    "[^()]*(\\(" +
                    "[^()]*" +
                    "\\)[^()]*)*" +
                    "\\)[^()]*)*" +
                    "\\)\\s*\\{",
                returnBegin: true,
                label: "func.def",
                contains: [
                    PARAMS,
                    hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE, scope: "title.function" })
                ]
            },
            PROPERTY_ACCESS,
            {
                match: [/\binit(?=\s*\()/],
                scope: { 1: "title.function" },
                contains: [PARAMS]
            },
            FUNCTION_CALL,
            UPPER_CASE_CONSTANT,
            CLASS_OR_EXTENDS,
            {
                match: /\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`
            }
        ]
    };
}

export { lox as default };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,[encoded data, 11384 characters]
