|
| 1 | +// assets/js/aria.js |
| 2 | +/** @typedef {import('highlight.js').HLJSApi} HLJSApi */ |
| 3 | +/** @param {HLJSApi} hljs */ |
| 4 | +export default function (hljs) { |
| 5 | + // ---------- Lexical ---------- |
| 6 | + |
| 7 | + const LINE_COMMENT = hljs.COMMENT('#', '$'); |
| 8 | + const SHEBANG = hljs.SHEBANG({ binary: '' }); |
| 9 | + |
| 10 | + // escapes: \n \t \\ \xNN \u{...} |
| 11 | + const ESCAPE = { |
| 12 | + className: 'subst', |
| 13 | + begin: /\\(?:[nt\\]|x[0-9A-Fa-f]{2}|u\{[0-9A-Fa-f]+\})/ |
| 14 | + }; |
| 15 | + const SQ_STRING = { className: 'string', begin: /'/, end: /'/, contains: [ESCAPE] }; |
| 16 | + const DQ_STRING = { className: 'string', begin: /"/, end: /"/, contains: [ESCAPE] }; |
| 17 | + |
| 18 | + // numbers |
| 19 | + const HEX_INT = { className: 'number', begin: /0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*/ }; |
| 20 | + const OCT_INT = { className: 'number', begin: /0o[0-7]+(?:_[0-7]+)*/ }; |
| 21 | + const BIN_INT = { className: 'number', begin: /0b[01]+(?:_[01]+)*/ }; |
| 22 | + const DEC_INT = { className: 'number', begin: /-?(?:0|[1-9][0-9]*)(?:_[0-9]+)*/ }; |
| 23 | + const DEC_FLOAT = { |
| 24 | + className: 'number', |
| 25 | + // -? DIGITS '.' DIGITS (exp)? |
| 26 | + begin: /-?(?:0|[1-9][0-9]*)\.[0-9]+(?:[eE][+-]?[0-9]+)?/, |
| 27 | + illegal: /_/ // no underscores in floats |
| 28 | + }; |
| 29 | + |
| 30 | + // identifiers (approx) |
| 31 | + const IDENT = /[A-Za-z_$][\w$]*/u; |
| 32 | + |
| 33 | + // ---------- Keywords ---------- |
| 34 | + |
| 35 | + const KEYWORDS = { |
| 36 | + keyword: [ |
| 37 | + 'assert', 'else', 'elsif', 'extension', 'if', 'include', 'match', 'return', 'throw', 'while', |
| 38 | + 'val', 'var', 'type', 'func', 'operator', 'struct', 'enum', 'mixin', 'import', 'from', 'in', |
| 39 | + 'and', 'case', 'isa', 'instance', 'reverse', 'try', 'catch', 'break', 'continue', 'for' |
| 40 | + ].join(' '), |
| 41 | + literal: 'true false', |
| 42 | + built_in: 'println assert', |
| 43 | + type: 'Int Float String Bool Result Maybe Any' |
| 44 | + }; |
| 45 | + |
| 46 | + // ---------- Declarations & titles ---------- |
| 47 | + |
| 48 | + const FUNC_DEF = { |
| 49 | + className: 'function', |
| 50 | + begin: new RegExp(`\\bfunc\\s+(${IDENT.source})\\s*\\(`), |
| 51 | + beginScope: { 1: 'title.function' }, |
| 52 | + end: /\)/, |
| 53 | + excludeEnd: true, |
| 54 | + keywords: KEYWORDS, |
| 55 | + contains: [LINE_COMMENT, DQ_STRING, SQ_STRING, DEC_FLOAT, HEX_INT, OCT_INT, BIN_INT, DEC_INT] |
| 56 | + }; |
| 57 | + |
| 58 | + const METHOD_DEF = { |
| 59 | + className: 'function', |
| 60 | + begin: new RegExp(`\\b(?:instance|type)\\s+func\\s+(${IDENT.source})\\s*\\(`), |
| 61 | + beginScope: { 1: 'title.function' }, |
| 62 | + end: /\)/, |
| 63 | + excludeEnd: true, |
| 64 | + keywords: KEYWORDS, |
| 65 | + contains: [LINE_COMMENT, DQ_STRING, SQ_STRING, DEC_FLOAT, HEX_INT, OCT_INT, BIN_INT, DEC_INT] |
| 66 | + }; |
| 67 | + |
| 68 | + // operator symbols from grammar |
| 69 | + const OP_SYM = /\+\-|u\-|\+|\-|\*|\/|%|<<|>>|==|<=|>=|<|>|\&|\||\^|\(\)|\[\]=|\[\]/; |
| 70 | + const OP_DEF = { |
| 71 | + className: 'function', |
| 72 | + begin: new RegExp(`\\b(?:reverse\\s+)?operator\\s+(${OP_SYM.source})\\s*\\(`), |
| 73 | + beginScope: { 1: 'title.function' }, |
| 74 | + end: /\)/, |
| 75 | + excludeEnd: true, |
| 76 | + keywords: KEYWORDS, |
| 77 | + contains: [LINE_COMMENT] |
| 78 | + }; |
| 79 | + |
| 80 | + const TYPE_LIKE_DEF = { |
| 81 | + className: 'class', |
| 82 | + variants: [ |
| 83 | + { begin: new RegExp(`\\bstruct\\s+(${IDENT.source})\\b`) }, |
| 84 | + { begin: new RegExp(`\\benum\\s+(${IDENT.source})\\b`) }, |
| 85 | + { begin: new RegExp(`\\bmixin\\s+(${IDENT.source})\\b`) } |
| 86 | + ], |
| 87 | + beginScope: { 1: 'title.class' } |
| 88 | + }; |
| 89 | + |
| 90 | + const EXTENSION_DEF = { |
| 91 | + begin: new RegExp(`\\bextension\\s+(${IDENT.source})\\b`), |
| 92 | + beginScope: { 1: 'type' } |
| 93 | + }; |
| 94 | + |
| 95 | + const ENUM_CASE_DECL = { |
| 96 | + className: 'constant', |
| 97 | + begin: new RegExp(`\\bcase\\s+(${IDENT.source})\\b`), |
| 98 | + beginScope: { 1: 'constant' } |
| 99 | + }; |
| 100 | + |
| 101 | + const ENUM_CASE_USE = { |
| 102 | + className: 'constant', |
| 103 | + begin: new RegExp(`::\\s*(${IDENT.source})`), |
| 104 | + beginScope: { 1: 'constant' } |
| 105 | + }; |
| 106 | + |
| 107 | + // lambdas: |args| => ... |
| 108 | + const LAMBDA_HEAD = { |
| 109 | + begin: /\|/, |
| 110 | + end: /\|\s*=>/, |
| 111 | + excludeEnd: true, |
| 112 | + contains: [LINE_COMMENT, { className: 'params', begin: /[^|]+/ }], |
| 113 | + relevance: 1 |
| 114 | + }; |
| 115 | + |
| 116 | + // postfix try-protocol |
| 117 | + const TRY_PROTOCOL = { className: 'operator', begin: /\?\?|\!\!/ }; |
| 118 | + |
| 119 | + // compound assign ops used in statements |
| 120 | + const ASSIGN_OP = { className: 'operator', begin: /\+=|-=|\*=|\/=|%=/, relevance: 0 }; |
| 121 | + |
| 122 | + const INDEXING = { |
| 123 | + begin: /\[/, end: /\]/, |
| 124 | + contains: [LINE_COMMENT, DQ_STRING, SQ_STRING, DEC_FLOAT, HEX_INT, OCT_INT, BIN_INT, DEC_INT], |
| 125 | + relevance: 0 |
| 126 | + }; |
| 127 | + |
| 128 | + const OBJECT_WRITE = { |
| 129 | + begin: /\{/, end: /\}/, |
| 130 | + contains: [LINE_COMMENT, DQ_STRING, SQ_STRING, INDEXING], |
| 131 | + relevance: 0 |
| 132 | + }; |
| 133 | + |
| 134 | + const IMPORTS = { |
| 135 | + begin: /\bimport\b/, end: /;/, |
| 136 | + keywords: KEYWORDS, |
| 137 | + contains: [LINE_COMMENT, { begin: /\bfrom\b/, className: 'keyword' }], |
| 138 | + relevance: 0 |
| 139 | + }; |
| 140 | + |
| 141 | + // ---------- REPL transcript support ---------- |
| 142 | + // Prompt line: 〉... |
| 143 | + const REPL_PROMPT = { className: 'meta', begin: /^〉\s?/m, relevance: 0 }; |
| 144 | + // Continuation lines: ::: ... |
| 145 | + const REPL_CONT = { className: 'meta', begin: /^:::\s?/m, relevance: 0 }; |
| 146 | + |
| 147 | + return { |
| 148 | + name: 'Aria', |
| 149 | + aliases: ['aria'], |
| 150 | + keywords: KEYWORDS, |
| 151 | + contains: [ |
| 152 | + SHEBANG, |
| 153 | + REPL_PROMPT, REPL_CONT, |
| 154 | + LINE_COMMENT, |
| 155 | + DQ_STRING, SQ_STRING, |
| 156 | + DEC_FLOAT, HEX_INT, OCT_INT, BIN_INT, DEC_INT, |
| 157 | + FUNC_DEF, METHOD_DEF, OP_DEF, |
| 158 | + TYPE_LIKE_DEF, EXTENSION_DEF, |
| 159 | + ENUM_CASE_DECL, ENUM_CASE_USE, |
| 160 | + LAMBDA_HEAD, TRY_PROTOCOL, ASSIGN_OP, |
| 161 | + INDEXING, OBJECT_WRITE, |
| 162 | + IMPORTS |
| 163 | + ] |
| 164 | + }; |
| 165 | +} |
0 commit comments