1import type * as monacoType from 'monaco-editor/esm/vs/editor/editor.api';
2
3interface CloudWatchLanguage extends monacoType.languages.IMonarchLanguage {
4  keywords: string[];
5  operators: string[];
6  builtinFunctions: string[];
7}
8
9export const SELECT = 'SELECT';
10export const FROM = 'FROM';
11export const WHERE = 'WHERE';
12export const GROUP = 'GROUP';
13export const ORDER = 'ORDER';
14export const BY = 'BY';
15export const DESC = 'DESC';
16export const ASC = 'ASC';
17export const LIMIT = 'LIMIT';
18export const WITH = 'WITH';
19export const SCHEMA = 'SCHEMA';
20
21export const KEYWORDS = [SELECT, FROM, WHERE, GROUP, ORDER, BY, DESC, ASC, LIMIT, WITH, SCHEMA];
22export const STATISTICS = ['AVG', 'COUNT', 'MAX', 'MIN', 'SUM'];
23
24export const AND = 'AND';
25export const LOGICAL_OPERATORS = [AND];
26
27export const EQUALS = '=';
28export const NOT_EQUALS = '!=';
29export const COMPARISON_OPERATORS = [EQUALS, NOT_EQUALS];
30
31export const language: CloudWatchLanguage = {
32  defaultToken: '',
33  tokenPostfix: '.sql',
34  ignoreCase: true,
35  brackets: [
36    { open: '[', close: ']', token: 'delimiter.square' },
37    { open: '(', close: ')', token: 'delimiter.parenthesis' },
38  ],
39  keywords: KEYWORDS,
40  operators: LOGICAL_OPERATORS,
41  builtinFunctions: STATISTICS,
42  tokenizer: {
43    root: [
44      [/\$[a-zA-Z0-9-_]+/, 'variable'],
45      { include: '@comments' },
46      { include: '@whitespace' },
47      { include: '@numbers' },
48      { include: '@strings' },
49      { include: '@complexIdentifiers' },
50      [/[;,.]/, 'delimiter'],
51      [/[()]/, '@brackets'],
52      [
53        /[\w@#$]+/,
54        {
55          cases: {
56            '@keywords': 'keyword',
57            '@operators': 'operator',
58            '@builtinFunctions': 'predefined',
59            '@default': 'identifier',
60          },
61        },
62      ],
63      [/[=!%&+\-*/|~^]/, 'operator'], // TODO: strip these options
64    ],
65    whitespace: [[/\s+/, 'white']],
66    comments: [[/--+.*/, 'comment']],
67    comment: [
68      [/[^*/]+/, 'comment'],
69      [/./, 'comment'],
70    ],
71    numbers: [
72      [/0[xX][0-9a-fA-F]*/, 'number'],
73      [/[$][+-]*\d*(\.\d*)?/, 'number'],
74      [/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, 'number'],
75    ],
76    strings: [
77      [/N'/, { token: 'string', next: '@string' }],
78      [/'/, { token: 'string', next: '@string' }],
79      [/"/, { token: 'type', next: '@string_double' }],
80    ],
81    string: [
82      [/[^']+/, 'string'],
83      [/''/, 'string'],
84      [/'/, { token: 'string', next: '@pop' }],
85    ],
86    string_double: [
87      [/[^\\"]+/, 'type'],
88      [/"/, 'type', '@pop'],
89    ],
90    complexIdentifiers: [
91      [/\[/, { token: 'identifier.quote', next: '@bracketedIdentifier' }],
92      [/"/, { token: 'identifier.quote', next: '@quotedIdentifier' }],
93    ],
94    bracketedIdentifier: [
95      [/[^\]]+/, 'identifier'],
96      [/]]/, 'identifier'],
97      [/]/, { token: 'identifier.quote', next: '@pop' }],
98    ],
99    quotedIdentifier: [
100      [/[^"]+/, 'identifier'],
101      [/""/, 'identifier'],
102      [/"/, { token: 'identifier.quote', next: '@pop' }],
103    ],
104  },
105};
106
107export const conf: monacoType.languages.LanguageConfiguration = {
108  comments: {
109    lineComment: '--',
110    blockComment: ['/*', '*/'],
111  },
112  brackets: [
113    ['{', '}'],
114    ['[', ']'],
115    ['(', ')'],
116  ],
117  autoClosingPairs: [
118    { open: '{', close: '}' },
119    { open: '[', close: ']' },
120    { open: '(', close: ')' },
121    { open: '"', close: '"' },
122    { open: "'", close: "'" },
123  ],
124  surroundingPairs: [
125    { open: '{', close: '}' },
126    { open: '[', close: ']' },
127    { open: '(', close: ')' },
128    { open: '"', close: '"' },
129    { open: "'", close: "'" },
130  ],
131};
132