wren.js 5.0 KB

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