UNPKG

5.16 kBJavaScriptView Raw
1/*
2Language: Wren
3Description: Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in a familiar, modern syntax.
4Category: scripting
5Author: @joshgoebel
6Maintainer: @joshgoebel
7Website: https://wren.io/
8*/
9
10/** @type LanguageFn */
11function wren(hljs) {
12 const regex = hljs.regex;
13 const IDENT_RE = /[a-zA-Z]\w*/;
14 const KEYWORDS = [
15 "as",
16 "break",
17 "class",
18 "construct",
19 "continue",
20 "else",
21 "for",
22 "foreign",
23 "if",
24 "import",
25 "in",
26 "is",
27 "return",
28 "static",
29 "var",
30 "while"
31 ];
32 const LITERALS = [
33 "true",
34 "false",
35 "null"
36 ];
37 const LANGUAGE_VARS = [
38 "this",
39 "super"
40 ];
41 const CORE_CLASSES = [
42 "Bool",
43 "Class",
44 "Fiber",
45 "Fn",
46 "List",
47 "Map",
48 "Null",
49 "Num",
50 "Object",
51 "Range",
52 "Sequence",
53 "String",
54 "System"
55 ];
56 const OPERATORS = [
57 "-",
58 "~",
59 /\*/,
60 "%",
61 /\.\.\./,
62 /\.\./,
63 /\+/,
64 "<<",
65 ">>",
66 ">=",
67 "<=",
68 "<",
69 ">",
70 /\^/,
71 /!=/,
72 /!/,
73 /\bis\b/,
74 "==",
75 "&&",
76 "&",
77 /\|\|/,
78 /\|/,
79 /\?:/,
80 "="
81 ];
82 const FUNCTION = {
83 relevance: 0,
84 match: regex.concat(/\b(?!(if|while|for|else|super)\b)/, IDENT_RE, /(?=\s*[({])/),
85 className: "title.function"
86 };
87 const FUNCTION_DEFINITION = {
88 match: regex.concat(
89 regex.either(
90 regex.concat(/\b(?!(if|while|for|else|super)\b)/, IDENT_RE),
91 regex.either(...OPERATORS)
92 ),
93 /(?=\s*\([^)]+\)\s*\{)/),
94 className: "title.function",
95 starts: { contains: [
96 {
97 begin: /\(/,
98 end: /\)/,
99 contains: [
100 {
101 relevance: 0,
102 scope: "params",
103 match: IDENT_RE
104 }
105 ]
106 }
107 ] }
108 };
109 const CLASS_DEFINITION = {
110 variants: [
111 { match: [
112 /class\s+/,
113 IDENT_RE,
114 /\s+is\s+/,
115 IDENT_RE
116 ] },
117 { match: [
118 /class\s+/,
119 IDENT_RE
120 ] }
121 ],
122 scope: {
123 2: "title.class",
124 4: "title.class.inherited"
125 },
126 keywords: KEYWORDS
127 };
128
129 const OPERATOR = {
130 relevance: 0,
131 match: regex.either(...OPERATORS),
132 className: "operator"
133 };
134
135 const TRIPLE_STRING = {
136 className: "string",
137 begin: /"""/,
138 end: /"""/
139 };
140
141 const PROPERTY = {
142 className: "property",
143 begin: regex.concat(/\./, regex.lookahead(IDENT_RE)),
144 end: IDENT_RE,
145 excludeBegin: true,
146 relevance: 0
147 };
148
149 const FIELD = {
150 relevance: 0,
151 match: regex.concat(/\b_/, IDENT_RE),
152 scope: "variable"
153 };
154
155 // CamelCase
156 const CLASS_REFERENCE = {
157 relevance: 0,
158 match: /\b[A-Z]+[a-z]+([A-Z]+[a-z]+)*/,
159 scope: "title.class",
160 keywords: { _: CORE_CLASSES }
161 };
162
163 // TODO: add custom number modes
164 const NUMBER = hljs.C_NUMBER_MODE;
165
166 const SETTER = {
167 match: [
168 IDENT_RE,
169 /\s*/,
170 /=/,
171 /\s*/,
172 /\(/,
173 IDENT_RE,
174 /\)\s*\{/
175 ],
176 scope: {
177 1: "title.function",
178 3: "operator",
179 6: "params"
180 }
181 };
182
183 const COMMENT_DOCS = hljs.COMMENT(
184 /\/\*\*/,
185 /\*\//,
186 { contains: [
187 {
188 match: /@[a-z]+/,
189 scope: "doctag"
190 },
191 "self"
192 ] }
193 );
194 const SUBST = {
195 scope: "subst",
196 begin: /%\(/,
197 end: /\)/,
198 contains: [
199 NUMBER,
200 CLASS_REFERENCE,
201 FUNCTION,
202 FIELD,
203 OPERATOR
204 ]
205 };
206 const STRING = {
207 scope: "string",
208 begin: /"/,
209 end: /"/,
210 contains: [
211 SUBST,
212 {
213 scope: "char.escape",
214 variants: [
215 { match: /\\\\|\\["0%abefnrtv]/ },
216 { match: /\\x[0-9A-F]{2}/ },
217 { match: /\\u[0-9A-F]{4}/ },
218 { match: /\\U[0-9A-F]{8}/ }
219 ]
220 }
221 ]
222 };
223 SUBST.contains.push(STRING);
224
225 const ALL_KWS = [
226 ...KEYWORDS,
227 ...LANGUAGE_VARS,
228 ...LITERALS
229 ];
230 const VARIABLE = {
231 relevance: 0,
232 match: regex.concat(
233 "\\b(?!",
234 ALL_KWS.join("|"),
235 "\\b)",
236 /[a-zA-Z_]\w*(?:[?!]|\b)/
237 ),
238 className: "variable"
239 };
240
241 // TODO: reconsider this in the future
242 const ATTRIBUTE = {
243 // scope: "meta",
244 scope: "comment",
245 variants: [
246 {
247 begin: [
248 /#!?/,
249 /[A-Za-z_]+(?=\()/
250 ],
251 beginScope: {
252 // 2: "attr"
253 },
254 keywords: { literal: LITERALS },
255 contains: [
256 // NUMBER,
257 // VARIABLE
258 ],
259 end: /\)/
260 },
261 {
262 begin: [
263 /#!?/,
264 /[A-Za-z_]+/
265 ],
266 beginScope: {
267 // 2: "attr"
268 },
269 end: /$/
270 }
271 ]
272 };
273
274 return {
275 name: "Wren",
276 keywords: {
277 keyword: KEYWORDS,
278 "variable.language": LANGUAGE_VARS,
279 literal: LITERALS
280 },
281 contains: [
282 ATTRIBUTE,
283 NUMBER,
284 STRING,
285 TRIPLE_STRING,
286 COMMENT_DOCS,
287 hljs.C_LINE_COMMENT_MODE,
288 hljs.C_BLOCK_COMMENT_MODE,
289 CLASS_REFERENCE,
290 CLASS_DEFINITION,
291 SETTER,
292 FUNCTION_DEFINITION,
293 FUNCTION,
294 OPERATOR,
295 FIELD,
296 PROPERTY,
297 VARIABLE
298 ]
299 };
300}
301
302module.exports = wren;