hexo/node_modules/highlight.js/lib/languages/wren.js

303 lines
5.3 KiB
JavaScript

/*
Language: Wren
Description: Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in a familiar, modern syntax.
Category: scripting
Author: @joshgoebel
Maintainer: @joshgoebel
Website: https://wren.io/
*/
/** @type LanguageFn */
function wren(hljs) {
const regex = hljs.regex;
const IDENT_RE = /[a-zA-Z]\w*/;
const KEYWORDS = [
"as",
"break",
"class",
"construct",
"continue",
"else",
"for",
"foreign",
"if",
"import",
"in",
"is",
"return",
"static",
"var",
"while"
];
const LITERALS = [
"true",
"false",
"null"
];
const LANGUAGE_VARS = [
"this",
"super"
];
const CORE_CLASSES = [
"Bool",
"Class",
"Fiber",
"Fn",
"List",
"Map",
"Null",
"Num",
"Object",
"Range",
"Sequence",
"String",
"System"
];
const OPERATORS = [
"-",
"~",
/\*/,
"%",
/\.\.\./,
/\.\./,
/\+/,
"<<",
">>",
">=",
"<=",
"<",
">",
/\^/,
/!=/,
/!/,
/\bis\b/,
"==",
"&&",
"&",
/\|\|/,
/\|/,
/\?:/,
"="
];
const FUNCTION = {
relevance: 0,
match: regex.concat(/\b(?!(if|while|for|else|super)\b)/, IDENT_RE, /(?=\s*[({])/),
className: "title.function"
};
const FUNCTION_DEFINITION = {
match: regex.concat(
regex.either(
regex.concat(/\b(?!(if|while|for|else|super)\b)/, IDENT_RE),
regex.either(...OPERATORS)
),
/(?=\s*\([^)]+\)\s*\{)/),
className: "title.function",
starts: { contains: [
{
begin: /\(/,
end: /\)/,
contains: [
{
relevance: 0,
scope: "params",
match: IDENT_RE
}
]
}
] }
};
const CLASS_DEFINITION = {
variants: [
{ match: [
/class\s+/,
IDENT_RE,
/\s+is\s+/,
IDENT_RE
] },
{ match: [
/class\s+/,
IDENT_RE
] }
],
scope: {
2: "title.class",
4: "title.class.inherited"
},
keywords: KEYWORDS
};
const OPERATOR = {
relevance: 0,
match: regex.either(...OPERATORS),
className: "operator"
};
const TRIPLE_STRING = {
className: "string",
begin: /"""/,
end: /"""/
};
const PROPERTY = {
className: "property",
begin: regex.concat(/\./, regex.lookahead(IDENT_RE)),
end: IDENT_RE,
excludeBegin: true,
relevance: 0
};
const FIELD = {
relevance: 0,
match: regex.concat(/\b_/, IDENT_RE),
scope: "variable"
};
// CamelCase
const CLASS_REFERENCE = {
relevance: 0,
match: /\b[A-Z]+[a-z]+([A-Z]+[a-z]+)*/,
scope: "title.class",
keywords: { _: CORE_CLASSES }
};
// TODO: add custom number modes
const NUMBER = hljs.C_NUMBER_MODE;
const SETTER = {
match: [
IDENT_RE,
/\s*/,
/=/,
/\s*/,
/\(/,
IDENT_RE,
/\)\s*\{/
],
scope: {
1: "title.function",
3: "operator",
6: "params"
}
};
const COMMENT_DOCS = hljs.COMMENT(
/\/\*\*/,
/\*\//,
{ contains: [
{
match: /@[a-z]+/,
scope: "doctag"
},
"self"
] }
);
const SUBST = {
scope: "subst",
begin: /%\(/,
end: /\)/,
contains: [
NUMBER,
CLASS_REFERENCE,
FUNCTION,
FIELD,
OPERATOR
]
};
const STRING = {
scope: "string",
begin: /"/,
end: /"/,
contains: [
SUBST,
{
scope: "char.escape",
variants: [
{ match: /\\\\|\\["0%abefnrtv]/ },
{ match: /\\x[0-9A-F]{2}/ },
{ match: /\\u[0-9A-F]{4}/ },
{ match: /\\U[0-9A-F]{8}/ }
]
}
]
};
SUBST.contains.push(STRING);
const ALL_KWS = [
...KEYWORDS,
...LANGUAGE_VARS,
...LITERALS
];
const VARIABLE = {
relevance: 0,
match: regex.concat(
"\\b(?!",
ALL_KWS.join("|"),
"\\b)",
/[a-zA-Z_]\w*(?:[?!]|\b)/
),
className: "variable"
};
// TODO: reconsider this in the future
const ATTRIBUTE = {
// scope: "meta",
scope: "comment",
variants: [
{
begin: [
/#!?/,
/[A-Za-z_]+(?=\()/
],
beginScope: {
// 2: "attr"
},
keywords: { literal: LITERALS },
contains: [
// NUMBER,
// VARIABLE
],
end: /\)/
},
{
begin: [
/#!?/,
/[A-Za-z_]+/
],
beginScope: {
// 2: "attr"
},
end: /$/
}
]
};
return {
name: "Wren",
keywords: {
keyword: KEYWORDS,
"variable.language": LANGUAGE_VARS,
literal: LITERALS
},
contains: [
ATTRIBUTE,
NUMBER,
STRING,
TRIPLE_STRING,
COMMENT_DOCS,
hljs.C_LINE_COMMENT_MODE,
hljs.C_BLOCK_COMMENT_MODE,
CLASS_REFERENCE,
CLASS_DEFINITION,
SETTER,
FUNCTION_DEFINITION,
FUNCTION,
OPERATOR,
FIELD,
PROPERTY,
VARIABLE
]
};
}
module.exports = wren;