export const languageConfiguration = { wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, comments: { lineComment: '//', blockComment: ['/*', '*/'] as [string, string], }, brackets: [ ['{', '}'], ['[', ']'], ['(', ')'], ] as any, autoClosingPairs: [ { open: '{', close: '}' }, { open: '[', close: ']' }, { open: '(', close: ')' }, { open: '"', close: '"' }, { open: "'", close: "'" }, { open: '`', close: '`' }, ] as any, surroundingPairs: [ { open: '{', close: '}' }, { open: '[', close: ']' }, { open: '(', close: ')' }, { open: '"', close: '"' }, { open: "'", close: "'" }, { open: '`', close: '`' }, ] as any, folding: { offSide: false, }, }; // Expr-lang keywords const keywords = ['let', 'true', 'false', 'nil', 'in', 'not', 'and', 'or', 'if', 'else']; // Expr-lang built-in functions const stringFunctions = [ 'trim', 'trimPrefix', 'trimSuffix', 'upper', 'lower', 'split', 'splitAfter', 'replace', 'repeat', 'indexOf', 'lastIndexOf', 'hasPrefix', 'hasSuffix', 'contains', 'startsWith', 'endsWith', ]; const dateFunctions = ['now', 'duration', 'date', 'timezone']; const numberFunctions = ['max', 'min', 'abs', 'ceil', 'floor', 'round']; const arrayFunctions = [ 'all', 'any', 'one', 'none', 'map', 'filter', 'find', 'findIndex', 'findLast', 'findLastIndex', 'groupBy', 'count', 'concat', 'flatten', 'uniq', 'join', 'reduce', 'sum', 'mean', 'median', 'first', 'last', 'take', 'reverse', 'sort', 'sortBy', ]; const mapFunctions = ['keys', 'values']; const typeConversionFunctions = ['type', 'int', 'float', 'string', 'toJSON', 'fromJSON', 'toBase64', 'fromBase64', 'toPairs', 'fromPairs']; const miscFunctions = ['len', 'get']; const bitwiseFunctions = ['bitand', 'bitor', 'bitxor', 'bitnand', 'bitnot', 'bitshl', 'bitshr', 'bitushr']; const builtinFunctions = [ ...stringFunctions, ...dateFunctions, ...numberFunctions, ...arrayFunctions, ...mapFunctions, ...typeConversionFunctions, ...miscFunctions, ...bitwiseFunctions, ]; export const language = { defaultToken: '', tokenPostfix: '.expr', brackets: [ { open: '(', close: ')', token: 'delimiter.parenthesis' }, { open: '{', close: '}', token: 'delimiter.curly' }, { open: '[', close: ']', token: 'delimiter.square' }, ], keywords, builtinFunctions, operators: ['+', '-', '*', '/', '%', '^', '**', '==', '!=', '<', '>', '<=', '>=', '!', '&&', '||', '?:', '??', '.', '?.', 'in', 'matches', '..', '|'], escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, digits: /\d+(_+\d+)*/, hexdigits: /[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/, octdigits: /[0-7]+(_+[0-7]+)*/, bindigits: /[01]+(_+[01]+)*/, tokenizer: { root: [ { include: '@whitespace' }, { include: '@comments' }, { include: '@numbers' }, { include: '@strings' }, { include: '@bytes' }, // Function calls: identifier followed by '(' [/[a-zA-Z_]\w*(?=\s*\()/, { cases: { '@builtinFunctions': 'keyword.function', '@default': 'identifier.function' } }], // Keywords and identifiers [/[a-zA-Z_]\w*/, { cases: { '@keywords': 'keyword', '@default': 'identifier' } }], // Operators [/[?][?:]/, 'operator'], // ??, ?: [/[?][.]/, 'operator'], // ?. [/[.]{2}/, 'operator'], // .. [/[*]{2}/, 'operator'], // ** [/[|]/, 'operator'], // | [/[+\-*/%^]/, 'operator'], [/==|!=|<=|>=|<|>/, 'operator'], [/!|&&|\|\|/, 'operator'], [/[=]/, 'operator'], [/[.~]/, 'operator'], // Delimiters [/[,;]/, 'delimiter'], [/[{}()\[\]]/, '@brackets'], ], whitespace: [[/[ \t\r\n]+/, 'white']], comments: [ [/\/\/.*$/, 'comment'], [/\/\*/, { token: 'comment.quote', next: '@comment' }], ], comment: [ [/[^*/]+/, 'comment'], [/\*\//, { token: 'comment.quote', next: '@pop' }], [/./, 'comment'], ], numbers: [ [/0[xX]@hexdigits/, 'number.hex'], [/0[oO]@octdigits/, 'number.octal'], [/0[bB]@bindigits/, 'number.binary'], [/(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?/, 'number'], ], strings: [ [/"/, { token: 'string.double', next: '@string_double' }], [/'/, { token: 'string', next: '@string_single' }], [/`/, { token: 'string.backtick', next: '@string_backtick' }], ], string_double: [ [/[^"\\]+/, 'string.double'], [/@escapes/, 'string.escape'], [/\\./, 'string.escape.invalid'], [/"/, { token: 'string.double', next: '@pop' }], ], string_single: [ [/[^'\\]+/, 'string'], [/@escapes/, 'string.escape'], [/\\./, 'string.escape.invalid'], [/'/, { token: 'string', next: '@pop' }], ], string_backtick: [ [/[^`]+/, 'string.backtick'], [/`/, { token: 'string.backtick', next: '@pop' }], ], bytes: [ [/[bB]"/, { token: 'string.bytes', next: '@bytes_double' }], [/[bB]'/, { token: 'string.bytes', next: '@bytes_single' }], ], bytes_double: [ [/[^"\\]+/, 'string.bytes'], [/\\(?:[abfnrtv\\"]|x[0-9A-Fa-f]{2}|[0-7]{3})/, 'string.escape'], [/\\./, 'string.escape.invalid'], [/"/, { token: 'string.bytes', next: '@pop' }], ], bytes_single: [ [/[^'\\]+/, 'string.bytes'], [/\\(?:[abfnrtv\\']|x[0-9A-Fa-f]{2}|[0-7]{3})/, 'string.escape'], [/\\./, 'string.escape.invalid'], [/'/, { token: 'string.bytes', next: '@pop' }], ], }, };