2025-04-01 10:38:02 +09:00

247 lines
6.1 KiB
TypeScript

import type * as monacoType from 'monaco-editor/esm/vs/editor/editor.api';
// OpenSearch PPL syntax: https://github.com/opensearch-project/opensearch-spark/blob/0.5/ppl-spark-integration/src/main/antlr4/OpenSearchPPLParser.g4
interface CloudWatchPPLLanguage extends monacoType.languages.IMonarchLanguage {
commands: string[];
operators: string[];
builtinFunctions: string[];
}
export const CLOUDWATCH_PPL_LANGUAGE_DEFINITION_ID = 'logs-ppl';
// COMMANDS
export const WHERE = 'where';
export const FIELDS = 'fields';
export const DEDUP = 'dedup';
export const STATS = 'stats';
export const EVENTSTATS = 'eventstats';
export const SORT = 'sort';
export const EVAL = 'eval';
export const HEAD = 'head';
export const TOP = 'top';
export const RARE = 'rare';
export const PARSE = 'parse';
export const PPL_COMMANDS = [WHERE, FIELDS, STATS, EVENTSTATS, DEDUP, SORT, TOP, RARE, HEAD, EVAL, PARSE];
// KEYWORDS
export const AS = 'as';
export const BY = 'by';
export const BETWEEN = 'between';
export const FROM = 'from';
// PARAMETERS
const KEEP_EMPTY = 'keepempty';
const CONSECUTIVE = 'consecutive';
const PARTITIONS = 'partitions';
const ALLNUM = 'allnum';
const DELIM = 'delim';
const DEDUP_SPLITVALUES = 'dedup_splitvalues';
export const STATS_PARAMETERS = [PARTITIONS, ALLNUM, DELIM, DEDUP_SPLITVALUES];
export const DEDUP_PARAMETERS = [KEEP_EMPTY, CONSECUTIVE];
export const PARAMETERS_WITH_BOOLEAN_VALUES = [ALLNUM, DEDUP_SPLITVALUES, KEEP_EMPTY, CONSECUTIVE];
export const BOOLEAN_LITERALS = ['true', 'false'];
export const IN = 'in';
export const ALL_KEYWORDS = [...STATS_PARAMETERS, ...DEDUP_PARAMETERS, ...BOOLEAN_LITERALS, AS, BY, IN, BETWEEN, FROM];
// FUNCTIONS
export const MATH_FUNCTIONS = [
'abs',
'acos',
'asin',
'atan',
'atan2',
'ceil',
'ceiling',
'conv',
'cos',
'cot',
'crc32',
'degrees',
'e',
'exp',
'floor',
'ln',
'log',
'log2',
'log10',
'mod',
'pi',
'pow',
'power',
'radians',
'rand',
'round',
'sign',
'sin',
'sqrt',
'cbrt',
];
export const DATE_TIME_FUNCTIONS = [
'datediff',
'day',
'dayofmonth',
'dayofweek',
'dayofyear',
'hour',
'minute',
'second',
'month',
'quarter',
'weekday',
'weekofyear',
'year',
'now',
'curdate',
'current_date',
];
export const TEXT_FUNCTIONS = [
'concat',
'concat_ws',
'length',
'lower',
'ltrim',
'reverse',
'rtrim',
'right',
'substring',
'substr',
'trim',
'upper',
];
export const SPAN = 'span';
export const POSITION = 'position';
export const CONDITION_FUNCTIONS = ['like', 'isnull', 'isnotnull', 'exists', 'ifnull', 'nullif', 'if', 'ispresent'];
export const SORT_FIELD_FUNCTIONS = ['auto', 'str', 'ip', 'num'];
export const PPL_FUNCTIONS = [...MATH_FUNCTIONS, ...DATE_TIME_FUNCTIONS, ...TEXT_FUNCTIONS];
export const EVAL_FUNCTIONS: string[] = [...PPL_FUNCTIONS, POSITION];
export const STATS_FUNCTIONS = [
'avg',
'count',
'sum',
'min',
'max',
'stddev_samp',
'stddev_pop',
'percentile',
'percentile_approx',
'distinct_count',
'dc',
];
export const ALL_FUNCTIONS = [
...PPL_FUNCTIONS,
...STATS_FUNCTIONS,
...CONDITION_FUNCTIONS,
...SORT_FIELD_FUNCTIONS,
POSITION,
SPAN,
];
// OPERATORS
export const PLUS = '+';
export const MINUS = '-';
export const NOT = 'not';
export const FIELD_OPERATORS = [PLUS, MINUS];
export const ARITHMETIC_OPERATORS = [PLUS, MINUS, '*', '/', '%'];
export const COMPARISON_OPERATORS = ['>', '>=', '<', '!=', '<=', '='];
export const LOGICAL_EXPRESSION_OPERATORS = ['and', 'or', 'xor', NOT];
export const PPL_OPERATORS = [...ARITHMETIC_OPERATORS, ...LOGICAL_EXPRESSION_OPERATORS, ...COMPARISON_OPERATORS];
export const language: CloudWatchPPLLanguage = {
defaultToken: '',
id: CLOUDWATCH_PPL_LANGUAGE_DEFINITION_ID,
ignoreCase: true,
commands: PPL_COMMANDS,
operators: PPL_OPERATORS,
keywords: ALL_KEYWORDS,
builtinFunctions: ALL_FUNCTIONS,
brackets: [{ open: '(', close: ')', token: 'delimiter.parenthesis' }],
tokenizer: {
root: [
{ include: '@comments' },
{ include: '@regexes' },
{ include: '@whitespace' },
{ include: '@variables' },
{ include: '@strings' },
{ include: '@numbers' },
[/[,.:]/, 'delimiter'],
[/\|/, 'delimiter.pipe'],
[/[()\[\]]/, 'delimiter.parenthesis'],
[
/[\w@#$]+/,
{
cases: {
'@commands': 'keyword.command',
'@keywords': 'keyword',
'@builtinFunctions': 'predefined',
'@operators': 'operator',
'@default': 'identifier',
},
},
],
[/[+\-*/^%=!<>]/, 'operator'], // handles the math operators
[/[,.:]/, 'operator'],
],
// template variable syntax
variables: [
[/\${/, { token: 'variable', next: '@variable_bracket' }],
[/\$[a-zA-Z0-9-_]+/, 'variable'],
],
variable_bracket: [
[/[a-zA-Z0-9-_:]+/, 'variable'],
[/}/, { token: 'variable', next: '@pop' }],
],
whitespace: [[/\s+/, 'white']],
comments: [
[/^#.*/, 'comment'],
[/\s+#.*/, 'comment'],
],
numbers: [
[/0[xX][0-9a-fA-F]*/, 'number'],
[/[$][+-]*\d*(\.\d*)?/, 'number'],
[/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, 'number'],
],
strings: [
[/'/, { token: 'string', next: '@string' }],
[/"/, { token: 'string', next: '@string_double' }],
[/`/, { token: 'string.backtick', next: '@string_backtick' }],
],
string: [
[/[^']+/, 'string'],
[/''/, 'string'],
[/'/, { token: 'string', next: '@pop' }],
],
string_double: [
[/[^\\"]+/, 'string'],
[/"/, 'string', '@pop'],
],
string_backtick: [
[/[^\\`]+/, 'string.backtick'],
[/`/, 'string.backtick', '@pop'],
],
regexes: [[/\/.*?\/(?!\s*\d)/, 'regexp']],
},
};
export const conf: monacoType.languages.LanguageConfiguration = {
brackets: [['(', ')']],
autoClosingPairs: [
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
{ open: '`', close: '`' },
],
surroundingPairs: [
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
{ open: '`', close: '`' },
],
};