From ff4952684cb8a5fc749a8e92a09e9888743108ef Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Thu, 7 Dec 2023 10:23:39 +0100 Subject: [PATCH] [ES|QL] Advanced validation and autocomplete (#170071) ## Summary Fixes https://github.com/elastic/kibana/issues/166242 , #166876, #166173 , part of #166092, #166084 List of tasks: * [x] AST work ( #166185 ) * [x] Basic validate work ( #166185 ) * [x] Hover feature ( #166185 ) * [x] Initial autocomplete work with new AST ( #166185 ) * Complete validation feature for MVP * [x] wildcards support ( #170014 ) * [x] remote index validation support ( #171996 ) * [x] wildcard support as `count` argument ( #172054 ) * [x] Aggressive caching for field queries: * cache as much as possible the `FROM` queries - possible clear the cache every 10/15 minutes? * do not fire a query when code == submitted code * cache as much as possible the custom `FROM` built from `ENRICH` policies - same clear policy as above * [x] Add unsupported fields warning messages * [x] Notify usage of `project` command with deprecation `warning` * Complete autocomplete work ( #171664 ) * [x] `stats` * [x] `where` * [x] `eval` * `math syntax` * [x] Aggressive cache for fields queries? ( #171866 ) * [x] Fix when cursor is not at the end position ( #172060 ) * [x] Revisit copy messages * Label Kibana-only messages * [x] Extend hover feature ( #171940 ) * [x] Disable editor query highlight for warnings ( #171968 ) * Fix editor highlight with new grammar * [x] on multi-line ( #172080 ) * [x] for functions ( #172287 ) ## Release notes Enhance ES|QL query editing experience with client side validation. Enhance ES|QL suggestions experience with more in context suggestions leveraging field and variable types. Show meta informations on ES|QL query hover on policy names. Show function signature on ES|QL query hover on function text. ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Stratoula Kalafateli Co-authored-by: Abdon Pijpelink --- packages/kbn-monaco/index.ts | 2 +- .../kbn-monaco/src/common/error_listener.ts | 1 + .../kbn-monaco/src/esql/antlr/esql_lexer.g4 | 244 +- .../src/esql/antlr/esql_lexer.interp | 183 +- .../src/esql/antlr/esql_lexer.tokens | 161 +- .../kbn-monaco/src/esql/antlr/esql_lexer.ts | 1359 ++--- .../kbn-monaco/src/esql/antlr/esql_parser.g4 | 223 +- .../src/esql/antlr/esql_parser.interp | 132 +- .../src/esql/antlr/esql_parser.tokens | 161 +- .../kbn-monaco/src/esql/antlr/esql_parser.ts | 4362 +++++++---------- .../src/esql/antlr/esql_parser_listener.ts | 606 ++- packages/kbn-monaco/src/esql/index.ts | 2 +- packages/kbn-monaco/src/esql/language.ts | 77 +- .../kbn-monaco/src/esql/lib/antlr_facade.ts | 11 +- .../kbn-monaco/src/esql/lib/ast/ast_errors.ts | 50 + .../src/esql/lib/ast/ast_factory.ts | 249 + .../src/esql/lib/ast/ast_helpers.ts | 240 + .../src/esql/lib/ast/ast_position_utils.ts | 22 + .../kbn-monaco/src/esql/lib/ast/ast_walker.ts | 544 ++ .../lib/ast/autocomplete/autocomplete.test.ts | 780 +++ .../esql/lib/ast/autocomplete/autocomplete.ts | 1098 +++++ .../lib/ast/autocomplete/complete_items.ts | 80 + .../autocomplete/documentation_util.ts} | 0 .../esql/lib/ast/autocomplete/factories.ts | 268 + .../src/esql/lib/ast/autocomplete/types.ts | 28 + .../src/esql/lib/ast/definitions/aggs.ts | 127 + .../src/esql/lib/ast/definitions/builtin.ts | 348 ++ .../src/esql/lib/ast/definitions/commands.ts | 280 ++ .../definitions/functions.ts} | 633 +-- .../src/esql/lib/ast/definitions/helpers.ts | 101 + .../src/esql/lib/ast/definitions/literals.ts | 142 + .../src/esql/lib/ast/definitions/options.ts | 106 + .../src/esql/lib/ast/definitions/types.ts | 75 + .../src/esql/lib/ast/hover/index.ts | 81 + .../src/esql/lib/ast/shared/constants.ts | 9 + .../src/esql/lib/ast/shared/context.ts | 158 + .../src/esql/lib/ast/shared/helpers.ts | 451 ++ .../esql/lib/ast/shared/resources_helpers.ts | 66 + .../src/esql/lib/ast/shared/types.ts | 22 + .../src/esql/lib/ast/shared/variables.ts | 172 + .../src/esql/lib/ast/signature/index.ts | 22 + packages/kbn-monaco/src/esql/lib/ast/types.ts | 86 + .../src/esql/lib/ast/validation/errors.ts | 217 + .../src/esql/lib/ast/validation/helpers.ts | 21 + .../src/esql/lib/ast/validation/resources.ts | 85 + .../src/esql/lib/ast/validation/types.ts | 127 + .../lib/ast/validation/validation.test.ts | 1440 ++++++ .../src/esql/lib/ast/validation/validation.ts | 780 +++ .../comparison_commands.ts | 116 - .../date_math_expressions.ts | 157 - .../dynamic_commands.ts | 114 - .../autocomplete_definitions/index.ts | 41 - .../operators_commands.ts | 119 - .../ordering_commands.ts | 54 - .../processing_commands.ts | 197 - .../source_commands.ts | 31 - .../autocomplete_listener.test.ts | 226 - .../lib/autocomplete/autocomplete_listener.ts | 641 --- .../src/esql/lib/autocomplete/dymanic_item.ts | 21 - .../src/esql/lib/autocomplete/helpers.ts | 33 - .../src/esql/lib/autocomplete/types.ts | 36 - .../src/esql/lib/monaco/esql_ast_provider.ts | 121 + .../lib/monaco/esql_completion_provider.ts | 136 - .../esql/lib/monaco/esql_error_listener.ts | 53 + .../src/esql/lib/monaco/esql_line_tokens.ts | 5 +- .../src/esql/lib/monaco/esql_state.ts | 14 +- .../src/esql/lib/monaco/esql_theme.ts | 11 +- .../src/esql/lib/monaco/esql_token_helpers.ts | 33 + .../esql/lib/monaco/esql_tokens_provider.ts | 20 +- .../kbn-monaco/src/esql/worker/esql_worker.ts | 51 +- packages/kbn-monaco/src/types.ts | 16 +- .../src/editor_footer.tsx | 42 +- .../kbn-text-based-editor/src/helpers.test.ts | 35 +- packages/kbn-text-based-editor/src/helpers.ts | 42 +- .../src/text_based_languages_editor.tsx | 301 +- .../translations/translations/fr-FR.json | 123 - .../translations/translations/ja-JP.json | 123 - .../translations/translations/zh-CN.json | 123 - 78 files changed, 12342 insertions(+), 7125 deletions(-) create mode 100644 packages/kbn-monaco/src/esql/lib/ast/ast_errors.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/ast_factory.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/ast_helpers.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/ast_position_utils.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/ast_walker.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.test.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/autocomplete/complete_items.ts rename packages/kbn-monaco/src/esql/lib/{autocomplete/autocomplete_definitions/utils.ts => ast/autocomplete/documentation_util.ts} (100%) create mode 100644 packages/kbn-monaco/src/esql/lib/ast/autocomplete/factories.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/autocomplete/types.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/definitions/aggs.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/definitions/builtin.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/definitions/commands.ts rename packages/kbn-monaco/src/esql/lib/{autocomplete/autocomplete_definitions/functions_commands.ts => ast/definitions/functions.ts} (52%) create mode 100644 packages/kbn-monaco/src/esql/lib/ast/definitions/helpers.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/definitions/literals.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/definitions/options.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/definitions/types.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/hover/index.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/shared/constants.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/shared/context.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/shared/helpers.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/shared/resources_helpers.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/shared/types.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/shared/variables.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/signature/index.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/types.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/validation/errors.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/validation/helpers.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/validation/resources.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/validation/types.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/validation/validation.test.ts create mode 100644 packages/kbn-monaco/src/esql/lib/ast/validation/validation.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/date_math_expressions.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/ordering_commands.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/source_commands.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/helpers.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/autocomplete/types.ts create mode 100644 packages/kbn-monaco/src/esql/lib/monaco/esql_ast_provider.ts delete mode 100644 packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts create mode 100644 packages/kbn-monaco/src/esql/lib/monaco/esql_error_listener.ts create mode 100644 packages/kbn-monaco/src/esql/lib/monaco/esql_token_helpers.ts diff --git a/packages/kbn-monaco/index.ts b/packages/kbn-monaco/index.ts index d7ff4d4abc94a..2ebb05bd0e393 100644 --- a/packages/kbn-monaco/index.ts +++ b/packages/kbn-monaco/index.ts @@ -12,7 +12,7 @@ export { monaco } from './src/monaco_imports'; export { XJsonLang } from './src/xjson'; export { SQLLang } from './src/sql'; export { ESQL_LANG_ID, ESQL_THEME_ID, ESQLLang } from './src/esql'; -export type { ESQLCustomAutocompleteCallbacks } from './src/esql'; +export type { ESQLCallbacks } from './src/esql'; export * from './src/painless'; /* eslint-disable-next-line @kbn/eslint/module_migration */ diff --git a/packages/kbn-monaco/src/common/error_listener.ts b/packages/kbn-monaco/src/common/error_listener.ts index b072b132b26ac..efcacb88d2c2a 100644 --- a/packages/kbn-monaco/src/common/error_listener.ts +++ b/packages/kbn-monaco/src/common/error_listener.ts @@ -31,6 +31,7 @@ export class ANTLREErrorListener implements ANTLRErrorListener { startColumn: column, endColumn, message, + severity: 8, }); } diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 b/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 index 815cf7f237bfb..90a892d8d1dd6 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 @@ -4,26 +4,27 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - + lexer grammar esql_lexer; +options { } DISSECT : D I S S E C T -> pushMode(EXPRESSION); -GROK : G R O K -> pushMode(EXPRESSION); +DROP : D R O P -> pushMode(SOURCE_IDENTIFIERS); +ENRICH : E N R I C H -> pushMode(SOURCE_IDENTIFIERS); EVAL : E V A L -> pushMode(EXPRESSION); -EXPLAIN : E X P L A I N -> pushMode(EXPLAIN_MODE); FROM : F R O M -> pushMode(SOURCE_IDENTIFIERS); +GROK : G R O K -> pushMode(EXPRESSION); +KEEP : K E E P -> pushMode(SOURCE_IDENTIFIERS); +LIMIT : L I M I T -> pushMode(EXPRESSION); +MV_EXPAND : M V UNDERSCORE E X P A N D -> pushMode(SOURCE_IDENTIFIERS); +PROJECT : P R O J E C T -> pushMode(SOURCE_IDENTIFIERS); +RENAME : R E N A M E -> pushMode(SOURCE_IDENTIFIERS); ROW : R O W -> pushMode(EXPRESSION); +SHOW : S H O W -> pushMode(EXPRESSION); +SORT : S O R T -> pushMode(EXPRESSION); STATS : S T A T S -> pushMode(EXPRESSION); WHERE : W H E R E -> pushMode(EXPRESSION); -SORT : S O R T -> pushMode(EXPRESSION); -MV_EXPAND : M V UNDERSCORE E X P A N D -> pushMode(EXPRESSION); -LIMIT : L I M I T -> pushMode(EXPRESSION); -PROJECT : P R O J E C T -> pushMode(EXPRESSION); -DROP : D R O P -> pushMode(EXPRESSION); -RENAME : R E N A M E -> pushMode(EXPRESSION); -SHOW : S H O W -> pushMode(EXPRESSION); -ENRICH : E N R I C H -> pushMode(ENRICH_IDENTIFIERS); -KEEP : K E E P -> pushMode(EXPRESSION); +UNKNOWN_CMD : ~[ \r\n\t[\]/]+ -> pushMode(EXPRESSION); LINE_COMMENT : '//' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN) @@ -36,12 +37,7 @@ MULTILINE_COMMENT WS : [ \r\n\t]+ -> channel(HIDDEN) ; -mode EXPLAIN_MODE; -EXPLAIN_OPENING_BRACKET : '[' -> type(OPENING_BRACKET), pushMode(DEFAULT_MODE); -EXPLAIN_PIPE : '|' -> type(PIPE), popMode; -EXPLAIN_WS : WS -> channel(HIDDEN); -EXPLAIN_LINE_COMMENT : LINE_COMMENT -> channel(HIDDEN); -EXPLAIN_MULTILINE_COMMENT : MULTILINE_COMMENT -> channel(HIDDEN); + mode EXPRESSION; PIPE : '|' -> popMode; @@ -82,169 +78,60 @@ DECIMAL_LITERAL | DOT DIGIT+ EXPONENT ; -BY : 'by'; - -DATE_LITERAL - : 'year' - | 'month' - | 'day' - | 'second' - | 'minute' - | 'hour' - | 'week' - | 'millisecond' - | 'years' - | 'months' - | 'days' - | 'seconds' - | 'minutes' - | 'hours' - | 'weeks' - | 'milliseconds' - ; +BY : B Y; -AND : 'and'; +AND : A N D; +ASC : A S C; ASSIGN : '='; COMMA : ','; +DESC : D E S C; DOT : '.'; +FALSE : F A L S E; +FIRST : F I R S T; +LAST : L A S T; LP : '('; -OPENING_BRACKET : '[' -> pushMode(EXPRESSION), pushMode(EXPRESSION); -CLOSING_BRACKET : ']' -> popMode, popMode; -NOT : N O T; -LIKE: L I K E; -RLIKE: R L I K E; IN: I N; IS: I S; -AS: A S; +LIKE: L I K E; +NOT : N O T; NULL : N U L L; -OR : 'or'; +NULLS : N U L L S; +OR : O R; +PARAM: '?'; +RLIKE: R L I K E; RP : ')'; +TRUE : T R U E; +INFO : I N F O; +FUNCTIONS : F U N C T I O N S; UNDERSCORE: '_'; -INFO : 'info'; -FUNCTIONS : 'functions'; - -BOOLEAN_VALUE - : 'true' - | 'false' - ; - -COMPARISON_OPERATOR - : '==' - |'!=' - | '<' - | '<=' - | '>' - | '>=' - ; + +EQ : '=='; +NEQ : '!='; +LT : '<'; +LTE : '<='; +GT : '>'; +GTE : '>='; PLUS : '+'; MINUS : '-'; ASTERISK : '*'; SLASH : '/'; PERCENT : '%'; -TEN: '10'; - -ORDERING - : 'asc' - | 'desc' - ; - -NULLS_ORDERING: 'nulls'; -NULLS_ORDERING_DIRECTION - : 'first' - | 'last' - ; -MATH_FUNCTION - : R O U N D - | A B S - | P O W - | L O G TEN - | P I - | T A U - | E - | S U B S T R I N G - | T R I M - | C O N C A T - | C O A L E S C E - | G R E A T E S T - | L E F T - | N O W - | R I G H T - | S T A R T S UNDERSCORE W I T H - | D A T E UNDERSCORE F O R M A T - | D A T E UNDERSCORE T R U N C - | D A T E UNDERSCORE P A R S E - | A U T O UNDERSCORE B U C K E T - | D A T E UNDERSCORE E X T R A C T - | I S UNDERSCORE F I N I T E - | I S UNDERSCORE I N F I N I T E - | C A S E - | L E N G T H - | M V UNDERSCORE M A X - | M V UNDERSCORE M I N - | M V UNDERSCORE A V G - | M V UNDERSCORE S U M - | M V UNDERSCORE C O U N T - | M V UNDERSCORE C O N C A T - | M V UNDERSCORE J O I N - | M V UNDERSCORE M E D I A N - | M V UNDERSCORE D E D U P E - | M E T A D A T A - | S P L I T - | T O UNDERSCORE S T R I N G - | T O UNDERSCORE S T R - | T O UNDERSCORE B O O L - | T O UNDERSCORE B O O L E A N - | T O UNDERSCORE D A T E T I M E - | T O UNDERSCORE D T - | T O UNDERSCORE D B L - | T O UNDERSCORE D O U B L E - | T O UNDERSCORE D E G R E E S - | T O UNDERSCORE I N T - | T O UNDERSCORE I N T E G E R - | T O UNDERSCORE I P - | T O UNDERSCORE L O N G - | T O UNDERSCORE R A D I A N S - | T O UNDERSCORE V E R S I O N - | T O UNDERSCORE U N S I G N E D UNDERSCORE L O N G - ; - -UNARY_FUNCTION - : A V G - | M I N - | M A X - | S U M - | C O U N T - | C O U N T UNDERSCORE D I S T I N C T - | P E R C E N T I L E - | M E D I A N - | M E D I A N UNDERSCORE A B S O L U T E UNDERSCORE D E V I A T I O N - | A C O S - | A S I N - | A T A N - | A T A N '2' - | C E I L - | C O S - | C O S H - | F L O O R - | L T R I M - | S I N - | S I N H - | S Q R T - | T A N - | T A N H - ; +// Brackets are funny. We can happen upon a CLOSING_BRACKET in two ways - one +// way is to start in an explain command which then shifts us to expression +// mode. Thus, the two popModes on CLOSING_BRACKET. The other way could as +// the start of a multivalued field constant. To line up with the double pop +// the explain mode needs, we double push when we see that. +OPENING_BRACKET : '[' -> pushMode(EXPRESSION), pushMode(EXPRESSION); +CLOSING_BRACKET : ']' -> popMode, popMode; -WHERE_FUNCTIONS - : C I D R UNDERSCORE M A T C H - ; UNQUOTED_IDENTIFIER - : LETTER (LETTER | DIGIT | '_' | ASTERISK)* + : LETTER (LETTER | DIGIT | '_')* // only allow @ at beginning of identifier to keep the option to allow @ as infix operator in the future // also, single `_` and `@` characters are not valid identifiers - | ('_' | '@') (LETTER | DIGIT | '_' | ASTERISK)+ + | ('_' | '@') (LETTER | DIGIT | '_')+ ; QUOTED_IDENTIFIER @@ -264,6 +151,7 @@ EXPR_WS ; + mode SOURCE_IDENTIFIERS; SRC_PIPE : '|' -> type(PIPE), popMode; @@ -271,7 +159,10 @@ SRC_OPENING_BRACKET : '[' -> type(OPENING_BRACKET), pushMode(SOURCE_IDENTIFIERS) SRC_CLOSING_BRACKET : ']' -> popMode, popMode, type(CLOSING_BRACKET); SRC_COMMA : ',' -> type(COMMA); SRC_ASSIGN : '=' -> type(ASSIGN); +AS : A S; METADATA: M E T A D A T A; +ON : O N; +WITH : W I T H; SRC_UNQUOTED_IDENTIFIER : SRC_UNQUOTED_IDENTIFIER_PART+ @@ -298,41 +189,6 @@ SRC_WS : WS -> channel(HIDDEN) ; -mode ENRICH_IDENTIFIERS; - -ON : O N; -WITH : W I T H; - -ENR_PIPE : '|' -> type(PIPE), popMode; -ENR_CLOSING_BRACKET : ']' -> popMode, popMode, type(CLOSING_BRACKET); -ENR_COMMA : ',' -> type(COMMA); -ENR_ASSIGN : '=' -> type(ASSIGN); - -ENR_UNQUOTED_IDENTIFIER - : ENR_UNQUOTED_IDENTIFIER_PART+ - ; - -fragment ENR_UNQUOTED_IDENTIFIER_PART - : ~[=`|,[\]/ \t\r\n]+ - | '/' ~[*/] // allow single / but not followed by another / or * which would start a comment - ; - -ENR_QUOTED_IDENTIFIER - : QUOTED_IDENTIFIER - ; - -ENR_LINE_COMMENT - : LINE_COMMENT -> channel(HIDDEN) - ; - -ENR_MULTILINE_COMMENT - : MULTILINE_COMMENT -> channel(HIDDEN) - ; - -ENR_WS - : WS -> channel(HIDDEN) - ; - fragment A : [aA]; // match either an 'a' or 'A' fragment B : [bB]; fragment C : [cC]; diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp b/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp index 80f8a20f9d322..0ff1f62c47445 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp @@ -27,46 +27,41 @@ null null null null -'by' null -'and' null null '.' +null +null +null '(' null -']' null null null null null null +'?' null -'or' ')' -'_' -'info' -'functions' null null +null +'_' +'==' +'!=' +'<' +'<=' +'>' +'>=' '+' '-' '*' '/' '%' -'10' -null -'nulls' -null -null -null -null -null -null -null -null null +']' null null null @@ -85,113 +80,103 @@ null token symbolic names: null DISSECT -GROK +DROP +ENRICH EVAL -EXPLAIN FROM -ROW -STATS -WHERE -SORT -MV_EXPAND +GROK +KEEP LIMIT +MV_EXPAND PROJECT -DROP RENAME +ROW SHOW -ENRICH -KEEP +SORT +STATS +WHERE +UNKNOWN_CMD LINE_COMMENT MULTILINE_COMMENT WS -EXPLAIN_WS -EXPLAIN_LINE_COMMENT -EXPLAIN_MULTILINE_COMMENT PIPE STRING INTEGER_LITERAL DECIMAL_LITERAL BY -DATE_LITERAL AND +ASC ASSIGN COMMA +DESC DOT +FALSE +FIRST +LAST LP -OPENING_BRACKET -CLOSING_BRACKET -NOT -LIKE -RLIKE IN IS -AS +LIKE +NOT NULL +NULLS OR +PARAM +RLIKE RP -UNDERSCORE +TRUE INFO FUNCTIONS -BOOLEAN_VALUE -COMPARISON_OPERATOR +UNDERSCORE +EQ +NEQ +LT +LTE +GT +GTE PLUS MINUS ASTERISK SLASH PERCENT -TEN -ORDERING -NULLS_ORDERING -NULLS_ORDERING_DIRECTION -MATH_FUNCTION -UNARY_FUNCTION -WHERE_FUNCTIONS +OPENING_BRACKET +CLOSING_BRACKET UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS +AS METADATA +ON +WITH SRC_UNQUOTED_IDENTIFIER SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS -ON -WITH -ENR_UNQUOTED_IDENTIFIER -ENR_QUOTED_IDENTIFIER -ENR_LINE_COMMENT -ENR_MULTILINE_COMMENT -ENR_WS -EXPLAIN_PIPE rule names: DISSECT -GROK +DROP +ENRICH EVAL -EXPLAIN FROM -ROW -STATS -WHERE -SORT -MV_EXPAND +GROK +KEEP LIMIT +MV_EXPAND PROJECT -DROP RENAME +ROW SHOW -ENRICH -KEEP +SORT +STATS +WHERE +UNKNOWN_CMD LINE_COMMENT MULTILINE_COMMENT WS -EXPLAIN_OPENING_BRACKET -EXPLAIN_PIPE -EXPLAIN_WS -EXPLAIN_LINE_COMMENT -EXPLAIN_MULTILINE_COMMENT PIPE DIGIT LETTER @@ -202,40 +187,43 @@ STRING INTEGER_LITERAL DECIMAL_LITERAL BY -DATE_LITERAL AND +ASC ASSIGN COMMA +DESC DOT +FALSE +FIRST +LAST LP -OPENING_BRACKET -CLOSING_BRACKET -NOT -LIKE -RLIKE IN IS -AS +LIKE +NOT NULL +NULLS OR +PARAM +RLIKE RP -UNDERSCORE +TRUE INFO FUNCTIONS -BOOLEAN_VALUE -COMPARISON_OPERATOR +UNDERSCORE +EQ +NEQ +LT +LTE +GT +GTE PLUS MINUS ASTERISK SLASH PERCENT -TEN -ORDERING -NULLS_ORDERING -NULLS_ORDERING_DIRECTION -MATH_FUNCTION -UNARY_FUNCTION -WHERE_FUNCTIONS +OPENING_BRACKET +CLOSING_BRACKET UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT @@ -246,25 +234,16 @@ SRC_OPENING_BRACKET SRC_CLOSING_BRACKET SRC_COMMA SRC_ASSIGN +AS METADATA +ON +WITH SRC_UNQUOTED_IDENTIFIER SRC_UNQUOTED_IDENTIFIER_PART SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS -ON -WITH -ENR_PIPE -ENR_CLOSING_BRACKET -ENR_COMMA -ENR_ASSIGN -ENR_UNQUOTED_IDENTIFIER -ENR_UNQUOTED_IDENTIFIER_PART -ENR_QUOTED_IDENTIFIER -ENR_LINE_COMMENT -ENR_MULTILINE_COMMENT -ENR_WS A B C @@ -298,10 +277,8 @@ HIDDEN mode names: DEFAULT_MODE -EXPLAIN_MODE EXPRESSION SOURCE_IDENTIFIERS -ENRICH_IDENTIFIERS atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 83, 1600, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 4, 115, 9, 115, 4, 116, 9, 116, 4, 117, 9, 117, 4, 118, 9, 118, 4, 119, 9, 119, 4, 120, 9, 120, 4, 121, 9, 121, 4, 122, 9, 122, 4, 123, 9, 123, 4, 124, 9, 124, 4, 125, 9, 125, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 399, 10, 19, 12, 19, 14, 19, 402, 11, 19, 3, 19, 5, 19, 405, 10, 19, 3, 19, 5, 19, 408, 10, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 417, 10, 20, 12, 20, 14, 20, 420, 11, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 428, 10, 21, 13, 21, 14, 21, 429, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 5, 32, 471, 10, 32, 3, 32, 6, 32, 474, 10, 32, 13, 32, 14, 32, 475, 3, 33, 3, 33, 3, 33, 7, 33, 481, 10, 33, 12, 33, 14, 33, 484, 11, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 7, 33, 492, 10, 33, 12, 33, 14, 33, 495, 11, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 5, 33, 502, 10, 33, 3, 33, 5, 33, 505, 10, 33, 5, 33, 507, 10, 33, 3, 34, 6, 34, 510, 10, 34, 13, 34, 14, 34, 511, 3, 35, 6, 35, 515, 10, 35, 13, 35, 14, 35, 516, 3, 35, 3, 35, 7, 35, 521, 10, 35, 12, 35, 14, 35, 524, 11, 35, 3, 35, 3, 35, 6, 35, 528, 10, 35, 13, 35, 14, 35, 529, 3, 35, 6, 35, 533, 10, 35, 13, 35, 14, 35, 534, 3, 35, 3, 35, 7, 35, 539, 10, 35, 12, 35, 14, 35, 542, 11, 35, 5, 35, 544, 10, 35, 3, 35, 3, 35, 3, 35, 3, 35, 6, 35, 550, 10, 35, 13, 35, 14, 35, 551, 3, 35, 3, 35, 5, 35, 556, 10, 35, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 5, 37, 655, 10, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 5, 57, 739, 10, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 5, 58, 751, 10, 58, 3, 59, 3, 59, 3, 60, 3, 60, 3, 61, 3, 61, 3, 62, 3, 62, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 5, 65, 773, 10, 65, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 5, 67, 790, 10, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 5, 68, 1222, 10, 68, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 5, 69, 1375, 10, 69, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 7, 71, 1393, 10, 71, 12, 71, 14, 71, 1396, 11, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 6, 71, 1403, 10, 71, 13, 71, 14, 71, 1404, 5, 71, 1407, 10, 71, 3, 72, 3, 72, 3, 72, 3, 72, 7, 72, 1413, 10, 72, 12, 72, 14, 72, 1416, 11, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 82, 6, 82, 1467, 10, 82, 13, 82, 14, 82, 1468, 3, 83, 6, 83, 1472, 10, 83, 13, 83, 14, 83, 1473, 3, 83, 3, 83, 5, 83, 1478, 10, 83, 3, 84, 3, 84, 3, 85, 3, 85, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 88, 3, 89, 3, 89, 3, 89, 3, 89, 3, 89, 3, 90, 3, 90, 3, 90, 3, 90, 3, 90, 3, 91, 3, 91, 3, 91, 3, 91, 3, 91, 3, 91, 3, 92, 3, 92, 3, 92, 3, 92, 3, 93, 3, 93, 3, 93, 3, 93, 3, 94, 6, 94, 1522, 10, 94, 13, 94, 14, 94, 1523, 3, 95, 6, 95, 1527, 10, 95, 13, 95, 14, 95, 1528, 3, 95, 3, 95, 5, 95, 1533, 10, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 97, 3, 97, 3, 98, 3, 98, 3, 98, 3, 98, 3, 99, 3, 99, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 3, 107, 3, 107, 3, 108, 3, 108, 3, 109, 3, 109, 3, 110, 3, 110, 3, 111, 3, 111, 3, 112, 3, 112, 3, 113, 3, 113, 3, 114, 3, 114, 3, 115, 3, 115, 3, 116, 3, 116, 3, 117, 3, 117, 3, 118, 3, 118, 3, 119, 3, 119, 3, 120, 3, 120, 3, 121, 3, 121, 3, 122, 3, 122, 3, 123, 3, 123, 3, 124, 3, 124, 3, 125, 3, 125, 4, 418, 493, 2, 2, 126, 7, 2, 3, 9, 2, 4, 11, 2, 5, 13, 2, 6, 15, 2, 7, 17, 2, 8, 19, 2, 9, 21, 2, 10, 23, 2, 11, 25, 2, 12, 27, 2, 13, 29, 2, 14, 31, 2, 15, 33, 2, 16, 35, 2, 17, 37, 2, 18, 39, 2, 19, 41, 2, 20, 43, 2, 21, 45, 2, 22, 47, 2, 2, 49, 2, 83, 51, 2, 23, 53, 2, 24, 55, 2, 25, 57, 2, 26, 59, 2, 2, 61, 2, 2, 63, 2, 2, 65, 2, 2, 67, 2, 2, 69, 2, 27, 71, 2, 28, 73, 2, 29, 75, 2, 30, 77, 2, 31, 79, 2, 32, 81, 2, 33, 83, 2, 34, 85, 2, 35, 87, 2, 36, 89, 2, 37, 91, 2, 38, 93, 2, 39, 95, 2, 40, 97, 2, 41, 99, 2, 42, 101, 2, 43, 103, 2, 44, 105, 2, 45, 107, 2, 46, 109, 2, 47, 111, 2, 48, 113, 2, 49, 115, 2, 50, 117, 2, 51, 119, 2, 52, 121, 2, 53, 123, 2, 54, 125, 2, 55, 127, 2, 56, 129, 2, 57, 131, 2, 58, 133, 2, 59, 135, 2, 60, 137, 2, 61, 139, 2, 62, 141, 2, 63, 143, 2, 64, 145, 2, 65, 147, 2, 66, 149, 2, 67, 151, 2, 68, 153, 2, 69, 155, 2, 2, 157, 2, 2, 159, 2, 2, 161, 2, 2, 163, 2, 2, 165, 2, 70, 167, 2, 71, 169, 2, 2, 171, 2, 72, 173, 2, 73, 175, 2, 74, 177, 2, 75, 179, 2, 76, 181, 2, 77, 183, 2, 2, 185, 2, 2, 187, 2, 2, 189, 2, 2, 191, 2, 78, 193, 2, 2, 195, 2, 79, 197, 2, 80, 199, 2, 81, 201, 2, 82, 203, 2, 2, 205, 2, 2, 207, 2, 2, 209, 2, 2, 211, 2, 2, 213, 2, 2, 215, 2, 2, 217, 2, 2, 219, 2, 2, 221, 2, 2, 223, 2, 2, 225, 2, 2, 227, 2, 2, 229, 2, 2, 231, 2, 2, 233, 2, 2, 235, 2, 2, 237, 2, 2, 239, 2, 2, 241, 2, 2, 243, 2, 2, 245, 2, 2, 247, 2, 2, 249, 2, 2, 251, 2, 2, 253, 2, 2, 7, 2, 3, 4, 5, 6, 39, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 3, 2, 50, 59, 4, 2, 67, 92, 99, 124, 7, 2, 36, 36, 94, 94, 112, 112, 116, 116, 118, 118, 6, 2, 12, 12, 15, 15, 36, 36, 94, 94, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 4, 2, 66, 66, 97, 97, 3, 2, 98, 98, 12, 2, 11, 12, 15, 15, 34, 34, 46, 46, 49, 49, 63, 63, 93, 93, 95, 95, 98, 98, 126, 126, 4, 2, 44, 44, 49, 49, 4, 2, 67, 67, 99, 99, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 2, 1700, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 3, 47, 3, 2, 2, 2, 3, 49, 3, 2, 2, 2, 3, 51, 3, 2, 2, 2, 3, 53, 3, 2, 2, 2, 3, 55, 3, 2, 2, 2, 4, 57, 3, 2, 2, 2, 4, 69, 3, 2, 2, 2, 4, 71, 3, 2, 2, 2, 4, 73, 3, 2, 2, 2, 4, 75, 3, 2, 2, 2, 4, 77, 3, 2, 2, 2, 4, 79, 3, 2, 2, 2, 4, 81, 3, 2, 2, 2, 4, 83, 3, 2, 2, 2, 4, 85, 3, 2, 2, 2, 4, 87, 3, 2, 2, 2, 4, 89, 3, 2, 2, 2, 4, 91, 3, 2, 2, 2, 4, 93, 3, 2, 2, 2, 4, 95, 3, 2, 2, 2, 4, 97, 3, 2, 2, 2, 4, 99, 3, 2, 2, 2, 4, 101, 3, 2, 2, 2, 4, 103, 3, 2, 2, 2, 4, 105, 3, 2, 2, 2, 4, 107, 3, 2, 2, 2, 4, 109, 3, 2, 2, 2, 4, 111, 3, 2, 2, 2, 4, 113, 3, 2, 2, 2, 4, 115, 3, 2, 2, 2, 4, 117, 3, 2, 2, 2, 4, 119, 3, 2, 2, 2, 4, 121, 3, 2, 2, 2, 4, 123, 3, 2, 2, 2, 4, 125, 3, 2, 2, 2, 4, 127, 3, 2, 2, 2, 4, 129, 3, 2, 2, 2, 4, 131, 3, 2, 2, 2, 4, 133, 3, 2, 2, 2, 4, 135, 3, 2, 2, 2, 4, 137, 3, 2, 2, 2, 4, 139, 3, 2, 2, 2, 4, 141, 3, 2, 2, 2, 4, 143, 3, 2, 2, 2, 4, 145, 3, 2, 2, 2, 4, 147, 3, 2, 2, 2, 4, 149, 3, 2, 2, 2, 4, 151, 3, 2, 2, 2, 4, 153, 3, 2, 2, 2, 5, 155, 3, 2, 2, 2, 5, 157, 3, 2, 2, 2, 5, 159, 3, 2, 2, 2, 5, 161, 3, 2, 2, 2, 5, 163, 3, 2, 2, 2, 5, 165, 3, 2, 2, 2, 5, 167, 3, 2, 2, 2, 5, 171, 3, 2, 2, 2, 5, 173, 3, 2, 2, 2, 5, 175, 3, 2, 2, 2, 5, 177, 3, 2, 2, 2, 6, 179, 3, 2, 2, 2, 6, 181, 3, 2, 2, 2, 6, 183, 3, 2, 2, 2, 6, 185, 3, 2, 2, 2, 6, 187, 3, 2, 2, 2, 6, 189, 3, 2, 2, 2, 6, 191, 3, 2, 2, 2, 6, 195, 3, 2, 2, 2, 6, 197, 3, 2, 2, 2, 6, 199, 3, 2, 2, 2, 6, 201, 3, 2, 2, 2, 7, 255, 3, 2, 2, 2, 9, 265, 3, 2, 2, 2, 11, 272, 3, 2, 2, 2, 13, 279, 3, 2, 2, 2, 15, 289, 3, 2, 2, 2, 17, 296, 3, 2, 2, 2, 19, 302, 3, 2, 2, 2, 21, 310, 3, 2, 2, 2, 23, 318, 3, 2, 2, 2, 25, 325, 3, 2, 2, 2, 27, 337, 3, 2, 2, 2, 29, 345, 3, 2, 2, 2, 31, 355, 3, 2, 2, 2, 33, 362, 3, 2, 2, 2, 35, 371, 3, 2, 2, 2, 37, 378, 3, 2, 2, 2, 39, 387, 3, 2, 2, 2, 41, 394, 3, 2, 2, 2, 43, 411, 3, 2, 2, 2, 45, 427, 3, 2, 2, 2, 47, 433, 3, 2, 2, 2, 49, 438, 3, 2, 2, 2, 51, 443, 3, 2, 2, 2, 53, 447, 3, 2, 2, 2, 55, 451, 3, 2, 2, 2, 57, 455, 3, 2, 2, 2, 59, 459, 3, 2, 2, 2, 61, 461, 3, 2, 2, 2, 63, 463, 3, 2, 2, 2, 65, 466, 3, 2, 2, 2, 67, 468, 3, 2, 2, 2, 69, 506, 3, 2, 2, 2, 71, 509, 3, 2, 2, 2, 73, 555, 3, 2, 2, 2, 75, 557, 3, 2, 2, 2, 77, 654, 3, 2, 2, 2, 79, 656, 3, 2, 2, 2, 81, 660, 3, 2, 2, 2, 83, 662, 3, 2, 2, 2, 85, 664, 3, 2, 2, 2, 87, 666, 3, 2, 2, 2, 89, 668, 3, 2, 2, 2, 91, 673, 3, 2, 2, 2, 93, 678, 3, 2, 2, 2, 95, 682, 3, 2, 2, 2, 97, 687, 3, 2, 2, 2, 99, 693, 3, 2, 2, 2, 101, 696, 3, 2, 2, 2, 103, 699, 3, 2, 2, 2, 105, 702, 3, 2, 2, 2, 107, 707, 3, 2, 2, 2, 109, 710, 3, 2, 2, 2, 111, 712, 3, 2, 2, 2, 113, 714, 3, 2, 2, 2, 115, 719, 3, 2, 2, 2, 117, 738, 3, 2, 2, 2, 119, 750, 3, 2, 2, 2, 121, 752, 3, 2, 2, 2, 123, 754, 3, 2, 2, 2, 125, 756, 3, 2, 2, 2, 127, 758, 3, 2, 2, 2, 129, 760, 3, 2, 2, 2, 131, 762, 3, 2, 2, 2, 133, 772, 3, 2, 2, 2, 135, 774, 3, 2, 2, 2, 137, 789, 3, 2, 2, 2, 139, 1221, 3, 2, 2, 2, 141, 1374, 3, 2, 2, 2, 143, 1376, 3, 2, 2, 2, 145, 1406, 3, 2, 2, 2, 147, 1408, 3, 2, 2, 2, 149, 1419, 3, 2, 2, 2, 151, 1423, 3, 2, 2, 2, 153, 1427, 3, 2, 2, 2, 155, 1431, 3, 2, 2, 2, 157, 1436, 3, 2, 2, 2, 159, 1442, 3, 2, 2, 2, 161, 1448, 3, 2, 2, 2, 163, 1452, 3, 2, 2, 2, 165, 1456, 3, 2, 2, 2, 167, 1466, 3, 2, 2, 2, 169, 1477, 3, 2, 2, 2, 171, 1479, 3, 2, 2, 2, 173, 1481, 3, 2, 2, 2, 175, 1485, 3, 2, 2, 2, 177, 1489, 3, 2, 2, 2, 179, 1493, 3, 2, 2, 2, 181, 1496, 3, 2, 2, 2, 183, 1501, 3, 2, 2, 2, 185, 1506, 3, 2, 2, 2, 187, 1512, 3, 2, 2, 2, 189, 1516, 3, 2, 2, 2, 191, 1521, 3, 2, 2, 2, 193, 1532, 3, 2, 2, 2, 195, 1534, 3, 2, 2, 2, 197, 1536, 3, 2, 2, 2, 199, 1540, 3, 2, 2, 2, 201, 1544, 3, 2, 2, 2, 203, 1548, 3, 2, 2, 2, 205, 1550, 3, 2, 2, 2, 207, 1552, 3, 2, 2, 2, 209, 1554, 3, 2, 2, 2, 211, 1556, 3, 2, 2, 2, 213, 1558, 3, 2, 2, 2, 215, 1560, 3, 2, 2, 2, 217, 1562, 3, 2, 2, 2, 219, 1564, 3, 2, 2, 2, 221, 1566, 3, 2, 2, 2, 223, 1568, 3, 2, 2, 2, 225, 1570, 3, 2, 2, 2, 227, 1572, 3, 2, 2, 2, 229, 1574, 3, 2, 2, 2, 231, 1576, 3, 2, 2, 2, 233, 1578, 3, 2, 2, 2, 235, 1580, 3, 2, 2, 2, 237, 1582, 3, 2, 2, 2, 239, 1584, 3, 2, 2, 2, 241, 1586, 3, 2, 2, 2, 243, 1588, 3, 2, 2, 2, 245, 1590, 3, 2, 2, 2, 247, 1592, 3, 2, 2, 2, 249, 1594, 3, 2, 2, 2, 251, 1596, 3, 2, 2, 2, 253, 1598, 3, 2, 2, 2, 255, 256, 5, 209, 103, 2, 256, 257, 5, 219, 108, 2, 257, 258, 5, 239, 118, 2, 258, 259, 5, 239, 118, 2, 259, 260, 5, 211, 104, 2, 260, 261, 5, 207, 102, 2, 261, 262, 5, 241, 119, 2, 262, 263, 3, 2, 2, 2, 263, 264, 8, 2, 2, 2, 264, 8, 3, 2, 2, 2, 265, 266, 5, 215, 106, 2, 266, 267, 5, 237, 117, 2, 267, 268, 5, 231, 114, 2, 268, 269, 5, 223, 110, 2, 269, 270, 3, 2, 2, 2, 270, 271, 8, 3, 2, 2, 271, 10, 3, 2, 2, 2, 272, 273, 5, 211, 104, 2, 273, 274, 5, 245, 121, 2, 274, 275, 5, 203, 100, 2, 275, 276, 5, 225, 111, 2, 276, 277, 3, 2, 2, 2, 277, 278, 8, 4, 2, 2, 278, 12, 3, 2, 2, 2, 279, 280, 5, 211, 104, 2, 280, 281, 5, 249, 123, 2, 281, 282, 5, 233, 115, 2, 282, 283, 5, 225, 111, 2, 283, 284, 5, 203, 100, 2, 284, 285, 5, 219, 108, 2, 285, 286, 5, 229, 113, 2, 286, 287, 3, 2, 2, 2, 287, 288, 8, 5, 3, 2, 288, 14, 3, 2, 2, 2, 289, 290, 5, 213, 105, 2, 290, 291, 5, 237, 117, 2, 291, 292, 5, 231, 114, 2, 292, 293, 5, 227, 112, 2, 293, 294, 3, 2, 2, 2, 294, 295, 8, 6, 4, 2, 295, 16, 3, 2, 2, 2, 296, 297, 5, 237, 117, 2, 297, 298, 5, 231, 114, 2, 298, 299, 5, 247, 122, 2, 299, 300, 3, 2, 2, 2, 300, 301, 8, 7, 2, 2, 301, 18, 3, 2, 2, 2, 302, 303, 5, 239, 118, 2, 303, 304, 5, 241, 119, 2, 304, 305, 5, 203, 100, 2, 305, 306, 5, 241, 119, 2, 306, 307, 5, 239, 118, 2, 307, 308, 3, 2, 2, 2, 308, 309, 8, 8, 2, 2, 309, 20, 3, 2, 2, 2, 310, 311, 5, 247, 122, 2, 311, 312, 5, 217, 107, 2, 312, 313, 5, 211, 104, 2, 313, 314, 5, 237, 117, 2, 314, 315, 5, 211, 104, 2, 315, 316, 3, 2, 2, 2, 316, 317, 8, 9, 2, 2, 317, 22, 3, 2, 2, 2, 318, 319, 5, 239, 118, 2, 319, 320, 5, 231, 114, 2, 320, 321, 5, 237, 117, 2, 321, 322, 5, 241, 119, 2, 322, 323, 3, 2, 2, 2, 323, 324, 8, 10, 2, 2, 324, 24, 3, 2, 2, 2, 325, 326, 5, 227, 112, 2, 326, 327, 5, 245, 121, 2, 327, 328, 5, 111, 54, 2, 328, 329, 5, 211, 104, 2, 329, 330, 5, 249, 123, 2, 330, 331, 5, 233, 115, 2, 331, 332, 5, 203, 100, 2, 332, 333, 5, 229, 113, 2, 333, 334, 5, 209, 103, 2, 334, 335, 3, 2, 2, 2, 335, 336, 8, 11, 2, 2, 336, 26, 3, 2, 2, 2, 337, 338, 5, 225, 111, 2, 338, 339, 5, 219, 108, 2, 339, 340, 5, 227, 112, 2, 340, 341, 5, 219, 108, 2, 341, 342, 5, 241, 119, 2, 342, 343, 3, 2, 2, 2, 343, 344, 8, 12, 2, 2, 344, 28, 3, 2, 2, 2, 345, 346, 5, 233, 115, 2, 346, 347, 5, 237, 117, 2, 347, 348, 5, 231, 114, 2, 348, 349, 5, 221, 109, 2, 349, 350, 5, 211, 104, 2, 350, 351, 5, 207, 102, 2, 351, 352, 5, 241, 119, 2, 352, 353, 3, 2, 2, 2, 353, 354, 8, 13, 2, 2, 354, 30, 3, 2, 2, 2, 355, 356, 5, 209, 103, 2, 356, 357, 5, 237, 117, 2, 357, 358, 5, 231, 114, 2, 358, 359, 5, 233, 115, 2, 359, 360, 3, 2, 2, 2, 360, 361, 8, 14, 2, 2, 361, 32, 3, 2, 2, 2, 362, 363, 5, 237, 117, 2, 363, 364, 5, 211, 104, 2, 364, 365, 5, 229, 113, 2, 365, 366, 5, 203, 100, 2, 366, 367, 5, 227, 112, 2, 367, 368, 5, 211, 104, 2, 368, 369, 3, 2, 2, 2, 369, 370, 8, 15, 2, 2, 370, 34, 3, 2, 2, 2, 371, 372, 5, 239, 118, 2, 372, 373, 5, 217, 107, 2, 373, 374, 5, 231, 114, 2, 374, 375, 5, 247, 122, 2, 375, 376, 3, 2, 2, 2, 376, 377, 8, 16, 2, 2, 377, 36, 3, 2, 2, 2, 378, 379, 5, 211, 104, 2, 379, 380, 5, 229, 113, 2, 380, 381, 5, 237, 117, 2, 381, 382, 5, 219, 108, 2, 382, 383, 5, 207, 102, 2, 383, 384, 5, 217, 107, 2, 384, 385, 3, 2, 2, 2, 385, 386, 8, 17, 5, 2, 386, 38, 3, 2, 2, 2, 387, 388, 5, 223, 110, 2, 388, 389, 5, 211, 104, 2, 389, 390, 5, 211, 104, 2, 390, 391, 5, 233, 115, 2, 391, 392, 3, 2, 2, 2, 392, 393, 8, 18, 2, 2, 393, 40, 3, 2, 2, 2, 394, 395, 7, 49, 2, 2, 395, 396, 7, 49, 2, 2, 396, 400, 3, 2, 2, 2, 397, 399, 10, 2, 2, 2, 398, 397, 3, 2, 2, 2, 399, 402, 3, 2, 2, 2, 400, 398, 3, 2, 2, 2, 400, 401, 3, 2, 2, 2, 401, 404, 3, 2, 2, 2, 402, 400, 3, 2, 2, 2, 403, 405, 7, 15, 2, 2, 404, 403, 3, 2, 2, 2, 404, 405, 3, 2, 2, 2, 405, 407, 3, 2, 2, 2, 406, 408, 7, 12, 2, 2, 407, 406, 3, 2, 2, 2, 407, 408, 3, 2, 2, 2, 408, 409, 3, 2, 2, 2, 409, 410, 8, 19, 6, 2, 410, 42, 3, 2, 2, 2, 411, 412, 7, 49, 2, 2, 412, 413, 7, 44, 2, 2, 413, 418, 3, 2, 2, 2, 414, 417, 5, 43, 20, 2, 415, 417, 11, 2, 2, 2, 416, 414, 3, 2, 2, 2, 416, 415, 3, 2, 2, 2, 417, 420, 3, 2, 2, 2, 418, 419, 3, 2, 2, 2, 418, 416, 3, 2, 2, 2, 419, 421, 3, 2, 2, 2, 420, 418, 3, 2, 2, 2, 421, 422, 7, 44, 2, 2, 422, 423, 7, 49, 2, 2, 423, 424, 3, 2, 2, 2, 424, 425, 8, 20, 6, 2, 425, 44, 3, 2, 2, 2, 426, 428, 9, 3, 2, 2, 427, 426, 3, 2, 2, 2, 428, 429, 3, 2, 2, 2, 429, 427, 3, 2, 2, 2, 429, 430, 3, 2, 2, 2, 430, 431, 3, 2, 2, 2, 431, 432, 8, 21, 6, 2, 432, 46, 3, 2, 2, 2, 433, 434, 7, 93, 2, 2, 434, 435, 3, 2, 2, 2, 435, 436, 8, 22, 7, 2, 436, 437, 8, 22, 8, 2, 437, 48, 3, 2, 2, 2, 438, 439, 7, 126, 2, 2, 439, 440, 3, 2, 2, 2, 440, 441, 8, 23, 9, 2, 441, 442, 8, 23, 10, 2, 442, 50, 3, 2, 2, 2, 443, 444, 5, 45, 21, 2, 444, 445, 3, 2, 2, 2, 445, 446, 8, 24, 6, 2, 446, 52, 3, 2, 2, 2, 447, 448, 5, 41, 19, 2, 448, 449, 3, 2, 2, 2, 449, 450, 8, 25, 6, 2, 450, 54, 3, 2, 2, 2, 451, 452, 5, 43, 20, 2, 452, 453, 3, 2, 2, 2, 453, 454, 8, 26, 6, 2, 454, 56, 3, 2, 2, 2, 455, 456, 7, 126, 2, 2, 456, 457, 3, 2, 2, 2, 457, 458, 8, 27, 10, 2, 458, 58, 3, 2, 2, 2, 459, 460, 9, 4, 2, 2, 460, 60, 3, 2, 2, 2, 461, 462, 9, 5, 2, 2, 462, 62, 3, 2, 2, 2, 463, 464, 7, 94, 2, 2, 464, 465, 9, 6, 2, 2, 465, 64, 3, 2, 2, 2, 466, 467, 10, 7, 2, 2, 467, 66, 3, 2, 2, 2, 468, 470, 9, 8, 2, 2, 469, 471, 9, 9, 2, 2, 470, 469, 3, 2, 2, 2, 470, 471, 3, 2, 2, 2, 471, 473, 3, 2, 2, 2, 472, 474, 5, 59, 28, 2, 473, 472, 3, 2, 2, 2, 474, 475, 3, 2, 2, 2, 475, 473, 3, 2, 2, 2, 475, 476, 3, 2, 2, 2, 476, 68, 3, 2, 2, 2, 477, 482, 7, 36, 2, 2, 478, 481, 5, 63, 30, 2, 479, 481, 5, 65, 31, 2, 480, 478, 3, 2, 2, 2, 480, 479, 3, 2, 2, 2, 481, 484, 3, 2, 2, 2, 482, 480, 3, 2, 2, 2, 482, 483, 3, 2, 2, 2, 483, 485, 3, 2, 2, 2, 484, 482, 3, 2, 2, 2, 485, 507, 7, 36, 2, 2, 486, 487, 7, 36, 2, 2, 487, 488, 7, 36, 2, 2, 488, 489, 7, 36, 2, 2, 489, 493, 3, 2, 2, 2, 490, 492, 10, 2, 2, 2, 491, 490, 3, 2, 2, 2, 492, 495, 3, 2, 2, 2, 493, 494, 3, 2, 2, 2, 493, 491, 3, 2, 2, 2, 494, 496, 3, 2, 2, 2, 495, 493, 3, 2, 2, 2, 496, 497, 7, 36, 2, 2, 497, 498, 7, 36, 2, 2, 498, 499, 7, 36, 2, 2, 499, 501, 3, 2, 2, 2, 500, 502, 7, 36, 2, 2, 501, 500, 3, 2, 2, 2, 501, 502, 3, 2, 2, 2, 502, 504, 3, 2, 2, 2, 503, 505, 7, 36, 2, 2, 504, 503, 3, 2, 2, 2, 504, 505, 3, 2, 2, 2, 505, 507, 3, 2, 2, 2, 506, 477, 3, 2, 2, 2, 506, 486, 3, 2, 2, 2, 507, 70, 3, 2, 2, 2, 508, 510, 5, 59, 28, 2, 509, 508, 3, 2, 2, 2, 510, 511, 3, 2, 2, 2, 511, 509, 3, 2, 2, 2, 511, 512, 3, 2, 2, 2, 512, 72, 3, 2, 2, 2, 513, 515, 5, 59, 28, 2, 514, 513, 3, 2, 2, 2, 515, 516, 3, 2, 2, 2, 516, 514, 3, 2, 2, 2, 516, 517, 3, 2, 2, 2, 517, 518, 3, 2, 2, 2, 518, 522, 5, 85, 41, 2, 519, 521, 5, 59, 28, 2, 520, 519, 3, 2, 2, 2, 521, 524, 3, 2, 2, 2, 522, 520, 3, 2, 2, 2, 522, 523, 3, 2, 2, 2, 523, 556, 3, 2, 2, 2, 524, 522, 3, 2, 2, 2, 525, 527, 5, 85, 41, 2, 526, 528, 5, 59, 28, 2, 527, 526, 3, 2, 2, 2, 528, 529, 3, 2, 2, 2, 529, 527, 3, 2, 2, 2, 529, 530, 3, 2, 2, 2, 530, 556, 3, 2, 2, 2, 531, 533, 5, 59, 28, 2, 532, 531, 3, 2, 2, 2, 533, 534, 3, 2, 2, 2, 534, 532, 3, 2, 2, 2, 534, 535, 3, 2, 2, 2, 535, 543, 3, 2, 2, 2, 536, 540, 5, 85, 41, 2, 537, 539, 5, 59, 28, 2, 538, 537, 3, 2, 2, 2, 539, 542, 3, 2, 2, 2, 540, 538, 3, 2, 2, 2, 540, 541, 3, 2, 2, 2, 541, 544, 3, 2, 2, 2, 542, 540, 3, 2, 2, 2, 543, 536, 3, 2, 2, 2, 543, 544, 3, 2, 2, 2, 544, 545, 3, 2, 2, 2, 545, 546, 5, 67, 32, 2, 546, 556, 3, 2, 2, 2, 547, 549, 5, 85, 41, 2, 548, 550, 5, 59, 28, 2, 549, 548, 3, 2, 2, 2, 550, 551, 3, 2, 2, 2, 551, 549, 3, 2, 2, 2, 551, 552, 3, 2, 2, 2, 552, 553, 3, 2, 2, 2, 553, 554, 5, 67, 32, 2, 554, 556, 3, 2, 2, 2, 555, 514, 3, 2, 2, 2, 555, 525, 3, 2, 2, 2, 555, 532, 3, 2, 2, 2, 555, 547, 3, 2, 2, 2, 556, 74, 3, 2, 2, 2, 557, 558, 7, 100, 2, 2, 558, 559, 7, 123, 2, 2, 559, 76, 3, 2, 2, 2, 560, 561, 7, 123, 2, 2, 561, 562, 7, 103, 2, 2, 562, 563, 7, 99, 2, 2, 563, 655, 7, 116, 2, 2, 564, 565, 7, 111, 2, 2, 565, 566, 7, 113, 2, 2, 566, 567, 7, 112, 2, 2, 567, 568, 7, 118, 2, 2, 568, 655, 7, 106, 2, 2, 569, 570, 7, 102, 2, 2, 570, 571, 7, 99, 2, 2, 571, 655, 7, 123, 2, 2, 572, 573, 7, 117, 2, 2, 573, 574, 7, 103, 2, 2, 574, 575, 7, 101, 2, 2, 575, 576, 7, 113, 2, 2, 576, 577, 7, 112, 2, 2, 577, 655, 7, 102, 2, 2, 578, 579, 7, 111, 2, 2, 579, 580, 7, 107, 2, 2, 580, 581, 7, 112, 2, 2, 581, 582, 7, 119, 2, 2, 582, 583, 7, 118, 2, 2, 583, 655, 7, 103, 2, 2, 584, 585, 7, 106, 2, 2, 585, 586, 7, 113, 2, 2, 586, 587, 7, 119, 2, 2, 587, 655, 7, 116, 2, 2, 588, 589, 7, 121, 2, 2, 589, 590, 7, 103, 2, 2, 590, 591, 7, 103, 2, 2, 591, 655, 7, 109, 2, 2, 592, 593, 7, 111, 2, 2, 593, 594, 7, 107, 2, 2, 594, 595, 7, 110, 2, 2, 595, 596, 7, 110, 2, 2, 596, 597, 7, 107, 2, 2, 597, 598, 7, 117, 2, 2, 598, 599, 7, 103, 2, 2, 599, 600, 7, 101, 2, 2, 600, 601, 7, 113, 2, 2, 601, 602, 7, 112, 2, 2, 602, 655, 7, 102, 2, 2, 603, 604, 7, 123, 2, 2, 604, 605, 7, 103, 2, 2, 605, 606, 7, 99, 2, 2, 606, 607, 7, 116, 2, 2, 607, 655, 7, 117, 2, 2, 608, 609, 7, 111, 2, 2, 609, 610, 7, 113, 2, 2, 610, 611, 7, 112, 2, 2, 611, 612, 7, 118, 2, 2, 612, 613, 7, 106, 2, 2, 613, 655, 7, 117, 2, 2, 614, 615, 7, 102, 2, 2, 615, 616, 7, 99, 2, 2, 616, 617, 7, 123, 2, 2, 617, 655, 7, 117, 2, 2, 618, 619, 7, 117, 2, 2, 619, 620, 7, 103, 2, 2, 620, 621, 7, 101, 2, 2, 621, 622, 7, 113, 2, 2, 622, 623, 7, 112, 2, 2, 623, 624, 7, 102, 2, 2, 624, 655, 7, 117, 2, 2, 625, 626, 7, 111, 2, 2, 626, 627, 7, 107, 2, 2, 627, 628, 7, 112, 2, 2, 628, 629, 7, 119, 2, 2, 629, 630, 7, 118, 2, 2, 630, 631, 7, 103, 2, 2, 631, 655, 7, 117, 2, 2, 632, 633, 7, 106, 2, 2, 633, 634, 7, 113, 2, 2, 634, 635, 7, 119, 2, 2, 635, 636, 7, 116, 2, 2, 636, 655, 7, 117, 2, 2, 637, 638, 7, 121, 2, 2, 638, 639, 7, 103, 2, 2, 639, 640, 7, 103, 2, 2, 640, 641, 7, 109, 2, 2, 641, 655, 7, 117, 2, 2, 642, 643, 7, 111, 2, 2, 643, 644, 7, 107, 2, 2, 644, 645, 7, 110, 2, 2, 645, 646, 7, 110, 2, 2, 646, 647, 7, 107, 2, 2, 647, 648, 7, 117, 2, 2, 648, 649, 7, 103, 2, 2, 649, 650, 7, 101, 2, 2, 650, 651, 7, 113, 2, 2, 651, 652, 7, 112, 2, 2, 652, 653, 7, 102, 2, 2, 653, 655, 7, 117, 2, 2, 654, 560, 3, 2, 2, 2, 654, 564, 3, 2, 2, 2, 654, 569, 3, 2, 2, 2, 654, 572, 3, 2, 2, 2, 654, 578, 3, 2, 2, 2, 654, 584, 3, 2, 2, 2, 654, 588, 3, 2, 2, 2, 654, 592, 3, 2, 2, 2, 654, 603, 3, 2, 2, 2, 654, 608, 3, 2, 2, 2, 654, 614, 3, 2, 2, 2, 654, 618, 3, 2, 2, 2, 654, 625, 3, 2, 2, 2, 654, 632, 3, 2, 2, 2, 654, 637, 3, 2, 2, 2, 654, 642, 3, 2, 2, 2, 655, 78, 3, 2, 2, 2, 656, 657, 7, 99, 2, 2, 657, 658, 7, 112, 2, 2, 658, 659, 7, 102, 2, 2, 659, 80, 3, 2, 2, 2, 660, 661, 7, 63, 2, 2, 661, 82, 3, 2, 2, 2, 662, 663, 7, 46, 2, 2, 663, 84, 3, 2, 2, 2, 664, 665, 7, 48, 2, 2, 665, 86, 3, 2, 2, 2, 666, 667, 7, 42, 2, 2, 667, 88, 3, 2, 2, 2, 668, 669, 7, 93, 2, 2, 669, 670, 3, 2, 2, 2, 670, 671, 8, 43, 2, 2, 671, 672, 8, 43, 2, 2, 672, 90, 3, 2, 2, 2, 673, 674, 7, 95, 2, 2, 674, 675, 3, 2, 2, 2, 675, 676, 8, 44, 10, 2, 676, 677, 8, 44, 10, 2, 677, 92, 3, 2, 2, 2, 678, 679, 5, 229, 113, 2, 679, 680, 5, 231, 114, 2, 680, 681, 5, 241, 119, 2, 681, 94, 3, 2, 2, 2, 682, 683, 5, 225, 111, 2, 683, 684, 5, 219, 108, 2, 684, 685, 5, 223, 110, 2, 685, 686, 5, 211, 104, 2, 686, 96, 3, 2, 2, 2, 687, 688, 5, 237, 117, 2, 688, 689, 5, 225, 111, 2, 689, 690, 5, 219, 108, 2, 690, 691, 5, 223, 110, 2, 691, 692, 5, 211, 104, 2, 692, 98, 3, 2, 2, 2, 693, 694, 5, 219, 108, 2, 694, 695, 5, 229, 113, 2, 695, 100, 3, 2, 2, 2, 696, 697, 5, 219, 108, 2, 697, 698, 5, 239, 118, 2, 698, 102, 3, 2, 2, 2, 699, 700, 5, 203, 100, 2, 700, 701, 5, 239, 118, 2, 701, 104, 3, 2, 2, 2, 702, 703, 5, 229, 113, 2, 703, 704, 5, 243, 120, 2, 704, 705, 5, 225, 111, 2, 705, 706, 5, 225, 111, 2, 706, 106, 3, 2, 2, 2, 707, 708, 7, 113, 2, 2, 708, 709, 7, 116, 2, 2, 709, 108, 3, 2, 2, 2, 710, 711, 7, 43, 2, 2, 711, 110, 3, 2, 2, 2, 712, 713, 7, 97, 2, 2, 713, 112, 3, 2, 2, 2, 714, 715, 7, 107, 2, 2, 715, 716, 7, 112, 2, 2, 716, 717, 7, 104, 2, 2, 717, 718, 7, 113, 2, 2, 718, 114, 3, 2, 2, 2, 719, 720, 7, 104, 2, 2, 720, 721, 7, 119, 2, 2, 721, 722, 7, 112, 2, 2, 722, 723, 7, 101, 2, 2, 723, 724, 7, 118, 2, 2, 724, 725, 7, 107, 2, 2, 725, 726, 7, 113, 2, 2, 726, 727, 7, 112, 2, 2, 727, 728, 7, 117, 2, 2, 728, 116, 3, 2, 2, 2, 729, 730, 7, 118, 2, 2, 730, 731, 7, 116, 2, 2, 731, 732, 7, 119, 2, 2, 732, 739, 7, 103, 2, 2, 733, 734, 7, 104, 2, 2, 734, 735, 7, 99, 2, 2, 735, 736, 7, 110, 2, 2, 736, 737, 7, 117, 2, 2, 737, 739, 7, 103, 2, 2, 738, 729, 3, 2, 2, 2, 738, 733, 3, 2, 2, 2, 739, 118, 3, 2, 2, 2, 740, 741, 7, 63, 2, 2, 741, 751, 7, 63, 2, 2, 742, 743, 7, 35, 2, 2, 743, 751, 7, 63, 2, 2, 744, 751, 7, 62, 2, 2, 745, 746, 7, 62, 2, 2, 746, 751, 7, 63, 2, 2, 747, 751, 7, 64, 2, 2, 748, 749, 7, 64, 2, 2, 749, 751, 7, 63, 2, 2, 750, 740, 3, 2, 2, 2, 750, 742, 3, 2, 2, 2, 750, 744, 3, 2, 2, 2, 750, 745, 3, 2, 2, 2, 750, 747, 3, 2, 2, 2, 750, 748, 3, 2, 2, 2, 751, 120, 3, 2, 2, 2, 752, 753, 7, 45, 2, 2, 753, 122, 3, 2, 2, 2, 754, 755, 7, 47, 2, 2, 755, 124, 3, 2, 2, 2, 756, 757, 7, 44, 2, 2, 757, 126, 3, 2, 2, 2, 758, 759, 7, 49, 2, 2, 759, 128, 3, 2, 2, 2, 760, 761, 7, 39, 2, 2, 761, 130, 3, 2, 2, 2, 762, 763, 7, 51, 2, 2, 763, 764, 7, 50, 2, 2, 764, 132, 3, 2, 2, 2, 765, 766, 7, 99, 2, 2, 766, 767, 7, 117, 2, 2, 767, 773, 7, 101, 2, 2, 768, 769, 7, 102, 2, 2, 769, 770, 7, 103, 2, 2, 770, 771, 7, 117, 2, 2, 771, 773, 7, 101, 2, 2, 772, 765, 3, 2, 2, 2, 772, 768, 3, 2, 2, 2, 773, 134, 3, 2, 2, 2, 774, 775, 7, 112, 2, 2, 775, 776, 7, 119, 2, 2, 776, 777, 7, 110, 2, 2, 777, 778, 7, 110, 2, 2, 778, 779, 7, 117, 2, 2, 779, 136, 3, 2, 2, 2, 780, 781, 7, 104, 2, 2, 781, 782, 7, 107, 2, 2, 782, 783, 7, 116, 2, 2, 783, 784, 7, 117, 2, 2, 784, 790, 7, 118, 2, 2, 785, 786, 7, 110, 2, 2, 786, 787, 7, 99, 2, 2, 787, 788, 7, 117, 2, 2, 788, 790, 7, 118, 2, 2, 789, 780, 3, 2, 2, 2, 789, 785, 3, 2, 2, 2, 790, 138, 3, 2, 2, 2, 791, 792, 5, 237, 117, 2, 792, 793, 5, 231, 114, 2, 793, 794, 5, 243, 120, 2, 794, 795, 5, 229, 113, 2, 795, 796, 5, 209, 103, 2, 796, 1222, 3, 2, 2, 2, 797, 798, 5, 203, 100, 2, 798, 799, 5, 205, 101, 2, 799, 800, 5, 239, 118, 2, 800, 1222, 3, 2, 2, 2, 801, 802, 5, 233, 115, 2, 802, 803, 5, 231, 114, 2, 803, 804, 5, 247, 122, 2, 804, 1222, 3, 2, 2, 2, 805, 806, 5, 225, 111, 2, 806, 807, 5, 231, 114, 2, 807, 808, 5, 215, 106, 2, 808, 809, 5, 131, 64, 2, 809, 1222, 3, 2, 2, 2, 810, 811, 5, 233, 115, 2, 811, 812, 5, 219, 108, 2, 812, 1222, 3, 2, 2, 2, 813, 814, 5, 241, 119, 2, 814, 815, 5, 203, 100, 2, 815, 816, 5, 243, 120, 2, 816, 1222, 3, 2, 2, 2, 817, 1222, 5, 211, 104, 2, 818, 819, 5, 239, 118, 2, 819, 820, 5, 243, 120, 2, 820, 821, 5, 205, 101, 2, 821, 822, 5, 239, 118, 2, 822, 823, 5, 241, 119, 2, 823, 824, 5, 237, 117, 2, 824, 825, 5, 219, 108, 2, 825, 826, 5, 229, 113, 2, 826, 827, 5, 215, 106, 2, 827, 1222, 3, 2, 2, 2, 828, 829, 5, 241, 119, 2, 829, 830, 5, 237, 117, 2, 830, 831, 5, 219, 108, 2, 831, 832, 5, 227, 112, 2, 832, 1222, 3, 2, 2, 2, 833, 834, 5, 207, 102, 2, 834, 835, 5, 231, 114, 2, 835, 836, 5, 229, 113, 2, 836, 837, 5, 207, 102, 2, 837, 838, 5, 203, 100, 2, 838, 839, 5, 241, 119, 2, 839, 1222, 3, 2, 2, 2, 840, 841, 5, 207, 102, 2, 841, 842, 5, 231, 114, 2, 842, 843, 5, 203, 100, 2, 843, 844, 5, 225, 111, 2, 844, 845, 5, 211, 104, 2, 845, 846, 5, 239, 118, 2, 846, 847, 5, 207, 102, 2, 847, 848, 5, 211, 104, 2, 848, 1222, 3, 2, 2, 2, 849, 850, 5, 215, 106, 2, 850, 851, 5, 237, 117, 2, 851, 852, 5, 211, 104, 2, 852, 853, 5, 203, 100, 2, 853, 854, 5, 241, 119, 2, 854, 855, 5, 211, 104, 2, 855, 856, 5, 239, 118, 2, 856, 857, 5, 241, 119, 2, 857, 1222, 3, 2, 2, 2, 858, 859, 5, 225, 111, 2, 859, 860, 5, 211, 104, 2, 860, 861, 5, 213, 105, 2, 861, 862, 5, 241, 119, 2, 862, 1222, 3, 2, 2, 2, 863, 864, 5, 229, 113, 2, 864, 865, 5, 231, 114, 2, 865, 866, 5, 247, 122, 2, 866, 1222, 3, 2, 2, 2, 867, 868, 5, 237, 117, 2, 868, 869, 5, 219, 108, 2, 869, 870, 5, 215, 106, 2, 870, 871, 5, 217, 107, 2, 871, 872, 5, 241, 119, 2, 872, 1222, 3, 2, 2, 2, 873, 874, 5, 239, 118, 2, 874, 875, 5, 241, 119, 2, 875, 876, 5, 203, 100, 2, 876, 877, 5, 237, 117, 2, 877, 878, 5, 241, 119, 2, 878, 879, 5, 239, 118, 2, 879, 880, 5, 111, 54, 2, 880, 881, 5, 247, 122, 2, 881, 882, 5, 219, 108, 2, 882, 883, 5, 241, 119, 2, 883, 884, 5, 217, 107, 2, 884, 1222, 3, 2, 2, 2, 885, 886, 5, 209, 103, 2, 886, 887, 5, 203, 100, 2, 887, 888, 5, 241, 119, 2, 888, 889, 5, 211, 104, 2, 889, 890, 5, 111, 54, 2, 890, 891, 5, 213, 105, 2, 891, 892, 5, 231, 114, 2, 892, 893, 5, 237, 117, 2, 893, 894, 5, 227, 112, 2, 894, 895, 5, 203, 100, 2, 895, 896, 5, 241, 119, 2, 896, 1222, 3, 2, 2, 2, 897, 898, 5, 209, 103, 2, 898, 899, 5, 203, 100, 2, 899, 900, 5, 241, 119, 2, 900, 901, 5, 211, 104, 2, 901, 902, 5, 111, 54, 2, 902, 903, 5, 241, 119, 2, 903, 904, 5, 237, 117, 2, 904, 905, 5, 243, 120, 2, 905, 906, 5, 229, 113, 2, 906, 907, 5, 207, 102, 2, 907, 1222, 3, 2, 2, 2, 908, 909, 5, 209, 103, 2, 909, 910, 5, 203, 100, 2, 910, 911, 5, 241, 119, 2, 911, 912, 5, 211, 104, 2, 912, 913, 5, 111, 54, 2, 913, 914, 5, 233, 115, 2, 914, 915, 5, 203, 100, 2, 915, 916, 5, 237, 117, 2, 916, 917, 5, 239, 118, 2, 917, 918, 5, 211, 104, 2, 918, 1222, 3, 2, 2, 2, 919, 920, 5, 203, 100, 2, 920, 921, 5, 243, 120, 2, 921, 922, 5, 241, 119, 2, 922, 923, 5, 231, 114, 2, 923, 924, 5, 111, 54, 2, 924, 925, 5, 205, 101, 2, 925, 926, 5, 243, 120, 2, 926, 927, 5, 207, 102, 2, 927, 928, 5, 223, 110, 2, 928, 929, 5, 211, 104, 2, 929, 930, 5, 241, 119, 2, 930, 1222, 3, 2, 2, 2, 931, 932, 5, 209, 103, 2, 932, 933, 5, 203, 100, 2, 933, 934, 5, 241, 119, 2, 934, 935, 5, 211, 104, 2, 935, 936, 5, 111, 54, 2, 936, 937, 5, 211, 104, 2, 937, 938, 5, 249, 123, 2, 938, 939, 5, 241, 119, 2, 939, 940, 5, 237, 117, 2, 940, 941, 5, 203, 100, 2, 941, 942, 5, 207, 102, 2, 942, 943, 5, 241, 119, 2, 943, 1222, 3, 2, 2, 2, 944, 945, 5, 219, 108, 2, 945, 946, 5, 239, 118, 2, 946, 947, 5, 111, 54, 2, 947, 948, 5, 213, 105, 2, 948, 949, 5, 219, 108, 2, 949, 950, 5, 229, 113, 2, 950, 951, 5, 219, 108, 2, 951, 952, 5, 241, 119, 2, 952, 953, 5, 211, 104, 2, 953, 1222, 3, 2, 2, 2, 954, 955, 5, 219, 108, 2, 955, 956, 5, 239, 118, 2, 956, 957, 5, 111, 54, 2, 957, 958, 5, 219, 108, 2, 958, 959, 5, 229, 113, 2, 959, 960, 5, 213, 105, 2, 960, 961, 5, 219, 108, 2, 961, 962, 5, 229, 113, 2, 962, 963, 5, 219, 108, 2, 963, 964, 5, 241, 119, 2, 964, 965, 5, 211, 104, 2, 965, 1222, 3, 2, 2, 2, 966, 967, 5, 207, 102, 2, 967, 968, 5, 203, 100, 2, 968, 969, 5, 239, 118, 2, 969, 970, 5, 211, 104, 2, 970, 1222, 3, 2, 2, 2, 971, 972, 5, 225, 111, 2, 972, 973, 5, 211, 104, 2, 973, 974, 5, 229, 113, 2, 974, 975, 5, 215, 106, 2, 975, 976, 5, 241, 119, 2, 976, 977, 5, 217, 107, 2, 977, 1222, 3, 2, 2, 2, 978, 979, 5, 227, 112, 2, 979, 980, 5, 245, 121, 2, 980, 981, 5, 111, 54, 2, 981, 982, 5, 227, 112, 2, 982, 983, 5, 203, 100, 2, 983, 984, 5, 249, 123, 2, 984, 1222, 3, 2, 2, 2, 985, 986, 5, 227, 112, 2, 986, 987, 5, 245, 121, 2, 987, 988, 5, 111, 54, 2, 988, 989, 5, 227, 112, 2, 989, 990, 5, 219, 108, 2, 990, 991, 5, 229, 113, 2, 991, 1222, 3, 2, 2, 2, 992, 993, 5, 227, 112, 2, 993, 994, 5, 245, 121, 2, 994, 995, 5, 111, 54, 2, 995, 996, 5, 203, 100, 2, 996, 997, 5, 245, 121, 2, 997, 998, 5, 215, 106, 2, 998, 1222, 3, 2, 2, 2, 999, 1000, 5, 227, 112, 2, 1000, 1001, 5, 245, 121, 2, 1001, 1002, 5, 111, 54, 2, 1002, 1003, 5, 239, 118, 2, 1003, 1004, 5, 243, 120, 2, 1004, 1005, 5, 227, 112, 2, 1005, 1222, 3, 2, 2, 2, 1006, 1007, 5, 227, 112, 2, 1007, 1008, 5, 245, 121, 2, 1008, 1009, 5, 111, 54, 2, 1009, 1010, 5, 207, 102, 2, 1010, 1011, 5, 231, 114, 2, 1011, 1012, 5, 243, 120, 2, 1012, 1013, 5, 229, 113, 2, 1013, 1014, 5, 241, 119, 2, 1014, 1222, 3, 2, 2, 2, 1015, 1016, 5, 227, 112, 2, 1016, 1017, 5, 245, 121, 2, 1017, 1018, 5, 111, 54, 2, 1018, 1019, 5, 207, 102, 2, 1019, 1020, 5, 231, 114, 2, 1020, 1021, 5, 229, 113, 2, 1021, 1022, 5, 207, 102, 2, 1022, 1023, 5, 203, 100, 2, 1023, 1024, 5, 241, 119, 2, 1024, 1222, 3, 2, 2, 2, 1025, 1026, 5, 227, 112, 2, 1026, 1027, 5, 245, 121, 2, 1027, 1028, 5, 111, 54, 2, 1028, 1029, 5, 221, 109, 2, 1029, 1030, 5, 231, 114, 2, 1030, 1031, 5, 219, 108, 2, 1031, 1032, 5, 229, 113, 2, 1032, 1222, 3, 2, 2, 2, 1033, 1034, 5, 227, 112, 2, 1034, 1035, 5, 245, 121, 2, 1035, 1036, 5, 111, 54, 2, 1036, 1037, 5, 227, 112, 2, 1037, 1038, 5, 211, 104, 2, 1038, 1039, 5, 209, 103, 2, 1039, 1040, 5, 219, 108, 2, 1040, 1041, 5, 203, 100, 2, 1041, 1042, 5, 229, 113, 2, 1042, 1222, 3, 2, 2, 2, 1043, 1044, 5, 227, 112, 2, 1044, 1045, 5, 245, 121, 2, 1045, 1046, 5, 111, 54, 2, 1046, 1047, 5, 209, 103, 2, 1047, 1048, 5, 211, 104, 2, 1048, 1049, 5, 209, 103, 2, 1049, 1050, 5, 243, 120, 2, 1050, 1051, 5, 233, 115, 2, 1051, 1052, 5, 211, 104, 2, 1052, 1222, 3, 2, 2, 2, 1053, 1054, 5, 227, 112, 2, 1054, 1055, 5, 211, 104, 2, 1055, 1056, 5, 241, 119, 2, 1056, 1057, 5, 203, 100, 2, 1057, 1058, 5, 209, 103, 2, 1058, 1059, 5, 203, 100, 2, 1059, 1060, 5, 241, 119, 2, 1060, 1061, 5, 203, 100, 2, 1061, 1222, 3, 2, 2, 2, 1062, 1063, 5, 239, 118, 2, 1063, 1064, 5, 233, 115, 2, 1064, 1065, 5, 225, 111, 2, 1065, 1066, 5, 219, 108, 2, 1066, 1067, 5, 241, 119, 2, 1067, 1222, 3, 2, 2, 2, 1068, 1069, 5, 241, 119, 2, 1069, 1070, 5, 231, 114, 2, 1070, 1071, 5, 111, 54, 2, 1071, 1072, 5, 239, 118, 2, 1072, 1073, 5, 241, 119, 2, 1073, 1074, 5, 237, 117, 2, 1074, 1075, 5, 219, 108, 2, 1075, 1076, 5, 229, 113, 2, 1076, 1077, 5, 215, 106, 2, 1077, 1222, 3, 2, 2, 2, 1078, 1079, 5, 241, 119, 2, 1079, 1080, 5, 231, 114, 2, 1080, 1081, 5, 111, 54, 2, 1081, 1082, 5, 239, 118, 2, 1082, 1083, 5, 241, 119, 2, 1083, 1084, 5, 237, 117, 2, 1084, 1222, 3, 2, 2, 2, 1085, 1086, 5, 241, 119, 2, 1086, 1087, 5, 231, 114, 2, 1087, 1088, 5, 111, 54, 2, 1088, 1089, 5, 205, 101, 2, 1089, 1090, 5, 231, 114, 2, 1090, 1091, 5, 231, 114, 2, 1091, 1092, 5, 225, 111, 2, 1092, 1222, 3, 2, 2, 2, 1093, 1094, 5, 241, 119, 2, 1094, 1095, 5, 231, 114, 2, 1095, 1096, 5, 111, 54, 2, 1096, 1097, 5, 205, 101, 2, 1097, 1098, 5, 231, 114, 2, 1098, 1099, 5, 231, 114, 2, 1099, 1100, 5, 225, 111, 2, 1100, 1101, 5, 211, 104, 2, 1101, 1102, 5, 203, 100, 2, 1102, 1103, 5, 229, 113, 2, 1103, 1222, 3, 2, 2, 2, 1104, 1105, 5, 241, 119, 2, 1105, 1106, 5, 231, 114, 2, 1106, 1107, 5, 111, 54, 2, 1107, 1108, 5, 209, 103, 2, 1108, 1109, 5, 203, 100, 2, 1109, 1110, 5, 241, 119, 2, 1110, 1111, 5, 211, 104, 2, 1111, 1112, 5, 241, 119, 2, 1112, 1113, 5, 219, 108, 2, 1113, 1114, 5, 227, 112, 2, 1114, 1115, 5, 211, 104, 2, 1115, 1222, 3, 2, 2, 2, 1116, 1117, 5, 241, 119, 2, 1117, 1118, 5, 231, 114, 2, 1118, 1119, 5, 111, 54, 2, 1119, 1120, 5, 209, 103, 2, 1120, 1121, 5, 241, 119, 2, 1121, 1222, 3, 2, 2, 2, 1122, 1123, 5, 241, 119, 2, 1123, 1124, 5, 231, 114, 2, 1124, 1125, 5, 111, 54, 2, 1125, 1126, 5, 209, 103, 2, 1126, 1127, 5, 205, 101, 2, 1127, 1128, 5, 225, 111, 2, 1128, 1222, 3, 2, 2, 2, 1129, 1130, 5, 241, 119, 2, 1130, 1131, 5, 231, 114, 2, 1131, 1132, 5, 111, 54, 2, 1132, 1133, 5, 209, 103, 2, 1133, 1134, 5, 231, 114, 2, 1134, 1135, 5, 243, 120, 2, 1135, 1136, 5, 205, 101, 2, 1136, 1137, 5, 225, 111, 2, 1137, 1138, 5, 211, 104, 2, 1138, 1222, 3, 2, 2, 2, 1139, 1140, 5, 241, 119, 2, 1140, 1141, 5, 231, 114, 2, 1141, 1142, 5, 111, 54, 2, 1142, 1143, 5, 209, 103, 2, 1143, 1144, 5, 211, 104, 2, 1144, 1145, 5, 215, 106, 2, 1145, 1146, 5, 237, 117, 2, 1146, 1147, 5, 211, 104, 2, 1147, 1148, 5, 211, 104, 2, 1148, 1149, 5, 239, 118, 2, 1149, 1222, 3, 2, 2, 2, 1150, 1151, 5, 241, 119, 2, 1151, 1152, 5, 231, 114, 2, 1152, 1153, 5, 111, 54, 2, 1153, 1154, 5, 219, 108, 2, 1154, 1155, 5, 229, 113, 2, 1155, 1156, 5, 241, 119, 2, 1156, 1222, 3, 2, 2, 2, 1157, 1158, 5, 241, 119, 2, 1158, 1159, 5, 231, 114, 2, 1159, 1160, 5, 111, 54, 2, 1160, 1161, 5, 219, 108, 2, 1161, 1162, 5, 229, 113, 2, 1162, 1163, 5, 241, 119, 2, 1163, 1164, 5, 211, 104, 2, 1164, 1165, 5, 215, 106, 2, 1165, 1166, 5, 211, 104, 2, 1166, 1167, 5, 237, 117, 2, 1167, 1222, 3, 2, 2, 2, 1168, 1169, 5, 241, 119, 2, 1169, 1170, 5, 231, 114, 2, 1170, 1171, 5, 111, 54, 2, 1171, 1172, 5, 219, 108, 2, 1172, 1173, 5, 233, 115, 2, 1173, 1222, 3, 2, 2, 2, 1174, 1175, 5, 241, 119, 2, 1175, 1176, 5, 231, 114, 2, 1176, 1177, 5, 111, 54, 2, 1177, 1178, 5, 225, 111, 2, 1178, 1179, 5, 231, 114, 2, 1179, 1180, 5, 229, 113, 2, 1180, 1181, 5, 215, 106, 2, 1181, 1222, 3, 2, 2, 2, 1182, 1183, 5, 241, 119, 2, 1183, 1184, 5, 231, 114, 2, 1184, 1185, 5, 111, 54, 2, 1185, 1186, 5, 237, 117, 2, 1186, 1187, 5, 203, 100, 2, 1187, 1188, 5, 209, 103, 2, 1188, 1189, 5, 219, 108, 2, 1189, 1190, 5, 203, 100, 2, 1190, 1191, 5, 229, 113, 2, 1191, 1192, 5, 239, 118, 2, 1192, 1222, 3, 2, 2, 2, 1193, 1194, 5, 241, 119, 2, 1194, 1195, 5, 231, 114, 2, 1195, 1196, 5, 111, 54, 2, 1196, 1197, 5, 245, 121, 2, 1197, 1198, 5, 211, 104, 2, 1198, 1199, 5, 237, 117, 2, 1199, 1200, 5, 239, 118, 2, 1200, 1201, 5, 219, 108, 2, 1201, 1202, 5, 231, 114, 2, 1202, 1203, 5, 229, 113, 2, 1203, 1222, 3, 2, 2, 2, 1204, 1205, 5, 241, 119, 2, 1205, 1206, 5, 231, 114, 2, 1206, 1207, 5, 111, 54, 2, 1207, 1208, 5, 243, 120, 2, 1208, 1209, 5, 229, 113, 2, 1209, 1210, 5, 239, 118, 2, 1210, 1211, 5, 219, 108, 2, 1211, 1212, 5, 215, 106, 2, 1212, 1213, 5, 229, 113, 2, 1213, 1214, 5, 211, 104, 2, 1214, 1215, 5, 209, 103, 2, 1215, 1216, 5, 111, 54, 2, 1216, 1217, 5, 225, 111, 2, 1217, 1218, 5, 231, 114, 2, 1218, 1219, 5, 229, 113, 2, 1219, 1220, 5, 215, 106, 2, 1220, 1222, 3, 2, 2, 2, 1221, 791, 3, 2, 2, 2, 1221, 797, 3, 2, 2, 2, 1221, 801, 3, 2, 2, 2, 1221, 805, 3, 2, 2, 2, 1221, 810, 3, 2, 2, 2, 1221, 813, 3, 2, 2, 2, 1221, 817, 3, 2, 2, 2, 1221, 818, 3, 2, 2, 2, 1221, 828, 3, 2, 2, 2, 1221, 833, 3, 2, 2, 2, 1221, 840, 3, 2, 2, 2, 1221, 849, 3, 2, 2, 2, 1221, 858, 3, 2, 2, 2, 1221, 863, 3, 2, 2, 2, 1221, 867, 3, 2, 2, 2, 1221, 873, 3, 2, 2, 2, 1221, 885, 3, 2, 2, 2, 1221, 897, 3, 2, 2, 2, 1221, 908, 3, 2, 2, 2, 1221, 919, 3, 2, 2, 2, 1221, 931, 3, 2, 2, 2, 1221, 944, 3, 2, 2, 2, 1221, 954, 3, 2, 2, 2, 1221, 966, 3, 2, 2, 2, 1221, 971, 3, 2, 2, 2, 1221, 978, 3, 2, 2, 2, 1221, 985, 3, 2, 2, 2, 1221, 992, 3, 2, 2, 2, 1221, 999, 3, 2, 2, 2, 1221, 1006, 3, 2, 2, 2, 1221, 1015, 3, 2, 2, 2, 1221, 1025, 3, 2, 2, 2, 1221, 1033, 3, 2, 2, 2, 1221, 1043, 3, 2, 2, 2, 1221, 1053, 3, 2, 2, 2, 1221, 1062, 3, 2, 2, 2, 1221, 1068, 3, 2, 2, 2, 1221, 1078, 3, 2, 2, 2, 1221, 1085, 3, 2, 2, 2, 1221, 1093, 3, 2, 2, 2, 1221, 1104, 3, 2, 2, 2, 1221, 1116, 3, 2, 2, 2, 1221, 1122, 3, 2, 2, 2, 1221, 1129, 3, 2, 2, 2, 1221, 1139, 3, 2, 2, 2, 1221, 1150, 3, 2, 2, 2, 1221, 1157, 3, 2, 2, 2, 1221, 1168, 3, 2, 2, 2, 1221, 1174, 3, 2, 2, 2, 1221, 1182, 3, 2, 2, 2, 1221, 1193, 3, 2, 2, 2, 1221, 1204, 3, 2, 2, 2, 1222, 140, 3, 2, 2, 2, 1223, 1224, 5, 203, 100, 2, 1224, 1225, 5, 245, 121, 2, 1225, 1226, 5, 215, 106, 2, 1226, 1375, 3, 2, 2, 2, 1227, 1228, 5, 227, 112, 2, 1228, 1229, 5, 219, 108, 2, 1229, 1230, 5, 229, 113, 2, 1230, 1375, 3, 2, 2, 2, 1231, 1232, 5, 227, 112, 2, 1232, 1233, 5, 203, 100, 2, 1233, 1234, 5, 249, 123, 2, 1234, 1375, 3, 2, 2, 2, 1235, 1236, 5, 239, 118, 2, 1236, 1237, 5, 243, 120, 2, 1237, 1238, 5, 227, 112, 2, 1238, 1375, 3, 2, 2, 2, 1239, 1240, 5, 207, 102, 2, 1240, 1241, 5, 231, 114, 2, 1241, 1242, 5, 243, 120, 2, 1242, 1243, 5, 229, 113, 2, 1243, 1244, 5, 241, 119, 2, 1244, 1375, 3, 2, 2, 2, 1245, 1246, 5, 207, 102, 2, 1246, 1247, 5, 231, 114, 2, 1247, 1248, 5, 243, 120, 2, 1248, 1249, 5, 229, 113, 2, 1249, 1250, 5, 241, 119, 2, 1250, 1251, 5, 111, 54, 2, 1251, 1252, 5, 209, 103, 2, 1252, 1253, 5, 219, 108, 2, 1253, 1254, 5, 239, 118, 2, 1254, 1255, 5, 241, 119, 2, 1255, 1256, 5, 219, 108, 2, 1256, 1257, 5, 229, 113, 2, 1257, 1258, 5, 207, 102, 2, 1258, 1259, 5, 241, 119, 2, 1259, 1375, 3, 2, 2, 2, 1260, 1261, 5, 233, 115, 2, 1261, 1262, 5, 211, 104, 2, 1262, 1263, 5, 237, 117, 2, 1263, 1264, 5, 207, 102, 2, 1264, 1265, 5, 211, 104, 2, 1265, 1266, 5, 229, 113, 2, 1266, 1267, 5, 241, 119, 2, 1267, 1268, 5, 219, 108, 2, 1268, 1269, 5, 225, 111, 2, 1269, 1270, 5, 211, 104, 2, 1270, 1375, 3, 2, 2, 2, 1271, 1272, 5, 227, 112, 2, 1272, 1273, 5, 211, 104, 2, 1273, 1274, 5, 209, 103, 2, 1274, 1275, 5, 219, 108, 2, 1275, 1276, 5, 203, 100, 2, 1276, 1277, 5, 229, 113, 2, 1277, 1375, 3, 2, 2, 2, 1278, 1279, 5, 227, 112, 2, 1279, 1280, 5, 211, 104, 2, 1280, 1281, 5, 209, 103, 2, 1281, 1282, 5, 219, 108, 2, 1282, 1283, 5, 203, 100, 2, 1283, 1284, 5, 229, 113, 2, 1284, 1285, 5, 111, 54, 2, 1285, 1286, 5, 203, 100, 2, 1286, 1287, 5, 205, 101, 2, 1287, 1288, 5, 239, 118, 2, 1288, 1289, 5, 231, 114, 2, 1289, 1290, 5, 225, 111, 2, 1290, 1291, 5, 243, 120, 2, 1291, 1292, 5, 241, 119, 2, 1292, 1293, 5, 211, 104, 2, 1293, 1294, 5, 111, 54, 2, 1294, 1295, 5, 209, 103, 2, 1295, 1296, 5, 211, 104, 2, 1296, 1297, 5, 245, 121, 2, 1297, 1298, 5, 219, 108, 2, 1298, 1299, 5, 203, 100, 2, 1299, 1300, 5, 241, 119, 2, 1300, 1301, 5, 219, 108, 2, 1301, 1302, 5, 231, 114, 2, 1302, 1303, 5, 229, 113, 2, 1303, 1375, 3, 2, 2, 2, 1304, 1305, 5, 203, 100, 2, 1305, 1306, 5, 207, 102, 2, 1306, 1307, 5, 231, 114, 2, 1307, 1308, 5, 239, 118, 2, 1308, 1375, 3, 2, 2, 2, 1309, 1310, 5, 203, 100, 2, 1310, 1311, 5, 239, 118, 2, 1311, 1312, 5, 219, 108, 2, 1312, 1313, 5, 229, 113, 2, 1313, 1375, 3, 2, 2, 2, 1314, 1315, 5, 203, 100, 2, 1315, 1316, 5, 241, 119, 2, 1316, 1317, 5, 203, 100, 2, 1317, 1318, 5, 229, 113, 2, 1318, 1375, 3, 2, 2, 2, 1319, 1320, 5, 203, 100, 2, 1320, 1321, 5, 241, 119, 2, 1321, 1322, 5, 203, 100, 2, 1322, 1323, 5, 229, 113, 2, 1323, 1324, 7, 52, 2, 2, 1324, 1375, 3, 2, 2, 2, 1325, 1326, 5, 207, 102, 2, 1326, 1327, 5, 211, 104, 2, 1327, 1328, 5, 219, 108, 2, 1328, 1329, 5, 225, 111, 2, 1329, 1375, 3, 2, 2, 2, 1330, 1331, 5, 207, 102, 2, 1331, 1332, 5, 231, 114, 2, 1332, 1333, 5, 239, 118, 2, 1333, 1375, 3, 2, 2, 2, 1334, 1335, 5, 207, 102, 2, 1335, 1336, 5, 231, 114, 2, 1336, 1337, 5, 239, 118, 2, 1337, 1338, 5, 217, 107, 2, 1338, 1375, 3, 2, 2, 2, 1339, 1340, 5, 213, 105, 2, 1340, 1341, 5, 225, 111, 2, 1341, 1342, 5, 231, 114, 2, 1342, 1343, 5, 231, 114, 2, 1343, 1344, 5, 237, 117, 2, 1344, 1375, 3, 2, 2, 2, 1345, 1346, 5, 225, 111, 2, 1346, 1347, 5, 241, 119, 2, 1347, 1348, 5, 237, 117, 2, 1348, 1349, 5, 219, 108, 2, 1349, 1350, 5, 227, 112, 2, 1350, 1375, 3, 2, 2, 2, 1351, 1352, 5, 239, 118, 2, 1352, 1353, 5, 219, 108, 2, 1353, 1354, 5, 229, 113, 2, 1354, 1375, 3, 2, 2, 2, 1355, 1356, 5, 239, 118, 2, 1356, 1357, 5, 219, 108, 2, 1357, 1358, 5, 229, 113, 2, 1358, 1359, 5, 217, 107, 2, 1359, 1375, 3, 2, 2, 2, 1360, 1361, 5, 239, 118, 2, 1361, 1362, 5, 235, 116, 2, 1362, 1363, 5, 237, 117, 2, 1363, 1364, 5, 241, 119, 2, 1364, 1375, 3, 2, 2, 2, 1365, 1366, 5, 241, 119, 2, 1366, 1367, 5, 203, 100, 2, 1367, 1368, 5, 229, 113, 2, 1368, 1375, 3, 2, 2, 2, 1369, 1370, 5, 241, 119, 2, 1370, 1371, 5, 203, 100, 2, 1371, 1372, 5, 229, 113, 2, 1372, 1373, 5, 217, 107, 2, 1373, 1375, 3, 2, 2, 2, 1374, 1223, 3, 2, 2, 2, 1374, 1227, 3, 2, 2, 2, 1374, 1231, 3, 2, 2, 2, 1374, 1235, 3, 2, 2, 2, 1374, 1239, 3, 2, 2, 2, 1374, 1245, 3, 2, 2, 2, 1374, 1260, 3, 2, 2, 2, 1374, 1271, 3, 2, 2, 2, 1374, 1278, 3, 2, 2, 2, 1374, 1304, 3, 2, 2, 2, 1374, 1309, 3, 2, 2, 2, 1374, 1314, 3, 2, 2, 2, 1374, 1319, 3, 2, 2, 2, 1374, 1325, 3, 2, 2, 2, 1374, 1330, 3, 2, 2, 2, 1374, 1334, 3, 2, 2, 2, 1374, 1339, 3, 2, 2, 2, 1374, 1345, 3, 2, 2, 2, 1374, 1351, 3, 2, 2, 2, 1374, 1355, 3, 2, 2, 2, 1374, 1360, 3, 2, 2, 2, 1374, 1365, 3, 2, 2, 2, 1374, 1369, 3, 2, 2, 2, 1375, 142, 3, 2, 2, 2, 1376, 1377, 5, 207, 102, 2, 1377, 1378, 5, 219, 108, 2, 1378, 1379, 5, 209, 103, 2, 1379, 1380, 5, 237, 117, 2, 1380, 1381, 5, 111, 54, 2, 1381, 1382, 5, 227, 112, 2, 1382, 1383, 5, 203, 100, 2, 1383, 1384, 5, 241, 119, 2, 1384, 1385, 5, 207, 102, 2, 1385, 1386, 5, 217, 107, 2, 1386, 144, 3, 2, 2, 2, 1387, 1394, 5, 61, 29, 2, 1388, 1393, 5, 61, 29, 2, 1389, 1393, 5, 59, 28, 2, 1390, 1393, 7, 97, 2, 2, 1391, 1393, 5, 125, 61, 2, 1392, 1388, 3, 2, 2, 2, 1392, 1389, 3, 2, 2, 2, 1392, 1390, 3, 2, 2, 2, 1392, 1391, 3, 2, 2, 2, 1393, 1396, 3, 2, 2, 2, 1394, 1392, 3, 2, 2, 2, 1394, 1395, 3, 2, 2, 2, 1395, 1407, 3, 2, 2, 2, 1396, 1394, 3, 2, 2, 2, 1397, 1402, 9, 10, 2, 2, 1398, 1403, 5, 61, 29, 2, 1399, 1403, 5, 59, 28, 2, 1400, 1403, 7, 97, 2, 2, 1401, 1403, 5, 125, 61, 2, 1402, 1398, 3, 2, 2, 2, 1402, 1399, 3, 2, 2, 2, 1402, 1400, 3, 2, 2, 2, 1402, 1401, 3, 2, 2, 2, 1403, 1404, 3, 2, 2, 2, 1404, 1402, 3, 2, 2, 2, 1404, 1405, 3, 2, 2, 2, 1405, 1407, 3, 2, 2, 2, 1406, 1387, 3, 2, 2, 2, 1406, 1397, 3, 2, 2, 2, 1407, 146, 3, 2, 2, 2, 1408, 1414, 7, 98, 2, 2, 1409, 1413, 10, 11, 2, 2, 1410, 1411, 7, 98, 2, 2, 1411, 1413, 7, 98, 2, 2, 1412, 1409, 3, 2, 2, 2, 1412, 1410, 3, 2, 2, 2, 1413, 1416, 3, 2, 2, 2, 1414, 1412, 3, 2, 2, 2, 1414, 1415, 3, 2, 2, 2, 1415, 1417, 3, 2, 2, 2, 1416, 1414, 3, 2, 2, 2, 1417, 1418, 7, 98, 2, 2, 1418, 148, 3, 2, 2, 2, 1419, 1420, 5, 41, 19, 2, 1420, 1421, 3, 2, 2, 2, 1421, 1422, 8, 73, 6, 2, 1422, 150, 3, 2, 2, 2, 1423, 1424, 5, 43, 20, 2, 1424, 1425, 3, 2, 2, 2, 1425, 1426, 8, 74, 6, 2, 1426, 152, 3, 2, 2, 2, 1427, 1428, 5, 45, 21, 2, 1428, 1429, 3, 2, 2, 2, 1429, 1430, 8, 75, 6, 2, 1430, 154, 3, 2, 2, 2, 1431, 1432, 7, 126, 2, 2, 1432, 1433, 3, 2, 2, 2, 1433, 1434, 8, 76, 9, 2, 1434, 1435, 8, 76, 10, 2, 1435, 156, 3, 2, 2, 2, 1436, 1437, 7, 93, 2, 2, 1437, 1438, 3, 2, 2, 2, 1438, 1439, 8, 77, 7, 2, 1439, 1440, 8, 77, 4, 2, 1440, 1441, 8, 77, 4, 2, 1441, 158, 3, 2, 2, 2, 1442, 1443, 7, 95, 2, 2, 1443, 1444, 3, 2, 2, 2, 1444, 1445, 8, 78, 10, 2, 1445, 1446, 8, 78, 10, 2, 1446, 1447, 8, 78, 11, 2, 1447, 160, 3, 2, 2, 2, 1448, 1449, 7, 46, 2, 2, 1449, 1450, 3, 2, 2, 2, 1450, 1451, 8, 79, 12, 2, 1451, 162, 3, 2, 2, 2, 1452, 1453, 7, 63, 2, 2, 1453, 1454, 3, 2, 2, 2, 1454, 1455, 8, 80, 13, 2, 1455, 164, 3, 2, 2, 2, 1456, 1457, 5, 227, 112, 2, 1457, 1458, 5, 211, 104, 2, 1458, 1459, 5, 241, 119, 2, 1459, 1460, 5, 203, 100, 2, 1460, 1461, 5, 209, 103, 2, 1461, 1462, 5, 203, 100, 2, 1462, 1463, 5, 241, 119, 2, 1463, 1464, 5, 203, 100, 2, 1464, 166, 3, 2, 2, 2, 1465, 1467, 5, 169, 83, 2, 1466, 1465, 3, 2, 2, 2, 1467, 1468, 3, 2, 2, 2, 1468, 1466, 3, 2, 2, 2, 1468, 1469, 3, 2, 2, 2, 1469, 168, 3, 2, 2, 2, 1470, 1472, 10, 12, 2, 2, 1471, 1470, 3, 2, 2, 2, 1472, 1473, 3, 2, 2, 2, 1473, 1471, 3, 2, 2, 2, 1473, 1474, 3, 2, 2, 2, 1474, 1478, 3, 2, 2, 2, 1475, 1476, 7, 49, 2, 2, 1476, 1478, 10, 13, 2, 2, 1477, 1471, 3, 2, 2, 2, 1477, 1475, 3, 2, 2, 2, 1478, 170, 3, 2, 2, 2, 1479, 1480, 5, 147, 72, 2, 1480, 172, 3, 2, 2, 2, 1481, 1482, 5, 41, 19, 2, 1482, 1483, 3, 2, 2, 2, 1483, 1484, 8, 85, 6, 2, 1484, 174, 3, 2, 2, 2, 1485, 1486, 5, 43, 20, 2, 1486, 1487, 3, 2, 2, 2, 1487, 1488, 8, 86, 6, 2, 1488, 176, 3, 2, 2, 2, 1489, 1490, 5, 45, 21, 2, 1490, 1491, 3, 2, 2, 2, 1491, 1492, 8, 87, 6, 2, 1492, 178, 3, 2, 2, 2, 1493, 1494, 5, 231, 114, 2, 1494, 1495, 5, 229, 113, 2, 1495, 180, 3, 2, 2, 2, 1496, 1497, 5, 247, 122, 2, 1497, 1498, 5, 219, 108, 2, 1498, 1499, 5, 241, 119, 2, 1499, 1500, 5, 217, 107, 2, 1500, 182, 3, 2, 2, 2, 1501, 1502, 7, 126, 2, 2, 1502, 1503, 3, 2, 2, 2, 1503, 1504, 8, 90, 9, 2, 1504, 1505, 8, 90, 10, 2, 1505, 184, 3, 2, 2, 2, 1506, 1507, 7, 95, 2, 2, 1507, 1508, 3, 2, 2, 2, 1508, 1509, 8, 91, 10, 2, 1509, 1510, 8, 91, 10, 2, 1510, 1511, 8, 91, 11, 2, 1511, 186, 3, 2, 2, 2, 1512, 1513, 7, 46, 2, 2, 1513, 1514, 3, 2, 2, 2, 1514, 1515, 8, 92, 12, 2, 1515, 188, 3, 2, 2, 2, 1516, 1517, 7, 63, 2, 2, 1517, 1518, 3, 2, 2, 2, 1518, 1519, 8, 93, 13, 2, 1519, 190, 3, 2, 2, 2, 1520, 1522, 5, 193, 95, 2, 1521, 1520, 3, 2, 2, 2, 1522, 1523, 3, 2, 2, 2, 1523, 1521, 3, 2, 2, 2, 1523, 1524, 3, 2, 2, 2, 1524, 192, 3, 2, 2, 2, 1525, 1527, 10, 12, 2, 2, 1526, 1525, 3, 2, 2, 2, 1527, 1528, 3, 2, 2, 2, 1528, 1526, 3, 2, 2, 2, 1528, 1529, 3, 2, 2, 2, 1529, 1533, 3, 2, 2, 2, 1530, 1531, 7, 49, 2, 2, 1531, 1533, 10, 13, 2, 2, 1532, 1526, 3, 2, 2, 2, 1532, 1530, 3, 2, 2, 2, 1533, 194, 3, 2, 2, 2, 1534, 1535, 5, 147, 72, 2, 1535, 196, 3, 2, 2, 2, 1536, 1537, 5, 41, 19, 2, 1537, 1538, 3, 2, 2, 2, 1538, 1539, 8, 97, 6, 2, 1539, 198, 3, 2, 2, 2, 1540, 1541, 5, 43, 20, 2, 1541, 1542, 3, 2, 2, 2, 1542, 1543, 8, 98, 6, 2, 1543, 200, 3, 2, 2, 2, 1544, 1545, 5, 45, 21, 2, 1545, 1546, 3, 2, 2, 2, 1546, 1547, 8, 99, 6, 2, 1547, 202, 3, 2, 2, 2, 1548, 1549, 9, 14, 2, 2, 1549, 204, 3, 2, 2, 2, 1550, 1551, 9, 15, 2, 2, 1551, 206, 3, 2, 2, 2, 1552, 1553, 9, 16, 2, 2, 1553, 208, 3, 2, 2, 2, 1554, 1555, 9, 17, 2, 2, 1555, 210, 3, 2, 2, 2, 1556, 1557, 9, 8, 2, 2, 1557, 212, 3, 2, 2, 2, 1558, 1559, 9, 18, 2, 2, 1559, 214, 3, 2, 2, 2, 1560, 1561, 9, 19, 2, 2, 1561, 216, 3, 2, 2, 2, 1562, 1563, 9, 20, 2, 2, 1563, 218, 3, 2, 2, 2, 1564, 1565, 9, 21, 2, 2, 1565, 220, 3, 2, 2, 2, 1566, 1567, 9, 22, 2, 2, 1567, 222, 3, 2, 2, 2, 1568, 1569, 9, 23, 2, 2, 1569, 224, 3, 2, 2, 2, 1570, 1571, 9, 24, 2, 2, 1571, 226, 3, 2, 2, 2, 1572, 1573, 9, 25, 2, 2, 1573, 228, 3, 2, 2, 2, 1574, 1575, 9, 26, 2, 2, 1575, 230, 3, 2, 2, 2, 1576, 1577, 9, 27, 2, 2, 1577, 232, 3, 2, 2, 2, 1578, 1579, 9, 28, 2, 2, 1579, 234, 3, 2, 2, 2, 1580, 1581, 9, 29, 2, 2, 1581, 236, 3, 2, 2, 2, 1582, 1583, 9, 30, 2, 2, 1583, 238, 3, 2, 2, 2, 1584, 1585, 9, 31, 2, 2, 1585, 240, 3, 2, 2, 2, 1586, 1587, 9, 32, 2, 2, 1587, 242, 3, 2, 2, 2, 1588, 1589, 9, 33, 2, 2, 1589, 244, 3, 2, 2, 2, 1590, 1591, 9, 34, 2, 2, 1591, 246, 3, 2, 2, 2, 1592, 1593, 9, 35, 2, 2, 1593, 248, 3, 2, 2, 2, 1594, 1595, 9, 36, 2, 2, 1595, 250, 3, 2, 2, 2, 1596, 1597, 9, 37, 2, 2, 1597, 252, 3, 2, 2, 2, 1598, 1599, 9, 38, 2, 2, 1599, 254, 3, 2, 2, 2, 50, 2, 3, 4, 5, 6, 400, 404, 407, 416, 418, 429, 470, 475, 480, 482, 493, 501, 504, 506, 511, 516, 522, 529, 534, 540, 543, 551, 555, 654, 738, 750, 772, 789, 1221, 1374, 1392, 1394, 1402, 1404, 1406, 1412, 1414, 1468, 1473, 1477, 1523, 1528, 1532, 14, 7, 4, 2, 7, 3, 2, 7, 5, 2, 7, 6, 2, 2, 3, 2, 9, 37, 2, 7, 2, 2, 9, 26, 2, 6, 2, 2, 9, 38, 2, 9, 34, 2, 9, 33, 2] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 78, 813, 8, 1, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 6, 18, 362, 10, 18, 13, 18, 14, 18, 363, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 372, 10, 19, 12, 19, 14, 19, 375, 11, 19, 3, 19, 5, 19, 378, 10, 19, 3, 19, 5, 19, 381, 10, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 390, 10, 20, 12, 20, 14, 20, 393, 11, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 401, 10, 21, 13, 21, 14, 21, 402, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 5, 27, 422, 10, 27, 3, 27, 6, 27, 425, 10, 27, 13, 27, 14, 27, 426, 3, 28, 3, 28, 3, 28, 7, 28, 432, 10, 28, 12, 28, 14, 28, 435, 11, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 443, 10, 28, 12, 28, 14, 28, 446, 11, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 453, 10, 28, 3, 28, 5, 28, 456, 10, 28, 5, 28, 458, 10, 28, 3, 29, 6, 29, 461, 10, 29, 13, 29, 14, 29, 462, 3, 30, 6, 30, 466, 10, 30, 13, 30, 14, 30, 467, 3, 30, 3, 30, 7, 30, 472, 10, 30, 12, 30, 14, 30, 475, 11, 30, 3, 30, 3, 30, 6, 30, 479, 10, 30, 13, 30, 14, 30, 480, 3, 30, 6, 30, 484, 10, 30, 13, 30, 14, 30, 485, 3, 30, 3, 30, 7, 30, 490, 10, 30, 12, 30, 14, 30, 493, 11, 30, 5, 30, 495, 10, 30, 3, 30, 3, 30, 3, 30, 3, 30, 6, 30, 501, 10, 30, 13, 30, 14, 30, 502, 3, 30, 3, 30, 5, 30, 507, 10, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 62, 3, 62, 3, 63, 3, 63, 3, 64, 3, 64, 3, 65, 3, 65, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 69, 7, 69, 651, 10, 69, 12, 69, 14, 69, 654, 11, 69, 3, 69, 3, 69, 3, 69, 3, 69, 6, 69, 660, 10, 69, 13, 69, 14, 69, 661, 5, 69, 664, 10, 69, 3, 70, 3, 70, 3, 70, 3, 70, 7, 70, 670, 10, 70, 12, 70, 14, 70, 673, 11, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 83, 6, 83, 735, 10, 83, 13, 83, 14, 83, 736, 3, 84, 6, 84, 740, 10, 84, 13, 84, 14, 84, 741, 3, 84, 3, 84, 5, 84, 746, 10, 84, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 88, 3, 88, 3, 89, 3, 89, 3, 90, 3, 90, 3, 91, 3, 91, 3, 92, 3, 92, 3, 93, 3, 93, 3, 94, 3, 94, 3, 95, 3, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 98, 3, 98, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 3, 107, 3, 107, 3, 108, 3, 108, 3, 109, 3, 109, 3, 110, 3, 110, 3, 111, 3, 111, 3, 112, 3, 112, 3, 113, 3, 113, 3, 114, 3, 114, 4, 391, 444, 2, 2, 115, 5, 2, 3, 7, 2, 4, 9, 2, 5, 11, 2, 6, 13, 2, 7, 15, 2, 8, 17, 2, 9, 19, 2, 10, 21, 2, 11, 23, 2, 12, 25, 2, 13, 27, 2, 14, 29, 2, 15, 31, 2, 16, 33, 2, 17, 35, 2, 18, 37, 2, 19, 39, 2, 20, 41, 2, 21, 43, 2, 22, 45, 2, 23, 47, 2, 2, 49, 2, 2, 51, 2, 2, 53, 2, 2, 55, 2, 2, 57, 2, 24, 59, 2, 25, 61, 2, 26, 63, 2, 27, 65, 2, 28, 67, 2, 29, 69, 2, 30, 71, 2, 31, 73, 2, 32, 75, 2, 33, 77, 2, 34, 79, 2, 35, 81, 2, 36, 83, 2, 37, 85, 2, 38, 87, 2, 39, 89, 2, 40, 91, 2, 41, 93, 2, 42, 95, 2, 43, 97, 2, 44, 99, 2, 45, 101, 2, 46, 103, 2, 47, 105, 2, 48, 107, 2, 49, 109, 2, 50, 111, 2, 51, 113, 2, 52, 115, 2, 53, 117, 2, 54, 119, 2, 55, 121, 2, 56, 123, 2, 57, 125, 2, 58, 127, 2, 59, 129, 2, 60, 131, 2, 61, 133, 2, 62, 135, 2, 63, 137, 2, 64, 139, 2, 65, 141, 2, 66, 143, 2, 67, 145, 2, 68, 147, 2, 69, 149, 2, 2, 151, 2, 2, 153, 2, 2, 155, 2, 2, 157, 2, 2, 159, 2, 70, 161, 2, 71, 163, 2, 72, 165, 2, 73, 167, 2, 74, 169, 2, 2, 171, 2, 75, 173, 2, 76, 175, 2, 77, 177, 2, 78, 179, 2, 2, 181, 2, 2, 183, 2, 2, 185, 2, 2, 187, 2, 2, 189, 2, 2, 191, 2, 2, 193, 2, 2, 195, 2, 2, 197, 2, 2, 199, 2, 2, 201, 2, 2, 203, 2, 2, 205, 2, 2, 207, 2, 2, 209, 2, 2, 211, 2, 2, 213, 2, 2, 215, 2, 2, 217, 2, 2, 219, 2, 2, 221, 2, 2, 223, 2, 2, 225, 2, 2, 227, 2, 2, 229, 2, 2, 5, 2, 3, 4, 40, 8, 2, 11, 12, 15, 15, 34, 34, 49, 49, 93, 93, 95, 95, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 3, 2, 50, 59, 4, 2, 67, 92, 99, 124, 7, 2, 36, 36, 94, 94, 112, 112, 116, 116, 118, 118, 6, 2, 12, 12, 15, 15, 36, 36, 94, 94, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 4, 2, 66, 66, 97, 97, 3, 2, 98, 98, 12, 2, 11, 12, 15, 15, 34, 34, 46, 46, 49, 49, 63, 63, 93, 93, 95, 95, 98, 98, 126, 126, 4, 2, 44, 44, 49, 49, 4, 2, 67, 67, 99, 99, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 2, 816, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 3, 45, 3, 2, 2, 2, 3, 57, 3, 2, 2, 2, 3, 59, 3, 2, 2, 2, 3, 61, 3, 2, 2, 2, 3, 63, 3, 2, 2, 2, 3, 65, 3, 2, 2, 2, 3, 67, 3, 2, 2, 2, 3, 69, 3, 2, 2, 2, 3, 71, 3, 2, 2, 2, 3, 73, 3, 2, 2, 2, 3, 75, 3, 2, 2, 2, 3, 77, 3, 2, 2, 2, 3, 79, 3, 2, 2, 2, 3, 81, 3, 2, 2, 2, 3, 83, 3, 2, 2, 2, 3, 85, 3, 2, 2, 2, 3, 87, 3, 2, 2, 2, 3, 89, 3, 2, 2, 2, 3, 91, 3, 2, 2, 2, 3, 93, 3, 2, 2, 2, 3, 95, 3, 2, 2, 2, 3, 97, 3, 2, 2, 2, 3, 99, 3, 2, 2, 2, 3, 101, 3, 2, 2, 2, 3, 103, 3, 2, 2, 2, 3, 105, 3, 2, 2, 2, 3, 107, 3, 2, 2, 2, 3, 109, 3, 2, 2, 2, 3, 111, 3, 2, 2, 2, 3, 113, 3, 2, 2, 2, 3, 115, 3, 2, 2, 2, 3, 117, 3, 2, 2, 2, 3, 119, 3, 2, 2, 2, 3, 121, 3, 2, 2, 2, 3, 123, 3, 2, 2, 2, 3, 125, 3, 2, 2, 2, 3, 127, 3, 2, 2, 2, 3, 129, 3, 2, 2, 2, 3, 131, 3, 2, 2, 2, 3, 133, 3, 2, 2, 2, 3, 135, 3, 2, 2, 2, 3, 137, 3, 2, 2, 2, 3, 139, 3, 2, 2, 2, 3, 141, 3, 2, 2, 2, 3, 143, 3, 2, 2, 2, 3, 145, 3, 2, 2, 2, 3, 147, 3, 2, 2, 2, 4, 149, 3, 2, 2, 2, 4, 151, 3, 2, 2, 2, 4, 153, 3, 2, 2, 2, 4, 155, 3, 2, 2, 2, 4, 157, 3, 2, 2, 2, 4, 159, 3, 2, 2, 2, 4, 161, 3, 2, 2, 2, 4, 163, 3, 2, 2, 2, 4, 165, 3, 2, 2, 2, 4, 167, 3, 2, 2, 2, 4, 171, 3, 2, 2, 2, 4, 173, 3, 2, 2, 2, 4, 175, 3, 2, 2, 2, 4, 177, 3, 2, 2, 2, 5, 231, 3, 2, 2, 2, 7, 241, 3, 2, 2, 2, 9, 248, 3, 2, 2, 2, 11, 257, 3, 2, 2, 2, 13, 264, 3, 2, 2, 2, 15, 271, 3, 2, 2, 2, 17, 278, 3, 2, 2, 2, 19, 285, 3, 2, 2, 2, 21, 293, 3, 2, 2, 2, 23, 305, 3, 2, 2, 2, 25, 315, 3, 2, 2, 2, 27, 324, 3, 2, 2, 2, 29, 330, 3, 2, 2, 2, 31, 337, 3, 2, 2, 2, 33, 344, 3, 2, 2, 2, 35, 352, 3, 2, 2, 2, 37, 361, 3, 2, 2, 2, 39, 367, 3, 2, 2, 2, 41, 384, 3, 2, 2, 2, 43, 400, 3, 2, 2, 2, 45, 406, 3, 2, 2, 2, 47, 410, 3, 2, 2, 2, 49, 412, 3, 2, 2, 2, 51, 414, 3, 2, 2, 2, 53, 417, 3, 2, 2, 2, 55, 419, 3, 2, 2, 2, 57, 457, 3, 2, 2, 2, 59, 460, 3, 2, 2, 2, 61, 506, 3, 2, 2, 2, 63, 508, 3, 2, 2, 2, 65, 511, 3, 2, 2, 2, 67, 515, 3, 2, 2, 2, 69, 519, 3, 2, 2, 2, 71, 521, 3, 2, 2, 2, 73, 523, 3, 2, 2, 2, 75, 528, 3, 2, 2, 2, 77, 530, 3, 2, 2, 2, 79, 536, 3, 2, 2, 2, 81, 542, 3, 2, 2, 2, 83, 547, 3, 2, 2, 2, 85, 549, 3, 2, 2, 2, 87, 552, 3, 2, 2, 2, 89, 555, 3, 2, 2, 2, 91, 560, 3, 2, 2, 2, 93, 564, 3, 2, 2, 2, 95, 569, 3, 2, 2, 2, 97, 575, 3, 2, 2, 2, 99, 578, 3, 2, 2, 2, 101, 580, 3, 2, 2, 2, 103, 586, 3, 2, 2, 2, 105, 588, 3, 2, 2, 2, 107, 593, 3, 2, 2, 2, 109, 598, 3, 2, 2, 2, 111, 608, 3, 2, 2, 2, 113, 610, 3, 2, 2, 2, 115, 613, 3, 2, 2, 2, 117, 616, 3, 2, 2, 2, 119, 618, 3, 2, 2, 2, 121, 621, 3, 2, 2, 2, 123, 623, 3, 2, 2, 2, 125, 626, 3, 2, 2, 2, 127, 628, 3, 2, 2, 2, 129, 630, 3, 2, 2, 2, 131, 632, 3, 2, 2, 2, 133, 634, 3, 2, 2, 2, 135, 636, 3, 2, 2, 2, 137, 641, 3, 2, 2, 2, 139, 663, 3, 2, 2, 2, 141, 665, 3, 2, 2, 2, 143, 676, 3, 2, 2, 2, 145, 680, 3, 2, 2, 2, 147, 684, 3, 2, 2, 2, 149, 688, 3, 2, 2, 2, 151, 693, 3, 2, 2, 2, 153, 699, 3, 2, 2, 2, 155, 705, 3, 2, 2, 2, 157, 709, 3, 2, 2, 2, 159, 713, 3, 2, 2, 2, 161, 716, 3, 2, 2, 2, 163, 725, 3, 2, 2, 2, 165, 728, 3, 2, 2, 2, 167, 734, 3, 2, 2, 2, 169, 745, 3, 2, 2, 2, 171, 747, 3, 2, 2, 2, 173, 749, 3, 2, 2, 2, 175, 753, 3, 2, 2, 2, 177, 757, 3, 2, 2, 2, 179, 761, 3, 2, 2, 2, 181, 763, 3, 2, 2, 2, 183, 765, 3, 2, 2, 2, 185, 767, 3, 2, 2, 2, 187, 769, 3, 2, 2, 2, 189, 771, 3, 2, 2, 2, 191, 773, 3, 2, 2, 2, 193, 775, 3, 2, 2, 2, 195, 777, 3, 2, 2, 2, 197, 779, 3, 2, 2, 2, 199, 781, 3, 2, 2, 2, 201, 783, 3, 2, 2, 2, 203, 785, 3, 2, 2, 2, 205, 787, 3, 2, 2, 2, 207, 789, 3, 2, 2, 2, 209, 791, 3, 2, 2, 2, 211, 793, 3, 2, 2, 2, 213, 795, 3, 2, 2, 2, 215, 797, 3, 2, 2, 2, 217, 799, 3, 2, 2, 2, 219, 801, 3, 2, 2, 2, 221, 803, 3, 2, 2, 2, 223, 805, 3, 2, 2, 2, 225, 807, 3, 2, 2, 2, 227, 809, 3, 2, 2, 2, 229, 811, 3, 2, 2, 2, 231, 232, 5, 185, 92, 2, 232, 233, 5, 195, 97, 2, 233, 234, 5, 215, 107, 2, 234, 235, 5, 215, 107, 2, 235, 236, 5, 187, 93, 2, 236, 237, 5, 183, 91, 2, 237, 238, 5, 217, 108, 2, 238, 239, 3, 2, 2, 2, 239, 240, 8, 2, 2, 2, 240, 6, 3, 2, 2, 2, 241, 242, 5, 185, 92, 2, 242, 243, 5, 213, 106, 2, 243, 244, 5, 207, 103, 2, 244, 245, 5, 209, 104, 2, 245, 246, 3, 2, 2, 2, 246, 247, 8, 3, 3, 2, 247, 8, 3, 2, 2, 2, 248, 249, 5, 187, 93, 2, 249, 250, 5, 205, 102, 2, 250, 251, 5, 213, 106, 2, 251, 252, 5, 195, 97, 2, 252, 253, 5, 183, 91, 2, 253, 254, 5, 193, 96, 2, 254, 255, 3, 2, 2, 2, 255, 256, 8, 4, 3, 2, 256, 10, 3, 2, 2, 2, 257, 258, 5, 187, 93, 2, 258, 259, 5, 221, 110, 2, 259, 260, 5, 179, 89, 2, 260, 261, 5, 201, 100, 2, 261, 262, 3, 2, 2, 2, 262, 263, 8, 5, 2, 2, 263, 12, 3, 2, 2, 2, 264, 265, 5, 189, 94, 2, 265, 266, 5, 213, 106, 2, 266, 267, 5, 207, 103, 2, 267, 268, 5, 203, 101, 2, 268, 269, 3, 2, 2, 2, 269, 270, 8, 6, 3, 2, 270, 14, 3, 2, 2, 2, 271, 272, 5, 191, 95, 2, 272, 273, 5, 213, 106, 2, 273, 274, 5, 207, 103, 2, 274, 275, 5, 199, 99, 2, 275, 276, 3, 2, 2, 2, 276, 277, 8, 7, 2, 2, 277, 16, 3, 2, 2, 2, 278, 279, 5, 199, 99, 2, 279, 280, 5, 187, 93, 2, 280, 281, 5, 187, 93, 2, 281, 282, 5, 209, 104, 2, 282, 283, 3, 2, 2, 2, 283, 284, 8, 8, 3, 2, 284, 18, 3, 2, 2, 2, 285, 286, 5, 201, 100, 2, 286, 287, 5, 195, 97, 2, 287, 288, 5, 203, 101, 2, 288, 289, 5, 195, 97, 2, 289, 290, 5, 217, 108, 2, 290, 291, 3, 2, 2, 2, 291, 292, 8, 9, 2, 2, 292, 20, 3, 2, 2, 2, 293, 294, 5, 203, 101, 2, 294, 295, 5, 221, 110, 2, 295, 296, 5, 111, 55, 2, 296, 297, 5, 187, 93, 2, 297, 298, 5, 225, 112, 2, 298, 299, 5, 209, 104, 2, 299, 300, 5, 179, 89, 2, 300, 301, 5, 205, 102, 2, 301, 302, 5, 185, 92, 2, 302, 303, 3, 2, 2, 2, 303, 304, 8, 10, 3, 2, 304, 22, 3, 2, 2, 2, 305, 306, 5, 209, 104, 2, 306, 307, 5, 213, 106, 2, 307, 308, 5, 207, 103, 2, 308, 309, 5, 197, 98, 2, 309, 310, 5, 187, 93, 2, 310, 311, 5, 183, 91, 2, 311, 312, 5, 217, 108, 2, 312, 313, 3, 2, 2, 2, 313, 314, 8, 11, 3, 2, 314, 24, 3, 2, 2, 2, 315, 316, 5, 213, 106, 2, 316, 317, 5, 187, 93, 2, 317, 318, 5, 205, 102, 2, 318, 319, 5, 179, 89, 2, 319, 320, 5, 203, 101, 2, 320, 321, 5, 187, 93, 2, 321, 322, 3, 2, 2, 2, 322, 323, 8, 12, 3, 2, 323, 26, 3, 2, 2, 2, 324, 325, 5, 213, 106, 2, 325, 326, 5, 207, 103, 2, 326, 327, 5, 223, 111, 2, 327, 328, 3, 2, 2, 2, 328, 329, 8, 13, 2, 2, 329, 28, 3, 2, 2, 2, 330, 331, 5, 215, 107, 2, 331, 332, 5, 193, 96, 2, 332, 333, 5, 207, 103, 2, 333, 334, 5, 223, 111, 2, 334, 335, 3, 2, 2, 2, 335, 336, 8, 14, 2, 2, 336, 30, 3, 2, 2, 2, 337, 338, 5, 215, 107, 2, 338, 339, 5, 207, 103, 2, 339, 340, 5, 213, 106, 2, 340, 341, 5, 217, 108, 2, 341, 342, 3, 2, 2, 2, 342, 343, 8, 15, 2, 2, 343, 32, 3, 2, 2, 2, 344, 345, 5, 215, 107, 2, 345, 346, 5, 217, 108, 2, 346, 347, 5, 179, 89, 2, 347, 348, 5, 217, 108, 2, 348, 349, 5, 215, 107, 2, 349, 350, 3, 2, 2, 2, 350, 351, 8, 16, 2, 2, 351, 34, 3, 2, 2, 2, 352, 353, 5, 223, 111, 2, 353, 354, 5, 193, 96, 2, 354, 355, 5, 187, 93, 2, 355, 356, 5, 213, 106, 2, 356, 357, 5, 187, 93, 2, 357, 358, 3, 2, 2, 2, 358, 359, 8, 17, 2, 2, 359, 36, 3, 2, 2, 2, 360, 362, 10, 2, 2, 2, 361, 360, 3, 2, 2, 2, 362, 363, 3, 2, 2, 2, 363, 361, 3, 2, 2, 2, 363, 364, 3, 2, 2, 2, 364, 365, 3, 2, 2, 2, 365, 366, 8, 18, 2, 2, 366, 38, 3, 2, 2, 2, 367, 368, 7, 49, 2, 2, 368, 369, 7, 49, 2, 2, 369, 373, 3, 2, 2, 2, 370, 372, 10, 3, 2, 2, 371, 370, 3, 2, 2, 2, 372, 375, 3, 2, 2, 2, 373, 371, 3, 2, 2, 2, 373, 374, 3, 2, 2, 2, 374, 377, 3, 2, 2, 2, 375, 373, 3, 2, 2, 2, 376, 378, 7, 15, 2, 2, 377, 376, 3, 2, 2, 2, 377, 378, 3, 2, 2, 2, 378, 380, 3, 2, 2, 2, 379, 381, 7, 12, 2, 2, 380, 379, 3, 2, 2, 2, 380, 381, 3, 2, 2, 2, 381, 382, 3, 2, 2, 2, 382, 383, 8, 19, 4, 2, 383, 40, 3, 2, 2, 2, 384, 385, 7, 49, 2, 2, 385, 386, 7, 44, 2, 2, 386, 391, 3, 2, 2, 2, 387, 390, 5, 41, 20, 2, 388, 390, 11, 2, 2, 2, 389, 387, 3, 2, 2, 2, 389, 388, 3, 2, 2, 2, 390, 393, 3, 2, 2, 2, 391, 392, 3, 2, 2, 2, 391, 389, 3, 2, 2, 2, 392, 394, 3, 2, 2, 2, 393, 391, 3, 2, 2, 2, 394, 395, 7, 44, 2, 2, 395, 396, 7, 49, 2, 2, 396, 397, 3, 2, 2, 2, 397, 398, 8, 20, 4, 2, 398, 42, 3, 2, 2, 2, 399, 401, 9, 4, 2, 2, 400, 399, 3, 2, 2, 2, 401, 402, 3, 2, 2, 2, 402, 400, 3, 2, 2, 2, 402, 403, 3, 2, 2, 2, 403, 404, 3, 2, 2, 2, 404, 405, 8, 21, 4, 2, 405, 44, 3, 2, 2, 2, 406, 407, 7, 126, 2, 2, 407, 408, 3, 2, 2, 2, 408, 409, 8, 22, 5, 2, 409, 46, 3, 2, 2, 2, 410, 411, 9, 5, 2, 2, 411, 48, 3, 2, 2, 2, 412, 413, 9, 6, 2, 2, 413, 50, 3, 2, 2, 2, 414, 415, 7, 94, 2, 2, 415, 416, 9, 7, 2, 2, 416, 52, 3, 2, 2, 2, 417, 418, 10, 8, 2, 2, 418, 54, 3, 2, 2, 2, 419, 421, 9, 9, 2, 2, 420, 422, 9, 10, 2, 2, 421, 420, 3, 2, 2, 2, 421, 422, 3, 2, 2, 2, 422, 424, 3, 2, 2, 2, 423, 425, 5, 47, 23, 2, 424, 423, 3, 2, 2, 2, 425, 426, 3, 2, 2, 2, 426, 424, 3, 2, 2, 2, 426, 427, 3, 2, 2, 2, 427, 56, 3, 2, 2, 2, 428, 433, 7, 36, 2, 2, 429, 432, 5, 51, 25, 2, 430, 432, 5, 53, 26, 2, 431, 429, 3, 2, 2, 2, 431, 430, 3, 2, 2, 2, 432, 435, 3, 2, 2, 2, 433, 431, 3, 2, 2, 2, 433, 434, 3, 2, 2, 2, 434, 436, 3, 2, 2, 2, 435, 433, 3, 2, 2, 2, 436, 458, 7, 36, 2, 2, 437, 438, 7, 36, 2, 2, 438, 439, 7, 36, 2, 2, 439, 440, 7, 36, 2, 2, 440, 444, 3, 2, 2, 2, 441, 443, 10, 3, 2, 2, 442, 441, 3, 2, 2, 2, 443, 446, 3, 2, 2, 2, 444, 445, 3, 2, 2, 2, 444, 442, 3, 2, 2, 2, 445, 447, 3, 2, 2, 2, 446, 444, 3, 2, 2, 2, 447, 448, 7, 36, 2, 2, 448, 449, 7, 36, 2, 2, 449, 450, 7, 36, 2, 2, 450, 452, 3, 2, 2, 2, 451, 453, 7, 36, 2, 2, 452, 451, 3, 2, 2, 2, 452, 453, 3, 2, 2, 2, 453, 455, 3, 2, 2, 2, 454, 456, 7, 36, 2, 2, 455, 454, 3, 2, 2, 2, 455, 456, 3, 2, 2, 2, 456, 458, 3, 2, 2, 2, 457, 428, 3, 2, 2, 2, 457, 437, 3, 2, 2, 2, 458, 58, 3, 2, 2, 2, 459, 461, 5, 47, 23, 2, 460, 459, 3, 2, 2, 2, 461, 462, 3, 2, 2, 2, 462, 460, 3, 2, 2, 2, 462, 463, 3, 2, 2, 2, 463, 60, 3, 2, 2, 2, 464, 466, 5, 47, 23, 2, 465, 464, 3, 2, 2, 2, 466, 467, 3, 2, 2, 2, 467, 465, 3, 2, 2, 2, 467, 468, 3, 2, 2, 2, 468, 469, 3, 2, 2, 2, 469, 473, 5, 75, 37, 2, 470, 472, 5, 47, 23, 2, 471, 470, 3, 2, 2, 2, 472, 475, 3, 2, 2, 2, 473, 471, 3, 2, 2, 2, 473, 474, 3, 2, 2, 2, 474, 507, 3, 2, 2, 2, 475, 473, 3, 2, 2, 2, 476, 478, 5, 75, 37, 2, 477, 479, 5, 47, 23, 2, 478, 477, 3, 2, 2, 2, 479, 480, 3, 2, 2, 2, 480, 478, 3, 2, 2, 2, 480, 481, 3, 2, 2, 2, 481, 507, 3, 2, 2, 2, 482, 484, 5, 47, 23, 2, 483, 482, 3, 2, 2, 2, 484, 485, 3, 2, 2, 2, 485, 483, 3, 2, 2, 2, 485, 486, 3, 2, 2, 2, 486, 494, 3, 2, 2, 2, 487, 491, 5, 75, 37, 2, 488, 490, 5, 47, 23, 2, 489, 488, 3, 2, 2, 2, 490, 493, 3, 2, 2, 2, 491, 489, 3, 2, 2, 2, 491, 492, 3, 2, 2, 2, 492, 495, 3, 2, 2, 2, 493, 491, 3, 2, 2, 2, 494, 487, 3, 2, 2, 2, 494, 495, 3, 2, 2, 2, 495, 496, 3, 2, 2, 2, 496, 497, 5, 55, 27, 2, 497, 507, 3, 2, 2, 2, 498, 500, 5, 75, 37, 2, 499, 501, 5, 47, 23, 2, 500, 499, 3, 2, 2, 2, 501, 502, 3, 2, 2, 2, 502, 500, 3, 2, 2, 2, 502, 503, 3, 2, 2, 2, 503, 504, 3, 2, 2, 2, 504, 505, 5, 55, 27, 2, 505, 507, 3, 2, 2, 2, 506, 465, 3, 2, 2, 2, 506, 476, 3, 2, 2, 2, 506, 483, 3, 2, 2, 2, 506, 498, 3, 2, 2, 2, 507, 62, 3, 2, 2, 2, 508, 509, 5, 181, 90, 2, 509, 510, 5, 227, 113, 2, 510, 64, 3, 2, 2, 2, 511, 512, 5, 179, 89, 2, 512, 513, 5, 205, 102, 2, 513, 514, 5, 185, 92, 2, 514, 66, 3, 2, 2, 2, 515, 516, 5, 179, 89, 2, 516, 517, 5, 215, 107, 2, 517, 518, 5, 183, 91, 2, 518, 68, 3, 2, 2, 2, 519, 520, 7, 63, 2, 2, 520, 70, 3, 2, 2, 2, 521, 522, 7, 46, 2, 2, 522, 72, 3, 2, 2, 2, 523, 524, 5, 185, 92, 2, 524, 525, 5, 187, 93, 2, 525, 526, 5, 215, 107, 2, 526, 527, 5, 183, 91, 2, 527, 74, 3, 2, 2, 2, 528, 529, 7, 48, 2, 2, 529, 76, 3, 2, 2, 2, 530, 531, 5, 189, 94, 2, 531, 532, 5, 179, 89, 2, 532, 533, 5, 201, 100, 2, 533, 534, 5, 215, 107, 2, 534, 535, 5, 187, 93, 2, 535, 78, 3, 2, 2, 2, 536, 537, 5, 189, 94, 2, 537, 538, 5, 195, 97, 2, 538, 539, 5, 213, 106, 2, 539, 540, 5, 215, 107, 2, 540, 541, 5, 217, 108, 2, 541, 80, 3, 2, 2, 2, 542, 543, 5, 201, 100, 2, 543, 544, 5, 179, 89, 2, 544, 545, 5, 215, 107, 2, 545, 546, 5, 217, 108, 2, 546, 82, 3, 2, 2, 2, 547, 548, 7, 42, 2, 2, 548, 84, 3, 2, 2, 2, 549, 550, 5, 195, 97, 2, 550, 551, 5, 205, 102, 2, 551, 86, 3, 2, 2, 2, 552, 553, 5, 195, 97, 2, 553, 554, 5, 215, 107, 2, 554, 88, 3, 2, 2, 2, 555, 556, 5, 201, 100, 2, 556, 557, 5, 195, 97, 2, 557, 558, 5, 199, 99, 2, 558, 559, 5, 187, 93, 2, 559, 90, 3, 2, 2, 2, 560, 561, 5, 205, 102, 2, 561, 562, 5, 207, 103, 2, 562, 563, 5, 217, 108, 2, 563, 92, 3, 2, 2, 2, 564, 565, 5, 205, 102, 2, 565, 566, 5, 219, 109, 2, 566, 567, 5, 201, 100, 2, 567, 568, 5, 201, 100, 2, 568, 94, 3, 2, 2, 2, 569, 570, 5, 205, 102, 2, 570, 571, 5, 219, 109, 2, 571, 572, 5, 201, 100, 2, 572, 573, 5, 201, 100, 2, 573, 574, 5, 215, 107, 2, 574, 96, 3, 2, 2, 2, 575, 576, 5, 207, 103, 2, 576, 577, 5, 213, 106, 2, 577, 98, 3, 2, 2, 2, 578, 579, 7, 65, 2, 2, 579, 100, 3, 2, 2, 2, 580, 581, 5, 213, 106, 2, 581, 582, 5, 201, 100, 2, 582, 583, 5, 195, 97, 2, 583, 584, 5, 199, 99, 2, 584, 585, 5, 187, 93, 2, 585, 102, 3, 2, 2, 2, 586, 587, 7, 43, 2, 2, 587, 104, 3, 2, 2, 2, 588, 589, 5, 217, 108, 2, 589, 590, 5, 213, 106, 2, 590, 591, 5, 219, 109, 2, 591, 592, 5, 187, 93, 2, 592, 106, 3, 2, 2, 2, 593, 594, 5, 195, 97, 2, 594, 595, 5, 205, 102, 2, 595, 596, 5, 189, 94, 2, 596, 597, 5, 207, 103, 2, 597, 108, 3, 2, 2, 2, 598, 599, 5, 189, 94, 2, 599, 600, 5, 219, 109, 2, 600, 601, 5, 205, 102, 2, 601, 602, 5, 183, 91, 2, 602, 603, 5, 217, 108, 2, 603, 604, 5, 195, 97, 2, 604, 605, 5, 207, 103, 2, 605, 606, 5, 205, 102, 2, 606, 607, 5, 215, 107, 2, 607, 110, 3, 2, 2, 2, 608, 609, 7, 97, 2, 2, 609, 112, 3, 2, 2, 2, 610, 611, 7, 63, 2, 2, 611, 612, 7, 63, 2, 2, 612, 114, 3, 2, 2, 2, 613, 614, 7, 35, 2, 2, 614, 615, 7, 63, 2, 2, 615, 116, 3, 2, 2, 2, 616, 617, 7, 62, 2, 2, 617, 118, 3, 2, 2, 2, 618, 619, 7, 62, 2, 2, 619, 620, 7, 63, 2, 2, 620, 120, 3, 2, 2, 2, 621, 622, 7, 64, 2, 2, 622, 122, 3, 2, 2, 2, 623, 624, 7, 64, 2, 2, 624, 625, 7, 63, 2, 2, 625, 124, 3, 2, 2, 2, 626, 627, 7, 45, 2, 2, 627, 126, 3, 2, 2, 2, 628, 629, 7, 47, 2, 2, 629, 128, 3, 2, 2, 2, 630, 631, 7, 44, 2, 2, 631, 130, 3, 2, 2, 2, 632, 633, 7, 49, 2, 2, 633, 132, 3, 2, 2, 2, 634, 635, 7, 39, 2, 2, 635, 134, 3, 2, 2, 2, 636, 637, 7, 93, 2, 2, 637, 638, 3, 2, 2, 2, 638, 639, 8, 67, 2, 2, 639, 640, 8, 67, 2, 2, 640, 136, 3, 2, 2, 2, 641, 642, 7, 95, 2, 2, 642, 643, 3, 2, 2, 2, 643, 644, 8, 68, 5, 2, 644, 645, 8, 68, 5, 2, 645, 138, 3, 2, 2, 2, 646, 652, 5, 49, 24, 2, 647, 651, 5, 49, 24, 2, 648, 651, 5, 47, 23, 2, 649, 651, 7, 97, 2, 2, 650, 647, 3, 2, 2, 2, 650, 648, 3, 2, 2, 2, 650, 649, 3, 2, 2, 2, 651, 654, 3, 2, 2, 2, 652, 650, 3, 2, 2, 2, 652, 653, 3, 2, 2, 2, 653, 664, 3, 2, 2, 2, 654, 652, 3, 2, 2, 2, 655, 659, 9, 11, 2, 2, 656, 660, 5, 49, 24, 2, 657, 660, 5, 47, 23, 2, 658, 660, 7, 97, 2, 2, 659, 656, 3, 2, 2, 2, 659, 657, 3, 2, 2, 2, 659, 658, 3, 2, 2, 2, 660, 661, 3, 2, 2, 2, 661, 659, 3, 2, 2, 2, 661, 662, 3, 2, 2, 2, 662, 664, 3, 2, 2, 2, 663, 646, 3, 2, 2, 2, 663, 655, 3, 2, 2, 2, 664, 140, 3, 2, 2, 2, 665, 671, 7, 98, 2, 2, 666, 670, 10, 12, 2, 2, 667, 668, 7, 98, 2, 2, 668, 670, 7, 98, 2, 2, 669, 666, 3, 2, 2, 2, 669, 667, 3, 2, 2, 2, 670, 673, 3, 2, 2, 2, 671, 669, 3, 2, 2, 2, 671, 672, 3, 2, 2, 2, 672, 674, 3, 2, 2, 2, 673, 671, 3, 2, 2, 2, 674, 675, 7, 98, 2, 2, 675, 142, 3, 2, 2, 2, 676, 677, 5, 39, 19, 2, 677, 678, 3, 2, 2, 2, 678, 679, 8, 71, 4, 2, 679, 144, 3, 2, 2, 2, 680, 681, 5, 41, 20, 2, 681, 682, 3, 2, 2, 2, 682, 683, 8, 72, 4, 2, 683, 146, 3, 2, 2, 2, 684, 685, 5, 43, 21, 2, 685, 686, 3, 2, 2, 2, 686, 687, 8, 73, 4, 2, 687, 148, 3, 2, 2, 2, 688, 689, 7, 126, 2, 2, 689, 690, 3, 2, 2, 2, 690, 691, 8, 74, 6, 2, 691, 692, 8, 74, 5, 2, 692, 150, 3, 2, 2, 2, 693, 694, 7, 93, 2, 2, 694, 695, 3, 2, 2, 2, 695, 696, 8, 75, 7, 2, 696, 697, 8, 75, 3, 2, 697, 698, 8, 75, 3, 2, 698, 152, 3, 2, 2, 2, 699, 700, 7, 95, 2, 2, 700, 701, 3, 2, 2, 2, 701, 702, 8, 76, 5, 2, 702, 703, 8, 76, 5, 2, 703, 704, 8, 76, 8, 2, 704, 154, 3, 2, 2, 2, 705, 706, 7, 46, 2, 2, 706, 707, 3, 2, 2, 2, 707, 708, 8, 77, 9, 2, 708, 156, 3, 2, 2, 2, 709, 710, 7, 63, 2, 2, 710, 711, 3, 2, 2, 2, 711, 712, 8, 78, 10, 2, 712, 158, 3, 2, 2, 2, 713, 714, 5, 179, 89, 2, 714, 715, 5, 215, 107, 2, 715, 160, 3, 2, 2, 2, 716, 717, 5, 203, 101, 2, 717, 718, 5, 187, 93, 2, 718, 719, 5, 217, 108, 2, 719, 720, 5, 179, 89, 2, 720, 721, 5, 185, 92, 2, 721, 722, 5, 179, 89, 2, 722, 723, 5, 217, 108, 2, 723, 724, 5, 179, 89, 2, 724, 162, 3, 2, 2, 2, 725, 726, 5, 207, 103, 2, 726, 727, 5, 205, 102, 2, 727, 164, 3, 2, 2, 2, 728, 729, 5, 223, 111, 2, 729, 730, 5, 195, 97, 2, 730, 731, 5, 217, 108, 2, 731, 732, 5, 193, 96, 2, 732, 166, 3, 2, 2, 2, 733, 735, 5, 169, 84, 2, 734, 733, 3, 2, 2, 2, 735, 736, 3, 2, 2, 2, 736, 734, 3, 2, 2, 2, 736, 737, 3, 2, 2, 2, 737, 168, 3, 2, 2, 2, 738, 740, 10, 13, 2, 2, 739, 738, 3, 2, 2, 2, 740, 741, 3, 2, 2, 2, 741, 739, 3, 2, 2, 2, 741, 742, 3, 2, 2, 2, 742, 746, 3, 2, 2, 2, 743, 744, 7, 49, 2, 2, 744, 746, 10, 14, 2, 2, 745, 739, 3, 2, 2, 2, 745, 743, 3, 2, 2, 2, 746, 170, 3, 2, 2, 2, 747, 748, 5, 141, 70, 2, 748, 172, 3, 2, 2, 2, 749, 750, 5, 39, 19, 2, 750, 751, 3, 2, 2, 2, 751, 752, 8, 86, 4, 2, 752, 174, 3, 2, 2, 2, 753, 754, 5, 41, 20, 2, 754, 755, 3, 2, 2, 2, 755, 756, 8, 87, 4, 2, 756, 176, 3, 2, 2, 2, 757, 758, 5, 43, 21, 2, 758, 759, 3, 2, 2, 2, 759, 760, 8, 88, 4, 2, 760, 178, 3, 2, 2, 2, 761, 762, 9, 15, 2, 2, 762, 180, 3, 2, 2, 2, 763, 764, 9, 16, 2, 2, 764, 182, 3, 2, 2, 2, 765, 766, 9, 17, 2, 2, 766, 184, 3, 2, 2, 2, 767, 768, 9, 18, 2, 2, 768, 186, 3, 2, 2, 2, 769, 770, 9, 9, 2, 2, 770, 188, 3, 2, 2, 2, 771, 772, 9, 19, 2, 2, 772, 190, 3, 2, 2, 2, 773, 774, 9, 20, 2, 2, 774, 192, 3, 2, 2, 2, 775, 776, 9, 21, 2, 2, 776, 194, 3, 2, 2, 2, 777, 778, 9, 22, 2, 2, 778, 196, 3, 2, 2, 2, 779, 780, 9, 23, 2, 2, 780, 198, 3, 2, 2, 2, 781, 782, 9, 24, 2, 2, 782, 200, 3, 2, 2, 2, 783, 784, 9, 25, 2, 2, 784, 202, 3, 2, 2, 2, 785, 786, 9, 26, 2, 2, 786, 204, 3, 2, 2, 2, 787, 788, 9, 27, 2, 2, 788, 206, 3, 2, 2, 2, 789, 790, 9, 28, 2, 2, 790, 208, 3, 2, 2, 2, 791, 792, 9, 29, 2, 2, 792, 210, 3, 2, 2, 2, 793, 794, 9, 30, 2, 2, 794, 212, 3, 2, 2, 2, 795, 796, 9, 31, 2, 2, 796, 214, 3, 2, 2, 2, 797, 798, 9, 32, 2, 2, 798, 216, 3, 2, 2, 2, 799, 800, 9, 33, 2, 2, 800, 218, 3, 2, 2, 2, 801, 802, 9, 34, 2, 2, 802, 220, 3, 2, 2, 2, 803, 804, 9, 35, 2, 2, 804, 222, 3, 2, 2, 2, 805, 806, 9, 36, 2, 2, 806, 224, 3, 2, 2, 2, 807, 808, 9, 37, 2, 2, 808, 226, 3, 2, 2, 2, 809, 810, 9, 38, 2, 2, 810, 228, 3, 2, 2, 2, 811, 812, 9, 39, 2, 2, 812, 230, 3, 2, 2, 2, 39, 2, 3, 4, 363, 373, 377, 380, 389, 391, 402, 421, 426, 431, 433, 444, 452, 455, 457, 462, 467, 473, 480, 485, 491, 494, 502, 506, 650, 652, 659, 661, 663, 669, 671, 736, 741, 745, 11, 7, 3, 2, 7, 4, 2, 2, 3, 2, 6, 2, 2, 9, 23, 2, 9, 63, 2, 9, 64, 2, 9, 31, 2, 9, 30, 2] \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens b/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens index b72e97b9a2961..c3160ce1f6472 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens @@ -1,98 +1,93 @@ DISSECT=1 -GROK=2 -EVAL=3 -EXPLAIN=4 +DROP=2 +ENRICH=3 +EVAL=4 FROM=5 -ROW=6 -STATS=7 -WHERE=8 -SORT=9 -MV_EXPAND=10 -LIMIT=11 -PROJECT=12 -DROP=13 -RENAME=14 -SHOW=15 -ENRICH=16 -KEEP=17 +GROK=6 +KEEP=7 +LIMIT=8 +MV_EXPAND=9 +PROJECT=10 +RENAME=11 +ROW=12 +SHOW=13 +SORT=14 +STATS=15 +WHERE=16 +UNKNOWN_CMD=17 LINE_COMMENT=18 MULTILINE_COMMENT=19 WS=20 -EXPLAIN_WS=21 -EXPLAIN_LINE_COMMENT=22 -EXPLAIN_MULTILINE_COMMENT=23 -PIPE=24 -STRING=25 -INTEGER_LITERAL=26 -DECIMAL_LITERAL=27 -BY=28 -DATE_LITERAL=29 -AND=30 -ASSIGN=31 -COMMA=32 -DOT=33 -LP=34 -OPENING_BRACKET=35 -CLOSING_BRACKET=36 -NOT=37 +PIPE=21 +STRING=22 +INTEGER_LITERAL=23 +DECIMAL_LITERAL=24 +BY=25 +AND=26 +ASC=27 +ASSIGN=28 +COMMA=29 +DESC=30 +DOT=31 +FALSE=32 +FIRST=33 +LAST=34 +LP=35 +IN=36 +IS=37 LIKE=38 -RLIKE=39 -IN=40 -IS=41 -AS=42 -NULL=43 -OR=44 +NOT=39 +NULL=40 +NULLS=41 +OR=42 +PARAM=43 +RLIKE=44 RP=45 -UNDERSCORE=46 +TRUE=46 INFO=47 FUNCTIONS=48 -BOOLEAN_VALUE=49 -COMPARISON_OPERATOR=50 -PLUS=51 -MINUS=52 -ASTERISK=53 -SLASH=54 -PERCENT=55 -TEN=56 -ORDERING=57 -NULLS_ORDERING=58 -NULLS_ORDERING_DIRECTION=59 -MATH_FUNCTION=60 -UNARY_FUNCTION=61 -WHERE_FUNCTIONS=62 +UNDERSCORE=49 +EQ=50 +NEQ=51 +LT=52 +LTE=53 +GT=54 +GTE=55 +PLUS=56 +MINUS=57 +ASTERISK=58 +SLASH=59 +PERCENT=60 +OPENING_BRACKET=61 +CLOSING_BRACKET=62 UNQUOTED_IDENTIFIER=63 QUOTED_IDENTIFIER=64 EXPR_LINE_COMMENT=65 EXPR_MULTILINE_COMMENT=66 EXPR_WS=67 -METADATA=68 -SRC_UNQUOTED_IDENTIFIER=69 -SRC_QUOTED_IDENTIFIER=70 -SRC_LINE_COMMENT=71 -SRC_MULTILINE_COMMENT=72 -SRC_WS=73 -ON=74 -WITH=75 -ENR_UNQUOTED_IDENTIFIER=76 -ENR_QUOTED_IDENTIFIER=77 -ENR_LINE_COMMENT=78 -ENR_MULTILINE_COMMENT=79 -ENR_WS=80 -EXPLAIN_PIPE=81 -'by'=28 -'and'=30 -'.'=33 -'('=34 -']'=36 -'or'=44 +AS=68 +METADATA=69 +ON=70 +WITH=71 +SRC_UNQUOTED_IDENTIFIER=72 +SRC_QUOTED_IDENTIFIER=73 +SRC_LINE_COMMENT=74 +SRC_MULTILINE_COMMENT=75 +SRC_WS=76 +'.'=31 +'('=35 +'?'=43 ')'=45 -'_'=46 -'info'=47 -'functions'=48 -'+'=51 -'-'=52 -'*'=53 -'/'=54 -'%'=55 -'10'=56 -'nulls'=58 +'_'=49 +'=='=50 +'!='=51 +'<'=52 +'<='=53 +'>'=54 +'>='=55 +'+'=56 +'-'=57 +'*'=58 +'/'=59 +'%'=60 +']'=62 diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts b/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts index 1c5fc5a918aa4..4bbb3eb4968c3 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts @@ -18,90 +18,83 @@ import * as Utils from "antlr4ts/misc/Utils"; export class esql_lexer extends Lexer { public static readonly DISSECT = 1; - public static readonly GROK = 2; - public static readonly EVAL = 3; - public static readonly EXPLAIN = 4; + public static readonly DROP = 2; + public static readonly ENRICH = 3; + public static readonly EVAL = 4; public static readonly FROM = 5; - public static readonly ROW = 6; - public static readonly STATS = 7; - public static readonly WHERE = 8; - public static readonly SORT = 9; - public static readonly MV_EXPAND = 10; - public static readonly LIMIT = 11; - public static readonly PROJECT = 12; - public static readonly DROP = 13; - public static readonly RENAME = 14; - public static readonly SHOW = 15; - public static readonly ENRICH = 16; - public static readonly KEEP = 17; + public static readonly GROK = 6; + public static readonly KEEP = 7; + public static readonly LIMIT = 8; + public static readonly MV_EXPAND = 9; + public static readonly PROJECT = 10; + public static readonly RENAME = 11; + public static readonly ROW = 12; + public static readonly SHOW = 13; + public static readonly SORT = 14; + public static readonly STATS = 15; + public static readonly WHERE = 16; + public static readonly UNKNOWN_CMD = 17; public static readonly LINE_COMMENT = 18; public static readonly MULTILINE_COMMENT = 19; public static readonly WS = 20; - public static readonly EXPLAIN_WS = 21; - public static readonly EXPLAIN_LINE_COMMENT = 22; - public static readonly EXPLAIN_MULTILINE_COMMENT = 23; - public static readonly PIPE = 24; - public static readonly STRING = 25; - public static readonly INTEGER_LITERAL = 26; - public static readonly DECIMAL_LITERAL = 27; - public static readonly BY = 28; - public static readonly DATE_LITERAL = 29; - public static readonly AND = 30; - public static readonly ASSIGN = 31; - public static readonly COMMA = 32; - public static readonly DOT = 33; - public static readonly LP = 34; - public static readonly OPENING_BRACKET = 35; - public static readonly CLOSING_BRACKET = 36; - public static readonly NOT = 37; + public static readonly PIPE = 21; + public static readonly STRING = 22; + public static readonly INTEGER_LITERAL = 23; + public static readonly DECIMAL_LITERAL = 24; + public static readonly BY = 25; + public static readonly AND = 26; + public static readonly ASC = 27; + public static readonly ASSIGN = 28; + public static readonly COMMA = 29; + public static readonly DESC = 30; + public static readonly DOT = 31; + public static readonly FALSE = 32; + public static readonly FIRST = 33; + public static readonly LAST = 34; + public static readonly LP = 35; + public static readonly IN = 36; + public static readonly IS = 37; public static readonly LIKE = 38; - public static readonly RLIKE = 39; - public static readonly IN = 40; - public static readonly IS = 41; - public static readonly AS = 42; - public static readonly NULL = 43; - public static readonly OR = 44; + public static readonly NOT = 39; + public static readonly NULL = 40; + public static readonly NULLS = 41; + public static readonly OR = 42; + public static readonly PARAM = 43; + public static readonly RLIKE = 44; public static readonly RP = 45; - public static readonly UNDERSCORE = 46; + public static readonly TRUE = 46; public static readonly INFO = 47; public static readonly FUNCTIONS = 48; - public static readonly BOOLEAN_VALUE = 49; - public static readonly COMPARISON_OPERATOR = 50; - public static readonly PLUS = 51; - public static readonly MINUS = 52; - public static readonly ASTERISK = 53; - public static readonly SLASH = 54; - public static readonly PERCENT = 55; - public static readonly TEN = 56; - public static readonly ORDERING = 57; - public static readonly NULLS_ORDERING = 58; - public static readonly NULLS_ORDERING_DIRECTION = 59; - public static readonly MATH_FUNCTION = 60; - public static readonly UNARY_FUNCTION = 61; - public static readonly WHERE_FUNCTIONS = 62; + public static readonly UNDERSCORE = 49; + public static readonly EQ = 50; + public static readonly NEQ = 51; + public static readonly LT = 52; + public static readonly LTE = 53; + public static readonly GT = 54; + public static readonly GTE = 55; + public static readonly PLUS = 56; + public static readonly MINUS = 57; + public static readonly ASTERISK = 58; + public static readonly SLASH = 59; + public static readonly PERCENT = 60; + public static readonly OPENING_BRACKET = 61; + public static readonly CLOSING_BRACKET = 62; public static readonly UNQUOTED_IDENTIFIER = 63; public static readonly QUOTED_IDENTIFIER = 64; public static readonly EXPR_LINE_COMMENT = 65; public static readonly EXPR_MULTILINE_COMMENT = 66; public static readonly EXPR_WS = 67; - public static readonly METADATA = 68; - public static readonly SRC_UNQUOTED_IDENTIFIER = 69; - public static readonly SRC_QUOTED_IDENTIFIER = 70; - public static readonly SRC_LINE_COMMENT = 71; - public static readonly SRC_MULTILINE_COMMENT = 72; - public static readonly SRC_WS = 73; - public static readonly ON = 74; - public static readonly WITH = 75; - public static readonly ENR_UNQUOTED_IDENTIFIER = 76; - public static readonly ENR_QUOTED_IDENTIFIER = 77; - public static readonly ENR_LINE_COMMENT = 78; - public static readonly ENR_MULTILINE_COMMENT = 79; - public static readonly ENR_WS = 80; - public static readonly EXPLAIN_PIPE = 81; - public static readonly EXPLAIN_MODE = 1; - public static readonly EXPRESSION = 2; - public static readonly SOURCE_IDENTIFIERS = 3; - public static readonly ENRICH_IDENTIFIERS = 4; + public static readonly AS = 68; + public static readonly METADATA = 69; + public static readonly ON = 70; + public static readonly WITH = 71; + public static readonly SRC_UNQUOTED_IDENTIFIER = 72; + public static readonly SRC_QUOTED_IDENTIFIER = 73; + public static readonly SRC_LINE_COMMENT = 74; + public static readonly SRC_MULTILINE_COMMENT = 75; + public static readonly SRC_WS = 76; + public static readonly EXPRESSION = 1; + public static readonly SOURCE_IDENTIFIERS = 2; // tslint:disable:no-trailing-whitespace public static readonly channelNames: string[] = [ @@ -110,30 +103,26 @@ export class esql_lexer extends Lexer { // tslint:disable:no-trailing-whitespace public static readonly modeNames: string[] = [ - "DEFAULT_MODE", "EXPLAIN_MODE", "EXPRESSION", "SOURCE_IDENTIFIERS", "ENRICH_IDENTIFIERS", + "DEFAULT_MODE", "EXPRESSION", "SOURCE_IDENTIFIERS", ]; public static readonly ruleNames: string[] = [ - "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", "WHERE", - "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", "ENRICH", - "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_OPENING_BRACKET", - "EXPLAIN_PIPE", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", - "PIPE", "DIGIT", "LETTER", "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", "EXPONENT", - "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", - "AND", "ASSIGN", "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", - "NOT", "LIKE", "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", - "INFO", "FUNCTIONS", "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", - "ASTERISK", "SLASH", "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", - "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", - "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", - "SRC_PIPE", "SRC_OPENING_BRACKET", "SRC_CLOSING_BRACKET", "SRC_COMMA", - "SRC_ASSIGN", "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_UNQUOTED_IDENTIFIER_PART", - "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", - "SRC_WS", "ON", "WITH", "ENR_PIPE", "ENR_CLOSING_BRACKET", "ENR_COMMA", - "ENR_ASSIGN", "ENR_UNQUOTED_IDENTIFIER", "ENR_UNQUOTED_IDENTIFIER_PART", - "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", - "ENR_WS", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", - "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + "DISSECT", "DROP", "ENRICH", "EVAL", "FROM", "GROK", "KEEP", "LIMIT", + "MV_EXPAND", "PROJECT", "RENAME", "ROW", "SHOW", "SORT", "STATS", "WHERE", + "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", "DIGIT", + "LETTER", "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", "EXPONENT", "STRING", + "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", "COMMA", + "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", "NOT", + "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "INFO", "FUNCTIONS", + "UNDERSCORE", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", + "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", + "EXPR_WS", "SRC_PIPE", "SRC_OPENING_BRACKET", "SRC_CLOSING_BRACKET", "SRC_COMMA", + "SRC_ASSIGN", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", + "SRC_UNQUOTED_IDENTIFIER_PART", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", + "SRC_MULTILINE_COMMENT", "SRC_WS", "A", "B", "C", "D", "E", "F", "G", + "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", + "V", "W", "X", "Y", "Z", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -141,27 +130,25 @@ export class esql_lexer extends Lexer { undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, - "'by'", undefined, "'and'", undefined, undefined, "'.'", "'('", undefined, - "']'", undefined, undefined, undefined, undefined, undefined, undefined, - undefined, "'or'", "')'", "'_'", "'info'", "'functions'", undefined, undefined, - "'+'", "'-'", "'*'", "'/'", "'%'", "'10'", undefined, "'nulls'", + undefined, undefined, undefined, "'.'", undefined, undefined, undefined, + "'('", undefined, undefined, undefined, undefined, undefined, undefined, + undefined, "'?'", undefined, "')'", undefined, undefined, undefined, "'_'", + "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", + "'%'", undefined, "']'", ]; private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", - "WHERE", "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", - "ENRICH", "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_WS", - "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "PIPE", "STRING", - "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", "AND", "ASSIGN", - "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", "NOT", "LIKE", - "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", "INFO", "FUNCTIONS", - "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", "ASTERISK", "SLASH", - "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", - "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", - "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", - "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", - "SRC_MULTILINE_COMMENT", "SRC_WS", "ON", "WITH", "ENR_UNQUOTED_IDENTIFIER", - "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", - "ENR_WS", "EXPLAIN_PIPE", + undefined, "DISSECT", "DROP", "ENRICH", "EVAL", "FROM", "GROK", "KEEP", + "LIMIT", "MV_EXPAND", "PROJECT", "RENAME", "ROW", "SHOW", "SORT", "STATS", + "WHERE", "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", + "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", + "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", + "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "INFO", + "FUNCTIONS", "UNDERSCORE", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", + "MINUS", "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", + "EXPR_WS", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", + "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", + "SRC_WS", ]; public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(esql_lexer._LITERAL_NAMES, esql_lexer._SYMBOLIC_NAMES, []); @@ -193,780 +180,400 @@ export class esql_lexer extends Lexer { // @Override public get modeNames(): string[] { return esql_lexer.modeNames; } - private static readonly _serializedATNSegments: number = 3; + private static readonly _serializedATNSegments: number = 2; private static readonly _serializedATNSegment0: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02S\u0640\b\x01" + - "\b\x01\b\x01\b\x01\b\x01\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04" + - "\x05\t\x05\x04\x06\t\x06\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04" + - "\v\t\v\x04\f\t\f\x04\r\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04" + - "\x11\t\x11\x04\x12\t\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04" + - "\x16\t\x16\x04\x17\t\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04" + - "\x1B\t\x1B\x04\x1C\t\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04" + - " \t \x04!\t!\x04\"\t\"\x04#\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(" + - "\t(\x04)\t)\x04*\t*\x04+\t+\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x04" + - "1\t1\x042\t2\x043\t3\x044\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04" + - ":\t:\x04;\t;\x04<\t<\x04=\t=\x04>\t>\x04?\t?\x04@\t@\x04A\tA\x04B\tB\x04" + - "C\tC\x04D\tD\x04E\tE\x04F\tF\x04G\tG\x04H\tH\x04I\tI\x04J\tJ\x04K\tK\x04" + - "L\tL\x04M\tM\x04N\tN\x04O\tO\x04P\tP\x04Q\tQ\x04R\tR\x04S\tS\x04T\tT\x04" + - "U\tU\x04V\tV\x04W\tW\x04X\tX\x04Y\tY\x04Z\tZ\x04[\t[\x04\\\t\\\x04]\t" + - "]\x04^\t^\x04_\t_\x04`\t`\x04a\ta\x04b\tb\x04c\tc\x04d\td\x04e\te\x04" + - "f\tf\x04g\tg\x04h\th\x04i\ti\x04j\tj\x04k\tk\x04l\tl\x04m\tm\x04n\tn\x04" + - "o\to\x04p\tp\x04q\tq\x04r\tr\x04s\ts\x04t\tt\x04u\tu\x04v\tv\x04w\tw\x04" + - "x\tx\x04y\ty\x04z\tz\x04{\t{\x04|\t|\x04}\t}\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03" + - "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03" + - "\x06\x03\x06\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\b\x03" + - "\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03" + - "\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03" + - "\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03" + - "\f\x03\f\x03\f\x03\f\x03\f\x03\f\x03\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\r\x03\r\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03" + - "\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03" + - "\x0F\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03" + - "\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x13\x03\x13\x03\x13\x03" + - "\x13\x07\x13\u018F\n\x13\f\x13\x0E\x13\u0192\v\x13\x03\x13\x05\x13\u0195" + - "\n\x13\x03\x13\x05\x13\u0198\n\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03" + - "\x14\x03\x14\x03\x14\x07\x14\u01A1\n\x14\f\x14\x0E\x14\u01A4\v\x14\x03" + - "\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x15\x06\x15\u01AC\n\x15\r\x15" + - "\x0E\x15\u01AD\x03\x15\x03\x15\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16" + - "\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18\x03\x18\x03\x18\x03\x18" + - "\x03\x19\x03\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B" + - "\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1D\x03\x1D\x03\x1E\x03\x1E" + - "\x03\x1E\x03\x1F\x03\x1F\x03 \x03 \x05 \u01D7\n \x03 \x06 \u01DA\n \r" + - " \x0E \u01DB\x03!\x03!\x03!\x07!\u01E1\n!\f!\x0E!\u01E4\v!\x03!\x03!\x03" + - "!\x03!\x03!\x03!\x07!\u01EC\n!\f!\x0E!\u01EF\v!\x03!\x03!\x03!\x03!\x03" + - "!\x05!\u01F6\n!\x03!\x05!\u01F9\n!\x05!\u01FB\n!\x03\"\x06\"\u01FE\n\"" + - "\r\"\x0E\"\u01FF\x03#\x06#\u0203\n#\r#\x0E#\u0204\x03#\x03#\x07#\u0209" + - "\n#\f#\x0E#\u020C\v#\x03#\x03#\x06#\u0210\n#\r#\x0E#\u0211\x03#\x06#\u0215" + - "\n#\r#\x0E#\u0216\x03#\x03#\x07#\u021B\n#\f#\x0E#\u021E\v#\x05#\u0220" + - "\n#\x03#\x03#\x03#\x03#\x06#\u0226\n#\r#\x0E#\u0227\x03#\x03#\x05#\u022C" + - "\n#\x03$\x03$\x03$\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x05" + - "%\u028F\n%\x03&\x03&\x03&\x03&\x03\'\x03\'\x03(\x03(\x03)\x03)\x03*\x03" + - "*\x03+\x03+\x03+\x03+\x03+\x03,\x03,\x03,\x03,\x03,\x03-\x03-\x03-\x03" + - "-\x03.\x03.\x03.\x03.\x03.\x03/\x03/\x03/\x03/\x03/\x03/\x030\x030\x03" + - "0\x031\x031\x031\x032\x032\x032\x033\x033\x033\x033\x033\x034\x034\x03" + - "4\x035\x035\x036\x036\x037\x037\x037\x037\x037\x038\x038\x038\x038\x03" + - "8\x038\x038\x038\x038\x038\x039\x039\x039\x039\x039\x039\x039\x039\x03" + - "9\x059\u02E3\n9\x03:\x03:\x03:\x03:\x03:\x03:\x03:\x03:\x03:\x03:\x05" + - ":\u02EF\n:\x03;\x03;\x03<\x03<\x03=\x03=\x03>\x03>\x03?\x03?\x03@\x03" + - "@\x03@\x03A\x03A\x03A\x03A\x03A\x03A\x03A\x05A\u0305\nA\x03B\x03B\x03" + - "B\x03B\x03B\x03B\x03C\x03C\x03C\x03C\x03C\x03C\x03C\x03C\x03C\x05C\u0316" + - "\nC\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x05D\u04C6\nD\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x05E\u055F\nE\x03" + - "F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03G\x03G\x03G\x03" + - "G\x03G\x07G\u0571\nG\fG\x0EG\u0574\vG\x03G\x03G\x03G\x03G\x03G\x06G\u057B" + - "\nG\rG\x0EG\u057C\x05G\u057F\nG\x03H\x03H\x03H\x03H\x07H\u0585\nH\fH\x0E" + - "H\u0588\vH\x03H\x03H\x03I\x03I\x03I\x03I\x03J\x03J\x03J\x03J\x03K\x03" + - "K\x03K\x03K\x03L\x03L\x03L\x03L\x03L\x03M\x03M\x03M\x03M\x03M\x03M\x03" + - "N\x03N\x03N\x03N\x03N\x03N\x03O\x03O\x03O\x03O\x03P\x03P\x03P\x03P\x03" + - "Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03R\x06R\u05BB\nR\rR\x0ER\u05BC" + - "\x03S\x06S\u05C0\nS\rS\x0ES\u05C1\x03S\x03S\x05S\u05C6\nS\x03T\x03T\x03" + - "U\x03U\x03U\x03U\x03V\x03V\x03V\x03V\x03W\x03W\x03W\x03W\x03X\x03X\x03" + - "X\x03Y\x03Y\x03Y\x03Y\x03Y\x03Z\x03Z\x03Z\x03Z\x03Z\x03[\x03[\x03[\x03" + - "[\x03[\x03[\x03\\\x03\\\x03\\\x03\\\x03]\x03]\x03]\x03]\x03^\x06^\u05F2" + - "\n^\r^\x0E^\u05F3\x03_\x06_\u05F7\n_\r_\x0E_\u05F8\x03_\x03_\x05_\u05FD" + - "\n_\x03`\x03`\x03a\x03a\x03a\x03a\x03b\x03b\x03b\x03b\x03c\x03c\x03c\x03" + - "c\x03d\x03d\x03e\x03e\x03f\x03f\x03g\x03g\x03h\x03h\x03i\x03i\x03j\x03" + - "j\x03k\x03k\x03l\x03l\x03m\x03m\x03n\x03n\x03o\x03o\x03p\x03p\x03q\x03" + - "q\x03r\x03r\x03s\x03s\x03t\x03t\x03u\x03u\x03v\x03v\x03w\x03w\x03x\x03" + - "x\x03y\x03y\x03z\x03z\x03{\x03{\x03|\x03|\x03}\x03}\x04\u01A2\u01ED\x02" + - "\x02~\x07\x02\x03\t\x02\x04\v\x02\x05\r\x02\x06\x0F\x02\x07\x11\x02\b" + - "\x13\x02\t\x15\x02\n\x17\x02\v\x19\x02\f\x1B\x02\r\x1D\x02\x0E\x1F\x02" + - "\x0F!\x02\x10#\x02\x11%\x02\x12\'\x02\x13)\x02\x14+\x02\x15-\x02\x16/" + - "\x02\x021\x02S3\x02\x175\x02\x187\x02\x199\x02\x1A;\x02\x02=\x02\x02?" + - "\x02\x02A\x02\x02C\x02\x02E\x02\x1BG\x02\x1CI\x02\x1DK\x02\x1EM\x02\x1F" + - "O\x02 Q\x02!S\x02\"U\x02#W\x02$Y\x02%[\x02&]\x02\'_\x02(a\x02)c\x02*e" + - "\x02+g\x02,i\x02-k\x02.m\x02/o\x020q\x021s\x022u\x023w\x024y\x025{\x02" + - "6}\x027\x7F\x028\x81\x029\x83\x02:\x85\x02;\x87\x02<\x89\x02=\x8B\x02" + - ">\x8D\x02?\x8F\x02@\x91\x02A\x93\x02B\x95\x02C\x97\x02D\x99\x02E\x9B\x02" + - "\x02\x9D\x02\x02\x9F\x02\x02\xA1\x02\x02\xA3\x02\x02\xA5\x02F\xA7\x02" + - "G\xA9\x02\x02\xAB\x02H\xAD\x02I\xAF\x02J\xB1\x02K\xB3\x02L\xB5\x02M\xB7" + - "\x02\x02\xB9\x02\x02\xBB\x02\x02\xBD\x02\x02\xBF\x02N\xC1\x02\x02\xC3" + - "\x02O\xC5\x02P\xC7\x02Q\xC9\x02R\xCB\x02\x02\xCD\x02\x02\xCF\x02\x02\xD1" + - "\x02\x02\xD3\x02\x02\xD5\x02\x02\xD7\x02\x02\xD9\x02\x02\xDB\x02\x02\xDD" + - "\x02\x02\xDF\x02\x02\xE1\x02\x02\xE3\x02\x02\xE5\x02\x02\xE7\x02\x02\xE9" + - "\x02\x02\xEB\x02\x02\xED\x02\x02\xEF\x02\x02\xF1\x02\x02\xF3\x02\x02\xF5" + - "\x02\x02\xF7\x02\x02\xF9\x02\x02\xFB\x02\x02\xFD\x02\x02\x07\x02\x03\x04" + - "\x05\x06\'\x04\x02\f\f\x0F\x0F\x05\x02\v\f\x0F\x0F\"\"\x03\x022;\x04\x02" + - "C\\c|\x07\x02$$^^ppttvv\x06\x02\f\f\x0F\x0F$$^^\x04\x02GGgg\x04\x02--" + - "//\x04\x02BBaa\x03\x02bb\f\x02\v\f\x0F\x0F\"\"..11??]]__bb~~\x04\x02," + - ",11\x04\x02CCcc\x04\x02DDdd\x04\x02EEee\x04\x02FFff\x04\x02HHhh\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02N\u032D\b\x01" + + "\b\x01\b\x01\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04" + + "\x06\t\x06\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f" + + "\t\f\x04\r\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11" + + "\x04\x12\t\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16" + + "\x04\x17\t\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B" + + "\x04\x1C\t\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!" + + "\t!\x04\"\t\"\x04#\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x04)\t" + + ")\x04*\t*\x04+\t+\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x041\t1\x04" + + "2\t2\x043\t3\x044\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04:\t:\x04" + + ";\t;\x04<\t<\x04=\t=\x04>\t>\x04?\t?\x04@\t@\x04A\tA\x04B\tB\x04C\tC\x04" + + "D\tD\x04E\tE\x04F\tF\x04G\tG\x04H\tH\x04I\tI\x04J\tJ\x04K\tK\x04L\tL\x04" + + "M\tM\x04N\tN\x04O\tO\x04P\tP\x04Q\tQ\x04R\tR\x04S\tS\x04T\tT\x04U\tU\x04" + + "V\tV\x04W\tW\x04X\tX\x04Y\tY\x04Z\tZ\x04[\t[\x04\\\t\\\x04]\t]\x04^\t" + + "^\x04_\t_\x04`\t`\x04a\ta\x04b\tb\x04c\tc\x04d\td\x04e\te\x04f\tf\x04" + + "g\tg\x04h\th\x04i\ti\x04j\tj\x04k\tk\x04l\tl\x04m\tm\x04n\tn\x04o\to\x04" + + "p\tp\x04q\tq\x04r\tr\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" + + "\x03\x03\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x07\x03\x07\x03" + + "\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\b\x03\b\x03" + + "\b\x03\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\n\x03\n\x03" + + "\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03" + + "\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03\f\x03\f\x03" + + "\f\x03\f\x03\f\x03\f\x03\f\x03\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03\x0E" + + "\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F" + + "\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + + "\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11" + + "\x03\x11\x03\x11\x03\x12\x06\x12\u016A\n\x12\r\x12\x0E\x12\u016B\x03\x12" + + "\x03\x12\x03\x13\x03\x13\x03\x13\x03\x13\x07\x13\u0174\n\x13\f\x13\x0E" + + "\x13\u0177\v\x13\x03\x13\x05\x13\u017A\n\x13\x03\x13\x05\x13\u017D\n\x13" + + "\x03\x13\x03\x13\x03\x14\x03\x14\x03\x14\x03\x14\x03\x14\x07\x14\u0186" + + "\n\x14\f\x14\x0E\x14\u0189\v\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x14" + + "\x03\x15\x06\x15\u0191\n\x15\r\x15\x0E\x15\u0192\x03\x15\x03\x15\x03\x16" + + "\x03\x16\x03\x16\x03\x16\x03\x17\x03\x17\x03\x18\x03\x18\x03\x19\x03\x19" + + "\x03\x19\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x05\x1B\u01A6\n\x1B\x03\x1B\x06" + + "\x1B\u01A9\n\x1B\r\x1B\x0E\x1B\u01AA\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u01B0" + + "\n\x1C\f\x1C\x0E\x1C\u01B3\v\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C" + + "\x03\x1C\x07\x1C\u01BB\n\x1C\f\x1C\x0E\x1C\u01BE\v\x1C\x03\x1C\x03\x1C" + + "\x03\x1C\x03\x1C\x03\x1C\x05\x1C\u01C5\n\x1C\x03\x1C\x05\x1C\u01C8\n\x1C" + + "\x05\x1C\u01CA\n\x1C\x03\x1D\x06\x1D\u01CD\n\x1D\r\x1D\x0E\x1D\u01CE\x03" + + "\x1E\x06\x1E\u01D2\n\x1E\r\x1E\x0E\x1E\u01D3\x03\x1E\x03\x1E\x07\x1E\u01D8" + + "\n\x1E\f\x1E\x0E\x1E\u01DB\v\x1E\x03\x1E\x03\x1E\x06\x1E\u01DF\n\x1E\r" + + "\x1E\x0E\x1E\u01E0\x03\x1E\x06\x1E\u01E4\n\x1E\r\x1E\x0E\x1E\u01E5\x03" + + "\x1E\x03\x1E\x07\x1E\u01EA\n\x1E\f\x1E\x0E\x1E\u01ED\v\x1E\x05\x1E\u01EF" + + "\n\x1E\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x06\x1E\u01F5\n\x1E\r\x1E\x0E\x1E" + + "\u01F6\x03\x1E\x03\x1E\x05\x1E\u01FB\n\x1E\x03\x1F\x03\x1F\x03\x1F\x03" + + " \x03 \x03 \x03 \x03!\x03!\x03!\x03!\x03\"\x03\"\x03#\x03#\x03$\x03$\x03" + + "$\x03$\x03$\x03%\x03%\x03&\x03&\x03&\x03&\x03&\x03&\x03\'\x03\'\x03\'" + + "\x03\'\x03\'\x03\'\x03(\x03(\x03(\x03(\x03(\x03)\x03)\x03*\x03*\x03*\x03" + + "+\x03+\x03+\x03,\x03,\x03,\x03,\x03,\x03-\x03-\x03-\x03-\x03.\x03.\x03" + + ".\x03.\x03.\x03/\x03/\x03/\x03/\x03/\x03/\x030\x030\x030\x031\x031\x03" + + "2\x032\x032\x032\x032\x032\x033\x033\x034\x034\x034\x034\x034\x035\x03" + + "5\x035\x035\x035\x036\x036\x036\x036\x036\x036\x036\x036\x036\x036\x03" + + "7\x037\x038\x038\x038\x039\x039\x039\x03:\x03:\x03;\x03;\x03;\x03<\x03" + + "<\x03=\x03=\x03=\x03>\x03>\x03?\x03?\x03@\x03@\x03A\x03A\x03B\x03B\x03" + + "C\x03C\x03C\x03C\x03C\x03D\x03D\x03D\x03D\x03D\x03E\x03E\x03E\x03E\x07" + + "E\u028B\nE\fE\x0EE\u028E\vE\x03E\x03E\x03E\x03E\x06E\u0294\nE\rE\x0EE" + + "\u0295\x05E\u0298\nE\x03F\x03F\x03F\x03F\x07F\u029E\nF\fF\x0EF\u02A1\v" + + "F\x03F\x03F\x03G\x03G\x03G\x03G\x03H\x03H\x03H\x03H\x03I\x03I\x03I\x03" + + "I\x03J\x03J\x03J\x03J\x03J\x03K\x03K\x03K\x03K\x03K\x03K\x03L\x03L\x03" + + "L\x03L\x03L\x03L\x03M\x03M\x03M\x03M\x03N\x03N\x03N\x03N\x03O\x03O\x03" + + "O\x03P\x03P\x03P\x03P\x03P\x03P\x03P\x03P\x03P\x03Q\x03Q\x03Q\x03R\x03" + + "R\x03R\x03R\x03R\x03S\x06S\u02DF\nS\rS\x0ES\u02E0\x03T\x06T\u02E4\nT\r" + + "T\x0ET\u02E5\x03T\x03T\x05T\u02EA\nT\x03U\x03U\x03V\x03V\x03V\x03V\x03" + + "W\x03W\x03W\x03W\x03X\x03X\x03X\x03X\x03Y\x03Y\x03Z\x03Z\x03[\x03[\x03" + + "\\\x03\\\x03]\x03]\x03^\x03^\x03_\x03_\x03`\x03`\x03a\x03a\x03b\x03b\x03" + + "c\x03c\x03d\x03d\x03e\x03e\x03f\x03f\x03g\x03g\x03h\x03h\x03i\x03i\x03" + + "j\x03j\x03k\x03k\x03l\x03l\x03m\x03m\x03n\x03n\x03o\x03o\x03p\x03p\x03" + + "q\x03q\x03r\x03r\x04\u0187\u01BC\x02\x02s\x05\x02\x03\x07\x02\x04\t\x02" + + "\x05\v\x02\x06\r\x02\x07\x0F\x02\b\x11\x02\t\x13\x02\n\x15\x02\v\x17\x02" + + "\f\x19\x02\r\x1B\x02\x0E\x1D\x02\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02" + + "\x13\'\x02\x14)\x02\x15+\x02\x16-\x02\x17/\x02\x021\x02\x023\x02\x025" + + "\x02\x027\x02\x029\x02\x18;\x02\x19=\x02\x1A?\x02\x1BA\x02\x1CC\x02\x1D" + + "E\x02\x1EG\x02\x1FI\x02 K\x02!M\x02\"O\x02#Q\x02$S\x02%U\x02&W\x02\'Y" + + "\x02([\x02)]\x02*_\x02+a\x02,c\x02-e\x02.g\x02/i\x020k\x021m\x022o\x02" + + "3q\x024s\x025u\x026w\x027y\x028{\x029}\x02:\x7F\x02;\x81\x02<\x83\x02" + + "=\x85\x02>\x87\x02?\x89\x02@\x8B\x02A\x8D\x02B\x8F\x02C\x91\x02D\x93\x02" + + "E\x95\x02\x02\x97\x02\x02\x99\x02\x02\x9B\x02\x02\x9D\x02\x02\x9F\x02" + + "F\xA1\x02G\xA3\x02H\xA5\x02I\xA7\x02J\xA9\x02\x02\xAB\x02K\xAD\x02L\xAF" + + "\x02M\xB1\x02N\xB3\x02\x02\xB5\x02\x02\xB7\x02\x02\xB9\x02\x02\xBB\x02" + + "\x02\xBD\x02\x02\xBF\x02\x02\xC1\x02\x02\xC3\x02\x02\xC5\x02\x02\xC7\x02" + + "\x02\xC9\x02\x02\xCB\x02\x02\xCD\x02\x02\xCF\x02\x02\xD1\x02\x02\xD3\x02" + + "\x02\xD5\x02\x02\xD7\x02\x02\xD9\x02\x02\xDB\x02\x02\xDD\x02\x02\xDF\x02" + + "\x02\xE1\x02\x02\xE3\x02\x02\xE5\x02\x02\x05\x02\x03\x04(\b\x02\v\f\x0F" + + "\x0F\"\"11]]__\x04\x02\f\f\x0F\x0F\x05\x02\v\f\x0F\x0F\"\"\x03\x022;\x04" + + "\x02C\\c|\x07\x02$$^^ppttvv\x06\x02\f\f\x0F\x0F$$^^\x04\x02GGgg\x04\x02" + + "--//\x04\x02BBaa\x03\x02bb\f\x02\v\f\x0F\x0F\"\"..11??]]__bb~~\x04\x02" + + ",,11\x04\x02CCcc\x04\x02DDdd\x04\x02EEee\x04\x02FFff\x04\x02HHhh\x04\x02" + "IIii\x04\x02JJjj\x04\x02KKkk\x04\x02LLll\x04\x02MMmm\x04\x02NNnn\x04\x02" + "OOoo\x04\x02PPpp\x04\x02QQqq\x04\x02RRrr\x04\x02SSss\x04\x02TTtt\x04\x02" + "UUuu\x04\x02VVvv\x04\x02WWww\x04\x02XXxx\x04\x02YYyy\x04\x02ZZzz\x04\x02" + - "[[{{\x04\x02\\\\||\x02\u06A4\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02" + - "\x02\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02" + - "\x02\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x15\x03\x02\x02\x02" + - "\x02\x17\x03\x02\x02\x02\x02\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02" + - "\x02\x1D\x03\x02\x02\x02\x02\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02" + - "\x02#\x03\x02\x02\x02\x02%\x03\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)" + - "\x03\x02\x02\x02\x02+\x03\x02\x02\x02\x02-\x03\x02\x02\x02\x03/\x03\x02" + - "\x02\x02\x031\x03\x02\x02\x02\x033\x03\x02\x02\x02\x035\x03\x02\x02\x02" + - "\x037\x03\x02\x02\x02\x049\x03\x02\x02\x02\x04E\x03\x02\x02\x02\x04G\x03" + - "\x02\x02\x02\x04I\x03\x02\x02\x02\x04K\x03\x02\x02\x02\x04M\x03\x02\x02" + - "\x02\x04O\x03\x02\x02\x02\x04Q\x03\x02\x02\x02\x04S\x03\x02\x02\x02\x04" + - "U\x03\x02\x02\x02\x04W\x03\x02\x02\x02\x04Y\x03\x02\x02\x02\x04[\x03\x02" + - "\x02\x02\x04]\x03\x02\x02\x02\x04_\x03\x02\x02\x02\x04a\x03\x02\x02\x02" + - "\x04c\x03\x02\x02\x02\x04e\x03\x02\x02\x02\x04g\x03\x02\x02\x02\x04i\x03" + - "\x02\x02\x02\x04k\x03\x02\x02\x02\x04m\x03\x02\x02\x02\x04o\x03\x02\x02" + - "\x02\x04q\x03\x02\x02\x02\x04s\x03\x02\x02\x02\x04u\x03\x02\x02\x02\x04" + - "w\x03\x02\x02\x02\x04y\x03\x02\x02\x02\x04{\x03\x02\x02\x02\x04}\x03\x02" + - "\x02\x02\x04\x7F\x03\x02\x02\x02\x04\x81\x03\x02\x02\x02\x04\x83\x03\x02" + - "\x02\x02\x04\x85\x03\x02\x02\x02\x04\x87\x03\x02\x02\x02\x04\x89\x03\x02" + - "\x02\x02\x04\x8B\x03\x02\x02\x02\x04\x8D\x03\x02\x02\x02\x04\x8F\x03\x02" + - "\x02\x02\x04\x91\x03\x02\x02\x02\x04\x93\x03\x02\x02\x02\x04\x95\x03\x02" + - "\x02\x02\x04\x97\x03\x02\x02\x02\x04\x99\x03\x02\x02\x02\x05\x9B\x03\x02" + - "\x02\x02\x05\x9D\x03\x02\x02\x02\x05\x9F\x03\x02\x02\x02\x05\xA1\x03\x02" + - "\x02\x02\x05\xA3\x03\x02\x02\x02\x05\xA5\x03\x02\x02\x02\x05\xA7\x03\x02" + - "\x02\x02\x05\xAB\x03\x02\x02\x02\x05\xAD\x03\x02\x02\x02\x05\xAF\x03\x02" + - "\x02\x02\x05\xB1\x03\x02\x02\x02\x06\xB3\x03\x02\x02\x02\x06\xB5\x03\x02" + - "\x02\x02\x06\xB7\x03\x02\x02\x02\x06\xB9\x03\x02\x02\x02\x06\xBB\x03\x02" + - "\x02\x02\x06\xBD\x03\x02\x02\x02\x06\xBF\x03\x02\x02\x02\x06\xC3\x03\x02" + - "\x02\x02\x06\xC5\x03\x02\x02\x02\x06\xC7\x03\x02\x02\x02\x06\xC9\x03\x02" + - "\x02\x02\x07\xFF\x03\x02\x02\x02\t\u0109\x03\x02\x02\x02\v\u0110\x03\x02" + - "\x02\x02\r\u0117\x03\x02\x02\x02\x0F\u0121\x03\x02\x02\x02\x11\u0128\x03" + - "\x02\x02\x02\x13\u012E\x03\x02\x02\x02\x15\u0136\x03\x02\x02\x02\x17\u013E" + - "\x03\x02\x02\x02\x19\u0145\x03\x02\x02\x02\x1B\u0151\x03\x02\x02\x02\x1D" + - "\u0159\x03\x02\x02\x02\x1F\u0163\x03\x02\x02\x02!\u016A\x03\x02\x02\x02" + - "#\u0173\x03\x02\x02\x02%\u017A\x03\x02\x02\x02\'\u0183\x03\x02\x02\x02" + - ")\u018A\x03\x02\x02\x02+\u019B\x03\x02\x02\x02-\u01AB\x03\x02\x02\x02" + - "/\u01B1\x03\x02\x02\x021\u01B6\x03\x02\x02\x023\u01BB\x03\x02\x02\x02" + - "5\u01BF\x03\x02\x02\x027\u01C3\x03\x02\x02\x029\u01C7\x03\x02\x02\x02" + - ";\u01CB\x03\x02\x02\x02=\u01CD\x03\x02\x02\x02?\u01CF\x03\x02\x02\x02" + - "A\u01D2\x03\x02\x02\x02C\u01D4\x03\x02\x02\x02E\u01FA\x03\x02\x02\x02" + - "G\u01FD\x03\x02\x02\x02I\u022B\x03\x02\x02\x02K\u022D\x03\x02\x02\x02" + - "M\u028E\x03\x02\x02\x02O\u0290\x03\x02\x02\x02Q\u0294\x03\x02\x02\x02" + - "S\u0296\x03\x02\x02\x02U\u0298\x03\x02\x02\x02W\u029A\x03\x02\x02\x02" + - "Y\u029C\x03\x02\x02\x02[\u02A1\x03\x02\x02\x02]\u02A6\x03\x02\x02\x02" + - "_\u02AA\x03\x02\x02\x02a\u02AF\x03\x02\x02\x02c\u02B5\x03\x02\x02\x02" + - "e\u02B8\x03\x02\x02\x02g\u02BB\x03\x02\x02\x02i\u02BE\x03\x02\x02\x02" + - "k\u02C3\x03\x02\x02\x02m\u02C6\x03\x02\x02\x02o\u02C8\x03\x02\x02\x02" + - "q\u02CA\x03\x02\x02\x02s\u02CF\x03\x02\x02\x02u\u02E2\x03\x02\x02\x02" + - "w\u02EE\x03\x02\x02\x02y\u02F0\x03\x02\x02\x02{\u02F2\x03\x02\x02\x02" + - "}\u02F4\x03\x02\x02\x02\x7F\u02F6\x03\x02\x02\x02\x81\u02F8\x03\x02\x02" + - "\x02\x83\u02FA\x03\x02\x02\x02\x85\u0304\x03\x02\x02\x02\x87\u0306\x03" + - "\x02\x02\x02\x89\u0315\x03\x02\x02\x02\x8B\u04C5\x03\x02\x02\x02\x8D\u055E" + - "\x03\x02\x02\x02\x8F\u0560\x03\x02\x02\x02\x91\u057E\x03\x02\x02\x02\x93" + - "\u0580\x03\x02\x02\x02\x95\u058B\x03\x02\x02\x02\x97\u058F\x03\x02\x02" + - "\x02\x99\u0593\x03\x02\x02\x02\x9B\u0597\x03\x02\x02\x02\x9D\u059C\x03" + - "\x02\x02\x02\x9F\u05A2\x03\x02\x02\x02\xA1\u05A8\x03\x02\x02\x02\xA3\u05AC" + - "\x03\x02\x02\x02\xA5\u05B0\x03\x02\x02\x02\xA7\u05BA\x03\x02\x02\x02\xA9" + - "\u05C5\x03\x02\x02\x02\xAB\u05C7\x03\x02\x02\x02\xAD\u05C9\x03\x02\x02" + - "\x02\xAF\u05CD\x03\x02\x02\x02\xB1\u05D1\x03\x02\x02\x02\xB3\u05D5\x03" + - "\x02\x02\x02\xB5\u05D8\x03\x02\x02\x02\xB7\u05DD\x03\x02\x02\x02\xB9\u05E2" + - "\x03\x02\x02\x02\xBB\u05E8\x03\x02\x02\x02\xBD\u05EC\x03\x02\x02\x02\xBF" + - "\u05F1\x03"; + "[[{{\x04\x02\\\\||\x02\u0330\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02" + + "\x02\x02\t\x03\x02\x02\x02\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02" + + "\x02\x0F\x03\x02\x02\x02\x02\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02" + + "\x02\x15\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02\x19\x03\x02\x02\x02" + + "\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02\x1F\x03\x02\x02\x02" + + "\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03\x02\x02\x02\x02\'" + + "\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02\x02\x03-\x03\x02" + + "\x02\x02\x039\x03\x02\x02\x02\x03;\x03\x02\x02\x02\x03=\x03\x02\x02\x02" + + "\x03?\x03\x02\x02\x02\x03A\x03\x02\x02\x02\x03C\x03\x02\x02\x02\x03E\x03" + + "\x02\x02\x02\x03G\x03\x02\x02\x02\x03I\x03\x02\x02\x02\x03K\x03\x02\x02" + + "\x02\x03M\x03\x02\x02\x02\x03O\x03\x02\x02\x02\x03Q\x03\x02\x02\x02\x03" + + "S\x03\x02\x02\x02\x03U\x03\x02\x02\x02\x03W\x03\x02\x02\x02\x03Y\x03\x02" + + "\x02\x02\x03[\x03\x02\x02\x02\x03]\x03\x02\x02\x02\x03_\x03\x02\x02\x02" + + "\x03a\x03\x02\x02\x02\x03c\x03\x02\x02\x02\x03e\x03\x02\x02\x02\x03g\x03" + + "\x02\x02\x02\x03i\x03\x02\x02\x02\x03k\x03\x02\x02\x02\x03m\x03\x02\x02" + + "\x02\x03o\x03\x02\x02\x02\x03q\x03\x02\x02\x02\x03s\x03\x02\x02\x02\x03" + + "u\x03\x02\x02\x02\x03w\x03\x02\x02\x02\x03y\x03\x02\x02\x02\x03{\x03\x02" + + "\x02\x02\x03}\x03\x02\x02\x02\x03\x7F\x03\x02\x02\x02\x03\x81\x03\x02" + + "\x02\x02\x03\x83\x03\x02\x02\x02\x03\x85\x03\x02\x02\x02\x03\x87\x03\x02" + + "\x02\x02\x03\x89\x03\x02\x02\x02\x03\x8B\x03\x02\x02\x02\x03\x8D\x03\x02" + + "\x02\x02\x03\x8F\x03\x02\x02\x02\x03\x91\x03\x02\x02\x02\x03\x93\x03\x02" + + "\x02\x02\x04\x95\x03\x02\x02\x02\x04\x97\x03\x02\x02\x02\x04\x99\x03\x02" + + "\x02\x02\x04\x9B\x03\x02\x02\x02\x04\x9D\x03\x02\x02\x02\x04\x9F\x03\x02" + + "\x02\x02\x04\xA1\x03\x02\x02\x02\x04\xA3\x03\x02\x02\x02\x04\xA5\x03\x02" + + "\x02\x02\x04\xA7\x03\x02\x02\x02\x04\xAB\x03\x02\x02\x02\x04\xAD\x03\x02" + + "\x02\x02\x04\xAF\x03\x02\x02\x02\x04\xB1\x03\x02\x02\x02\x05\xE7\x03\x02" + + "\x02\x02\x07\xF1\x03\x02\x02\x02\t\xF8\x03\x02\x02\x02\v\u0101\x03\x02" + + "\x02\x02\r\u0108\x03\x02\x02\x02\x0F\u010F\x03\x02\x02\x02\x11\u0116\x03" + + "\x02\x02\x02\x13\u011D\x03\x02\x02\x02\x15\u0125\x03\x02\x02\x02\x17\u0131" + + "\x03\x02\x02\x02\x19\u013B\x03\x02\x02\x02\x1B\u0144\x03\x02\x02\x02\x1D" + + "\u014A\x03\x02\x02\x02\x1F\u0151\x03\x02\x02\x02!\u0158\x03\x02\x02\x02" + + "#\u0160\x03\x02\x02\x02%\u0169\x03\x02\x02\x02\'\u016F\x03\x02\x02\x02" + + ")\u0180\x03\x02\x02\x02+\u0190\x03\x02\x02\x02-\u0196\x03\x02\x02\x02" + + "/\u019A\x03\x02\x02\x021\u019C\x03\x02\x02\x023\u019E\x03\x02\x02\x02" + + "5\u01A1\x03\x02\x02\x027\u01A3\x03\x02\x02\x029\u01C9\x03\x02\x02\x02" + + ";\u01CC\x03\x02\x02\x02=\u01FA\x03\x02\x02\x02?\u01FC\x03\x02\x02\x02" + + "A\u01FF\x03\x02\x02\x02C\u0203\x03\x02\x02\x02E\u0207\x03\x02\x02\x02" + + "G\u0209\x03\x02\x02\x02I\u020B\x03\x02\x02\x02K\u0210\x03\x02\x02\x02" + + "M\u0212\x03\x02\x02\x02O\u0218\x03\x02\x02\x02Q\u021E\x03\x02\x02\x02" + + "S\u0223\x03\x02\x02\x02U\u0225\x03\x02\x02\x02W\u0228\x03\x02\x02\x02" + + "Y\u022B\x03\x02\x02\x02[\u0230\x03\x02\x02\x02]\u0234\x03\x02\x02\x02" + + "_\u0239\x03\x02\x02\x02a\u023F\x03\x02\x02\x02c\u0242\x03\x02\x02\x02" + + "e\u0244\x03\x02\x02\x02g\u024A\x03\x02\x02\x02i\u024C\x03\x02\x02\x02" + + "k\u0251\x03\x02\x02\x02m\u0256\x03\x02\x02\x02o\u0260\x03\x02\x02\x02" + + "q\u0262\x03\x02\x02\x02s\u0265\x03\x02\x02\x02u\u0268\x03\x02\x02\x02" + + "w\u026A\x03\x02\x02\x02y\u026D\x03\x02\x02\x02{\u026F\x03\x02\x02\x02" + + "}\u0272\x03\x02\x02\x02\x7F\u0274\x03\x02\x02\x02\x81\u0276\x03\x02\x02" + + "\x02\x83\u0278\x03\x02\x02\x02\x85\u027A\x03\x02\x02\x02\x87\u027C\x03" + + "\x02\x02\x02\x89\u0281\x03\x02\x02\x02\x8B\u0297\x03\x02\x02\x02\x8D\u0299" + + "\x03\x02\x02\x02\x8F\u02A4\x03\x02\x02\x02\x91\u02A8\x03\x02\x02\x02\x93" + + "\u02AC\x03\x02\x02\x02\x95\u02B0\x03\x02\x02\x02\x97\u02B5\x03\x02\x02" + + "\x02\x99\u02BB\x03\x02\x02\x02\x9B\u02C1\x03\x02\x02\x02\x9D\u02C5\x03" + + "\x02\x02\x02\x9F\u02C9\x03\x02\x02\x02\xA1\u02CC\x03\x02\x02\x02\xA3\u02D5" + + "\x03\x02\x02\x02\xA5\u02D8\x03\x02\x02\x02\xA7\u02DE\x03\x02\x02\x02\xA9" + + "\u02E9\x03\x02\x02\x02\xAB\u02EB\x03\x02\x02\x02\xAD\u02ED\x03\x02\x02" + + "\x02\xAF\u02F1\x03\x02\x02\x02\xB1\u02F5\x03\x02\x02\x02\xB3\u02F9\x03" + + "\x02\x02\x02\xB5\u02FB\x03\x02\x02\x02\xB7\u02FD\x03\x02\x02\x02\xB9\u02FF" + + "\x03\x02\x02\x02\xBB\u0301\x03\x02\x02\x02\xBD\u0303\x03\x02\x02\x02\xBF" + + "\u0305\x03\x02\x02\x02\xC1\u0307\x03\x02\x02\x02\xC3\u0309\x03\x02\x02" + + "\x02\xC5\u030B\x03\x02\x02\x02\xC7\u030D\x03\x02\x02\x02\xC9\u030F\x03" + + "\x02\x02\x02\xCB\u0311\x03\x02\x02\x02\xCD\u0313\x03\x02\x02\x02\xCF\u0315" + + "\x03\x02\x02\x02\xD1\u0317\x03\x02\x02\x02\xD3\u0319\x03\x02\x02\x02\xD5" + + "\u031B\x03\x02\x02\x02\xD7\u031D\x03\x02\x02\x02\xD9\u031F\x03\x02\x02" + + "\x02\xDB\u0321\x03\x02\x02\x02\xDD\u0323\x03\x02\x02\x02\xDF\u0325\x03" + + "\x02\x02\x02\xE1\u0327\x03\x02\x02\x02\xE3\u0329\x03\x02\x02\x02\xE5\u032B" + + "\x03\x02\x02\x02\xE7\xE8\x05\xB9\\\x02\xE8\xE9\x05\xC3a\x02\xE9\xEA\x05" + + "\xD7k\x02\xEA\xEB\x05\xD7k\x02\xEB\xEC\x05\xBB]\x02\xEC\xED\x05\xB7[\x02" + + "\xED\xEE\x05\xD9l\x02\xEE\xEF\x03\x02\x02\x02\xEF\xF0\b\x02\x02\x02\xF0" + + "\x06\x03\x02\x02\x02\xF1\xF2\x05\xB9\\\x02\xF2\xF3\x05\xD5j\x02\xF3\xF4" + + "\x05\xCFg\x02\xF4\xF5\x05\xD1h\x02\xF5\xF6\x03\x02\x02\x02\xF6\xF7\b\x03" + + "\x03\x02\xF7\b\x03\x02\x02\x02\xF8\xF9\x05\xBB]\x02\xF9\xFA\x05\xCDf\x02" + + "\xFA\xFB\x05\xD5j\x02\xFB\xFC\x05\xC3a\x02\xFC\xFD\x05\xB7[\x02\xFD\xFE" + + "\x05\xC1`\x02\xFE\xFF\x03\x02\x02\x02\xFF\u0100\b\x04\x03\x02\u0100\n" + + "\x03\x02\x02\x02\u0101\u0102\x05\xBB]\x02\u0102\u0103\x05\xDDn\x02\u0103" + + "\u0104\x05\xB3Y\x02\u0104\u0105\x05\xC9d\x02\u0105\u0106\x03\x02\x02\x02" + + "\u0106\u0107\b\x05\x02\x02\u0107\f\x03\x02\x02\x02\u0108\u0109\x05\xBD" + + "^\x02\u0109\u010A\x05\xD5j\x02\u010A\u010B\x05\xCFg\x02\u010B\u010C\x05" + + "\xCBe\x02\u010C\u010D\x03\x02\x02\x02\u010D\u010E\b\x06\x03\x02\u010E" + + "\x0E\x03\x02\x02\x02\u010F\u0110\x05\xBF_\x02\u0110\u0111\x05\xD5j\x02" + + "\u0111\u0112\x05\xCFg\x02\u0112\u0113\x05\xC7c\x02\u0113\u0114\x03\x02" + + "\x02\x02\u0114\u0115\b\x07\x02\x02\u0115\x10\x03\x02\x02\x02\u0116\u0117" + + "\x05\xC7c\x02\u0117\u0118\x05\xBB]\x02\u0118\u0119\x05\xBB]\x02\u0119" + + "\u011A\x05\xD1h\x02\u011A\u011B\x03\x02\x02\x02\u011B\u011C\b\b\x03\x02" + + "\u011C\x12\x03\x02\x02\x02\u011D\u011E\x05\xC9d\x02\u011E\u011F\x05\xC3" + + "a\x02\u011F\u0120\x05\xCBe\x02\u0120\u0121\x05\xC3a\x02\u0121\u0122\x05" + + "\xD9l\x02\u0122\u0123\x03\x02\x02\x02\u0123\u0124\b\t\x02\x02\u0124\x14" + + "\x03\x02\x02\x02\u0125\u0126\x05\xCBe\x02\u0126\u0127\x05\xDDn\x02\u0127" + + "\u0128\x05o7\x02\u0128\u0129\x05\xBB]\x02\u0129\u012A\x05\xE1p\x02\u012A" + + "\u012B\x05\xD1h\x02\u012B\u012C\x05\xB3Y\x02\u012C\u012D\x05\xCDf\x02" + + "\u012D\u012E\x05\xB9\\\x02\u012E\u012F\x03\x02\x02\x02\u012F\u0130\b\n" + + "\x03\x02\u0130\x16\x03\x02\x02\x02\u0131\u0132\x05\xD1h\x02\u0132\u0133" + + "\x05\xD5j\x02\u0133\u0134\x05\xCFg\x02\u0134\u0135\x05\xC5b\x02\u0135" + + "\u0136\x05\xBB]\x02\u0136\u0137\x05\xB7[\x02\u0137\u0138\x05\xD9l\x02" + + "\u0138\u0139\x03\x02\x02\x02\u0139\u013A\b\v\x03\x02\u013A\x18\x03\x02" + + "\x02\x02\u013B\u013C\x05\xD5j\x02\u013C\u013D\x05\xBB]\x02\u013D\u013E" + + "\x05\xCDf\x02\u013E\u013F\x05\xB3Y\x02\u013F\u0140\x05\xCBe\x02\u0140" + + "\u0141\x05\xBB]\x02\u0141\u0142\x03\x02\x02\x02\u0142\u0143\b\f\x03\x02" + + "\u0143\x1A\x03\x02\x02\x02\u0144\u0145\x05\xD5j\x02\u0145\u0146\x05\xCF" + + "g\x02\u0146\u0147\x05\xDFo\x02\u0147\u0148\x03\x02\x02\x02\u0148\u0149" + + "\b\r\x02\x02\u0149\x1C\x03\x02\x02\x02\u014A\u014B\x05\xD7k\x02\u014B" + + "\u014C\x05\xC1`\x02\u014C\u014D\x05\xCFg\x02\u014D\u014E\x05\xDFo\x02" + + "\u014E\u014F\x03\x02\x02\x02\u014F\u0150\b\x0E\x02\x02\u0150\x1E\x03\x02" + + "\x02\x02\u0151\u0152\x05\xD7k\x02\u0152\u0153\x05\xCFg\x02\u0153\u0154" + + "\x05\xD5j\x02\u0154\u0155\x05\xD9l\x02\u0155\u0156\x03\x02\x02\x02\u0156" + + "\u0157\b\x0F\x02\x02\u0157 \x03\x02\x02\x02\u0158\u0159\x05\xD7k\x02\u0159" + + "\u015A\x05\xD9l\x02\u015A\u015B\x05\xB3Y\x02\u015B\u015C\x05\xD9l\x02" + + "\u015C\u015D\x05\xD7k\x02\u015D\u015E\x03\x02\x02\x02\u015E\u015F\b\x10" + + "\x02\x02\u015F\"\x03\x02\x02\x02\u0160\u0161\x05\xDFo\x02\u0161\u0162" + + "\x05\xC1`\x02\u0162\u0163\x05\xBB]\x02\u0163\u0164\x05\xD5j\x02\u0164" + + "\u0165\x05\xBB]\x02\u0165\u0166\x03\x02\x02\x02\u0166\u0167\b\x11\x02" + + "\x02\u0167$\x03\x02\x02\x02\u0168\u016A\n\x02\x02\x02\u0169\u0168\x03" + + "\x02\x02\x02\u016A\u016B\x03\x02\x02\x02\u016B\u0169\x03\x02\x02\x02\u016B" + + "\u016C\x03\x02\x02\x02\u016C\u016D\x03\x02\x02\x02\u016D\u016E\b\x12\x02" + + "\x02\u016E&\x03\x02\x02\x02\u016F\u0170\x071\x02\x02\u0170\u0171\x071" + + "\x02\x02\u0171\u0175\x03\x02\x02\x02\u0172\u0174\n\x03\x02\x02\u0173\u0172" + + "\x03\x02\x02\x02\u0174\u0177\x03\x02\x02\x02\u0175\u0173\x03\x02\x02\x02" + + "\u0175\u0176\x03\x02\x02\x02\u0176\u0179\x03\x02\x02\x02\u0177\u0175\x03" + + "\x02\x02\x02\u0178\u017A\x07\x0F\x02\x02\u0179\u0178\x03\x02\x02\x02\u0179" + + "\u017A\x03\x02\x02\x02\u017A\u017C\x03\x02\x02\x02\u017B\u017D\x07\f\x02" + + "\x02\u017C\u017B\x03\x02\x02\x02\u017C\u017D\x03\x02\x02\x02\u017D\u017E" + + "\x03\x02\x02\x02\u017E\u017F\b\x13\x04\x02\u017F(\x03\x02\x02\x02\u0180" + + "\u0181\x071\x02\x02\u0181\u0182\x07,\x02\x02\u0182\u0187\x03\x02\x02\x02" + + "\u0183\u0186\x05)\x14\x02\u0184\u0186\v\x02\x02\x02\u0185\u0183\x03\x02" + + "\x02\x02\u0185\u0184\x03\x02\x02\x02\u0186\u0189\x03\x02\x02\x02\u0187" + + "\u0188\x03\x02\x02\x02\u0187\u0185\x03\x02\x02\x02\u0188\u018A\x03\x02" + + "\x02\x02\u0189\u0187\x03\x02\x02\x02\u018A\u018B\x07,\x02\x02\u018B\u018C" + + "\x071\x02\x02\u018C\u018D\x03\x02\x02\x02\u018D\u018E\b\x14\x04\x02\u018E" + + "*\x03\x02\x02\x02\u018F\u0191\t\x04\x02\x02\u0190\u018F\x03\x02\x02\x02" + + "\u0191\u0192\x03\x02\x02\x02\u0192\u0190\x03\x02\x02\x02\u0192\u0193\x03" + + "\x02\x02\x02\u0193\u0194\x03\x02\x02\x02\u0194\u0195\b\x15\x04\x02\u0195" + + ",\x03\x02\x02\x02\u0196\u0197\x07~\x02\x02\u0197\u0198\x03\x02\x02\x02" + + "\u0198\u0199\b\x16\x05\x02\u0199.\x03\x02\x02\x02\u019A\u019B\t\x05\x02" + + "\x02\u019B0\x03\x02\x02\x02\u019C\u019D\t\x06\x02\x02\u019D2\x03\x02\x02" + + "\x02\u019E\u019F\x07^\x02\x02\u019F\u01A0\t\x07\x02\x02\u01A04\x03\x02" + + "\x02\x02\u01A1\u01A2\n\b\x02\x02\u01A26\x03\x02\x02\x02\u01A3\u01A5\t" + + "\t\x02\x02\u01A4\u01A6\t\n\x02\x02\u01A5\u01A4\x03\x02\x02\x02\u01A5\u01A6" + + "\x03\x02\x02\x02\u01A6\u01A8\x03\x02\x02\x02\u01A7\u01A9\x05/\x17\x02" + + "\u01A8\u01A7\x03\x02\x02\x02\u01A9\u01AA\x03\x02\x02\x02\u01AA\u01A8\x03" + + "\x02\x02\x02\u01AA\u01AB\x03\x02\x02\x02\u01AB8\x03\x02\x02\x02\u01AC" + + "\u01B1\x07$\x02\x02\u01AD\u01B0\x053\x19\x02\u01AE\u01B0\x055\x1A\x02" + + "\u01AF\u01AD\x03\x02\x02\x02\u01AF\u01AE\x03\x02\x02\x02\u01B0\u01B3\x03" + + "\x02\x02\x02\u01B1\u01AF\x03\x02\x02\x02\u01B1\u01B2\x03\x02\x02\x02\u01B2" + + "\u01B4\x03\x02\x02\x02\u01B3\u01B1\x03\x02\x02\x02\u01B4\u01CA\x07$\x02" + + "\x02\u01B5\u01B6\x07$\x02\x02\u01B6\u01B7\x07$\x02\x02\u01B7\u01B8\x07" + + "$\x02\x02\u01B8\u01BC\x03\x02\x02\x02\u01B9\u01BB\n\x03\x02\x02\u01BA" + + "\u01B9\x03\x02\x02\x02\u01BB\u01BE\x03\x02\x02\x02\u01BC\u01BD\x03\x02" + + "\x02\x02\u01BC\u01BA\x03\x02\x02\x02\u01BD\u01BF\x03\x02\x02\x02\u01BE" + + "\u01BC\x03\x02\x02\x02\u01BF\u01C0\x07$\x02\x02\u01C0\u01C1\x07$\x02\x02" + + "\u01C1\u01C2\x07$\x02\x02\u01C2\u01C4\x03\x02\x02\x02\u01C3\u01C5\x07" + + "$\x02\x02\u01C4\u01C3\x03\x02\x02\x02\u01C4\u01C5\x03\x02\x02\x02\u01C5" + + "\u01C7\x03\x02\x02\x02\u01C6\u01C8\x07$\x02\x02\u01C7\u01C6\x03\x02\x02" + + "\x02\u01C7\u01C8\x03\x02\x02\x02\u01C8\u01CA\x03\x02\x02\x02\u01C9\u01AC" + + "\x03\x02\x02\x02\u01C9\u01B5\x03\x02\x02\x02\u01CA:\x03\x02\x02\x02\u01CB" + + "\u01CD\x05/\x17\x02\u01CC\u01CB\x03\x02\x02\x02\u01CD\u01CE\x03\x02\x02" + + "\x02\u01CE\u01CC\x03\x02\x02\x02\u01CE\u01CF\x03\x02\x02\x02\u01CF<\x03" + + "\x02\x02\x02\u01D0\u01D2\x05/\x17\x02\u01D1\u01D0\x03\x02\x02\x02\u01D2" + + "\u01D3\x03\x02\x02\x02\u01D3\u01D1\x03\x02\x02\x02\u01D3\u01D4\x03\x02" + + "\x02\x02\u01D4\u01D5\x03\x02\x02\x02\u01D5\u01D9\x05K%\x02\u01D6\u01D8" + + "\x05/\x17\x02"; private static readonly _serializedATNSegment1: string = - "\x02\x02\x02\xC1\u05FC\x03\x02\x02\x02\xC3\u05FE\x03\x02\x02\x02\xC5\u0600" + - "\x03\x02\x02\x02\xC7\u0604\x03\x02\x02\x02\xC9\u0608\x03\x02\x02\x02\xCB" + - "\u060C\x03\x02\x02\x02\xCD\u060E\x03\x02\x02\x02\xCF\u0610\x03\x02\x02" + - "\x02\xD1\u0612\x03\x02\x02\x02\xD3\u0614\x03\x02\x02\x02\xD5\u0616\x03" + - "\x02\x02\x02\xD7\u0618\x03\x02\x02\x02\xD9\u061A\x03\x02\x02\x02\xDB\u061C" + - "\x03\x02\x02\x02\xDD\u061E\x03\x02\x02\x02\xDF\u0620\x03\x02\x02\x02\xE1" + - "\u0622\x03\x02\x02\x02\xE3\u0624\x03\x02\x02\x02\xE5\u0626\x03\x02\x02" + - "\x02\xE7\u0628\x03\x02\x02\x02\xE9\u062A\x03\x02\x02\x02\xEB\u062C\x03" + - "\x02\x02\x02\xED\u062E\x03\x02\x02\x02\xEF\u0630\x03\x02\x02\x02\xF1\u0632" + - "\x03\x02\x02\x02\xF3\u0634\x03\x02\x02\x02\xF5\u0636\x03\x02\x02\x02\xF7" + - "\u0638\x03\x02\x02\x02\xF9\u063A\x03\x02\x02\x02\xFB\u063C\x03\x02\x02" + - "\x02\xFD\u063E\x03\x02\x02\x02\xFF\u0100\x05\xD1g\x02\u0100\u0101\x05" + - "\xDBl\x02\u0101\u0102\x05\xEFv\x02\u0102\u0103\x05\xEFv\x02\u0103\u0104" + - "\x05\xD3h\x02\u0104\u0105\x05\xCFf\x02\u0105\u0106\x05\xF1w\x02\u0106" + - "\u0107\x03\x02\x02\x02\u0107\u0108\b\x02\x02\x02\u0108\b\x03\x02\x02\x02" + - "\u0109\u010A\x05\xD7j\x02\u010A\u010B\x05\xEDu\x02\u010B\u010C\x05\xE7" + - "r\x02\u010C\u010D\x05\xDFn\x02\u010D\u010E\x03\x02\x02\x02\u010E\u010F" + - "\b\x03\x02\x02\u010F\n\x03\x02\x02\x02\u0110\u0111\x05\xD3h\x02\u0111" + - "\u0112\x05\xF5y\x02\u0112\u0113\x05\xCBd\x02\u0113\u0114\x05\xE1o\x02" + - "\u0114\u0115\x03\x02\x02\x02\u0115\u0116\b\x04\x02\x02\u0116\f\x03\x02" + - "\x02\x02\u0117\u0118\x05\xD3h\x02\u0118\u0119\x05\xF9{\x02\u0119\u011A" + - "\x05\xE9s\x02\u011A\u011B\x05\xE1o\x02\u011B\u011C\x05\xCBd\x02\u011C" + - "\u011D\x05\xDBl\x02\u011D\u011E\x05\xE5q\x02\u011E\u011F\x03\x02\x02\x02" + - "\u011F\u0120\b\x05\x03\x02\u0120\x0E\x03\x02\x02\x02\u0121\u0122\x05\xD5" + - "i\x02\u0122\u0123\x05\xEDu\x02\u0123\u0124\x05\xE7r\x02\u0124\u0125\x05" + - "\xE3p\x02\u0125\u0126\x03\x02\x02\x02\u0126\u0127\b\x06\x04\x02\u0127" + - "\x10\x03\x02\x02\x02\u0128\u0129\x05\xEDu\x02\u0129\u012A\x05\xE7r\x02" + - "\u012A\u012B\x05\xF7z\x02\u012B\u012C\x03\x02\x02\x02\u012C\u012D\b\x07" + - "\x02\x02\u012D\x12\x03\x02\x02\x02\u012E\u012F\x05\xEFv\x02\u012F\u0130" + - "\x05\xF1w\x02\u0130\u0131\x05\xCBd\x02\u0131\u0132\x05\xF1w\x02\u0132" + - "\u0133\x05\xEFv\x02\u0133\u0134\x03\x02\x02\x02\u0134\u0135\b\b\x02\x02" + - "\u0135\x14\x03\x02\x02\x02\u0136\u0137\x05\xF7z\x02\u0137\u0138\x05\xD9" + - "k\x02\u0138\u0139\x05\xD3h\x02\u0139\u013A\x05\xEDu\x02\u013A\u013B\x05" + - "\xD3h\x02\u013B\u013C\x03\x02\x02\x02\u013C\u013D\b\t\x02\x02\u013D\x16" + - "\x03\x02\x02\x02\u013E\u013F\x05\xEFv\x02\u013F\u0140\x05\xE7r\x02\u0140" + - "\u0141\x05\xEDu\x02\u0141\u0142\x05\xF1w\x02\u0142\u0143\x03\x02\x02\x02" + - "\u0143\u0144\b\n\x02\x02\u0144\x18\x03\x02\x02\x02\u0145\u0146\x05\xE3" + - "p\x02\u0146\u0147\x05\xF5y\x02\u0147\u0148\x05o6\x02\u0148\u0149\x05\xD3" + - "h\x02\u0149\u014A\x05\xF9{\x02\u014A\u014B\x05\xE9s\x02\u014B\u014C\x05" + - "\xCBd\x02\u014C\u014D\x05\xE5q\x02\u014D\u014E\x05\xD1g\x02\u014E\u014F" + - "\x03\x02\x02\x02\u014F\u0150\b\v\x02\x02\u0150\x1A\x03\x02\x02\x02\u0151" + - "\u0152\x05\xE1o\x02\u0152\u0153\x05\xDBl\x02\u0153\u0154\x05\xE3p\x02" + - "\u0154\u0155\x05\xDBl\x02\u0155\u0156\x05\xF1w\x02\u0156\u0157\x03\x02" + - "\x02\x02\u0157\u0158\b\f\x02\x02\u0158\x1C\x03\x02\x02\x02\u0159\u015A" + - "\x05\xE9s\x02\u015A\u015B\x05\xEDu\x02\u015B\u015C\x05\xE7r\x02\u015C" + - "\u015D\x05\xDDm\x02\u015D\u015E\x05\xD3h\x02\u015E\u015F\x05\xCFf\x02" + - "\u015F\u0160\x05\xF1w\x02\u0160\u0161\x03\x02\x02\x02\u0161\u0162\b\r" + - "\x02\x02\u0162\x1E\x03\x02\x02\x02\u0163\u0164\x05\xD1g\x02\u0164\u0165" + - "\x05\xEDu\x02\u0165\u0166\x05\xE7r\x02\u0166\u0167\x05\xE9s\x02\u0167" + - "\u0168\x03\x02\x02\x02\u0168\u0169\b\x0E\x02\x02\u0169 \x03\x02\x02\x02" + - "\u016A\u016B\x05\xEDu\x02\u016B\u016C\x05\xD3h\x02\u016C\u016D\x05\xE5" + - "q\x02\u016D\u016E\x05\xCBd\x02\u016E\u016F\x05\xE3p\x02\u016F\u0170\x05" + - "\xD3h\x02\u0170\u0171\x03\x02\x02\x02\u0171\u0172\b\x0F\x02\x02\u0172" + - "\"\x03\x02\x02\x02\u0173\u0174\x05\xEFv\x02\u0174\u0175\x05\xD9k\x02\u0175" + - "\u0176\x05\xE7r\x02\u0176\u0177\x05\xF7z\x02\u0177\u0178\x03\x02\x02\x02" + - "\u0178\u0179\b\x10\x02\x02\u0179$\x03\x02\x02\x02\u017A\u017B\x05\xD3" + - "h\x02\u017B\u017C\x05\xE5q\x02\u017C\u017D\x05\xEDu\x02\u017D\u017E\x05" + - "\xDBl\x02\u017E\u017F\x05\xCFf\x02\u017F\u0180\x05\xD9k\x02\u0180\u0181" + - "\x03\x02\x02\x02\u0181\u0182\b\x11\x05\x02\u0182&\x03\x02\x02\x02\u0183" + - "\u0184\x05\xDFn\x02\u0184\u0185\x05\xD3h\x02\u0185\u0186\x05\xD3h\x02" + - "\u0186\u0187\x05\xE9s\x02\u0187\u0188\x03\x02\x02\x02\u0188\u0189\b\x12" + - "\x02\x02\u0189(\x03\x02\x02\x02\u018A\u018B\x071\x02\x02\u018B\u018C\x07" + - "1\x02\x02\u018C\u0190\x03\x02\x02\x02\u018D\u018F\n\x02\x02\x02\u018E" + - "\u018D\x03\x02\x02\x02\u018F\u0192\x03\x02\x02\x02\u0190\u018E\x03\x02" + - "\x02\x02\u0190\u0191\x03\x02\x02\x02\u0191\u0194\x03\x02\x02\x02\u0192" + - "\u0190\x03\x02\x02\x02\u0193\u0195\x07\x0F\x02\x02\u0194\u0193\x03\x02" + - "\x02\x02\u0194\u0195\x03\x02\x02\x02\u0195\u0197\x03\x02\x02\x02\u0196" + - "\u0198\x07\f\x02\x02\u0197\u0196\x03\x02\x02\x02\u0197\u0198\x03\x02\x02" + - "\x02\u0198\u0199\x03\x02\x02\x02\u0199\u019A\b\x13\x06\x02\u019A*\x03" + - "\x02\x02\x02\u019B\u019C\x071\x02\x02\u019C\u019D\x07,\x02\x02\u019D\u01A2" + - "\x03\x02\x02\x02\u019E\u01A1\x05+\x14\x02\u019F\u01A1\v\x02\x02\x02\u01A0" + - "\u019E\x03\x02\x02\x02\u01A0\u019F\x03\x02\x02\x02\u01A1\u01A4\x03\x02" + - "\x02\x02\u01A2\u01A3\x03\x02\x02\x02\u01A2\u01A0\x03\x02\x02\x02\u01A3" + - "\u01A5\x03\x02\x02\x02\u01A4\u01A2\x03\x02\x02\x02\u01A5\u01A6\x07,\x02" + - "\x02\u01A6\u01A7\x071\x02\x02\u01A7\u01A8\x03\x02\x02\x02\u01A8\u01A9" + - "\b\x14\x06\x02\u01A9,\x03\x02\x02\x02\u01AA\u01AC\t\x03\x02\x02\u01AB" + - "\u01AA\x03\x02\x02\x02\u01AC\u01AD\x03\x02\x02\x02\u01AD\u01AB\x03\x02" + - "\x02\x02\u01AD\u01AE\x03\x02\x02\x02\u01AE\u01AF\x03\x02\x02\x02\u01AF" + - "\u01B0\b\x15\x06\x02\u01B0.\x03\x02\x02\x02\u01B1\u01B2\x07]\x02\x02\u01B2" + - "\u01B3\x03\x02\x02\x02\u01B3\u01B4\b\x16\x07\x02\u01B4\u01B5\b\x16\b\x02" + - "\u01B50\x03\x02\x02\x02\u01B6\u01B7\x07~\x02\x02\u01B7\u01B8\x03\x02\x02" + - "\x02\u01B8\u01B9\b\x17\t\x02\u01B9\u01BA\b\x17\n\x02\u01BA2\x03\x02\x02" + - "\x02\u01BB\u01BC\x05-\x15\x02\u01BC\u01BD\x03\x02\x02\x02\u01BD\u01BE" + - "\b\x18\x06\x02\u01BE4\x03\x02\x02\x02\u01BF\u01C0\x05)\x13\x02\u01C0\u01C1" + - "\x03\x02\x02\x02\u01C1\u01C2\b\x19\x06\x02\u01C26\x03\x02\x02\x02\u01C3" + - "\u01C4\x05+\x14\x02\u01C4\u01C5\x03\x02\x02\x02\u01C5\u01C6\b\x1A\x06" + - "\x02\u01C68\x03\x02\x02\x02\u01C7\u01C8\x07~\x02\x02\u01C8\u01C9\x03\x02" + - "\x02\x02\u01C9\u01CA\b\x1B\n\x02\u01CA:\x03\x02\x02\x02\u01CB\u01CC\t" + - "\x04\x02\x02\u01CC<\x03\x02\x02\x02\u01CD\u01CE\t\x05\x02\x02\u01CE>\x03" + - "\x02\x02\x02\u01CF\u01D0\x07^\x02\x02\u01D0\u01D1\t\x06\x02\x02\u01D1" + - "@\x03\x02\x02\x02\u01D2\u01D3\n\x07\x02\x02\u01D3B\x03\x02\x02\x02\u01D4" + - "\u01D6\t\b\x02\x02\u01D5\u01D7\t\t\x02\x02\u01D6\u01D5\x03\x02\x02\x02" + - "\u01D6\u01D7\x03\x02\x02\x02\u01D7\u01D9\x03\x02\x02\x02\u01D8\u01DA\x05" + - ";\x1C\x02\u01D9\u01D8\x03\x02\x02\x02\u01DA\u01DB\x03\x02\x02\x02\u01DB" + - "\u01D9\x03\x02\x02\x02\u01DB\u01DC\x03\x02\x02\x02\u01DCD\x03\x02\x02" + - "\x02\u01DD\u01E2\x07$\x02\x02\u01DE\u01E1\x05?\x1E\x02\u01DF\u01E1\x05" + - "A\x1F\x02\u01E0\u01DE\x03\x02\x02\x02\u01E0\u01DF\x03\x02\x02\x02\u01E1" + - "\u01E4\x03\x02\x02\x02\u01E2\u01E0\x03\x02\x02\x02\u01E2\u01E3\x03\x02" + - "\x02\x02\u01E3\u01E5\x03\x02\x02\x02\u01E4\u01E2\x03\x02\x02\x02\u01E5" + - "\u01FB\x07$\x02\x02\u01E6\u01E7\x07$\x02\x02\u01E7\u01E8\x07$\x02\x02" + - "\u01E8\u01E9\x07$\x02\x02\u01E9\u01ED\x03\x02\x02\x02\u01EA\u01EC\n\x02" + - "\x02\x02\u01EB\u01EA\x03\x02\x02\x02\u01EC\u01EF\x03\x02\x02\x02\u01ED" + - "\u01EE\x03\x02\x02\x02\u01ED\u01EB\x03\x02\x02\x02\u01EE\u01F0\x03\x02" + - "\x02\x02\u01EF\u01ED\x03\x02\x02\x02\u01F0\u01F1\x07$\x02\x02\u01F1\u01F2" + - "\x07$\x02\x02\u01F2\u01F3\x07$\x02\x02\u01F3\u01F5\x03\x02\x02\x02\u01F4" + - "\u01F6\x07$\x02\x02\u01F5\u01F4\x03\x02\x02\x02\u01F5\u01F6\x03\x02\x02" + - "\x02\u01F6\u01F8\x03\x02\x02\x02\u01F7\u01F9\x07$\x02\x02\u01F8\u01F7" + - "\x03\x02\x02\x02\u01F8\u01F9\x03\x02\x02\x02\u01F9\u01FB\x03\x02\x02\x02" + - "\u01FA\u01DD\x03\x02\x02\x02\u01FA\u01E6\x03\x02\x02\x02\u01FBF\x03\x02" + - "\x02\x02\u01FC\u01FE\x05;\x1C\x02\u01FD\u01FC\x03\x02\x02\x02\u01FE\u01FF" + - "\x03\x02\x02\x02\u01FF\u01FD\x03\x02\x02\x02\u01FF\u0200\x03\x02\x02\x02" + - "\u0200H\x03\x02\x02\x02\u0201\u0203\x05;\x1C\x02\u0202\u0201\x03\x02\x02" + - "\x02\u0203\u0204\x03\x02\x02\x02\u0204\u0202\x03\x02\x02\x02\u0204\u0205" + - "\x03\x02\x02\x02\u0205\u0206\x03\x02\x02\x02\u0206\u020A\x05U)\x02\u0207" + - "\u0209\x05;\x1C\x02\u0208\u0207\x03\x02\x02\x02\u0209\u020C\x03\x02\x02" + - "\x02\u020A\u0208\x03\x02\x02\x02\u020A\u020B\x03\x02\x02\x02\u020B\u022C" + - "\x03\x02\x02\x02\u020C\u020A\x03\x02\x02\x02\u020D\u020F\x05U)\x02\u020E" + - "\u0210\x05;\x1C\x02\u020F\u020E\x03\x02\x02\x02\u0210\u0211\x03\x02\x02" + - "\x02\u0211\u020F\x03\x02\x02\x02\u0211\u0212\x03\x02\x02\x02\u0212\u022C" + - "\x03\x02\x02\x02\u0213\u0215\x05;\x1C\x02\u0214\u0213\x03\x02\x02\x02" + - "\u0215\u0216\x03\x02\x02\x02\u0216\u0214\x03\x02\x02\x02\u0216\u0217\x03" + - "\x02\x02\x02\u0217\u021F\x03\x02\x02\x02\u0218\u021C\x05U)\x02\u0219\u021B" + - "\x05;\x1C\x02\u021A\u0219\x03\x02\x02\x02\u021B\u021E\x03\x02\x02\x02" + - "\u021C\u021A\x03\x02\x02\x02\u021C\u021D\x03\x02\x02\x02\u021D\u0220\x03" + - "\x02\x02\x02\u021E\u021C\x03\x02\x02\x02\u021F\u0218\x03\x02\x02\x02\u021F" + - "\u0220\x03\x02\x02\x02\u0220\u0221\x03\x02\x02\x02\u0221\u0222\x05C \x02" + - "\u0222\u022C\x03\x02\x02\x02\u0223\u0225\x05U)\x02\u0224\u0226\x05;\x1C" + - "\x02\u0225\u0224\x03\x02\x02\x02\u0226\u0227\x03\x02\x02\x02\u0227\u0225" + - "\x03\x02\x02\x02\u0227\u0228\x03\x02\x02\x02\u0228\u0229\x03\x02\x02\x02" + - "\u0229\u022A\x05C \x02\u022A\u022C\x03\x02\x02\x02\u022B\u0202\x03\x02" + - "\x02\x02\u022B\u020D\x03\x02\x02\x02\u022B\u0214\x03\x02\x02\x02\u022B" + - "\u0223\x03\x02\x02\x02\u022CJ\x03\x02\x02\x02\u022D\u022E\x07d\x02\x02" + - "\u022E\u022F\x07{\x02\x02\u022FL\x03\x02\x02\x02\u0230\u0231\x07{\x02" + - "\x02\u0231\u0232\x07g\x02\x02\u0232\u0233\x07c\x02\x02\u0233\u028F\x07" + - "t\x02\x02\u0234\u0235\x07o\x02\x02\u0235\u0236\x07q\x02\x02\u0236\u0237" + - "\x07p\x02\x02\u0237\u0238\x07v\x02\x02\u0238\u028F\x07j\x02\x02\u0239" + - "\u023A\x07f\x02\x02\u023A\u023B\x07c\x02\x02\u023B\u028F\x07{\x02\x02" + - "\u023C\u023D\x07u\x02\x02\u023D\u023E\x07g\x02\x02\u023E\u023F\x07e\x02" + - "\x02\u023F\u0240\x07q\x02\x02\u0240\u0241\x07p\x02\x02\u0241\u028F\x07" + - "f\x02\x02\u0242\u0243\x07o\x02\x02\u0243\u0244\x07k\x02\x02\u0244\u0245" + - "\x07p\x02\x02\u0245\u0246\x07w\x02\x02\u0246\u0247\x07v\x02\x02\u0247" + - "\u028F\x07g\x02\x02\u0248\u0249\x07j\x02\x02\u0249\u024A\x07q\x02\x02" + - "\u024A\u024B\x07w\x02\x02\u024B\u028F\x07t\x02\x02\u024C\u024D\x07y\x02" + - "\x02\u024D\u024E\x07g\x02\x02\u024E\u024F\x07g\x02\x02\u024F\u028F\x07" + - "m\x02\x02\u0250\u0251\x07o\x02\x02\u0251\u0252\x07k\x02\x02\u0252\u0253" + - "\x07n\x02\x02\u0253\u0254\x07n\x02\x02\u0254\u0255\x07k\x02\x02\u0255" + - "\u0256\x07u\x02\x02\u0256\u0257\x07g\x02\x02\u0257\u0258\x07e\x02\x02" + - "\u0258\u0259\x07q\x02\x02\u0259\u025A\x07p\x02\x02\u025A\u028F\x07f\x02" + - "\x02\u025B\u025C\x07{\x02\x02\u025C\u025D\x07g\x02\x02\u025D\u025E\x07" + - "c\x02\x02\u025E\u025F\x07t\x02\x02\u025F\u028F\x07u\x02\x02\u0260\u0261" + - "\x07o\x02\x02\u0261\u0262\x07q\x02\x02\u0262\u0263\x07p\x02\x02\u0263" + - "\u0264\x07v\x02\x02\u0264\u0265\x07j\x02\x02\u0265\u028F\x07u\x02\x02" + - "\u0266\u0267\x07f\x02\x02\u0267\u0268\x07c\x02\x02\u0268\u0269\x07{\x02" + - "\x02\u0269\u028F\x07u\x02\x02\u026A\u026B\x07u\x02\x02\u026B\u026C\x07" + - "g\x02\x02\u026C\u026D\x07e\x02\x02\u026D\u026E\x07q\x02\x02\u026E\u026F" + - "\x07p\x02\x02\u026F\u0270\x07f\x02\x02\u0270\u028F\x07u\x02\x02\u0271" + - "\u0272\x07o\x02\x02\u0272\u0273\x07k\x02\x02\u0273\u0274\x07p\x02\x02" + - "\u0274\u0275\x07w\x02\x02\u0275\u0276\x07v\x02\x02\u0276\u0277\x07g\x02" + - "\x02\u0277\u028F\x07u\x02\x02\u0278\u0279\x07j\x02\x02\u0279\u027A\x07" + - "q\x02\x02\u027A\u027B\x07w\x02\x02\u027B\u027C\x07t\x02\x02\u027C\u028F" + - "\x07u\x02\x02\u027D\u027E\x07y\x02\x02\u027E\u027F\x07g\x02\x02\u027F" + - "\u0280\x07g\x02\x02\u0280\u0281\x07m\x02\x02\u0281\u028F\x07u\x02\x02" + - "\u0282\u0283\x07o\x02\x02\u0283\u0284\x07k\x02\x02\u0284\u0285\x07n\x02" + - "\x02\u0285\u0286\x07n\x02\x02\u0286\u0287\x07k\x02\x02\u0287\u0288\x07" + - "u\x02\x02\u0288\u0289\x07g\x02\x02\u0289\u028A\x07e\x02\x02\u028A\u028B" + - "\x07q\x02\x02\u028B\u028C\x07p\x02\x02\u028C\u028D\x07f\x02\x02\u028D" + - "\u028F\x07u\x02\x02\u028E\u0230\x03\x02\x02\x02\u028E\u0234\x03\x02\x02" + - "\x02\u028E\u0239\x03\x02\x02\x02\u028E\u023C\x03\x02\x02\x02\u028E\u0242" + - "\x03\x02\x02\x02\u028E\u0248\x03\x02\x02\x02\u028E\u024C\x03\x02\x02\x02" + - "\u028E\u0250\x03\x02\x02\x02\u028E\u025B\x03\x02\x02\x02\u028E\u0260\x03" + - "\x02\x02\x02\u028E\u0266\x03\x02\x02\x02\u028E\u026A\x03\x02\x02\x02\u028E" + - "\u0271\x03\x02\x02\x02\u028E\u0278\x03\x02\x02\x02\u028E\u027D\x03\x02" + - "\x02\x02\u028E\u0282\x03\x02\x02\x02\u028FN\x03\x02\x02\x02\u0290\u0291" + - "\x07c\x02\x02\u0291\u0292\x07p\x02\x02\u0292\u0293\x07f\x02\x02\u0293" + - "P\x03\x02\x02\x02\u0294\u0295\x07?\x02\x02\u0295R\x03\x02\x02\x02\u0296" + - "\u0297\x07.\x02\x02\u0297T\x03\x02\x02\x02\u0298\u0299\x070\x02\x02\u0299" + - "V\x03\x02\x02\x02\u029A\u029B\x07*\x02\x02\u029BX\x03\x02\x02\x02\u029C" + - "\u029D\x07]\x02\x02\u029D\u029E\x03\x02\x02\x02\u029E\u029F\b+\x02\x02" + - "\u029F\u02A0\b+\x02\x02\u02A0Z\x03\x02\x02\x02\u02A1\u02A2\x07_\x02\x02" + - "\u02A2\u02A3\x03\x02\x02\x02\u02A3\u02A4\b,\n\x02\u02A4\u02A5\b,\n\x02" + - "\u02A5\\\x03\x02\x02\x02\u02A6\u02A7\x05\xE5q\x02\u02A7\u02A8\x05\xE7" + - "r\x02\u02A8\u02A9\x05\xF1w\x02\u02A9^\x03\x02\x02\x02\u02AA\u02AB\x05" + - "\xE1o\x02\u02AB\u02AC\x05\xDBl\x02\u02AC\u02AD\x05\xDFn\x02\u02AD\u02AE" + - "\x05\xD3h\x02\u02AE`\x03\x02\x02\x02\u02AF\u02B0\x05\xEDu\x02\u02B0\u02B1" + - "\x05\xE1o\x02\u02B1\u02B2\x05\xDBl\x02\u02B2\u02B3\x05\xDFn\x02\u02B3" + - "\u02B4\x05\xD3h\x02\u02B4b\x03\x02\x02\x02\u02B5\u02B6\x05\xDBl\x02\u02B6" + - "\u02B7\x05\xE5q\x02\u02B7d\x03\x02\x02\x02\u02B8\u02B9\x05\xDBl\x02\u02B9" + - "\u02BA\x05\xEFv\x02\u02BAf\x03\x02\x02\x02\u02BB\u02BC\x05\xCBd\x02\u02BC" + - "\u02BD\x05\xEFv\x02\u02BDh\x03\x02\x02\x02\u02BE\u02BF\x05\xE5q\x02\u02BF" + - "\u02C0\x05\xF3x\x02\u02C0\u02C1\x05\xE1o\x02\u02C1\u02C2\x05\xE1o\x02" + - "\u02C2j\x03\x02\x02\x02\u02C3\u02C4\x07q\x02\x02\u02C4\u02C5\x07t\x02" + - "\x02\u02C5l\x03\x02\x02\x02\u02C6\u02C7\x07+\x02\x02\u02C7n\x03\x02\x02" + - "\x02\u02C8\u02C9\x07a\x02\x02\u02C9p\x03\x02\x02\x02\u02CA\u02CB\x07k" + - "\x02\x02\u02CB\u02CC\x07p\x02\x02\u02CC\u02CD\x07h\x02\x02\u02CD\u02CE" + - "\x07q\x02\x02\u02CEr\x03\x02\x02\x02\u02CF\u02D0\x07h\x02\x02\u02D0\u02D1" + - "\x07w\x02\x02\u02D1\u02D2\x07p\x02\x02\u02D2\u02D3\x07e\x02\x02\u02D3" + - "\u02D4\x07v\x02\x02\u02D4\u02D5\x07k\x02\x02\u02D5\u02D6\x07q\x02\x02" + - "\u02D6\u02D7\x07p\x02\x02\u02D7\u02D8\x07u\x02\x02\u02D8t\x03\x02\x02" + - "\x02\u02D9\u02DA\x07v\x02\x02\u02DA\u02DB\x07t\x02\x02\u02DB\u02DC\x07" + - "w\x02\x02\u02DC\u02E3\x07g\x02\x02\u02DD\u02DE\x07h\x02\x02\u02DE\u02DF" + - "\x07c\x02\x02\u02DF\u02E0\x07n\x02\x02\u02E0\u02E1\x07u\x02\x02\u02E1" + - "\u02E3\x07g\x02\x02\u02E2\u02D9\x03\x02\x02\x02\u02E2\u02DD\x03\x02\x02" + - "\x02\u02E3v\x03\x02\x02\x02\u02E4\u02E5\x07?\x02\x02\u02E5\u02EF\x07?" + - "\x02\x02\u02E6\u02E7\x07#\x02\x02\u02E7\u02EF\x07?\x02\x02\u02E8\u02EF" + - "\x07>\x02\x02\u02E9\u02EA\x07>\x02\x02\u02EA\u02EF\x07?\x02\x02\u02EB" + - "\u02EF\x07@\x02\x02\u02EC\u02ED\x07@\x02\x02\u02ED\u02EF\x07?\x02\x02" + - "\u02EE\u02E4\x03\x02\x02\x02\u02EE\u02E6\x03\x02\x02\x02\u02EE\u02E8\x03" + - "\x02\x02\x02\u02EE\u02E9\x03\x02\x02\x02\u02EE\u02EB\x03\x02\x02\x02\u02EE" + - "\u02EC\x03\x02\x02\x02\u02EFx\x03\x02\x02\x02\u02F0\u02F1\x07-\x02\x02" + - "\u02F1z\x03\x02\x02\x02\u02F2\u02F3\x07/\x02\x02\u02F3|\x03\x02\x02\x02" + - "\u02F4\u02F5\x07,\x02\x02\u02F5~\x03\x02\x02\x02\u02F6\u02F7\x071\x02" + - "\x02\u02F7\x80\x03\x02\x02\x02\u02F8\u02F9\x07\'\x02\x02\u02F9\x82\x03" + - "\x02\x02\x02\u02FA\u02FB\x073\x02\x02\u02FB\u02FC\x072\x02\x02\u02FC\x84" + - "\x03\x02\x02\x02\u02FD\u02FE\x07c\x02\x02\u02FE\u02FF\x07u\x02\x02\u02FF" + - "\u0305\x07e\x02\x02\u0300\u0301\x07f\x02\x02\u0301\u0302\x07g\x02\x02" + - "\u0302\u0303\x07u\x02\x02\u0303\u0305\x07e\x02\x02\u0304\u02FD\x03\x02" + - "\x02\x02\u0304\u0300\x03\x02\x02\x02\u0305\x86\x03\x02\x02\x02\u0306\u0307" + - "\x07p\x02\x02\u0307\u0308\x07w\x02\x02\u0308\u0309\x07n\x02\x02\u0309" + - "\u030A\x07n\x02\x02\u030A\u030B\x07u\x02\x02\u030B\x88\x03\x02\x02\x02" + - "\u030C\u030D\x07h\x02\x02\u030D\u030E\x07k\x02\x02\u030E\u030F\x07t\x02" + - "\x02\u030F\u0310\x07u\x02\x02\u0310\u0316\x07v\x02\x02\u0311\u0312\x07" + - "n\x02\x02\u0312\u0313\x07c\x02\x02\u0313\u0314\x07u\x02\x02\u0314\u0316" + - "\x07v\x02\x02\u0315\u030C\x03\x02\x02\x02\u0315\u0311\x03\x02\x02\x02" + - "\u0316\x8A\x03\x02\x02\x02\u0317\u0318\x05\xEDu\x02\u0318\u0319\x05\xE7" + - "r\x02\u0319\u031A\x05\xF3x\x02\u031A\u031B\x05\xE5q\x02\u031B\u031C\x05" + - "\xD1g\x02\u031C\u04C6\x03\x02\x02\x02\u031D\u031E\x05\xCBd\x02\u031E\u031F" + - "\x05\xCDe\x02\u031F\u0320\x05\xEFv\x02\u0320\u04C6\x03\x02\x02\x02\u0321" + - "\u0322\x05\xE9s\x02\u0322\u0323\x05\xE7r\x02\u0323\u0324\x05\xF7z\x02" + - "\u0324\u04C6\x03\x02\x02\x02\u0325\u0326\x05\xE1o\x02\u0326\u0327\x05" + - "\xE7r\x02\u0327\u0328\x05\xD7j\x02\u0328\u0329\x05\x83@\x02\u0329\u04C6" + - "\x03\x02\x02\x02\u032A\u032B\x05\xE9s\x02\u032B\u032C\x05\xDBl\x02\u032C" + - "\u04C6\x03\x02\x02\x02\u032D\u032E\x05\xF1w\x02\u032E\u032F\x05\xCBd\x02" + - "\u032F\u0330\x05\xF3x\x02\u0330\u04C6\x03\x02\x02\x02\u0331\u04C6\x05" + - "\xD3h\x02\u0332\u0333\x05\xEFv\x02\u0333\u0334\x05\xF3x\x02\u0334\u0335" + - "\x05\xCDe\x02\u0335\u0336\x05\xEFv\x02\u0336\u0337\x05\xF1w\x02\u0337" + - "\u0338\x05\xEDu\x02\u0338\u0339\x05\xDBl\x02\u0339\u033A\x05\xE5q\x02" + - "\u033A\u033B\x05\xD7j\x02\u033B\u04C6\x03\x02\x02\x02\u033C\u033D\x05" + - "\xF1w\x02\u033D\u033E\x05\xEDu\x02\u033E\u033F\x05\xDBl\x02\u033F\u0340" + - "\x05\xE3p\x02\u0340\u04C6\x03\x02\x02\x02\u0341\u0342\x05\xCFf\x02\u0342" + - "\u0343\x05\xE7r\x02\u0343\u0344\x05\xE5q\x02\u0344\u0345\x05\xCFf\x02" + - "\u0345\u0346\x05\xCBd\x02\u0346\u0347\x05\xF1w\x02\u0347\u04C6\x03\x02" + - "\x02\x02\u0348\u0349\x05\xCFf\x02\u0349\u034A\x05\xE7r\x02\u034A\u034B" + - "\x05\xCBd\x02\u034B\u034C\x05\xE1o\x02\u034C\u034D\x05\xD3h\x02\u034D" + - "\u034E\x05\xEFv\x02\u034E\u034F\x05\xCFf\x02\u034F\u0350\x05\xD3h\x02" + - "\u0350\u04C6\x03\x02\x02\x02\u0351\u0352\x05\xD7j\x02\u0352\u0353\x05" + - "\xEDu\x02\u0353\u0354\x05\xD3h\x02\u0354\u0355\x05\xCBd\x02\u0355\u0356" + - "\x05\xF1w\x02\u0356\u0357\x05\xD3h\x02\u0357\u0358\x05\xEFv\x02\u0358" + - "\u0359\x05\xF1w\x02\u0359\u04C6\x03\x02\x02\x02\u035A\u035B\x05\xE1o\x02" + - "\u035B\u035C\x05\xD3h\x02\u035C\u035D\x05\xD5i\x02\u035D\u035E\x05\xF1" + - "w\x02\u035E\u04C6\x03\x02\x02\x02\u035F\u0360\x05\xE5q\x02\u0360\u0361" + - "\x05\xE7r\x02\u0361\u0362\x05\xF7z\x02\u0362\u04C6\x03\x02\x02\x02\u0363" + - "\u0364\x05\xEDu\x02\u0364\u0365\x05\xDBl\x02\u0365\u0366\x05\xD7j\x02" + - "\u0366\u0367\x05\xD9k\x02\u0367\u0368\x05\xF1w\x02\u0368\u04C6\x03\x02" + - "\x02\x02\u0369\u036A\x05\xEFv\x02\u036A\u036B\x05\xF1w\x02\u036B\u036C" + - "\x05\xCBd\x02\u036C\u036D\x05\xEDu\x02\u036D\u036E\x05\xF1w\x02\u036E" + - "\u036F\x05\xEFv\x02\u036F\u0370\x05o6\x02\u0370\u0371\x05\xF7z\x02\u0371" + - "\u0372\x05\xDBl\x02\u0372\u0373\x05\xF1w\x02\u0373\u0374\x05\xD9k\x02" + - "\u0374\u04C6\x03\x02\x02\x02\u0375\u0376\x05\xD1g\x02\u0376\u0377\x05" + - "\xCBd\x02\u0377\u0378\x05\xF1w\x02\u0378\u0379\x05\xD3h\x02\u0379\u037A" + - "\x05o6\x02\u037A\u037B\x05\xD5i\x02\u037B\u037C\x05\xE7r\x02\u037C\u037D" + - "\x05\xEDu\x02\u037D\u037E\x05\xE3p\x02\u037E\u037F\x05\xCBd\x02\u037F" + - "\u0380\x05\xF1w\x02\u0380\u04C6\x03\x02\x02\x02\u0381\u0382\x05\xD1g\x02" + - "\u0382\u0383\x05\xCBd\x02\u0383\u0384\x05\xF1w\x02\u0384\u0385\x05\xD3" + - "h\x02\u0385\u0386\x05o6\x02\u0386\u0387\x05\xF1w\x02\u0387\u0388\x05\xED" + - "u\x02\u0388\u0389\x05\xF3x\x02\u0389\u038A\x05\xE5q\x02\u038A\u038B\x05" + - "\xCFf\x02\u038B\u04C6\x03\x02\x02\x02\u038C\u038D\x05\xD1g\x02\u038D\u038E" + - "\x05\xCBd\x02\u038E\u038F\x05\xF1w\x02\u038F\u0390\x05\xD3h\x02\u0390" + - "\u0391\x05o6\x02\u0391\u0392\x05\xE9s\x02\u0392\u0393\x05\xCBd\x02\u0393" + - "\u0394\x05\xEDu\x02\u0394\u0395\x05\xEFv\x02\u0395\u0396\x05\xD3h\x02" + - "\u0396\u04C6\x03\x02\x02\x02\u0397\u0398\x05\xCBd\x02\u0398\u0399\x05" + - "\xF3x\x02\u0399\u039A\x05\xF1w\x02\u039A\u039B\x05\xE7r\x02\u039B\u039C" + - "\x05o6\x02\u039C\u039D\x05\xCDe\x02\u039D\u039E\x05\xF3x\x02\u039E\u039F" + - "\x05\xCFf\x02\u039F\u03A0\x05\xDFn\x02\u03A0\u03A1\x05\xD3h\x02\u03A1" + - "\u03A2\x05\xF1w\x02\u03A2\u04C6\x03\x02\x02\x02\u03A3\u03A4\x05\xD1g\x02" + - "\u03A4\u03A5\x05\xCBd\x02\u03A5\u03A6\x05\xF1w\x02\u03A6\u03A7\x05\xD3" + - "h\x02\u03A7\u03A8\x05o6\x02\u03A8\u03A9\x05\xD3h\x02\u03A9\u03AA\x05\xF9" + - "{\x02\u03AA\u03AB\x05\xF1w\x02\u03AB\u03AC\x05\xEDu\x02\u03AC\u03AD\x05" + - "\xCBd\x02\u03AD\u03AE\x05\xCFf\x02\u03AE\u03AF\x05\xF1w\x02\u03AF\u04C6" + - "\x03\x02\x02\x02\u03B0\u03B1\x05\xDBl\x02\u03B1\u03B2\x05\xEFv\x02\u03B2" + - "\u03B3\x05o6\x02\u03B3\u03B4\x05\xD5i\x02\u03B4\u03B5\x05\xDBl\x02\u03B5" + - "\u03B6\x05\xE5q\x02\u03B6\u03B7\x05\xDBl\x02\u03B7\u03B8\x05\xF1w\x02" + - "\u03B8\u03B9\x05\xD3h\x02\u03B9\u04C6\x03\x02\x02\x02\u03BA\u03BB\x05" + - "\xDBl\x02\u03BB\u03BC\x05\xEFv\x02\u03BC\u03BD\x05o6\x02\u03BD\u03BE\x05" + - "\xDBl\x02\u03BE\u03BF\x05\xE5q\x02\u03BF\u03C0\x05\xD5i\x02\u03C0\u03C1" + - "\x05\xDBl\x02\u03C1\u03C2\x05\xE5q\x02\u03C2\u03C3\x05\xDBl\x02\u03C3" + - "\u03C4\x05\xF1w\x02\u03C4\u03C5\x05\xD3h\x02\u03C5\u04C6\x03\x02\x02\x02" + - "\u03C6\u03C7\x05\xCFf\x02\u03C7\u03C8\x05\xCBd\x02\u03C8\u03C9\x05\xEF" + - "v\x02\u03C9\u03CA\x05\xD3h\x02\u03CA\u04C6\x03\x02\x02\x02\u03CB\u03CC" + - "\x05\xE1o\x02\u03CC\u03CD\x05\xD3h\x02\u03CD\u03CE\x05\xE5q\x02\u03CE" + - "\u03CF\x05\xD7j\x02\u03CF\u03D0\x05\xF1w\x02\u03D0\u03D1\x05\xD9k\x02" + - "\u03D1\u04C6\x03\x02\x02\x02\u03D2\u03D3\x05\xE3p\x02\u03D3\u03D4\x05" + - "\xF5y\x02\u03D4\u03D5\x05o6\x02\u03D5\u03D6\x05\xE3p\x02\u03D6\u03D7\x05" + - "\xCBd\x02\u03D7\u03D8\x05\xF9{\x02\u03D8\u04C6\x03\x02\x02\x02\u03D9\u03DA" + - "\x05\xE3p\x02\u03DA\u03DB\x05\xF5y\x02\u03DB\u03DC\x05o6\x02\u03DC\u03DD" + - "\x05\xE3p\x02\u03DD\u03DE\x05\xDBl\x02\u03DE\u03DF\x05\xE5q\x02\u03DF" + - "\u04C6\x03\x02\x02\x02\u03E0\u03E1\x05\xE3p\x02\u03E1\u03E2\x05\xF5y\x02" + - "\u03E2\u03E3\x05o6\x02\u03E3\u03E4\x05\xCBd\x02\u03E4\u03E5\x05\xF5y\x02" + - "\u03E5\u03E6\x05\xD7j\x02\u03E6\u04C6\x03\x02\x02\x02\u03E7\u03E8\x05" + - "\xE3p\x02\u03E8\u03E9\x05\xF5y\x02\u03E9\u03EA\x05o6\x02\u03EA\u03EB\x05" + - "\xEFv\x02\u03EB\u03EC\x05\xF3x\x02\u03EC\u03ED\x05\xE3p\x02\u03ED\u04C6" + - "\x03\x02\x02\x02\u03EE\u03EF\x05\xE3p\x02\u03EF\u03F0\x05\xF5y\x02\u03F0" + - "\u03F1\x05o6"; - private static readonly _serializedATNSegment2: string = - "\x02\u03F1\u03F2\x05\xCFf\x02\u03F2\u03F3\x05\xE7r\x02\u03F3\u03F4\x05" + - "\xF3x\x02\u03F4\u03F5\x05\xE5q\x02\u03F5\u03F6\x05\xF1w\x02\u03F6\u04C6" + - "\x03\x02\x02\x02\u03F7\u03F8\x05\xE3p\x02\u03F8\u03F9\x05\xF5y\x02\u03F9" + - "\u03FA\x05o6\x02\u03FA\u03FB\x05\xCFf\x02\u03FB\u03FC\x05\xE7r\x02\u03FC" + - "\u03FD\x05\xE5q\x02\u03FD\u03FE\x05\xCFf\x02\u03FE\u03FF\x05\xCBd\x02" + - "\u03FF\u0400\x05\xF1w\x02\u0400\u04C6\x03\x02\x02\x02\u0401\u0402\x05" + - "\xE3p\x02\u0402\u0403\x05\xF5y\x02\u0403\u0404\x05o6\x02\u0404\u0405\x05" + - "\xDDm\x02\u0405\u0406\x05\xE7r\x02\u0406\u0407\x05\xDBl\x02\u0407\u0408" + - "\x05\xE5q\x02\u0408\u04C6\x03\x02\x02\x02\u0409\u040A\x05\xE3p\x02\u040A" + - "\u040B\x05\xF5y\x02\u040B\u040C\x05o6\x02\u040C\u040D\x05\xE3p\x02\u040D" + - "\u040E\x05\xD3h\x02\u040E\u040F\x05\xD1g\x02\u040F\u0410\x05\xDBl\x02" + - "\u0410\u0411\x05\xCBd\x02\u0411\u0412\x05\xE5q\x02\u0412\u04C6\x03\x02" + - "\x02\x02\u0413\u0414\x05\xE3p\x02\u0414\u0415\x05\xF5y\x02\u0415\u0416" + - "\x05o6\x02\u0416\u0417\x05\xD1g\x02\u0417\u0418\x05\xD3h\x02\u0418\u0419" + - "\x05\xD1g\x02\u0419\u041A\x05\xF3x\x02\u041A\u041B\x05\xE9s\x02\u041B" + - "\u041C\x05\xD3h\x02\u041C\u04C6\x03\x02\x02\x02\u041D\u041E\x05\xE3p\x02" + - "\u041E\u041F\x05\xD3h\x02\u041F\u0420\x05\xF1w\x02\u0420\u0421\x05\xCB" + - "d\x02\u0421\u0422\x05\xD1g\x02\u0422\u0423\x05\xCBd\x02\u0423\u0424\x05" + - "\xF1w\x02\u0424\u0425\x05\xCBd\x02\u0425\u04C6\x03\x02\x02\x02\u0426\u0427" + - "\x05\xEFv\x02\u0427\u0428\x05\xE9s\x02\u0428\u0429\x05\xE1o\x02\u0429" + - "\u042A\x05\xDBl\x02\u042A\u042B\x05\xF1w\x02\u042B\u04C6\x03\x02\x02\x02" + - "\u042C\u042D\x05\xF1w\x02\u042D\u042E\x05\xE7r\x02\u042E\u042F\x05o6\x02" + - "\u042F\u0430\x05\xEFv\x02\u0430\u0431\x05\xF1w\x02\u0431\u0432\x05\xED" + - "u\x02\u0432\u0433\x05\xDBl\x02\u0433\u0434\x05\xE5q\x02\u0434\u0435\x05" + - "\xD7j\x02\u0435\u04C6\x03\x02\x02\x02\u0436\u0437\x05\xF1w\x02\u0437\u0438" + - "\x05\xE7r\x02\u0438\u0439\x05o6\x02\u0439\u043A\x05\xEFv\x02\u043A\u043B" + - "\x05\xF1w\x02\u043B\u043C\x05\xEDu\x02\u043C\u04C6\x03\x02\x02\x02\u043D" + - "\u043E\x05\xF1w\x02\u043E\u043F\x05\xE7r\x02\u043F\u0440\x05o6\x02\u0440" + - "\u0441\x05\xCDe\x02\u0441\u0442\x05\xE7r\x02\u0442\u0443\x05\xE7r\x02" + - "\u0443\u0444\x05\xE1o\x02\u0444\u04C6\x03\x02\x02\x02\u0445\u0446\x05" + - "\xF1w\x02\u0446\u0447\x05\xE7r\x02\u0447\u0448\x05o6\x02\u0448\u0449\x05" + - "\xCDe\x02\u0449\u044A\x05\xE7r\x02\u044A\u044B\x05\xE7r\x02\u044B\u044C" + - "\x05\xE1o\x02\u044C\u044D\x05\xD3h\x02\u044D\u044E\x05\xCBd\x02\u044E" + - "\u044F\x05\xE5q\x02\u044F\u04C6\x03\x02\x02\x02\u0450\u0451\x05\xF1w\x02" + - "\u0451\u0452\x05\xE7r\x02\u0452\u0453\x05o6\x02\u0453\u0454\x05\xD1g\x02" + - "\u0454\u0455\x05\xCBd\x02\u0455\u0456\x05\xF1w\x02\u0456\u0457\x05\xD3" + - "h\x02\u0457\u0458\x05\xF1w\x02\u0458\u0459\x05\xDBl\x02\u0459\u045A\x05" + - "\xE3p\x02\u045A\u045B\x05\xD3h\x02\u045B\u04C6\x03\x02\x02\x02\u045C\u045D" + - "\x05\xF1w\x02\u045D\u045E\x05\xE7r\x02\u045E\u045F\x05o6\x02\u045F\u0460" + - "\x05\xD1g\x02\u0460\u0461\x05\xF1w\x02\u0461\u04C6\x03\x02\x02\x02\u0462" + - "\u0463\x05\xF1w\x02\u0463\u0464\x05\xE7r\x02\u0464\u0465\x05o6\x02\u0465" + - "\u0466\x05\xD1g\x02\u0466\u0467\x05\xCDe\x02\u0467\u0468\x05\xE1o\x02" + - "\u0468\u04C6\x03\x02\x02\x02\u0469\u046A\x05\xF1w\x02\u046A\u046B\x05" + - "\xE7r\x02\u046B\u046C\x05o6\x02\u046C\u046D\x05\xD1g\x02\u046D\u046E\x05" + - "\xE7r\x02\u046E\u046F\x05\xF3x\x02\u046F\u0470\x05\xCDe\x02\u0470\u0471" + - "\x05\xE1o\x02\u0471\u0472\x05\xD3h\x02\u0472\u04C6\x03\x02\x02\x02\u0473" + - "\u0474\x05\xF1w\x02\u0474\u0475\x05\xE7r\x02\u0475\u0476\x05o6\x02\u0476" + - "\u0477\x05\xD1g\x02\u0477\u0478\x05\xD3h\x02\u0478\u0479\x05\xD7j\x02" + - "\u0479\u047A\x05\xEDu\x02\u047A\u047B\x05\xD3h\x02\u047B\u047C\x05\xD3" + - "h\x02\u047C\u047D\x05\xEFv\x02\u047D\u04C6\x03\x02\x02\x02\u047E\u047F" + - "\x05\xF1w\x02\u047F\u0480\x05\xE7r\x02\u0480\u0481\x05o6\x02\u0481\u0482" + - "\x05\xDBl\x02\u0482\u0483\x05\xE5q\x02\u0483\u0484\x05\xF1w\x02\u0484" + - "\u04C6\x03\x02\x02\x02\u0485\u0486\x05\xF1w\x02\u0486\u0487\x05\xE7r\x02" + - "\u0487\u0488\x05o6\x02\u0488\u0489\x05\xDBl\x02\u0489\u048A\x05\xE5q\x02" + - "\u048A\u048B\x05\xF1w\x02\u048B\u048C\x05\xD3h\x02\u048C\u048D\x05\xD7" + - "j\x02\u048D\u048E\x05\xD3h\x02\u048E\u048F\x05\xEDu\x02\u048F\u04C6\x03" + - "\x02\x02\x02\u0490\u0491\x05\xF1w\x02\u0491\u0492\x05\xE7r\x02\u0492\u0493" + - "\x05o6\x02\u0493\u0494\x05\xDBl\x02\u0494\u0495\x05\xE9s\x02\u0495\u04C6" + - "\x03\x02\x02\x02\u0496\u0497\x05\xF1w\x02\u0497\u0498\x05\xE7r\x02\u0498" + - "\u0499\x05o6\x02\u0499\u049A\x05\xE1o\x02\u049A\u049B\x05\xE7r\x02\u049B" + - "\u049C\x05\xE5q\x02\u049C\u049D\x05\xD7j\x02\u049D\u04C6\x03\x02\x02\x02" + - "\u049E\u049F\x05\xF1w\x02\u049F\u04A0\x05\xE7r\x02\u04A0\u04A1\x05o6\x02" + - "\u04A1\u04A2\x05\xEDu\x02\u04A2\u04A3\x05\xCBd\x02\u04A3\u04A4\x05\xD1" + - "g\x02\u04A4\u04A5\x05\xDBl\x02\u04A5\u04A6\x05\xCBd\x02\u04A6\u04A7\x05" + - "\xE5q\x02\u04A7\u04A8\x05\xEFv\x02\u04A8\u04C6\x03\x02\x02\x02\u04A9\u04AA" + - "\x05\xF1w\x02\u04AA\u04AB\x05\xE7r\x02\u04AB\u04AC\x05o6\x02\u04AC\u04AD" + - "\x05\xF5y\x02\u04AD\u04AE\x05\xD3h\x02\u04AE\u04AF\x05\xEDu\x02\u04AF" + - "\u04B0\x05\xEFv\x02\u04B0\u04B1\x05\xDBl\x02\u04B1\u04B2\x05\xE7r\x02" + - "\u04B2\u04B3\x05\xE5q\x02\u04B3\u04C6\x03\x02\x02\x02\u04B4\u04B5\x05" + - "\xF1w\x02\u04B5\u04B6\x05\xE7r\x02\u04B6\u04B7\x05o6\x02\u04B7\u04B8\x05" + - "\xF3x\x02\u04B8\u04B9\x05\xE5q\x02\u04B9\u04BA\x05\xEFv\x02\u04BA\u04BB" + - "\x05\xDBl\x02\u04BB\u04BC\x05\xD7j\x02\u04BC\u04BD\x05\xE5q\x02\u04BD" + - "\u04BE\x05\xD3h\x02\u04BE\u04BF\x05\xD1g\x02\u04BF\u04C0\x05o6\x02\u04C0" + - "\u04C1\x05\xE1o\x02\u04C1\u04C2\x05\xE7r\x02\u04C2\u04C3\x05\xE5q\x02" + - "\u04C3\u04C4\x05\xD7j\x02\u04C4\u04C6\x03\x02\x02\x02\u04C5\u0317\x03" + - "\x02\x02\x02\u04C5\u031D\x03\x02\x02\x02\u04C5\u0321\x03\x02\x02\x02\u04C5" + - "\u0325\x03\x02\x02\x02\u04C5\u032A\x03\x02\x02\x02\u04C5\u032D\x03\x02" + - "\x02\x02\u04C5\u0331\x03\x02\x02\x02\u04C5\u0332\x03\x02\x02\x02\u04C5" + - "\u033C\x03\x02\x02\x02\u04C5\u0341\x03\x02\x02\x02\u04C5\u0348\x03\x02" + - "\x02\x02\u04C5\u0351\x03\x02\x02\x02\u04C5\u035A\x03\x02\x02\x02\u04C5" + - "\u035F\x03\x02\x02\x02\u04C5\u0363\x03\x02\x02\x02\u04C5\u0369\x03\x02" + - "\x02\x02\u04C5\u0375\x03\x02\x02\x02\u04C5\u0381\x03\x02\x02\x02\u04C5" + - "\u038C\x03\x02\x02\x02\u04C5\u0397\x03\x02\x02\x02\u04C5\u03A3\x03\x02" + - "\x02\x02\u04C5\u03B0\x03\x02\x02\x02\u04C5\u03BA\x03\x02\x02\x02\u04C5" + - "\u03C6\x03\x02\x02\x02\u04C5\u03CB\x03\x02\x02\x02\u04C5\u03D2\x03\x02" + - "\x02\x02\u04C5\u03D9\x03\x02\x02\x02\u04C5\u03E0\x03\x02\x02\x02\u04C5" + - "\u03E7\x03\x02\x02\x02\u04C5\u03EE\x03\x02\x02\x02\u04C5\u03F7\x03\x02" + - "\x02\x02\u04C5\u0401\x03\x02\x02\x02\u04C5\u0409\x03\x02\x02\x02\u04C5" + - "\u0413\x03\x02\x02\x02\u04C5\u041D\x03\x02\x02\x02\u04C5\u0426\x03\x02" + - "\x02\x02\u04C5\u042C\x03\x02\x02\x02\u04C5\u0436\x03\x02\x02\x02\u04C5" + - "\u043D\x03\x02\x02\x02\u04C5\u0445\x03\x02\x02\x02\u04C5\u0450\x03\x02" + - "\x02\x02\u04C5\u045C\x03\x02\x02\x02\u04C5\u0462\x03\x02\x02\x02\u04C5" + - "\u0469\x03\x02\x02\x02\u04C5\u0473\x03\x02\x02\x02\u04C5\u047E\x03\x02" + - "\x02\x02\u04C5\u0485\x03\x02\x02\x02\u04C5\u0490\x03\x02\x02\x02\u04C5" + - "\u0496\x03\x02\x02\x02\u04C5\u049E\x03\x02\x02\x02\u04C5\u04A9\x03\x02" + - "\x02\x02\u04C5\u04B4\x03\x02\x02\x02\u04C6\x8C\x03\x02\x02\x02\u04C7\u04C8" + - "\x05\xCBd\x02\u04C8\u04C9\x05\xF5y\x02\u04C9\u04CA\x05\xD7j\x02\u04CA" + - "\u055F\x03\x02\x02\x02\u04CB\u04CC\x05\xE3p\x02\u04CC\u04CD\x05\xDBl\x02" + - "\u04CD\u04CE\x05\xE5q\x02\u04CE\u055F\x03\x02\x02\x02\u04CF\u04D0\x05" + - "\xE3p\x02\u04D0\u04D1\x05\xCBd\x02\u04D1\u04D2\x05\xF9{\x02\u04D2\u055F" + - "\x03\x02\x02\x02\u04D3\u04D4\x05\xEFv\x02\u04D4\u04D5\x05\xF3x\x02\u04D5" + - "\u04D6\x05\xE3p\x02\u04D6\u055F\x03\x02\x02\x02\u04D7\u04D8\x05\xCFf\x02" + - "\u04D8\u04D9\x05\xE7r\x02\u04D9\u04DA\x05\xF3x\x02\u04DA\u04DB\x05\xE5" + - "q\x02\u04DB\u04DC\x05\xF1w\x02\u04DC\u055F\x03\x02\x02\x02\u04DD\u04DE" + - "\x05\xCFf\x02\u04DE\u04DF\x05\xE7r\x02\u04DF\u04E0\x05\xF3x\x02\u04E0" + - "\u04E1\x05\xE5q\x02\u04E1\u04E2\x05\xF1w\x02\u04E2\u04E3\x05o6\x02\u04E3" + - "\u04E4\x05\xD1g\x02\u04E4\u04E5\x05\xDBl\x02\u04E5\u04E6\x05\xEFv\x02" + - "\u04E6\u04E7\x05\xF1w\x02\u04E7\u04E8\x05\xDBl\x02\u04E8\u04E9\x05\xE5" + - "q\x02\u04E9\u04EA\x05\xCFf\x02\u04EA\u04EB\x05\xF1w\x02\u04EB\u055F\x03" + - "\x02\x02\x02\u04EC\u04ED\x05\xE9s\x02\u04ED\u04EE\x05\xD3h\x02\u04EE\u04EF" + - "\x05\xEDu\x02\u04EF\u04F0\x05\xCFf\x02\u04F0\u04F1\x05\xD3h\x02\u04F1" + - "\u04F2\x05\xE5q\x02\u04F2\u04F3\x05\xF1w\x02\u04F3\u04F4\x05\xDBl\x02" + - "\u04F4\u04F5\x05\xE1o\x02\u04F5\u04F6\x05\xD3h\x02\u04F6\u055F\x03\x02" + - "\x02\x02\u04F7\u04F8\x05\xE3p\x02\u04F8\u04F9\x05\xD3h\x02\u04F9\u04FA" + - "\x05\xD1g\x02\u04FA\u04FB\x05\xDBl\x02\u04FB\u04FC\x05\xCBd\x02\u04FC" + - "\u04FD\x05\xE5q\x02\u04FD\u055F\x03\x02\x02\x02\u04FE\u04FF\x05\xE3p\x02" + - "\u04FF\u0500\x05\xD3h\x02\u0500\u0501\x05\xD1g\x02\u0501\u0502\x05\xDB" + - "l\x02\u0502\u0503\x05\xCBd\x02\u0503\u0504\x05\xE5q\x02\u0504\u0505\x05" + - "o6\x02\u0505\u0506\x05\xCBd\x02\u0506\u0507\x05\xCDe\x02\u0507\u0508\x05" + - "\xEFv\x02\u0508\u0509\x05\xE7r\x02\u0509\u050A\x05\xE1o\x02\u050A\u050B" + - "\x05\xF3x\x02\u050B\u050C\x05\xF1w\x02\u050C\u050D\x05\xD3h\x02\u050D" + - "\u050E\x05o6\x02\u050E\u050F\x05\xD1g\x02\u050F\u0510\x05\xD3h\x02\u0510" + - "\u0511\x05\xF5y\x02\u0511\u0512\x05\xDBl\x02\u0512\u0513\x05\xCBd\x02" + - "\u0513\u0514\x05\xF1w\x02\u0514\u0515\x05\xDBl\x02\u0515\u0516\x05\xE7" + - "r\x02\u0516\u0517\x05\xE5q\x02\u0517\u055F\x03\x02\x02\x02\u0518\u0519" + - "\x05\xCBd\x02\u0519\u051A\x05\xCFf\x02\u051A\u051B\x05\xE7r\x02\u051B" + - "\u051C\x05\xEFv\x02\u051C\u055F\x03\x02\x02\x02\u051D\u051E\x05\xCBd\x02" + - "\u051E\u051F\x05\xEFv\x02\u051F\u0520\x05\xDBl\x02\u0520\u0521\x05\xE5" + - "q\x02\u0521\u055F\x03\x02\x02\x02\u0522\u0523\x05\xCBd\x02\u0523\u0524" + - "\x05\xF1w\x02\u0524\u0525\x05\xCBd\x02\u0525\u0526\x05\xE5q\x02\u0526" + - "\u055F\x03\x02\x02\x02\u0527\u0528\x05\xCBd\x02\u0528\u0529\x05\xF1w\x02" + - "\u0529\u052A\x05\xCBd\x02\u052A\u052B\x05\xE5q\x02\u052B\u052C\x074\x02" + - "\x02\u052C\u055F\x03\x02\x02\x02\u052D\u052E\x05\xCFf\x02\u052E\u052F" + - "\x05\xD3h\x02\u052F\u0530\x05\xDBl\x02\u0530\u0531\x05\xE1o\x02\u0531" + - "\u055F\x03\x02\x02\x02\u0532\u0533\x05\xCFf\x02\u0533\u0534\x05\xE7r\x02" + - "\u0534\u0535\x05\xEFv\x02\u0535\u055F\x03\x02\x02\x02\u0536\u0537\x05" + - "\xCFf\x02\u0537\u0538\x05\xE7r\x02\u0538\u0539\x05\xEFv\x02\u0539\u053A" + - "\x05\xD9k\x02\u053A\u055F\x03\x02\x02\x02\u053B\u053C\x05\xD5i\x02\u053C" + - "\u053D\x05\xE1o\x02\u053D\u053E\x05\xE7r\x02\u053E\u053F\x05\xE7r\x02" + - "\u053F\u0540\x05\xEDu\x02\u0540\u055F\x03\x02\x02\x02\u0541\u0542\x05" + - "\xE1o\x02\u0542\u0543\x05\xF1w\x02\u0543\u0544\x05\xEDu\x02\u0544\u0545" + - "\x05\xDBl\x02\u0545\u0546\x05\xE3p\x02\u0546\u055F\x03\x02\x02\x02\u0547" + - "\u0548\x05\xEFv\x02\u0548\u0549\x05\xDBl\x02\u0549\u054A\x05\xE5q\x02" + - "\u054A\u055F\x03\x02\x02\x02\u054B\u054C\x05\xEFv\x02\u054C\u054D\x05" + - "\xDBl\x02\u054D\u054E\x05\xE5q\x02\u054E\u054F\x05\xD9k\x02\u054F\u055F" + - "\x03\x02\x02\x02\u0550\u0551\x05\xEFv\x02\u0551\u0552\x05\xEBt\x02\u0552" + - "\u0553\x05\xEDu\x02\u0553\u0554\x05\xF1w\x02\u0554\u055F\x03\x02\x02\x02" + - "\u0555\u0556\x05\xF1w\x02\u0556\u0557\x05\xCBd\x02\u0557\u0558\x05\xE5" + - "q\x02\u0558\u055F\x03\x02\x02\x02\u0559\u055A\x05\xF1w\x02\u055A\u055B" + - "\x05\xCBd\x02\u055B\u055C\x05\xE5q\x02\u055C\u055D\x05\xD9k\x02\u055D" + - "\u055F\x03\x02\x02\x02\u055E\u04C7\x03\x02\x02\x02\u055E\u04CB\x03\x02" + - "\x02\x02\u055E\u04CF\x03\x02\x02\x02\u055E\u04D3\x03\x02\x02\x02\u055E" + - "\u04D7\x03\x02\x02\x02\u055E\u04DD\x03\x02\x02\x02\u055E\u04EC\x03\x02" + - "\x02\x02\u055E\u04F7\x03\x02\x02\x02\u055E\u04FE\x03\x02\x02\x02\u055E" + - "\u0518\x03\x02\x02\x02\u055E\u051D\x03\x02\x02\x02\u055E\u0522\x03\x02" + - "\x02\x02\u055E\u0527\x03\x02\x02\x02\u055E\u052D\x03\x02\x02\x02\u055E" + - "\u0532\x03\x02\x02\x02\u055E\u0536\x03\x02\x02\x02\u055E\u053B\x03\x02" + - "\x02\x02\u055E\u0541\x03\x02\x02\x02\u055E\u0547\x03\x02\x02\x02\u055E" + - "\u054B\x03\x02\x02\x02\u055E\u0550\x03\x02\x02\x02\u055E\u0555\x03\x02" + - "\x02\x02\u055E\u0559\x03\x02\x02\x02\u055F\x8E\x03\x02\x02\x02\u0560\u0561" + - "\x05\xCFf\x02\u0561\u0562\x05\xDBl\x02\u0562\u0563\x05\xD1g\x02\u0563" + - "\u0564\x05\xEDu\x02\u0564\u0565\x05o6\x02\u0565\u0566\x05\xE3p\x02\u0566" + - "\u0567\x05\xCBd\x02\u0567\u0568\x05\xF1w\x02\u0568\u0569\x05\xCFf\x02" + - "\u0569\u056A\x05\xD9k\x02\u056A\x90\x03\x02\x02\x02\u056B\u0572\x05=\x1D" + - "\x02\u056C\u0571\x05=\x1D\x02\u056D\u0571\x05;\x1C\x02\u056E\u0571\x07" + - "a\x02\x02\u056F\u0571\x05}=\x02\u0570\u056C\x03\x02\x02\x02\u0570\u056D" + - "\x03\x02\x02\x02\u0570\u056E\x03\x02\x02\x02\u0570\u056F\x03\x02\x02\x02" + - "\u0571\u0574\x03\x02\x02\x02\u0572\u0570\x03\x02\x02\x02\u0572\u0573\x03" + - "\x02\x02\x02\u0573\u057F\x03\x02\x02\x02\u0574\u0572\x03\x02\x02\x02\u0575" + - "\u057A\t\n\x02\x02\u0576\u057B\x05=\x1D\x02\u0577\u057B\x05;\x1C\x02\u0578" + - "\u057B\x07a\x02\x02\u0579\u057B\x05}=\x02\u057A\u0576\x03\x02\x02\x02" + - "\u057A\u0577\x03\x02\x02\x02\u057A\u0578\x03\x02\x02\x02\u057A\u0579\x03" + - "\x02\x02\x02\u057B\u057C\x03\x02\x02\x02\u057C\u057A\x03\x02\x02\x02\u057C" + - "\u057D\x03\x02\x02\x02\u057D\u057F\x03\x02\x02\x02\u057E\u056B\x03\x02" + - "\x02\x02\u057E\u0575\x03\x02\x02\x02\u057F\x92\x03\x02\x02\x02\u0580\u0586" + - "\x07b\x02\x02\u0581\u0585\n\v\x02\x02\u0582\u0583\x07b\x02\x02\u0583\u0585" + - "\x07b\x02\x02\u0584\u0581\x03\x02\x02\x02\u0584\u0582\x03\x02\x02\x02" + - "\u0585\u0588\x03\x02\x02\x02\u0586\u0584\x03\x02\x02\x02\u0586\u0587\x03" + - "\x02\x02\x02\u0587\u0589\x03\x02\x02\x02\u0588\u0586\x03\x02\x02\x02\u0589" + - "\u058A\x07b\x02\x02\u058A\x94\x03\x02\x02\x02\u058B\u058C\x05)\x13\x02" + - "\u058C\u058D\x03\x02\x02\x02\u058D\u058E\bI\x06\x02\u058E\x96\x03\x02" + - "\x02\x02\u058F\u0590\x05+\x14\x02\u0590\u0591\x03\x02\x02\x02\u0591\u0592" + - "\bJ\x06\x02\u0592\x98\x03\x02\x02\x02\u0593\u0594\x05-\x15\x02\u0594\u0595" + - "\x03\x02\x02\x02\u0595\u0596\bK\x06\x02\u0596\x9A\x03\x02\x02\x02\u0597" + - "\u0598\x07~\x02\x02\u0598\u0599\x03\x02\x02\x02\u0599\u059A\bL\t\x02\u059A" + - "\u059B\bL\n\x02\u059B\x9C\x03\x02\x02\x02\u059C\u059D\x07]\x02\x02\u059D" + - "\u059E\x03\x02\x02\x02\u059E\u059F\bM\x07\x02\u059F\u05A0\bM\x04\x02\u05A0" + - "\u05A1\bM\x04\x02\u05A1\x9E\x03\x02\x02\x02\u05A2\u05A3\x07_\x02\x02\u05A3" + - "\u05A4\x03\x02\x02\x02\u05A4\u05A5\bN\n\x02\u05A5\u05A6\bN\n\x02\u05A6" + - "\u05A7\bN\v\x02\u05A7\xA0\x03\x02\x02\x02\u05A8\u05A9\x07.\x02\x02\u05A9" + - "\u05AA\x03\x02\x02\x02\u05AA\u05AB\bO\f\x02\u05AB\xA2\x03\x02\x02\x02" + - "\u05AC\u05AD\x07?\x02\x02\u05AD\u05AE\x03\x02\x02\x02\u05AE\u05AF\bP\r" + - "\x02\u05AF\xA4\x03\x02\x02\x02\u05B0\u05B1\x05\xE3p\x02\u05B1\u05B2\x05" + - "\xD3h\x02\u05B2\u05B3\x05\xF1w\x02\u05B3\u05B4\x05\xCBd\x02\u05B4\u05B5" + - "\x05\xD1g\x02\u05B5\u05B6\x05\xCBd\x02\u05B6\u05B7\x05\xF1w\x02\u05B7" + - "\u05B8\x05\xCBd\x02\u05B8\xA6\x03\x02\x02\x02\u05B9\u05BB\x05\xA9S\x02" + - "\u05BA\u05B9\x03\x02\x02\x02\u05BB\u05BC\x03\x02\x02\x02\u05BC\u05BA\x03" + - "\x02\x02\x02\u05BC\u05BD\x03\x02\x02\x02\u05BD\xA8\x03\x02\x02\x02\u05BE" + - "\u05C0\n\f\x02\x02\u05BF\u05BE\x03\x02\x02\x02\u05C0\u05C1\x03\x02\x02" + - "\x02\u05C1\u05BF\x03\x02\x02\x02\u05C1\u05C2\x03\x02\x02\x02\u05C2\u05C6" + - "\x03\x02\x02\x02\u05C3\u05C4\x071\x02\x02\u05C4\u05C6\n\r\x02\x02\u05C5" + - "\u05BF\x03\x02\x02\x02\u05C5\u05C3\x03\x02\x02\x02\u05C6\xAA\x03\x02\x02" + - "\x02\u05C7\u05C8\x05\x93H\x02\u05C8\xAC\x03\x02\x02\x02\u05C9\u05CA\x05" + - ")\x13\x02\u05CA\u05CB\x03\x02\x02\x02\u05CB\u05CC\bU\x06\x02\u05CC\xAE" + - "\x03\x02\x02\x02\u05CD\u05CE\x05+\x14\x02\u05CE\u05CF\x03\x02\x02\x02" + - "\u05CF\u05D0\bV\x06\x02\u05D0\xB0\x03\x02\x02\x02\u05D1\u05D2\x05-\x15" + - "\x02\u05D2\u05D3\x03\x02\x02\x02\u05D3\u05D4\bW\x06\x02\u05D4\xB2\x03" + - "\x02\x02\x02\u05D5\u05D6\x05\xE7r\x02\u05D6\u05D7\x05\xE5q\x02\u05D7\xB4" + - "\x03\x02\x02\x02\u05D8\u05D9\x05\xF7z\x02\u05D9\u05DA\x05\xDBl\x02\u05DA" + - "\u05DB\x05\xF1w\x02\u05DB\u05DC\x05\xD9k\x02\u05DC\xB6\x03\x02\x02\x02" + - "\u05DD\u05DE\x07~\x02\x02\u05DE\u05DF\x03\x02\x02\x02\u05DF\u05E0\bZ\t" + - "\x02\u05E0\u05E1\bZ\n\x02\u05E1\xB8\x03\x02\x02\x02\u05E2\u05E3\x07_\x02" + - "\x02\u05E3\u05E4\x03\x02\x02\x02\u05E4\u05E5\b[\n\x02\u05E5\u05E6\b[\n" + - "\x02\u05E6\u05E7\b[\v\x02\u05E7\xBA\x03\x02\x02\x02\u05E8\u05E9\x07.\x02" + - "\x02\u05E9\u05EA\x03\x02\x02\x02\u05EA\u05EB\b\\\f\x02\u05EB\xBC\x03\x02" + - "\x02\x02\u05EC\u05ED\x07?\x02\x02\u05ED\u05EE\x03\x02\x02\x02\u05EE\u05EF" + - "\b]\r\x02\u05EF\xBE\x03\x02\x02\x02\u05F0\u05F2\x05\xC1_\x02\u05F1\u05F0" + - "\x03\x02\x02\x02\u05F2\u05F3\x03\x02\x02\x02\u05F3\u05F1\x03\x02\x02\x02" + - "\u05F3\u05F4\x03\x02\x02\x02\u05F4\xC0\x03\x02\x02\x02\u05F5\u05F7\n\f" + - "\x02\x02\u05F6\u05F5\x03\x02\x02\x02\u05F7\u05F8\x03\x02\x02\x02\u05F8" + - "\u05F6\x03\x02\x02\x02\u05F8\u05F9\x03\x02\x02\x02\u05F9\u05FD\x03\x02" + - "\x02\x02\u05FA\u05FB\x071\x02\x02\u05FB\u05FD\n\r\x02\x02\u05FC\u05F6" + - "\x03\x02\x02\x02\u05FC\u05FA\x03\x02\x02\x02\u05FD\xC2\x03\x02\x02\x02" + - "\u05FE\u05FF\x05\x93H\x02\u05FF\xC4\x03\x02\x02\x02\u0600\u0601\x05)\x13" + - "\x02\u0601\u0602\x03\x02\x02\x02\u0602\u0603\ba\x06\x02\u0603\xC6\x03" + - "\x02\x02\x02\u0604\u0605\x05+\x14\x02\u0605\u0606\x03\x02\x02\x02\u0606" + - "\u0607\bb\x06\x02\u0607\xC8\x03\x02\x02\x02\u0608\u0609\x05-\x15\x02\u0609" + - "\u060A\x03\x02\x02\x02\u060A\u060B\bc\x06\x02\u060B\xCA\x03\x02\x02\x02" + - "\u060C\u060D\t\x0E\x02\x02\u060D\xCC\x03\x02\x02\x02\u060E\u060F\t\x0F" + - "\x02\x02\u060F\xCE\x03\x02\x02\x02\u0610\u0611\t\x10\x02\x02\u0611\xD0" + - "\x03\x02\x02\x02\u0612\u0613\t\x11\x02\x02\u0613\xD2\x03\x02\x02\x02\u0614" + - "\u0615\t\b\x02\x02\u0615\xD4\x03\x02\x02\x02\u0616\u0617\t\x12\x02\x02" + - "\u0617\xD6\x03\x02\x02\x02\u0618\u0619\t\x13\x02\x02\u0619\xD8\x03\x02" + - "\x02\x02\u061A\u061B\t\x14\x02\x02\u061B\xDA\x03\x02\x02\x02\u061C\u061D" + - "\t\x15\x02\x02\u061D\xDC\x03\x02\x02\x02\u061E\u061F\t\x16\x02\x02\u061F" + - "\xDE\x03\x02\x02\x02\u0620\u0621\t\x17\x02\x02\u0621\xE0\x03\x02\x02\x02" + - "\u0622\u0623\t\x18\x02\x02\u0623\xE2\x03\x02\x02\x02\u0624\u0625\t\x19" + - "\x02\x02\u0625\xE4\x03\x02\x02\x02\u0626\u0627\t\x1A\x02\x02\u0627\xE6" + - "\x03\x02\x02\x02\u0628\u0629\t\x1B\x02\x02\u0629\xE8\x03\x02\x02\x02\u062A" + - "\u062B\t\x1C\x02\x02\u062B\xEA\x03\x02\x02\x02\u062C\u062D\t\x1D\x02\x02" + - "\u062D\xEC\x03\x02\x02\x02\u062E\u062F\t\x1E\x02\x02\u062F\xEE\x03\x02" + - "\x02\x02\u0630\u0631\t\x1F\x02\x02\u0631\xF0\x03\x02\x02\x02\u0632\u0633" + - "\t \x02\x02\u0633\xF2\x03\x02\x02\x02\u0634\u0635\t!\x02\x02\u0635\xF4" + - "\x03\x02\x02\x02\u0636\u0637\t\"\x02\x02\u0637\xF6\x03\x02\x02\x02\u0638" + - "\u0639\t#\x02\x02\u0639\xF8\x03\x02\x02\x02\u063A\u063B\t$\x02\x02\u063B" + - "\xFA\x03\x02\x02\x02\u063C\u063D\t%\x02\x02\u063D\xFC\x03\x02\x02\x02" + - "\u063E\u063F\t&\x02\x02\u063F\xFE\x03\x02\x02\x022\x02\x03\x04\x05\x06" + - "\u0190\u0194\u0197\u01A0\u01A2\u01AD\u01D6\u01DB\u01E0\u01E2\u01ED\u01F5" + - "\u01F8\u01FA\u01FF\u0204\u020A\u0211\u0216\u021C\u021F\u0227\u022B\u028E" + - "\u02E2\u02EE\u0304\u0315\u04C5\u055E\u0570\u0572\u057A\u057C\u057E\u0584" + - "\u0586\u05BC\u05C1\u05C5\u05F3\u05F8\u05FC\x0E\x07\x04\x02\x07\x03\x02" + - "\x07\x05\x02\x07\x06\x02\x02\x03\x02\t%\x02\x07\x02\x02\t\x1A\x02\x06" + - "\x02\x02\t&\x02\t\"\x02\t!\x02"; + "\u01D7\u01D6\x03\x02\x02\x02\u01D8\u01DB\x03\x02\x02\x02\u01D9\u01D7\x03" + + "\x02\x02\x02\u01D9\u01DA\x03\x02\x02\x02\u01DA\u01FB\x03\x02\x02\x02\u01DB" + + "\u01D9\x03\x02\x02\x02\u01DC\u01DE\x05K%\x02\u01DD\u01DF\x05/\x17\x02" + + "\u01DE\u01DD\x03\x02\x02\x02\u01DF\u01E0\x03\x02\x02\x02\u01E0\u01DE\x03" + + "\x02\x02\x02\u01E0\u01E1\x03\x02\x02\x02\u01E1\u01FB\x03\x02\x02\x02\u01E2" + + "\u01E4\x05/\x17\x02\u01E3\u01E2\x03\x02\x02\x02\u01E4\u01E5\x03\x02\x02" + + "\x02\u01E5\u01E3\x03\x02\x02\x02\u01E5\u01E6\x03\x02\x02\x02\u01E6\u01EE" + + "\x03\x02\x02\x02\u01E7\u01EB\x05K%\x02\u01E8\u01EA\x05/\x17\x02\u01E9" + + "\u01E8\x03\x02\x02\x02\u01EA\u01ED\x03\x02\x02\x02\u01EB\u01E9\x03\x02" + + "\x02\x02\u01EB\u01EC\x03\x02\x02\x02\u01EC\u01EF\x03\x02\x02\x02\u01ED" + + "\u01EB\x03\x02\x02\x02\u01EE\u01E7\x03\x02\x02\x02\u01EE\u01EF\x03\x02" + + "\x02\x02\u01EF\u01F0\x03\x02\x02\x02\u01F0\u01F1\x057\x1B\x02\u01F1\u01FB" + + "\x03\x02\x02\x02\u01F2\u01F4\x05K%\x02\u01F3\u01F5\x05/\x17\x02\u01F4" + + "\u01F3\x03\x02\x02\x02\u01F5\u01F6\x03\x02\x02\x02\u01F6\u01F4\x03\x02" + + "\x02\x02\u01F6\u01F7\x03\x02\x02\x02\u01F7\u01F8\x03\x02\x02\x02\u01F8" + + "\u01F9\x057\x1B\x02\u01F9\u01FB\x03\x02\x02\x02\u01FA\u01D1\x03\x02\x02" + + "\x02\u01FA\u01DC\x03\x02\x02\x02\u01FA\u01E3\x03\x02\x02\x02\u01FA\u01F2" + + "\x03\x02\x02\x02\u01FB>\x03\x02\x02\x02\u01FC\u01FD\x05\xB5Z\x02\u01FD" + + "\u01FE\x05\xE3q\x02\u01FE@\x03\x02\x02\x02\u01FF\u0200\x05\xB3Y\x02\u0200" + + "\u0201\x05\xCDf\x02\u0201\u0202\x05\xB9\\\x02\u0202B\x03\x02\x02\x02\u0203" + + "\u0204\x05\xB3Y\x02\u0204\u0205\x05\xD7k\x02\u0205\u0206\x05\xB7[\x02" + + "\u0206D\x03\x02\x02\x02\u0207\u0208\x07?\x02\x02\u0208F\x03\x02\x02\x02" + + "\u0209\u020A\x07.\x02\x02\u020AH\x03\x02\x02\x02\u020B\u020C\x05\xB9\\" + + "\x02\u020C\u020D\x05\xBB]\x02\u020D\u020E\x05\xD7k\x02\u020E\u020F\x05" + + "\xB7[\x02\u020FJ\x03\x02\x02\x02\u0210\u0211\x070\x02\x02\u0211L\x03\x02" + + "\x02\x02\u0212\u0213\x05\xBD^\x02\u0213\u0214\x05\xB3Y\x02\u0214\u0215" + + "\x05\xC9d\x02\u0215\u0216\x05\xD7k\x02\u0216\u0217\x05\xBB]\x02\u0217" + + "N\x03\x02\x02\x02\u0218\u0219\x05\xBD^\x02\u0219\u021A\x05\xC3a\x02\u021A" + + "\u021B\x05\xD5j\x02\u021B\u021C\x05\xD7k\x02\u021C\u021D\x05\xD9l\x02" + + "\u021DP\x03\x02\x02\x02\u021E\u021F\x05\xC9d\x02\u021F\u0220\x05\xB3Y" + + "\x02\u0220\u0221\x05\xD7k\x02\u0221\u0222\x05\xD9l\x02\u0222R\x03\x02" + + "\x02\x02\u0223\u0224\x07*\x02\x02\u0224T\x03\x02\x02\x02\u0225\u0226\x05" + + "\xC3a\x02\u0226\u0227\x05\xCDf\x02\u0227V\x03\x02\x02\x02\u0228\u0229" + + "\x05\xC3a\x02\u0229\u022A\x05\xD7k\x02\u022AX\x03\x02\x02\x02\u022B\u022C" + + "\x05\xC9d\x02\u022C\u022D\x05\xC3a\x02\u022D\u022E\x05\xC7c\x02\u022E" + + "\u022F\x05\xBB]\x02\u022FZ\x03\x02\x02\x02\u0230\u0231\x05\xCDf\x02\u0231" + + "\u0232\x05\xCFg\x02\u0232\u0233\x05\xD9l\x02\u0233\\\x03\x02\x02\x02\u0234" + + "\u0235\x05\xCDf\x02\u0235\u0236\x05\xDBm\x02\u0236\u0237\x05\xC9d\x02" + + "\u0237\u0238\x05\xC9d\x02\u0238^\x03\x02\x02\x02\u0239\u023A\x05\xCDf" + + "\x02\u023A\u023B\x05\xDBm\x02\u023B\u023C\x05\xC9d\x02\u023C\u023D\x05" + + "\xC9d\x02\u023D\u023E\x05\xD7k\x02\u023E`\x03\x02\x02\x02\u023F\u0240" + + "\x05\xCFg\x02\u0240\u0241\x05\xD5j\x02\u0241b\x03\x02\x02\x02\u0242\u0243" + + "\x07A\x02\x02\u0243d\x03\x02\x02\x02\u0244\u0245\x05\xD5j\x02\u0245\u0246" + + "\x05\xC9d\x02\u0246\u0247\x05\xC3a\x02\u0247\u0248\x05\xC7c\x02\u0248" + + "\u0249\x05\xBB]\x02\u0249f\x03\x02\x02\x02\u024A\u024B\x07+\x02\x02\u024B" + + "h\x03\x02\x02\x02\u024C\u024D\x05\xD9l\x02\u024D\u024E\x05\xD5j\x02\u024E" + + "\u024F\x05\xDBm\x02\u024F\u0250\x05\xBB]\x02\u0250j\x03\x02\x02\x02\u0251" + + "\u0252\x05\xC3a\x02\u0252\u0253\x05\xCDf\x02\u0253\u0254\x05\xBD^\x02" + + "\u0254\u0255\x05\xCFg\x02\u0255l\x03\x02\x02\x02\u0256\u0257\x05\xBD^" + + "\x02\u0257\u0258\x05\xDBm\x02\u0258\u0259\x05\xCDf\x02\u0259\u025A\x05" + + "\xB7[\x02\u025A\u025B\x05\xD9l\x02\u025B\u025C\x05\xC3a\x02\u025C\u025D" + + "\x05\xCFg\x02\u025D\u025E\x05\xCDf\x02\u025E\u025F\x05\xD7k\x02\u025F" + + "n\x03\x02\x02\x02\u0260\u0261\x07a\x02\x02\u0261p\x03\x02\x02\x02\u0262" + + "\u0263\x07?\x02\x02\u0263\u0264\x07?\x02\x02\u0264r\x03\x02\x02\x02\u0265" + + "\u0266\x07#\x02\x02\u0266\u0267\x07?\x02\x02\u0267t\x03\x02\x02\x02\u0268" + + "\u0269\x07>\x02\x02\u0269v\x03\x02\x02\x02\u026A\u026B\x07>\x02\x02\u026B" + + "\u026C\x07?\x02\x02\u026Cx\x03\x02\x02\x02\u026D\u026E\x07@\x02\x02\u026E" + + "z\x03\x02\x02\x02\u026F\u0270\x07@\x02\x02\u0270\u0271\x07?\x02\x02\u0271" + + "|\x03\x02\x02\x02\u0272\u0273\x07-\x02\x02\u0273~\x03\x02\x02\x02\u0274" + + "\u0275\x07/\x02\x02\u0275\x80\x03\x02\x02\x02\u0276\u0277\x07,\x02\x02" + + "\u0277\x82\x03\x02\x02\x02\u0278\u0279\x071\x02\x02\u0279\x84\x03\x02" + + "\x02\x02\u027A\u027B\x07\'\x02\x02\u027B\x86\x03\x02\x02\x02\u027C\u027D" + + "\x07]\x02\x02\u027D\u027E\x03\x02\x02\x02\u027E\u027F\bC\x02\x02\u027F" + + "\u0280\bC\x02\x02\u0280\x88\x03\x02\x02\x02\u0281\u0282\x07_\x02\x02\u0282" + + "\u0283\x03\x02\x02\x02\u0283\u0284\bD\x05\x02\u0284\u0285\bD\x05\x02\u0285" + + "\x8A\x03\x02\x02\x02\u0286\u028C\x051\x18\x02\u0287\u028B\x051\x18\x02" + + "\u0288\u028B\x05/\x17\x02\u0289\u028B\x07a\x02\x02\u028A\u0287\x03\x02" + + "\x02\x02\u028A\u0288\x03\x02\x02\x02\u028A\u0289\x03\x02\x02\x02\u028B" + + "\u028E\x03\x02\x02\x02\u028C\u028A\x03\x02\x02\x02\u028C\u028D\x03\x02" + + "\x02\x02\u028D\u0298\x03\x02\x02\x02\u028E\u028C\x03\x02\x02\x02\u028F" + + "\u0293\t\v\x02\x02\u0290\u0294\x051\x18\x02\u0291\u0294\x05/\x17\x02\u0292" + + "\u0294\x07a\x02\x02\u0293\u0290\x03\x02\x02\x02\u0293\u0291\x03\x02\x02" + + "\x02\u0293\u0292\x03\x02\x02\x02\u0294\u0295\x03\x02\x02\x02\u0295\u0293" + + "\x03\x02\x02\x02\u0295\u0296\x03\x02\x02\x02\u0296\u0298\x03\x02\x02\x02" + + "\u0297\u0286\x03\x02\x02\x02\u0297\u028F\x03\x02\x02\x02\u0298\x8C\x03" + + "\x02\x02\x02\u0299\u029F\x07b\x02\x02\u029A\u029E\n\f\x02\x02\u029B\u029C" + + "\x07b\x02\x02\u029C\u029E\x07b\x02\x02\u029D\u029A\x03\x02\x02\x02\u029D" + + "\u029B\x03\x02\x02\x02\u029E\u02A1\x03\x02\x02\x02\u029F\u029D\x03\x02" + + "\x02\x02\u029F\u02A0\x03\x02\x02\x02\u02A0\u02A2\x03\x02\x02\x02\u02A1" + + "\u029F\x03\x02\x02\x02\u02A2\u02A3\x07b\x02\x02\u02A3\x8E\x03\x02\x02" + + "\x02\u02A4\u02A5\x05\'\x13\x02\u02A5\u02A6\x03\x02\x02\x02\u02A6\u02A7" + + "\bG\x04\x02\u02A7\x90\x03\x02\x02\x02\u02A8\u02A9\x05)\x14\x02\u02A9\u02AA" + + "\x03\x02\x02\x02\u02AA\u02AB\bH\x04\x02\u02AB\x92\x03\x02\x02\x02\u02AC" + + "\u02AD\x05+\x15\x02\u02AD\u02AE\x03\x02\x02\x02\u02AE\u02AF\bI\x04\x02" + + "\u02AF\x94\x03\x02\x02\x02\u02B0\u02B1\x07~\x02\x02\u02B1\u02B2\x03\x02" + + "\x02\x02\u02B2\u02B3\bJ\x06\x02\u02B3\u02B4\bJ\x05\x02\u02B4\x96\x03\x02" + + "\x02\x02\u02B5\u02B6\x07]\x02\x02\u02B6\u02B7\x03\x02\x02\x02\u02B7\u02B8" + + "\bK\x07\x02\u02B8\u02B9\bK\x03\x02\u02B9\u02BA\bK\x03\x02\u02BA\x98\x03" + + "\x02\x02\x02\u02BB\u02BC\x07_\x02\x02\u02BC\u02BD\x03\x02\x02\x02\u02BD" + + "\u02BE\bL\x05\x02\u02BE\u02BF\bL\x05\x02\u02BF\u02C0\bL\b\x02\u02C0\x9A" + + "\x03\x02\x02\x02\u02C1\u02C2\x07.\x02\x02\u02C2\u02C3\x03\x02\x02\x02" + + "\u02C3\u02C4\bM\t\x02\u02C4\x9C\x03\x02\x02\x02\u02C5\u02C6\x07?\x02\x02" + + "\u02C6\u02C7\x03\x02\x02\x02\u02C7\u02C8\bN\n\x02\u02C8\x9E\x03\x02\x02" + + "\x02\u02C9\u02CA\x05\xB3Y\x02\u02CA\u02CB\x05\xD7k\x02\u02CB\xA0\x03\x02" + + "\x02\x02\u02CC\u02CD\x05\xCBe\x02\u02CD\u02CE\x05\xBB]\x02\u02CE\u02CF" + + "\x05\xD9l\x02\u02CF\u02D0\x05\xB3Y\x02\u02D0\u02D1\x05\xB9\\\x02\u02D1" + + "\u02D2\x05\xB3Y\x02\u02D2\u02D3\x05\xD9l\x02\u02D3\u02D4\x05\xB3Y\x02" + + "\u02D4\xA2\x03\x02\x02\x02\u02D5\u02D6\x05\xCFg\x02\u02D6\u02D7\x05\xCD" + + "f\x02\u02D7\xA4\x03\x02\x02\x02\u02D8\u02D9\x05\xDFo\x02\u02D9\u02DA\x05" + + "\xC3a\x02\u02DA\u02DB\x05\xD9l\x02\u02DB\u02DC\x05\xC1`\x02\u02DC\xA6" + + "\x03\x02\x02\x02\u02DD\u02DF\x05\xA9T\x02\u02DE\u02DD\x03\x02\x02\x02" + + "\u02DF\u02E0\x03\x02\x02\x02\u02E0\u02DE\x03\x02\x02\x02\u02E0\u02E1\x03" + + "\x02\x02\x02\u02E1\xA8\x03\x02\x02\x02\u02E2\u02E4\n\r\x02\x02\u02E3\u02E2" + + "\x03\x02\x02\x02\u02E4\u02E5\x03\x02\x02\x02\u02E5\u02E3\x03\x02\x02\x02" + + "\u02E5\u02E6\x03\x02\x02\x02\u02E6\u02EA\x03\x02\x02\x02\u02E7\u02E8\x07" + + "1\x02\x02\u02E8\u02EA\n\x0E\x02\x02\u02E9\u02E3\x03\x02\x02\x02\u02E9" + + "\u02E7\x03\x02\x02\x02\u02EA\xAA\x03\x02\x02\x02\u02EB\u02EC\x05\x8DF" + + "\x02\u02EC\xAC\x03\x02\x02\x02\u02ED\u02EE\x05\'\x13\x02\u02EE\u02EF\x03" + + "\x02\x02\x02\u02EF\u02F0\bV\x04\x02\u02F0\xAE\x03\x02\x02\x02\u02F1\u02F2" + + "\x05)\x14\x02\u02F2\u02F3\x03\x02\x02\x02\u02F3\u02F4\bW\x04\x02\u02F4" + + "\xB0\x03\x02\x02\x02\u02F5\u02F6\x05+\x15\x02\u02F6\u02F7\x03\x02\x02" + + "\x02\u02F7\u02F8\bX\x04\x02\u02F8\xB2\x03\x02\x02\x02\u02F9\u02FA\t\x0F" + + "\x02\x02\u02FA\xB4\x03\x02\x02\x02\u02FB\u02FC\t\x10\x02\x02\u02FC\xB6" + + "\x03\x02\x02\x02\u02FD\u02FE\t\x11\x02\x02\u02FE\xB8\x03\x02\x02\x02\u02FF" + + "\u0300\t\x12\x02\x02\u0300\xBA\x03\x02\x02\x02\u0301\u0302\t\t\x02\x02" + + "\u0302\xBC\x03\x02\x02\x02\u0303\u0304\t\x13\x02\x02\u0304\xBE\x03\x02" + + "\x02\x02\u0305\u0306\t\x14\x02\x02\u0306\xC0\x03\x02\x02\x02\u0307\u0308" + + "\t\x15\x02\x02\u0308\xC2\x03\x02\x02\x02\u0309\u030A\t\x16\x02\x02\u030A" + + "\xC4\x03\x02\x02\x02\u030B\u030C\t\x17\x02\x02\u030C\xC6\x03\x02\x02\x02" + + "\u030D\u030E\t\x18\x02\x02\u030E\xC8\x03\x02\x02\x02\u030F\u0310\t\x19" + + "\x02\x02\u0310\xCA\x03\x02\x02\x02\u0311\u0312\t\x1A\x02\x02\u0312\xCC" + + "\x03\x02\x02\x02\u0313\u0314\t\x1B\x02\x02\u0314\xCE\x03\x02\x02\x02\u0315" + + "\u0316\t\x1C\x02\x02\u0316\xD0\x03\x02\x02\x02\u0317\u0318\t\x1D\x02\x02" + + "\u0318\xD2\x03\x02\x02\x02\u0319\u031A\t\x1E\x02\x02\u031A\xD4\x03\x02" + + "\x02\x02\u031B\u031C\t\x1F\x02\x02\u031C\xD6\x03\x02\x02\x02\u031D\u031E" + + "\t \x02\x02\u031E\xD8\x03\x02\x02\x02\u031F\u0320\t!\x02\x02\u0320\xDA" + + "\x03\x02\x02\x02\u0321\u0322\t\"\x02\x02\u0322\xDC\x03\x02\x02\x02\u0323" + + "\u0324\t#\x02\x02\u0324\xDE\x03\x02\x02\x02\u0325\u0326\t$\x02\x02\u0326" + + "\xE0\x03\x02\x02\x02\u0327\u0328\t%\x02\x02\u0328\xE2\x03\x02\x02\x02" + + "\u0329\u032A\t&\x02\x02\u032A\xE4\x03\x02\x02\x02\u032B\u032C\t\'\x02" + + "\x02\u032C\xE6\x03\x02\x02\x02\'\x02\x03\x04\u016B\u0175\u0179\u017C\u0185" + + "\u0187\u0192\u01A5\u01AA\u01AF\u01B1\u01BC\u01C4\u01C7\u01C9\u01CE\u01D3" + + "\u01D9\u01E0\u01E5\u01EB\u01EE\u01F6\u01FA\u028A\u028C\u0293\u0295\u0297" + + "\u029D\u029F\u02E0\u02E5\u02E9\v\x07\x03\x02\x07\x04\x02\x02\x03\x02\x06" + + "\x02\x02\t\x17\x02\t?\x02\t@\x02\t\x1F\x02\t\x1E\x02"; public static readonly _serializedATN: string = Utils.join( [ esql_lexer._serializedATNSegment0, esql_lexer._serializedATNSegment1, - esql_lexer._serializedATNSegment2, ], "", ); diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 b/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 index af48024e56cc9..aa2e86b6979e1 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 @@ -20,8 +20,7 @@ query ; sourceCommand - : explainCommand - | fromCommand + : fromCommand | rowCommand | showCommand ; @@ -29,51 +28,30 @@ sourceCommand processingCommand : evalCommand | limitCommand - | projectCommand | keepCommand - | renameCommand - | dropCommand - | dissectCommand - | grokCommand | sortCommand | statsCommand | whereCommand - | mvExpandCommand + | dropCommand + | renameCommand + | dissectCommand + | grokCommand | enrichCommand - ; - -enrichCommand - : ENRICH policyName=enrichIdentifier (ON matchField=enrichFieldIdentifier)? (WITH enrichWithClause (COMMA enrichWithClause)*)? - ; - -enrichWithClause - : (newName=enrichFieldIdentifier ASSIGN)? enrichField=enrichFieldIdentifier - ; - -mvExpandCommand - : MV_EXPAND qualifiedNames + | mvExpandCommand ; whereCommand - : WHERE whereBooleanExpression - ; - -whereBooleanExpression - : NOT whereBooleanExpression - | valueExpression - | regexBooleanExpression - | left=whereBooleanExpression operator=AND right=whereBooleanExpression - | left=whereBooleanExpression operator=OR right=whereBooleanExpression - | valueExpression (NOT)? IN LP valueExpression (COMMA valueExpression)* RP - | (NOT)? WHERE_FUNCTIONS LP qualifiedName ((COMMA functionExpressionArgument)*)? RP - | valueExpression IS NOT? NULL + : WHERE booleanExpression ; booleanExpression - : NOT booleanExpression - | valueExpression - | left=booleanExpression operator=AND right=booleanExpression - | left=booleanExpression operator=OR right=booleanExpression + : NOT booleanExpression #logicalNot + | valueExpression #booleanDefault + | regexBooleanExpression #regexExpression + | left=booleanExpression operator=AND right=booleanExpression #logicalBinary + | left=booleanExpression operator=OR right=booleanExpression #logicalBinary + | valueExpression (NOT)? IN LP valueExpression (COMMA valueExpression)* RP #logicalIn + | valueExpression IS NOT? NULL #isNull ; regexBooleanExpression @@ -82,41 +60,26 @@ regexBooleanExpression ; valueExpression - : operatorExpression - | comparison + : operatorExpression #valueExpressionDefault + | left=operatorExpression comparisonOperator right=operatorExpression #comparison ; -comparison - : left=operatorExpression comparisonOperator right=operatorExpression - ; - -mathFn - : functionIdentifier LP (functionExpressionArgument (COMMA functionExpressionArgument)*)? RP - ; - -mathEvalFn - : mathFunctionIdentifier LP (mathFunctionExpressionArgument (COMMA mathFunctionExpressionArgument)*)? RP - ; - -dateExpression - : quantifier=number DATE_LITERAL - ; - operatorExpression - : primaryExpression - | mathFn - | mathEvalFn - | operator=(MINUS | PLUS) operatorExpression - | left=operatorExpression operator=(ASTERISK | SLASH | PERCENT) right=operatorExpression - | left=operatorExpression operator=(PLUS | MINUS) right=operatorExpression + : primaryExpression #operatorExpressionDefault + | operator=(MINUS | PLUS) operatorExpression #arithmeticUnary + | left=operatorExpression operator=(ASTERISK | SLASH | PERCENT) right=operatorExpression #arithmeticBinary + | left=operatorExpression operator=(PLUS | MINUS) right=operatorExpression #arithmeticBinary ; primaryExpression - : constant - | qualifiedName - | dateExpression - | LP booleanExpression RP - | identifier LP (booleanExpression (COMMA booleanExpression)*)? RP + : constant #constantDefault + | qualifiedName #dereference + | functionExpression #function + | LP booleanExpression RP #parenthesizedExpression + ; + +functionExpression + : identifier LP (ASTERISK | (booleanExpression (COMMA booleanExpression)*))? RP ; rowCommand @@ -129,18 +92,9 @@ fields field : booleanExpression - | userVariable ASSIGN booleanExpression + | qualifiedName ASSIGN booleanExpression ; -enrichFieldIdentifier - : ENR_UNQUOTED_IDENTIFIER - | ENR_QUOTED_IDENTIFIER - ; - -userVariable - : identifier - ; - fromCommand : FROM sourceIdentifier (COMMA sourceIdentifier)* metadata? ; @@ -154,7 +108,11 @@ evalCommand ; statsCommand - : STATS fields? (BY qualifiedNames)? + : STATS fields? (BY grouping)? + ; + +grouping + : qualifiedName (COMMA qualifiedName)* ; sourceIdentifier @@ -162,61 +120,26 @@ sourceIdentifier | SRC_QUOTED_IDENTIFIER ; -enrichIdentifier - : ENR_UNQUOTED_IDENTIFIER - | ENR_QUOTED_IDENTIFIER - ; - -functionExpressionArgument - : qualifiedName - | string - | number - ; - -mathFunctionExpressionArgument - : qualifiedName - | string - | number - | operatorExpression - | dateExpression - | comparison - ; - qualifiedName : identifier (DOT identifier)* ; -qualifiedNames - : qualifiedName (COMMA qualifiedName)* - ; - identifier : UNQUOTED_IDENTIFIER | QUOTED_IDENTIFIER - | ASTERISK - ; - -mathFunctionIdentifier - : MATH_FUNCTION - ; - -functionIdentifier - : UNARY_FUNCTION ; constant - : NULL - | numericValue - | booleanValue - | string - | OPENING_BRACKET numericValue (COMMA numericValue)* CLOSING_BRACKET - | OPENING_BRACKET booleanValue (COMMA booleanValue)* CLOSING_BRACKET - | OPENING_BRACKET string (COMMA string)* CLOSING_BRACKET - ; - -numericValue - : decimalValue - | integerValue + : NULL #nullLiteral + | integerValue UNQUOTED_IDENTIFIER #qualifiedIntegerLiteral + | decimalValue #decimalLiteral + | integerValue #integerLiteral + | booleanValue #booleanLiteral + | PARAM #inputParam + | string #stringLiteral + | OPENING_BRACKET numericValue (COMMA numericValue)* CLOSING_BRACKET #numericArrayLiteral + | OPENING_BRACKET booleanValue (COMMA booleanValue)* CLOSING_BRACKET #booleanArrayLiteral + | OPENING_BRACKET string (COMMA string)* CLOSING_BRACKET #stringArrayLiteral ; limitCommand @@ -228,40 +151,36 @@ sortCommand ; orderExpression - : booleanExpression (ORDERING)? (NULLS_ORDERING (NULLS_ORDERING_DIRECTION))? - ; - -projectCommand - : PROJECT qualifiedNames + : booleanExpression ordering=(ASC | DESC)? (NULLS nullOrdering=(FIRST | LAST))? ; keepCommand - : KEEP qualifiedNames + : KEEP sourceIdentifier (COMMA sourceIdentifier)* + | PROJECT sourceIdentifier (COMMA sourceIdentifier)* ; - dropCommand - : DROP qualifiedNames + : DROP sourceIdentifier (COMMA sourceIdentifier)* ; -renameVariable - : identifier (DOT identifier)* - ; - renameCommand : RENAME renameClause (COMMA renameClause)* ; -renameClause - : qualifiedName AS renameVariable +renameClause: + oldName=sourceIdentifier AS newName=sourceIdentifier ; dissectCommand - : DISSECT qualifiedNames string commandOptions? + : DISSECT primaryExpression string commandOptions? ; grokCommand - : GROK qualifiedNames string + : GROK primaryExpression string + ; + +mvExpandCommand + : MV_EXPAND sourceIdentifier ; commandOptions @@ -273,20 +192,20 @@ commandOption ; booleanValue - : BOOLEAN_VALUE + : TRUE | FALSE ; -number - : DECIMAL_LITERAL #decimalLiteral - | INTEGER_LITERAL #integerLiteral +numericValue + : decimalValue + | integerValue ; decimalValue - : DECIMAL_LITERAL + : (PLUS | MINUS)? DECIMAL_LITERAL ; integerValue - : INTEGER_LITERAL + : (PLUS | MINUS)? INTEGER_LITERAL ; string @@ -294,18 +213,18 @@ string ; comparisonOperator - : COMPARISON_OPERATOR + : EQ | NEQ | LT | LTE | GT | GTE ; -explainCommand - : EXPLAIN subqueryExpression +showCommand + : SHOW INFO #showInfo + | SHOW FUNCTIONS #showFunctions ; -subqueryExpression - : OPENING_BRACKET query CLOSING_BRACKET +enrichCommand + : ENRICH policyName=sourceIdentifier (ON matchField=sourceIdentifier)? (WITH enrichWithClause (COMMA enrichWithClause)*)? ; -showCommand - : SHOW INFO - | SHOW FUNCTIONS - ; +enrichWithClause + : (newName=sourceIdentifier ASSIGN)? enrichField=sourceIdentifier + ; \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.interp b/packages/kbn-monaco/src/esql/antlr/esql_parser.interp index 378d85247dc13..649902a25536b 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.interp +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.interp @@ -27,46 +27,41 @@ null null null null -'by' null -'and' null null '.' +null +null +null '(' null -']' null null null null null null +'?' null -'or' ')' -'_' -'info' -'functions' null null +null +'_' +'==' +'!=' +'<' +'<=' +'>' +'>=' '+' '-' '*' '/' '%' -'10' -null -'nulls' -null -null -null -null -null -null -null -null null +']' null null null @@ -85,149 +80,128 @@ null token symbolic names: null DISSECT -GROK +DROP +ENRICH EVAL -EXPLAIN FROM -ROW -STATS -WHERE -SORT -MV_EXPAND +GROK +KEEP LIMIT +MV_EXPAND PROJECT -DROP RENAME +ROW SHOW -ENRICH -KEEP +SORT +STATS +WHERE +UNKNOWN_CMD LINE_COMMENT MULTILINE_COMMENT WS -EXPLAIN_WS -EXPLAIN_LINE_COMMENT -EXPLAIN_MULTILINE_COMMENT PIPE STRING INTEGER_LITERAL DECIMAL_LITERAL BY -DATE_LITERAL AND +ASC ASSIGN COMMA +DESC DOT +FALSE +FIRST +LAST LP -OPENING_BRACKET -CLOSING_BRACKET -NOT -LIKE -RLIKE IN IS -AS +LIKE +NOT NULL +NULLS OR +PARAM +RLIKE RP -UNDERSCORE +TRUE INFO FUNCTIONS -BOOLEAN_VALUE -COMPARISON_OPERATOR +UNDERSCORE +EQ +NEQ +LT +LTE +GT +GTE PLUS MINUS ASTERISK SLASH PERCENT -TEN -ORDERING -NULLS_ORDERING -NULLS_ORDERING_DIRECTION -MATH_FUNCTION -UNARY_FUNCTION -WHERE_FUNCTIONS +OPENING_BRACKET +CLOSING_BRACKET UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS +AS METADATA +ON +WITH SRC_UNQUOTED_IDENTIFIER SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS -ON -WITH -ENR_UNQUOTED_IDENTIFIER -ENR_QUOTED_IDENTIFIER -ENR_LINE_COMMENT -ENR_MULTILINE_COMMENT -ENR_WS -EXPLAIN_PIPE rule names: singleStatement query sourceCommand processingCommand -enrichCommand -enrichWithClause -mvExpandCommand whereCommand -whereBooleanExpression booleanExpression regexBooleanExpression valueExpression -comparison -mathFn -mathEvalFn -dateExpression operatorExpression primaryExpression +functionExpression rowCommand fields field -enrichFieldIdentifier -userVariable fromCommand metadata evalCommand statsCommand +grouping sourceIdentifier -enrichIdentifier -functionExpressionArgument -mathFunctionExpressionArgument qualifiedName -qualifiedNames identifier -mathFunctionIdentifier -functionIdentifier constant -numericValue limitCommand sortCommand orderExpression -projectCommand keepCommand dropCommand -renameVariable renameCommand renameClause dissectCommand grokCommand +mvExpandCommand commandOptions commandOption booleanValue -number +numericValue decimalValue integerValue string comparisonOperator -explainCommand -subqueryExpression showCommand +enrichCommand +enrichWithClause atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 83, 598, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 132, 10, 3, 12, 3, 14, 3, 135, 11, 3, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 141, 10, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 156, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 162, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 168, 10, 6, 12, 6, 14, 6, 171, 11, 6, 5, 6, 173, 10, 6, 3, 7, 3, 7, 3, 7, 5, 7, 178, 10, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 195, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 202, 10, 10, 12, 10, 14, 10, 205, 11, 10, 3, 10, 3, 10, 3, 10, 5, 10, 210, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 217, 10, 10, 12, 10, 14, 10, 220, 11, 10, 5, 10, 222, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 229, 10, 10, 3, 10, 3, 10, 5, 10, 233, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 241, 10, 10, 12, 10, 14, 10, 244, 11, 10, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 250, 10, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 7, 11, 258, 10, 11, 12, 11, 14, 11, 261, 11, 11, 3, 12, 3, 12, 5, 12, 265, 10, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 5, 12, 272, 10, 12, 3, 12, 3, 12, 3, 12, 5, 12, 277, 10, 12, 3, 13, 3, 13, 5, 13, 281, 10, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 7, 15, 292, 10, 15, 12, 15, 14, 15, 295, 11, 15, 5, 15, 297, 10, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 7, 16, 306, 10, 16, 12, 16, 14, 16, 309, 11, 16, 5, 16, 311, 10, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 324, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 332, 10, 18, 12, 18, 14, 18, 335, 11, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 349, 10, 19, 12, 19, 14, 19, 352, 11, 19, 5, 19, 354, 10, 19, 3, 19, 3, 19, 5, 19, 358, 10, 19, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 7, 21, 366, 10, 21, 12, 21, 14, 21, 369, 11, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 376, 10, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 7, 25, 386, 10, 25, 12, 25, 14, 25, 389, 11, 25, 3, 25, 5, 25, 392, 10, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 7, 26, 399, 10, 26, 12, 26, 14, 26, 402, 11, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 5, 28, 411, 10, 28, 3, 28, 3, 28, 5, 28, 415, 10, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 5, 31, 424, 10, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 5, 32, 432, 10, 32, 3, 33, 3, 33, 3, 33, 7, 33, 437, 10, 33, 12, 33, 14, 33, 440, 11, 33, 3, 34, 3, 34, 3, 34, 7, 34, 445, 10, 34, 12, 34, 14, 34, 448, 11, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 464, 10, 38, 12, 38, 14, 38, 467, 11, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 475, 10, 38, 12, 38, 14, 38, 478, 11, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 486, 10, 38, 12, 38, 14, 38, 489, 11, 38, 3, 38, 3, 38, 5, 38, 493, 10, 38, 3, 39, 3, 39, 5, 39, 497, 10, 39, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 41, 7, 41, 506, 10, 41, 12, 41, 14, 41, 509, 11, 41, 3, 42, 3, 42, 5, 42, 513, 10, 42, 3, 42, 3, 42, 5, 42, 517, 10, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 7, 46, 531, 10, 46, 12, 46, 14, 46, 534, 11, 46, 3, 47, 3, 47, 3, 47, 3, 47, 7, 47, 540, 10, 47, 12, 47, 14, 47, 543, 11, 47, 3, 48, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 49, 5, 49, 553, 10, 49, 3, 50, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 7, 51, 562, 10, 51, 12, 51, 14, 51, 565, 11, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 54, 3, 54, 5, 54, 575, 10, 54, 3, 55, 3, 55, 3, 56, 3, 56, 3, 57, 3, 57, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 61, 5, 61, 596, 10, 61, 3, 61, 2, 2, 6, 4, 18, 20, 34, 62, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 80, 2, 82, 2, 84, 2, 86, 2, 88, 2, 90, 2, 92, 2, 94, 2, 96, 2, 98, 2, 100, 2, 102, 2, 104, 2, 106, 2, 108, 2, 110, 2, 112, 2, 114, 2, 116, 2, 118, 2, 120, 2, 2, 7, 3, 2, 53, 54, 3, 2, 55, 57, 3, 2, 78, 79, 3, 2, 71, 72, 4, 2, 55, 55, 65, 66, 2, 627, 2, 122, 3, 2, 2, 2, 4, 125, 3, 2, 2, 2, 6, 140, 3, 2, 2, 2, 8, 155, 3, 2, 2, 2, 10, 157, 3, 2, 2, 2, 12, 177, 3, 2, 2, 2, 14, 181, 3, 2, 2, 2, 16, 184, 3, 2, 2, 2, 18, 232, 3, 2, 2, 2, 20, 249, 3, 2, 2, 2, 22, 276, 3, 2, 2, 2, 24, 280, 3, 2, 2, 2, 26, 282, 3, 2, 2, 2, 28, 286, 3, 2, 2, 2, 30, 300, 3, 2, 2, 2, 32, 314, 3, 2, 2, 2, 34, 323, 3, 2, 2, 2, 36, 357, 3, 2, 2, 2, 38, 359, 3, 2, 2, 2, 40, 362, 3, 2, 2, 2, 42, 375, 3, 2, 2, 2, 44, 377, 3, 2, 2, 2, 46, 379, 3, 2, 2, 2, 48, 381, 3, 2, 2, 2, 50, 393, 3, 2, 2, 2, 52, 405, 3, 2, 2, 2, 54, 408, 3, 2, 2, 2, 56, 416, 3, 2, 2, 2, 58, 418, 3, 2, 2, 2, 60, 423, 3, 2, 2, 2, 62, 431, 3, 2, 2, 2, 64, 433, 3, 2, 2, 2, 66, 441, 3, 2, 2, 2, 68, 449, 3, 2, 2, 2, 70, 451, 3, 2, 2, 2, 72, 453, 3, 2, 2, 2, 74, 492, 3, 2, 2, 2, 76, 496, 3, 2, 2, 2, 78, 498, 3, 2, 2, 2, 80, 501, 3, 2, 2, 2, 82, 510, 3, 2, 2, 2, 84, 518, 3, 2, 2, 2, 86, 521, 3, 2, 2, 2, 88, 524, 3, 2, 2, 2, 90, 527, 3, 2, 2, 2, 92, 535, 3, 2, 2, 2, 94, 544, 3, 2, 2, 2, 96, 548, 3, 2, 2, 2, 98, 554, 3, 2, 2, 2, 100, 558, 3, 2, 2, 2, 102, 566, 3, 2, 2, 2, 104, 570, 3, 2, 2, 2, 106, 574, 3, 2, 2, 2, 108, 576, 3, 2, 2, 2, 110, 578, 3, 2, 2, 2, 112, 580, 3, 2, 2, 2, 114, 582, 3, 2, 2, 2, 116, 584, 3, 2, 2, 2, 118, 587, 3, 2, 2, 2, 120, 595, 3, 2, 2, 2, 122, 123, 5, 4, 3, 2, 123, 124, 7, 2, 2, 3, 124, 3, 3, 2, 2, 2, 125, 126, 8, 3, 1, 2, 126, 127, 5, 6, 4, 2, 127, 133, 3, 2, 2, 2, 128, 129, 12, 3, 2, 2, 129, 130, 7, 26, 2, 2, 130, 132, 5, 8, 5, 2, 131, 128, 3, 2, 2, 2, 132, 135, 3, 2, 2, 2, 133, 131, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 5, 3, 2, 2, 2, 135, 133, 3, 2, 2, 2, 136, 141, 5, 116, 59, 2, 137, 141, 5, 48, 25, 2, 138, 141, 5, 38, 20, 2, 139, 141, 5, 120, 61, 2, 140, 136, 3, 2, 2, 2, 140, 137, 3, 2, 2, 2, 140, 138, 3, 2, 2, 2, 140, 139, 3, 2, 2, 2, 141, 7, 3, 2, 2, 2, 142, 156, 5, 52, 27, 2, 143, 156, 5, 78, 40, 2, 144, 156, 5, 84, 43, 2, 145, 156, 5, 86, 44, 2, 146, 156, 5, 92, 47, 2, 147, 156, 5, 88, 45, 2, 148, 156, 5, 96, 49, 2, 149, 156, 5, 98, 50, 2, 150, 156, 5, 80, 41, 2, 151, 156, 5, 54, 28, 2, 152, 156, 5, 16, 9, 2, 153, 156, 5, 14, 8, 2, 154, 156, 5, 10, 6, 2, 155, 142, 3, 2, 2, 2, 155, 143, 3, 2, 2, 2, 155, 144, 3, 2, 2, 2, 155, 145, 3, 2, 2, 2, 155, 146, 3, 2, 2, 2, 155, 147, 3, 2, 2, 2, 155, 148, 3, 2, 2, 2, 155, 149, 3, 2, 2, 2, 155, 150, 3, 2, 2, 2, 155, 151, 3, 2, 2, 2, 155, 152, 3, 2, 2, 2, 155, 153, 3, 2, 2, 2, 155, 154, 3, 2, 2, 2, 156, 9, 3, 2, 2, 2, 157, 158, 7, 18, 2, 2, 158, 161, 5, 58, 30, 2, 159, 160, 7, 76, 2, 2, 160, 162, 5, 44, 23, 2, 161, 159, 3, 2, 2, 2, 161, 162, 3, 2, 2, 2, 162, 172, 3, 2, 2, 2, 163, 164, 7, 77, 2, 2, 164, 169, 5, 12, 7, 2, 165, 166, 7, 34, 2, 2, 166, 168, 5, 12, 7, 2, 167, 165, 3, 2, 2, 2, 168, 171, 3, 2, 2, 2, 169, 167, 3, 2, 2, 2, 169, 170, 3, 2, 2, 2, 170, 173, 3, 2, 2, 2, 171, 169, 3, 2, 2, 2, 172, 163, 3, 2, 2, 2, 172, 173, 3, 2, 2, 2, 173, 11, 3, 2, 2, 2, 174, 175, 5, 44, 23, 2, 175, 176, 7, 33, 2, 2, 176, 178, 3, 2, 2, 2, 177, 174, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2, 178, 179, 3, 2, 2, 2, 179, 180, 5, 44, 23, 2, 180, 13, 3, 2, 2, 2, 181, 182, 7, 12, 2, 2, 182, 183, 5, 66, 34, 2, 183, 15, 3, 2, 2, 2, 184, 185, 7, 10, 2, 2, 185, 186, 5, 18, 10, 2, 186, 17, 3, 2, 2, 2, 187, 188, 8, 10, 1, 2, 188, 189, 7, 39, 2, 2, 189, 233, 5, 18, 10, 10, 190, 233, 5, 24, 13, 2, 191, 233, 5, 22, 12, 2, 192, 194, 5, 24, 13, 2, 193, 195, 7, 39, 2, 2, 194, 193, 3, 2, 2, 2, 194, 195, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 197, 7, 42, 2, 2, 197, 198, 7, 36, 2, 2, 198, 203, 5, 24, 13, 2, 199, 200, 7, 34, 2, 2, 200, 202, 5, 24, 13, 2, 201, 199, 3, 2, 2, 2, 202, 205, 3, 2, 2, 2, 203, 201, 3, 2, 2, 2, 203, 204, 3, 2, 2, 2, 204, 206, 3, 2, 2, 2, 205, 203, 3, 2, 2, 2, 206, 207, 7, 47, 2, 2, 207, 233, 3, 2, 2, 2, 208, 210, 7, 39, 2, 2, 209, 208, 3, 2, 2, 2, 209, 210, 3, 2, 2, 2, 210, 211, 3, 2, 2, 2, 211, 212, 7, 64, 2, 2, 212, 213, 7, 36, 2, 2, 213, 221, 5, 64, 33, 2, 214, 215, 7, 34, 2, 2, 215, 217, 5, 60, 31, 2, 216, 214, 3, 2, 2, 2, 217, 220, 3, 2, 2, 2, 218, 216, 3, 2, 2, 2, 218, 219, 3, 2, 2, 2, 219, 222, 3, 2, 2, 2, 220, 218, 3, 2, 2, 2, 221, 218, 3, 2, 2, 2, 221, 222, 3, 2, 2, 2, 222, 223, 3, 2, 2, 2, 223, 224, 7, 47, 2, 2, 224, 233, 3, 2, 2, 2, 225, 226, 5, 24, 13, 2, 226, 228, 7, 43, 2, 2, 227, 229, 7, 39, 2, 2, 228, 227, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 230, 3, 2, 2, 2, 230, 231, 7, 45, 2, 2, 231, 233, 3, 2, 2, 2, 232, 187, 3, 2, 2, 2, 232, 190, 3, 2, 2, 2, 232, 191, 3, 2, 2, 2, 232, 192, 3, 2, 2, 2, 232, 209, 3, 2, 2, 2, 232, 225, 3, 2, 2, 2, 233, 242, 3, 2, 2, 2, 234, 235, 12, 7, 2, 2, 235, 236, 7, 32, 2, 2, 236, 241, 5, 18, 10, 8, 237, 238, 12, 6, 2, 2, 238, 239, 7, 46, 2, 2, 239, 241, 5, 18, 10, 7, 240, 234, 3, 2, 2, 2, 240, 237, 3, 2, 2, 2, 241, 244, 3, 2, 2, 2, 242, 240, 3, 2, 2, 2, 242, 243, 3, 2, 2, 2, 243, 19, 3, 2, 2, 2, 244, 242, 3, 2, 2, 2, 245, 246, 8, 11, 1, 2, 246, 247, 7, 39, 2, 2, 247, 250, 5, 20, 11, 6, 248, 250, 5, 24, 13, 2, 249, 245, 3, 2, 2, 2, 249, 248, 3, 2, 2, 2, 250, 259, 3, 2, 2, 2, 251, 252, 12, 4, 2, 2, 252, 253, 7, 32, 2, 2, 253, 258, 5, 20, 11, 5, 254, 255, 12, 3, 2, 2, 255, 256, 7, 46, 2, 2, 256, 258, 5, 20, 11, 4, 257, 251, 3, 2, 2, 2, 257, 254, 3, 2, 2, 2, 258, 261, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 21, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 262, 264, 5, 24, 13, 2, 263, 265, 7, 39, 2, 2, 264, 263, 3, 2, 2, 2, 264, 265, 3, 2, 2, 2, 265, 266, 3, 2, 2, 2, 266, 267, 7, 40, 2, 2, 267, 268, 5, 112, 57, 2, 268, 277, 3, 2, 2, 2, 269, 271, 5, 24, 13, 2, 270, 272, 7, 39, 2, 2, 271, 270, 3, 2, 2, 2, 271, 272, 3, 2, 2, 2, 272, 273, 3, 2, 2, 2, 273, 274, 7, 41, 2, 2, 274, 275, 5, 112, 57, 2, 275, 277, 3, 2, 2, 2, 276, 262, 3, 2, 2, 2, 276, 269, 3, 2, 2, 2, 277, 23, 3, 2, 2, 2, 278, 281, 5, 34, 18, 2, 279, 281, 5, 26, 14, 2, 280, 278, 3, 2, 2, 2, 280, 279, 3, 2, 2, 2, 281, 25, 3, 2, 2, 2, 282, 283, 5, 34, 18, 2, 283, 284, 5, 114, 58, 2, 284, 285, 5, 34, 18, 2, 285, 27, 3, 2, 2, 2, 286, 287, 5, 72, 37, 2, 287, 296, 7, 36, 2, 2, 288, 293, 5, 60, 31, 2, 289, 290, 7, 34, 2, 2, 290, 292, 5, 60, 31, 2, 291, 289, 3, 2, 2, 2, 292, 295, 3, 2, 2, 2, 293, 291, 3, 2, 2, 2, 293, 294, 3, 2, 2, 2, 294, 297, 3, 2, 2, 2, 295, 293, 3, 2, 2, 2, 296, 288, 3, 2, 2, 2, 296, 297, 3, 2, 2, 2, 297, 298, 3, 2, 2, 2, 298, 299, 7, 47, 2, 2, 299, 29, 3, 2, 2, 2, 300, 301, 5, 70, 36, 2, 301, 310, 7, 36, 2, 2, 302, 307, 5, 62, 32, 2, 303, 304, 7, 34, 2, 2, 304, 306, 5, 62, 32, 2, 305, 303, 3, 2, 2, 2, 306, 309, 3, 2, 2, 2, 307, 305, 3, 2, 2, 2, 307, 308, 3, 2, 2, 2, 308, 311, 3, 2, 2, 2, 309, 307, 3, 2, 2, 2, 310, 302, 3, 2, 2, 2, 310, 311, 3, 2, 2, 2, 311, 312, 3, 2, 2, 2, 312, 313, 7, 47, 2, 2, 313, 31, 3, 2, 2, 2, 314, 315, 5, 106, 54, 2, 315, 316, 7, 31, 2, 2, 316, 33, 3, 2, 2, 2, 317, 318, 8, 18, 1, 2, 318, 324, 5, 36, 19, 2, 319, 324, 5, 28, 15, 2, 320, 324, 5, 30, 16, 2, 321, 322, 9, 2, 2, 2, 322, 324, 5, 34, 18, 5, 323, 317, 3, 2, 2, 2, 323, 319, 3, 2, 2, 2, 323, 320, 3, 2, 2, 2, 323, 321, 3, 2, 2, 2, 324, 333, 3, 2, 2, 2, 325, 326, 12, 4, 2, 2, 326, 327, 9, 3, 2, 2, 327, 332, 5, 34, 18, 5, 328, 329, 12, 3, 2, 2, 329, 330, 9, 2, 2, 2, 330, 332, 5, 34, 18, 4, 331, 325, 3, 2, 2, 2, 331, 328, 3, 2, 2, 2, 332, 335, 3, 2, 2, 2, 333, 331, 3, 2, 2, 2, 333, 334, 3, 2, 2, 2, 334, 35, 3, 2, 2, 2, 335, 333, 3, 2, 2, 2, 336, 358, 5, 74, 38, 2, 337, 358, 5, 64, 33, 2, 338, 358, 5, 32, 17, 2, 339, 340, 7, 36, 2, 2, 340, 341, 5, 20, 11, 2, 341, 342, 7, 47, 2, 2, 342, 358, 3, 2, 2, 2, 343, 344, 5, 68, 35, 2, 344, 353, 7, 36, 2, 2, 345, 350, 5, 20, 11, 2, 346, 347, 7, 34, 2, 2, 347, 349, 5, 20, 11, 2, 348, 346, 3, 2, 2, 2, 349, 352, 3, 2, 2, 2, 350, 348, 3, 2, 2, 2, 350, 351, 3, 2, 2, 2, 351, 354, 3, 2, 2, 2, 352, 350, 3, 2, 2, 2, 353, 345, 3, 2, 2, 2, 353, 354, 3, 2, 2, 2, 354, 355, 3, 2, 2, 2, 355, 356, 7, 47, 2, 2, 356, 358, 3, 2, 2, 2, 357, 336, 3, 2, 2, 2, 357, 337, 3, 2, 2, 2, 357, 338, 3, 2, 2, 2, 357, 339, 3, 2, 2, 2, 357, 343, 3, 2, 2, 2, 358, 37, 3, 2, 2, 2, 359, 360, 7, 8, 2, 2, 360, 361, 5, 40, 21, 2, 361, 39, 3, 2, 2, 2, 362, 367, 5, 42, 22, 2, 363, 364, 7, 34, 2, 2, 364, 366, 5, 42, 22, 2, 365, 363, 3, 2, 2, 2, 366, 369, 3, 2, 2, 2, 367, 365, 3, 2, 2, 2, 367, 368, 3, 2, 2, 2, 368, 41, 3, 2, 2, 2, 369, 367, 3, 2, 2, 2, 370, 376, 5, 20, 11, 2, 371, 372, 5, 46, 24, 2, 372, 373, 7, 33, 2, 2, 373, 374, 5, 20, 11, 2, 374, 376, 3, 2, 2, 2, 375, 370, 3, 2, 2, 2, 375, 371, 3, 2, 2, 2, 376, 43, 3, 2, 2, 2, 377, 378, 9, 4, 2, 2, 378, 45, 3, 2, 2, 2, 379, 380, 5, 68, 35, 2, 380, 47, 3, 2, 2, 2, 381, 382, 7, 7, 2, 2, 382, 387, 5, 56, 29, 2, 383, 384, 7, 34, 2, 2, 384, 386, 5, 56, 29, 2, 385, 383, 3, 2, 2, 2, 386, 389, 3, 2, 2, 2, 387, 385, 3, 2, 2, 2, 387, 388, 3, 2, 2, 2, 388, 391, 3, 2, 2, 2, 389, 387, 3, 2, 2, 2, 390, 392, 5, 50, 26, 2, 391, 390, 3, 2, 2, 2, 391, 392, 3, 2, 2, 2, 392, 49, 3, 2, 2, 2, 393, 394, 7, 37, 2, 2, 394, 395, 7, 70, 2, 2, 395, 400, 5, 56, 29, 2, 396, 397, 7, 34, 2, 2, 397, 399, 5, 56, 29, 2, 398, 396, 3, 2, 2, 2, 399, 402, 3, 2, 2, 2, 400, 398, 3, 2, 2, 2, 400, 401, 3, 2, 2, 2, 401, 403, 3, 2, 2, 2, 402, 400, 3, 2, 2, 2, 403, 404, 7, 38, 2, 2, 404, 51, 3, 2, 2, 2, 405, 406, 7, 5, 2, 2, 406, 407, 5, 40, 21, 2, 407, 53, 3, 2, 2, 2, 408, 410, 7, 9, 2, 2, 409, 411, 5, 40, 21, 2, 410, 409, 3, 2, 2, 2, 410, 411, 3, 2, 2, 2, 411, 414, 3, 2, 2, 2, 412, 413, 7, 30, 2, 2, 413, 415, 5, 66, 34, 2, 414, 412, 3, 2, 2, 2, 414, 415, 3, 2, 2, 2, 415, 55, 3, 2, 2, 2, 416, 417, 9, 5, 2, 2, 417, 57, 3, 2, 2, 2, 418, 419, 9, 4, 2, 2, 419, 59, 3, 2, 2, 2, 420, 424, 5, 64, 33, 2, 421, 424, 5, 112, 57, 2, 422, 424, 5, 106, 54, 2, 423, 420, 3, 2, 2, 2, 423, 421, 3, 2, 2, 2, 423, 422, 3, 2, 2, 2, 424, 61, 3, 2, 2, 2, 425, 432, 5, 64, 33, 2, 426, 432, 5, 112, 57, 2, 427, 432, 5, 106, 54, 2, 428, 432, 5, 34, 18, 2, 429, 432, 5, 32, 17, 2, 430, 432, 5, 26, 14, 2, 431, 425, 3, 2, 2, 2, 431, 426, 3, 2, 2, 2, 431, 427, 3, 2, 2, 2, 431, 428, 3, 2, 2, 2, 431, 429, 3, 2, 2, 2, 431, 430, 3, 2, 2, 2, 432, 63, 3, 2, 2, 2, 433, 438, 5, 68, 35, 2, 434, 435, 7, 35, 2, 2, 435, 437, 5, 68, 35, 2, 436, 434, 3, 2, 2, 2, 437, 440, 3, 2, 2, 2, 438, 436, 3, 2, 2, 2, 438, 439, 3, 2, 2, 2, 439, 65, 3, 2, 2, 2, 440, 438, 3, 2, 2, 2, 441, 446, 5, 64, 33, 2, 442, 443, 7, 34, 2, 2, 443, 445, 5, 64, 33, 2, 444, 442, 3, 2, 2, 2, 445, 448, 3, 2, 2, 2, 446, 444, 3, 2, 2, 2, 446, 447, 3, 2, 2, 2, 447, 67, 3, 2, 2, 2, 448, 446, 3, 2, 2, 2, 449, 450, 9, 6, 2, 2, 450, 69, 3, 2, 2, 2, 451, 452, 7, 62, 2, 2, 452, 71, 3, 2, 2, 2, 453, 454, 7, 63, 2, 2, 454, 73, 3, 2, 2, 2, 455, 493, 7, 45, 2, 2, 456, 493, 5, 76, 39, 2, 457, 493, 5, 104, 53, 2, 458, 493, 5, 112, 57, 2, 459, 460, 7, 37, 2, 2, 460, 465, 5, 76, 39, 2, 461, 462, 7, 34, 2, 2, 462, 464, 5, 76, 39, 2, 463, 461, 3, 2, 2, 2, 464, 467, 3, 2, 2, 2, 465, 463, 3, 2, 2, 2, 465, 466, 3, 2, 2, 2, 466, 468, 3, 2, 2, 2, 467, 465, 3, 2, 2, 2, 468, 469, 7, 38, 2, 2, 469, 493, 3, 2, 2, 2, 470, 471, 7, 37, 2, 2, 471, 476, 5, 104, 53, 2, 472, 473, 7, 34, 2, 2, 473, 475, 5, 104, 53, 2, 474, 472, 3, 2, 2, 2, 475, 478, 3, 2, 2, 2, 476, 474, 3, 2, 2, 2, 476, 477, 3, 2, 2, 2, 477, 479, 3, 2, 2, 2, 478, 476, 3, 2, 2, 2, 479, 480, 7, 38, 2, 2, 480, 493, 3, 2, 2, 2, 481, 482, 7, 37, 2, 2, 482, 487, 5, 112, 57, 2, 483, 484, 7, 34, 2, 2, 484, 486, 5, 112, 57, 2, 485, 483, 3, 2, 2, 2, 486, 489, 3, 2, 2, 2, 487, 485, 3, 2, 2, 2, 487, 488, 3, 2, 2, 2, 488, 490, 3, 2, 2, 2, 489, 487, 3, 2, 2, 2, 490, 491, 7, 38, 2, 2, 491, 493, 3, 2, 2, 2, 492, 455, 3, 2, 2, 2, 492, 456, 3, 2, 2, 2, 492, 457, 3, 2, 2, 2, 492, 458, 3, 2, 2, 2, 492, 459, 3, 2, 2, 2, 492, 470, 3, 2, 2, 2, 492, 481, 3, 2, 2, 2, 493, 75, 3, 2, 2, 2, 494, 497, 5, 108, 55, 2, 495, 497, 5, 110, 56, 2, 496, 494, 3, 2, 2, 2, 496, 495, 3, 2, 2, 2, 497, 77, 3, 2, 2, 2, 498, 499, 7, 13, 2, 2, 499, 500, 7, 28, 2, 2, 500, 79, 3, 2, 2, 2, 501, 502, 7, 11, 2, 2, 502, 507, 5, 82, 42, 2, 503, 504, 7, 34, 2, 2, 504, 506, 5, 82, 42, 2, 505, 503, 3, 2, 2, 2, 506, 509, 3, 2, 2, 2, 507, 505, 3, 2, 2, 2, 507, 508, 3, 2, 2, 2, 508, 81, 3, 2, 2, 2, 509, 507, 3, 2, 2, 2, 510, 512, 5, 20, 11, 2, 511, 513, 7, 59, 2, 2, 512, 511, 3, 2, 2, 2, 512, 513, 3, 2, 2, 2, 513, 516, 3, 2, 2, 2, 514, 515, 7, 60, 2, 2, 515, 517, 7, 61, 2, 2, 516, 514, 3, 2, 2, 2, 516, 517, 3, 2, 2, 2, 517, 83, 3, 2, 2, 2, 518, 519, 7, 14, 2, 2, 519, 520, 5, 66, 34, 2, 520, 85, 3, 2, 2, 2, 521, 522, 7, 19, 2, 2, 522, 523, 5, 66, 34, 2, 523, 87, 3, 2, 2, 2, 524, 525, 7, 15, 2, 2, 525, 526, 5, 66, 34, 2, 526, 89, 3, 2, 2, 2, 527, 532, 5, 68, 35, 2, 528, 529, 7, 35, 2, 2, 529, 531, 5, 68, 35, 2, 530, 528, 3, 2, 2, 2, 531, 534, 3, 2, 2, 2, 532, 530, 3, 2, 2, 2, 532, 533, 3, 2, 2, 2, 533, 91, 3, 2, 2, 2, 534, 532, 3, 2, 2, 2, 535, 536, 7, 16, 2, 2, 536, 541, 5, 94, 48, 2, 537, 538, 7, 34, 2, 2, 538, 540, 5, 94, 48, 2, 539, 537, 3, 2, 2, 2, 540, 543, 3, 2, 2, 2, 541, 539, 3, 2, 2, 2, 541, 542, 3, 2, 2, 2, 542, 93, 3, 2, 2, 2, 543, 541, 3, 2, 2, 2, 544, 545, 5, 64, 33, 2, 545, 546, 7, 44, 2, 2, 546, 547, 5, 90, 46, 2, 547, 95, 3, 2, 2, 2, 548, 549, 7, 3, 2, 2, 549, 550, 5, 66, 34, 2, 550, 552, 5, 112, 57, 2, 551, 553, 5, 100, 51, 2, 552, 551, 3, 2, 2, 2, 552, 553, 3, 2, 2, 2, 553, 97, 3, 2, 2, 2, 554, 555, 7, 4, 2, 2, 555, 556, 5, 66, 34, 2, 556, 557, 5, 112, 57, 2, 557, 99, 3, 2, 2, 2, 558, 563, 5, 102, 52, 2, 559, 560, 7, 34, 2, 2, 560, 562, 5, 102, 52, 2, 561, 559, 3, 2, 2, 2, 562, 565, 3, 2, 2, 2, 563, 561, 3, 2, 2, 2, 563, 564, 3, 2, 2, 2, 564, 101, 3, 2, 2, 2, 565, 563, 3, 2, 2, 2, 566, 567, 5, 68, 35, 2, 567, 568, 7, 33, 2, 2, 568, 569, 5, 74, 38, 2, 569, 103, 3, 2, 2, 2, 570, 571, 7, 51, 2, 2, 571, 105, 3, 2, 2, 2, 572, 575, 7, 29, 2, 2, 573, 575, 7, 28, 2, 2, 574, 572, 3, 2, 2, 2, 574, 573, 3, 2, 2, 2, 575, 107, 3, 2, 2, 2, 576, 577, 7, 29, 2, 2, 577, 109, 3, 2, 2, 2, 578, 579, 7, 28, 2, 2, 579, 111, 3, 2, 2, 2, 580, 581, 7, 27, 2, 2, 581, 113, 3, 2, 2, 2, 582, 583, 7, 52, 2, 2, 583, 115, 3, 2, 2, 2, 584, 585, 7, 6, 2, 2, 585, 586, 5, 118, 60, 2, 586, 117, 3, 2, 2, 2, 587, 588, 7, 37, 2, 2, 588, 589, 5, 4, 3, 2, 589, 590, 7, 38, 2, 2, 590, 119, 3, 2, 2, 2, 591, 592, 7, 17, 2, 2, 592, 596, 7, 49, 2, 2, 593, 594, 7, 17, 2, 2, 594, 596, 7, 50, 2, 2, 595, 591, 3, 2, 2, 2, 595, 593, 3, 2, 2, 2, 596, 121, 3, 2, 2, 2, 60, 133, 140, 155, 161, 169, 172, 177, 194, 203, 209, 218, 221, 228, 232, 240, 242, 249, 257, 259, 264, 271, 276, 280, 293, 296, 307, 310, 323, 331, 333, 350, 353, 357, 367, 375, 387, 391, 400, 410, 414, 423, 431, 438, 446, 465, 476, 487, 492, 496, 507, 512, 516, 532, 541, 552, 563, 574, 595] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 78, 486, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 100, 10, 3, 12, 3, 14, 3, 103, 11, 3, 3, 4, 3, 4, 3, 4, 5, 4, 108, 10, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 122, 10, 5, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 134, 10, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 7, 7, 141, 10, 7, 12, 7, 14, 7, 144, 11, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 151, 10, 7, 3, 7, 3, 7, 5, 7, 155, 10, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 7, 7, 163, 10, 7, 12, 7, 14, 7, 166, 11, 7, 3, 8, 3, 8, 5, 8, 170, 10, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 177, 10, 8, 3, 8, 3, 8, 3, 8, 5, 8, 182, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 189, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 195, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 203, 10, 10, 12, 10, 14, 10, 206, 11, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 215, 10, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 7, 12, 223, 10, 12, 12, 12, 14, 12, 226, 11, 12, 5, 12, 228, 10, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 7, 14, 238, 10, 14, 12, 14, 14, 14, 241, 11, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 5, 15, 248, 10, 15, 3, 16, 3, 16, 3, 16, 3, 16, 7, 16, 254, 10, 16, 12, 16, 14, 16, 257, 11, 16, 3, 16, 5, 16, 260, 10, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 267, 10, 17, 12, 17, 14, 17, 270, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 5, 19, 279, 10, 19, 3, 19, 3, 19, 5, 19, 283, 10, 19, 3, 20, 3, 20, 3, 20, 7, 20, 288, 10, 20, 12, 20, 14, 20, 291, 11, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 7, 22, 298, 10, 22, 12, 22, 14, 22, 301, 11, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 7, 24, 318, 10, 24, 12, 24, 14, 24, 321, 11, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 7, 24, 329, 10, 24, 12, 24, 14, 24, 332, 11, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 7, 24, 340, 10, 24, 12, 24, 14, 24, 343, 11, 24, 3, 24, 3, 24, 5, 24, 347, 10, 24, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 7, 26, 356, 10, 26, 12, 26, 14, 26, 359, 11, 26, 3, 27, 3, 27, 5, 27, 363, 10, 27, 3, 27, 3, 27, 5, 27, 367, 10, 27, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 373, 10, 28, 12, 28, 14, 28, 376, 11, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 382, 10, 28, 12, 28, 14, 28, 385, 11, 28, 5, 28, 387, 10, 28, 3, 29, 3, 29, 3, 29, 3, 29, 7, 29, 393, 10, 29, 12, 29, 14, 29, 396, 11, 29, 3, 30, 3, 30, 3, 30, 3, 30, 7, 30, 402, 10, 30, 12, 30, 14, 30, 405, 11, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 5, 32, 415, 10, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 7, 35, 427, 10, 35, 12, 35, 14, 35, 430, 11, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 5, 38, 440, 10, 38, 3, 39, 5, 39, 443, 10, 39, 3, 39, 3, 39, 3, 40, 5, 40, 448, 10, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 5, 43, 460, 10, 43, 3, 44, 3, 44, 3, 44, 3, 44, 5, 44, 466, 10, 44, 3, 44, 3, 44, 3, 44, 3, 44, 7, 44, 472, 10, 44, 12, 44, 14, 44, 475, 11, 44, 5, 44, 477, 10, 44, 3, 45, 3, 45, 3, 45, 5, 45, 482, 10, 45, 3, 45, 3, 45, 3, 45, 2, 2, 5, 4, 12, 18, 46, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 80, 2, 82, 2, 84, 2, 86, 2, 88, 2, 2, 10, 3, 2, 58, 59, 3, 2, 60, 62, 3, 2, 74, 75, 3, 2, 65, 66, 4, 2, 29, 29, 32, 32, 3, 2, 35, 36, 4, 2, 34, 34, 48, 48, 3, 2, 52, 57, 2, 516, 2, 90, 3, 2, 2, 2, 4, 93, 3, 2, 2, 2, 6, 107, 3, 2, 2, 2, 8, 121, 3, 2, 2, 2, 10, 123, 3, 2, 2, 2, 12, 154, 3, 2, 2, 2, 14, 181, 3, 2, 2, 2, 16, 188, 3, 2, 2, 2, 18, 194, 3, 2, 2, 2, 20, 214, 3, 2, 2, 2, 22, 216, 3, 2, 2, 2, 24, 231, 3, 2, 2, 2, 26, 234, 3, 2, 2, 2, 28, 247, 3, 2, 2, 2, 30, 249, 3, 2, 2, 2, 32, 261, 3, 2, 2, 2, 34, 273, 3, 2, 2, 2, 36, 276, 3, 2, 2, 2, 38, 284, 3, 2, 2, 2, 40, 292, 3, 2, 2, 2, 42, 294, 3, 2, 2, 2, 44, 302, 3, 2, 2, 2, 46, 346, 3, 2, 2, 2, 48, 348, 3, 2, 2, 2, 50, 351, 3, 2, 2, 2, 52, 360, 3, 2, 2, 2, 54, 386, 3, 2, 2, 2, 56, 388, 3, 2, 2, 2, 58, 397, 3, 2, 2, 2, 60, 406, 3, 2, 2, 2, 62, 410, 3, 2, 2, 2, 64, 416, 3, 2, 2, 2, 66, 420, 3, 2, 2, 2, 68, 423, 3, 2, 2, 2, 70, 431, 3, 2, 2, 2, 72, 435, 3, 2, 2, 2, 74, 439, 3, 2, 2, 2, 76, 442, 3, 2, 2, 2, 78, 447, 3, 2, 2, 2, 80, 451, 3, 2, 2, 2, 82, 453, 3, 2, 2, 2, 84, 459, 3, 2, 2, 2, 86, 461, 3, 2, 2, 2, 88, 481, 3, 2, 2, 2, 90, 91, 5, 4, 3, 2, 91, 92, 7, 2, 2, 3, 92, 3, 3, 2, 2, 2, 93, 94, 8, 3, 1, 2, 94, 95, 5, 6, 4, 2, 95, 101, 3, 2, 2, 2, 96, 97, 12, 3, 2, 2, 97, 98, 7, 23, 2, 2, 98, 100, 5, 8, 5, 2, 99, 96, 3, 2, 2, 2, 100, 103, 3, 2, 2, 2, 101, 99, 3, 2, 2, 2, 101, 102, 3, 2, 2, 2, 102, 5, 3, 2, 2, 2, 103, 101, 3, 2, 2, 2, 104, 108, 5, 30, 16, 2, 105, 108, 5, 24, 13, 2, 106, 108, 5, 84, 43, 2, 107, 104, 3, 2, 2, 2, 107, 105, 3, 2, 2, 2, 107, 106, 3, 2, 2, 2, 108, 7, 3, 2, 2, 2, 109, 122, 5, 34, 18, 2, 110, 122, 5, 48, 25, 2, 111, 122, 5, 54, 28, 2, 112, 122, 5, 50, 26, 2, 113, 122, 5, 36, 19, 2, 114, 122, 5, 10, 6, 2, 115, 122, 5, 56, 29, 2, 116, 122, 5, 58, 30, 2, 117, 122, 5, 62, 32, 2, 118, 122, 5, 64, 33, 2, 119, 122, 5, 86, 44, 2, 120, 122, 5, 66, 34, 2, 121, 109, 3, 2, 2, 2, 121, 110, 3, 2, 2, 2, 121, 111, 3, 2, 2, 2, 121, 112, 3, 2, 2, 2, 121, 113, 3, 2, 2, 2, 121, 114, 3, 2, 2, 2, 121, 115, 3, 2, 2, 2, 121, 116, 3, 2, 2, 2, 121, 117, 3, 2, 2, 2, 121, 118, 3, 2, 2, 2, 121, 119, 3, 2, 2, 2, 121, 120, 3, 2, 2, 2, 122, 9, 3, 2, 2, 2, 123, 124, 7, 18, 2, 2, 124, 125, 5, 12, 7, 2, 125, 11, 3, 2, 2, 2, 126, 127, 8, 7, 1, 2, 127, 128, 7, 41, 2, 2, 128, 155, 5, 12, 7, 9, 129, 155, 5, 16, 9, 2, 130, 155, 5, 14, 8, 2, 131, 133, 5, 16, 9, 2, 132, 134, 7, 41, 2, 2, 133, 132, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 135, 3, 2, 2, 2, 135, 136, 7, 38, 2, 2, 136, 137, 7, 37, 2, 2, 137, 142, 5, 16, 9, 2, 138, 139, 7, 31, 2, 2, 139, 141, 5, 16, 9, 2, 140, 138, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 145, 3, 2, 2, 2, 144, 142, 3, 2, 2, 2, 145, 146, 7, 47, 2, 2, 146, 155, 3, 2, 2, 2, 147, 148, 5, 16, 9, 2, 148, 150, 7, 39, 2, 2, 149, 151, 7, 41, 2, 2, 150, 149, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 152, 3, 2, 2, 2, 152, 153, 7, 42, 2, 2, 153, 155, 3, 2, 2, 2, 154, 126, 3, 2, 2, 2, 154, 129, 3, 2, 2, 2, 154, 130, 3, 2, 2, 2, 154, 131, 3, 2, 2, 2, 154, 147, 3, 2, 2, 2, 155, 164, 3, 2, 2, 2, 156, 157, 12, 6, 2, 2, 157, 158, 7, 28, 2, 2, 158, 163, 5, 12, 7, 7, 159, 160, 12, 5, 2, 2, 160, 161, 7, 44, 2, 2, 161, 163, 5, 12, 7, 6, 162, 156, 3, 2, 2, 2, 162, 159, 3, 2, 2, 2, 163, 166, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 164, 165, 3, 2, 2, 2, 165, 13, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 167, 169, 5, 16, 9, 2, 168, 170, 7, 41, 2, 2, 169, 168, 3, 2, 2, 2, 169, 170, 3, 2, 2, 2, 170, 171, 3, 2, 2, 2, 171, 172, 7, 40, 2, 2, 172, 173, 5, 80, 41, 2, 173, 182, 3, 2, 2, 2, 174, 176, 5, 16, 9, 2, 175, 177, 7, 41, 2, 2, 176, 175, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2, 178, 179, 7, 46, 2, 2, 179, 180, 5, 80, 41, 2, 180, 182, 3, 2, 2, 2, 181, 167, 3, 2, 2, 2, 181, 174, 3, 2, 2, 2, 182, 15, 3, 2, 2, 2, 183, 189, 5, 18, 10, 2, 184, 185, 5, 18, 10, 2, 185, 186, 5, 82, 42, 2, 186, 187, 5, 18, 10, 2, 187, 189, 3, 2, 2, 2, 188, 183, 3, 2, 2, 2, 188, 184, 3, 2, 2, 2, 189, 17, 3, 2, 2, 2, 190, 191, 8, 10, 1, 2, 191, 195, 5, 20, 11, 2, 192, 193, 9, 2, 2, 2, 193, 195, 5, 18, 10, 5, 194, 190, 3, 2, 2, 2, 194, 192, 3, 2, 2, 2, 195, 204, 3, 2, 2, 2, 196, 197, 12, 4, 2, 2, 197, 198, 9, 3, 2, 2, 198, 203, 5, 18, 10, 5, 199, 200, 12, 3, 2, 2, 200, 201, 9, 2, 2, 2, 201, 203, 5, 18, 10, 4, 202, 196, 3, 2, 2, 2, 202, 199, 3, 2, 2, 2, 203, 206, 3, 2, 2, 2, 204, 202, 3, 2, 2, 2, 204, 205, 3, 2, 2, 2, 205, 19, 3, 2, 2, 2, 206, 204, 3, 2, 2, 2, 207, 215, 5, 46, 24, 2, 208, 215, 5, 42, 22, 2, 209, 215, 5, 22, 12, 2, 210, 211, 7, 37, 2, 2, 211, 212, 5, 12, 7, 2, 212, 213, 7, 47, 2, 2, 213, 215, 3, 2, 2, 2, 214, 207, 3, 2, 2, 2, 214, 208, 3, 2, 2, 2, 214, 209, 3, 2, 2, 2, 214, 210, 3, 2, 2, 2, 215, 21, 3, 2, 2, 2, 216, 217, 5, 44, 23, 2, 217, 227, 7, 37, 2, 2, 218, 228, 7, 60, 2, 2, 219, 224, 5, 12, 7, 2, 220, 221, 7, 31, 2, 2, 221, 223, 5, 12, 7, 2, 222, 220, 3, 2, 2, 2, 223, 226, 3, 2, 2, 2, 224, 222, 3, 2, 2, 2, 224, 225, 3, 2, 2, 2, 225, 228, 3, 2, 2, 2, 226, 224, 3, 2, 2, 2, 227, 218, 3, 2, 2, 2, 227, 219, 3, 2, 2, 2, 227, 228, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 230, 7, 47, 2, 2, 230, 23, 3, 2, 2, 2, 231, 232, 7, 14, 2, 2, 232, 233, 5, 26, 14, 2, 233, 25, 3, 2, 2, 2, 234, 239, 5, 28, 15, 2, 235, 236, 7, 31, 2, 2, 236, 238, 5, 28, 15, 2, 237, 235, 3, 2, 2, 2, 238, 241, 3, 2, 2, 2, 239, 237, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 27, 3, 2, 2, 2, 241, 239, 3, 2, 2, 2, 242, 248, 5, 12, 7, 2, 243, 244, 5, 42, 22, 2, 244, 245, 7, 30, 2, 2, 245, 246, 5, 12, 7, 2, 246, 248, 3, 2, 2, 2, 247, 242, 3, 2, 2, 2, 247, 243, 3, 2, 2, 2, 248, 29, 3, 2, 2, 2, 249, 250, 7, 7, 2, 2, 250, 255, 5, 40, 21, 2, 251, 252, 7, 31, 2, 2, 252, 254, 5, 40, 21, 2, 253, 251, 3, 2, 2, 2, 254, 257, 3, 2, 2, 2, 255, 253, 3, 2, 2, 2, 255, 256, 3, 2, 2, 2, 256, 259, 3, 2, 2, 2, 257, 255, 3, 2, 2, 2, 258, 260, 5, 32, 17, 2, 259, 258, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 31, 3, 2, 2, 2, 261, 262, 7, 63, 2, 2, 262, 263, 7, 71, 2, 2, 263, 268, 5, 40, 21, 2, 264, 265, 7, 31, 2, 2, 265, 267, 5, 40, 21, 2, 266, 264, 3, 2, 2, 2, 267, 270, 3, 2, 2, 2, 268, 266, 3, 2, 2, 2, 268, 269, 3, 2, 2, 2, 269, 271, 3, 2, 2, 2, 270, 268, 3, 2, 2, 2, 271, 272, 7, 64, 2, 2, 272, 33, 3, 2, 2, 2, 273, 274, 7, 6, 2, 2, 274, 275, 5, 26, 14, 2, 275, 35, 3, 2, 2, 2, 276, 278, 7, 17, 2, 2, 277, 279, 5, 26, 14, 2, 278, 277, 3, 2, 2, 2, 278, 279, 3, 2, 2, 2, 279, 282, 3, 2, 2, 2, 280, 281, 7, 27, 2, 2, 281, 283, 5, 38, 20, 2, 282, 280, 3, 2, 2, 2, 282, 283, 3, 2, 2, 2, 283, 37, 3, 2, 2, 2, 284, 289, 5, 42, 22, 2, 285, 286, 7, 31, 2, 2, 286, 288, 5, 42, 22, 2, 287, 285, 3, 2, 2, 2, 288, 291, 3, 2, 2, 2, 289, 287, 3, 2, 2, 2, 289, 290, 3, 2, 2, 2, 290, 39, 3, 2, 2, 2, 291, 289, 3, 2, 2, 2, 292, 293, 9, 4, 2, 2, 293, 41, 3, 2, 2, 2, 294, 299, 5, 44, 23, 2, 295, 296, 7, 33, 2, 2, 296, 298, 5, 44, 23, 2, 297, 295, 3, 2, 2, 2, 298, 301, 3, 2, 2, 2, 299, 297, 3, 2, 2, 2, 299, 300, 3, 2, 2, 2, 300, 43, 3, 2, 2, 2, 301, 299, 3, 2, 2, 2, 302, 303, 9, 5, 2, 2, 303, 45, 3, 2, 2, 2, 304, 347, 7, 42, 2, 2, 305, 306, 5, 78, 40, 2, 306, 307, 7, 65, 2, 2, 307, 347, 3, 2, 2, 2, 308, 347, 5, 76, 39, 2, 309, 347, 5, 78, 40, 2, 310, 347, 5, 72, 37, 2, 311, 347, 7, 45, 2, 2, 312, 347, 5, 80, 41, 2, 313, 314, 7, 63, 2, 2, 314, 319, 5, 74, 38, 2, 315, 316, 7, 31, 2, 2, 316, 318, 5, 74, 38, 2, 317, 315, 3, 2, 2, 2, 318, 321, 3, 2, 2, 2, 319, 317, 3, 2, 2, 2, 319, 320, 3, 2, 2, 2, 320, 322, 3, 2, 2, 2, 321, 319, 3, 2, 2, 2, 322, 323, 7, 64, 2, 2, 323, 347, 3, 2, 2, 2, 324, 325, 7, 63, 2, 2, 325, 330, 5, 72, 37, 2, 326, 327, 7, 31, 2, 2, 327, 329, 5, 72, 37, 2, 328, 326, 3, 2, 2, 2, 329, 332, 3, 2, 2, 2, 330, 328, 3, 2, 2, 2, 330, 331, 3, 2, 2, 2, 331, 333, 3, 2, 2, 2, 332, 330, 3, 2, 2, 2, 333, 334, 7, 64, 2, 2, 334, 347, 3, 2, 2, 2, 335, 336, 7, 63, 2, 2, 336, 341, 5, 80, 41, 2, 337, 338, 7, 31, 2, 2, 338, 340, 5, 80, 41, 2, 339, 337, 3, 2, 2, 2, 340, 343, 3, 2, 2, 2, 341, 339, 3, 2, 2, 2, 341, 342, 3, 2, 2, 2, 342, 344, 3, 2, 2, 2, 343, 341, 3, 2, 2, 2, 344, 345, 7, 64, 2, 2, 345, 347, 3, 2, 2, 2, 346, 304, 3, 2, 2, 2, 346, 305, 3, 2, 2, 2, 346, 308, 3, 2, 2, 2, 346, 309, 3, 2, 2, 2, 346, 310, 3, 2, 2, 2, 346, 311, 3, 2, 2, 2, 346, 312, 3, 2, 2, 2, 346, 313, 3, 2, 2, 2, 346, 324, 3, 2, 2, 2, 346, 335, 3, 2, 2, 2, 347, 47, 3, 2, 2, 2, 348, 349, 7, 10, 2, 2, 349, 350, 7, 25, 2, 2, 350, 49, 3, 2, 2, 2, 351, 352, 7, 16, 2, 2, 352, 357, 5, 52, 27, 2, 353, 354, 7, 31, 2, 2, 354, 356, 5, 52, 27, 2, 355, 353, 3, 2, 2, 2, 356, 359, 3, 2, 2, 2, 357, 355, 3, 2, 2, 2, 357, 358, 3, 2, 2, 2, 358, 51, 3, 2, 2, 2, 359, 357, 3, 2, 2, 2, 360, 362, 5, 12, 7, 2, 361, 363, 9, 6, 2, 2, 362, 361, 3, 2, 2, 2, 362, 363, 3, 2, 2, 2, 363, 366, 3, 2, 2, 2, 364, 365, 7, 43, 2, 2, 365, 367, 9, 7, 2, 2, 366, 364, 3, 2, 2, 2, 366, 367, 3, 2, 2, 2, 367, 53, 3, 2, 2, 2, 368, 369, 7, 9, 2, 2, 369, 374, 5, 40, 21, 2, 370, 371, 7, 31, 2, 2, 371, 373, 5, 40, 21, 2, 372, 370, 3, 2, 2, 2, 373, 376, 3, 2, 2, 2, 374, 372, 3, 2, 2, 2, 374, 375, 3, 2, 2, 2, 375, 387, 3, 2, 2, 2, 376, 374, 3, 2, 2, 2, 377, 378, 7, 12, 2, 2, 378, 383, 5, 40, 21, 2, 379, 380, 7, 31, 2, 2, 380, 382, 5, 40, 21, 2, 381, 379, 3, 2, 2, 2, 382, 385, 3, 2, 2, 2, 383, 381, 3, 2, 2, 2, 383, 384, 3, 2, 2, 2, 384, 387, 3, 2, 2, 2, 385, 383, 3, 2, 2, 2, 386, 368, 3, 2, 2, 2, 386, 377, 3, 2, 2, 2, 387, 55, 3, 2, 2, 2, 388, 389, 7, 4, 2, 2, 389, 394, 5, 40, 21, 2, 390, 391, 7, 31, 2, 2, 391, 393, 5, 40, 21, 2, 392, 390, 3, 2, 2, 2, 393, 396, 3, 2, 2, 2, 394, 392, 3, 2, 2, 2, 394, 395, 3, 2, 2, 2, 395, 57, 3, 2, 2, 2, 396, 394, 3, 2, 2, 2, 397, 398, 7, 13, 2, 2, 398, 403, 5, 60, 31, 2, 399, 400, 7, 31, 2, 2, 400, 402, 5, 60, 31, 2, 401, 399, 3, 2, 2, 2, 402, 405, 3, 2, 2, 2, 403, 401, 3, 2, 2, 2, 403, 404, 3, 2, 2, 2, 404, 59, 3, 2, 2, 2, 405, 403, 3, 2, 2, 2, 406, 407, 5, 40, 21, 2, 407, 408, 7, 70, 2, 2, 408, 409, 5, 40, 21, 2, 409, 61, 3, 2, 2, 2, 410, 411, 7, 3, 2, 2, 411, 412, 5, 20, 11, 2, 412, 414, 5, 80, 41, 2, 413, 415, 5, 68, 35, 2, 414, 413, 3, 2, 2, 2, 414, 415, 3, 2, 2, 2, 415, 63, 3, 2, 2, 2, 416, 417, 7, 8, 2, 2, 417, 418, 5, 20, 11, 2, 418, 419, 5, 80, 41, 2, 419, 65, 3, 2, 2, 2, 420, 421, 7, 11, 2, 2, 421, 422, 5, 40, 21, 2, 422, 67, 3, 2, 2, 2, 423, 428, 5, 70, 36, 2, 424, 425, 7, 31, 2, 2, 425, 427, 5, 70, 36, 2, 426, 424, 3, 2, 2, 2, 427, 430, 3, 2, 2, 2, 428, 426, 3, 2, 2, 2, 428, 429, 3, 2, 2, 2, 429, 69, 3, 2, 2, 2, 430, 428, 3, 2, 2, 2, 431, 432, 5, 44, 23, 2, 432, 433, 7, 30, 2, 2, 433, 434, 5, 46, 24, 2, 434, 71, 3, 2, 2, 2, 435, 436, 9, 8, 2, 2, 436, 73, 3, 2, 2, 2, 437, 440, 5, 76, 39, 2, 438, 440, 5, 78, 40, 2, 439, 437, 3, 2, 2, 2, 439, 438, 3, 2, 2, 2, 440, 75, 3, 2, 2, 2, 441, 443, 9, 2, 2, 2, 442, 441, 3, 2, 2, 2, 442, 443, 3, 2, 2, 2, 443, 444, 3, 2, 2, 2, 444, 445, 7, 26, 2, 2, 445, 77, 3, 2, 2, 2, 446, 448, 9, 2, 2, 2, 447, 446, 3, 2, 2, 2, 447, 448, 3, 2, 2, 2, 448, 449, 3, 2, 2, 2, 449, 450, 7, 25, 2, 2, 450, 79, 3, 2, 2, 2, 451, 452, 7, 24, 2, 2, 452, 81, 3, 2, 2, 2, 453, 454, 9, 9, 2, 2, 454, 83, 3, 2, 2, 2, 455, 456, 7, 15, 2, 2, 456, 460, 7, 49, 2, 2, 457, 458, 7, 15, 2, 2, 458, 460, 7, 50, 2, 2, 459, 455, 3, 2, 2, 2, 459, 457, 3, 2, 2, 2, 460, 85, 3, 2, 2, 2, 461, 462, 7, 5, 2, 2, 462, 465, 5, 40, 21, 2, 463, 464, 7, 72, 2, 2, 464, 466, 5, 40, 21, 2, 465, 463, 3, 2, 2, 2, 465, 466, 3, 2, 2, 2, 466, 476, 3, 2, 2, 2, 467, 468, 7, 73, 2, 2, 468, 473, 5, 88, 45, 2, 469, 470, 7, 31, 2, 2, 470, 472, 5, 88, 45, 2, 471, 469, 3, 2, 2, 2, 472, 475, 3, 2, 2, 2, 473, 471, 3, 2, 2, 2, 473, 474, 3, 2, 2, 2, 474, 477, 3, 2, 2, 2, 475, 473, 3, 2, 2, 2, 476, 467, 3, 2, 2, 2, 476, 477, 3, 2, 2, 2, 477, 87, 3, 2, 2, 2, 478, 479, 5, 40, 21, 2, 479, 480, 7, 30, 2, 2, 480, 482, 3, 2, 2, 2, 481, 478, 3, 2, 2, 2, 481, 482, 3, 2, 2, 2, 482, 483, 3, 2, 2, 2, 483, 484, 5, 40, 21, 2, 484, 89, 3, 2, 2, 2, 52, 101, 107, 121, 133, 142, 150, 154, 162, 164, 169, 176, 181, 188, 194, 202, 204, 214, 224, 227, 239, 247, 255, 259, 268, 278, 282, 289, 299, 319, 330, 341, 346, 357, 362, 366, 374, 383, 386, 394, 403, 414, 428, 439, 442, 447, 459, 465, 473, 476, 481] \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens b/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens index b72e97b9a2961..c3160ce1f6472 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens @@ -1,98 +1,93 @@ DISSECT=1 -GROK=2 -EVAL=3 -EXPLAIN=4 +DROP=2 +ENRICH=3 +EVAL=4 FROM=5 -ROW=6 -STATS=7 -WHERE=8 -SORT=9 -MV_EXPAND=10 -LIMIT=11 -PROJECT=12 -DROP=13 -RENAME=14 -SHOW=15 -ENRICH=16 -KEEP=17 +GROK=6 +KEEP=7 +LIMIT=8 +MV_EXPAND=9 +PROJECT=10 +RENAME=11 +ROW=12 +SHOW=13 +SORT=14 +STATS=15 +WHERE=16 +UNKNOWN_CMD=17 LINE_COMMENT=18 MULTILINE_COMMENT=19 WS=20 -EXPLAIN_WS=21 -EXPLAIN_LINE_COMMENT=22 -EXPLAIN_MULTILINE_COMMENT=23 -PIPE=24 -STRING=25 -INTEGER_LITERAL=26 -DECIMAL_LITERAL=27 -BY=28 -DATE_LITERAL=29 -AND=30 -ASSIGN=31 -COMMA=32 -DOT=33 -LP=34 -OPENING_BRACKET=35 -CLOSING_BRACKET=36 -NOT=37 +PIPE=21 +STRING=22 +INTEGER_LITERAL=23 +DECIMAL_LITERAL=24 +BY=25 +AND=26 +ASC=27 +ASSIGN=28 +COMMA=29 +DESC=30 +DOT=31 +FALSE=32 +FIRST=33 +LAST=34 +LP=35 +IN=36 +IS=37 LIKE=38 -RLIKE=39 -IN=40 -IS=41 -AS=42 -NULL=43 -OR=44 +NOT=39 +NULL=40 +NULLS=41 +OR=42 +PARAM=43 +RLIKE=44 RP=45 -UNDERSCORE=46 +TRUE=46 INFO=47 FUNCTIONS=48 -BOOLEAN_VALUE=49 -COMPARISON_OPERATOR=50 -PLUS=51 -MINUS=52 -ASTERISK=53 -SLASH=54 -PERCENT=55 -TEN=56 -ORDERING=57 -NULLS_ORDERING=58 -NULLS_ORDERING_DIRECTION=59 -MATH_FUNCTION=60 -UNARY_FUNCTION=61 -WHERE_FUNCTIONS=62 +UNDERSCORE=49 +EQ=50 +NEQ=51 +LT=52 +LTE=53 +GT=54 +GTE=55 +PLUS=56 +MINUS=57 +ASTERISK=58 +SLASH=59 +PERCENT=60 +OPENING_BRACKET=61 +CLOSING_BRACKET=62 UNQUOTED_IDENTIFIER=63 QUOTED_IDENTIFIER=64 EXPR_LINE_COMMENT=65 EXPR_MULTILINE_COMMENT=66 EXPR_WS=67 -METADATA=68 -SRC_UNQUOTED_IDENTIFIER=69 -SRC_QUOTED_IDENTIFIER=70 -SRC_LINE_COMMENT=71 -SRC_MULTILINE_COMMENT=72 -SRC_WS=73 -ON=74 -WITH=75 -ENR_UNQUOTED_IDENTIFIER=76 -ENR_QUOTED_IDENTIFIER=77 -ENR_LINE_COMMENT=78 -ENR_MULTILINE_COMMENT=79 -ENR_WS=80 -EXPLAIN_PIPE=81 -'by'=28 -'and'=30 -'.'=33 -'('=34 -']'=36 -'or'=44 +AS=68 +METADATA=69 +ON=70 +WITH=71 +SRC_UNQUOTED_IDENTIFIER=72 +SRC_QUOTED_IDENTIFIER=73 +SRC_LINE_COMMENT=74 +SRC_MULTILINE_COMMENT=75 +SRC_WS=76 +'.'=31 +'('=35 +'?'=43 ')'=45 -'_'=46 -'info'=47 -'functions'=48 -'+'=51 -'-'=52 -'*'=53 -'/'=54 -'%'=55 -'10'=56 -'nulls'=58 +'_'=49 +'=='=50 +'!='=51 +'<'=52 +'<='=53 +'>'=54 +'>='=55 +'+'=56 +'-'=57 +'*'=58 +'/'=59 +'%'=60 +']'=62 diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.ts b/packages/kbn-monaco/src/esql/antlr/esql_parser.ts index 494ffadd8aad9..8e0a4ca8199b8 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.ts @@ -28,162 +28,136 @@ import { esql_parserListener } from "./esql_parserListener"; export class esql_parser extends Parser { public static readonly DISSECT = 1; - public static readonly GROK = 2; - public static readonly EVAL = 3; - public static readonly EXPLAIN = 4; + public static readonly DROP = 2; + public static readonly ENRICH = 3; + public static readonly EVAL = 4; public static readonly FROM = 5; - public static readonly ROW = 6; - public static readonly STATS = 7; - public static readonly WHERE = 8; - public static readonly SORT = 9; - public static readonly MV_EXPAND = 10; - public static readonly LIMIT = 11; - public static readonly PROJECT = 12; - public static readonly DROP = 13; - public static readonly RENAME = 14; - public static readonly SHOW = 15; - public static readonly ENRICH = 16; - public static readonly KEEP = 17; + public static readonly GROK = 6; + public static readonly KEEP = 7; + public static readonly LIMIT = 8; + public static readonly MV_EXPAND = 9; + public static readonly PROJECT = 10; + public static readonly RENAME = 11; + public static readonly ROW = 12; + public static readonly SHOW = 13; + public static readonly SORT = 14; + public static readonly STATS = 15; + public static readonly WHERE = 16; + public static readonly UNKNOWN_CMD = 17; public static readonly LINE_COMMENT = 18; public static readonly MULTILINE_COMMENT = 19; public static readonly WS = 20; - public static readonly EXPLAIN_WS = 21; - public static readonly EXPLAIN_LINE_COMMENT = 22; - public static readonly EXPLAIN_MULTILINE_COMMENT = 23; - public static readonly PIPE = 24; - public static readonly STRING = 25; - public static readonly INTEGER_LITERAL = 26; - public static readonly DECIMAL_LITERAL = 27; - public static readonly BY = 28; - public static readonly DATE_LITERAL = 29; - public static readonly AND = 30; - public static readonly ASSIGN = 31; - public static readonly COMMA = 32; - public static readonly DOT = 33; - public static readonly LP = 34; - public static readonly OPENING_BRACKET = 35; - public static readonly CLOSING_BRACKET = 36; - public static readonly NOT = 37; + public static readonly PIPE = 21; + public static readonly STRING = 22; + public static readonly INTEGER_LITERAL = 23; + public static readonly DECIMAL_LITERAL = 24; + public static readonly BY = 25; + public static readonly AND = 26; + public static readonly ASC = 27; + public static readonly ASSIGN = 28; + public static readonly COMMA = 29; + public static readonly DESC = 30; + public static readonly DOT = 31; + public static readonly FALSE = 32; + public static readonly FIRST = 33; + public static readonly LAST = 34; + public static readonly LP = 35; + public static readonly IN = 36; + public static readonly IS = 37; public static readonly LIKE = 38; - public static readonly RLIKE = 39; - public static readonly IN = 40; - public static readonly IS = 41; - public static readonly AS = 42; - public static readonly NULL = 43; - public static readonly OR = 44; + public static readonly NOT = 39; + public static readonly NULL = 40; + public static readonly NULLS = 41; + public static readonly OR = 42; + public static readonly PARAM = 43; + public static readonly RLIKE = 44; public static readonly RP = 45; - public static readonly UNDERSCORE = 46; + public static readonly TRUE = 46; public static readonly INFO = 47; public static readonly FUNCTIONS = 48; - public static readonly BOOLEAN_VALUE = 49; - public static readonly COMPARISON_OPERATOR = 50; - public static readonly PLUS = 51; - public static readonly MINUS = 52; - public static readonly ASTERISK = 53; - public static readonly SLASH = 54; - public static readonly PERCENT = 55; - public static readonly TEN = 56; - public static readonly ORDERING = 57; - public static readonly NULLS_ORDERING = 58; - public static readonly NULLS_ORDERING_DIRECTION = 59; - public static readonly MATH_FUNCTION = 60; - public static readonly UNARY_FUNCTION = 61; - public static readonly WHERE_FUNCTIONS = 62; + public static readonly UNDERSCORE = 49; + public static readonly EQ = 50; + public static readonly NEQ = 51; + public static readonly LT = 52; + public static readonly LTE = 53; + public static readonly GT = 54; + public static readonly GTE = 55; + public static readonly PLUS = 56; + public static readonly MINUS = 57; + public static readonly ASTERISK = 58; + public static readonly SLASH = 59; + public static readonly PERCENT = 60; + public static readonly OPENING_BRACKET = 61; + public static readonly CLOSING_BRACKET = 62; public static readonly UNQUOTED_IDENTIFIER = 63; public static readonly QUOTED_IDENTIFIER = 64; public static readonly EXPR_LINE_COMMENT = 65; public static readonly EXPR_MULTILINE_COMMENT = 66; public static readonly EXPR_WS = 67; - public static readonly METADATA = 68; - public static readonly SRC_UNQUOTED_IDENTIFIER = 69; - public static readonly SRC_QUOTED_IDENTIFIER = 70; - public static readonly SRC_LINE_COMMENT = 71; - public static readonly SRC_MULTILINE_COMMENT = 72; - public static readonly SRC_WS = 73; - public static readonly ON = 74; - public static readonly WITH = 75; - public static readonly ENR_UNQUOTED_IDENTIFIER = 76; - public static readonly ENR_QUOTED_IDENTIFIER = 77; - public static readonly ENR_LINE_COMMENT = 78; - public static readonly ENR_MULTILINE_COMMENT = 79; - public static readonly ENR_WS = 80; - public static readonly EXPLAIN_PIPE = 81; + public static readonly AS = 68; + public static readonly METADATA = 69; + public static readonly ON = 70; + public static readonly WITH = 71; + public static readonly SRC_UNQUOTED_IDENTIFIER = 72; + public static readonly SRC_QUOTED_IDENTIFIER = 73; + public static readonly SRC_LINE_COMMENT = 74; + public static readonly SRC_MULTILINE_COMMENT = 75; + public static readonly SRC_WS = 76; public static readonly RULE_singleStatement = 0; public static readonly RULE_query = 1; public static readonly RULE_sourceCommand = 2; public static readonly RULE_processingCommand = 3; - public static readonly RULE_enrichCommand = 4; - public static readonly RULE_enrichWithClause = 5; - public static readonly RULE_mvExpandCommand = 6; - public static readonly RULE_whereCommand = 7; - public static readonly RULE_whereBooleanExpression = 8; - public static readonly RULE_booleanExpression = 9; - public static readonly RULE_regexBooleanExpression = 10; - public static readonly RULE_valueExpression = 11; - public static readonly RULE_comparison = 12; - public static readonly RULE_mathFn = 13; - public static readonly RULE_mathEvalFn = 14; - public static readonly RULE_dateExpression = 15; - public static readonly RULE_operatorExpression = 16; - public static readonly RULE_primaryExpression = 17; - public static readonly RULE_rowCommand = 18; - public static readonly RULE_fields = 19; - public static readonly RULE_field = 20; - public static readonly RULE_enrichFieldIdentifier = 21; - public static readonly RULE_userVariable = 22; - public static readonly RULE_fromCommand = 23; - public static readonly RULE_metadata = 24; - public static readonly RULE_evalCommand = 25; - public static readonly RULE_statsCommand = 26; - public static readonly RULE_sourceIdentifier = 27; - public static readonly RULE_enrichIdentifier = 28; - public static readonly RULE_functionExpressionArgument = 29; - public static readonly RULE_mathFunctionExpressionArgument = 30; - public static readonly RULE_qualifiedName = 31; - public static readonly RULE_qualifiedNames = 32; - public static readonly RULE_identifier = 33; - public static readonly RULE_mathFunctionIdentifier = 34; - public static readonly RULE_functionIdentifier = 35; - public static readonly RULE_constant = 36; - public static readonly RULE_numericValue = 37; - public static readonly RULE_limitCommand = 38; - public static readonly RULE_sortCommand = 39; - public static readonly RULE_orderExpression = 40; - public static readonly RULE_projectCommand = 41; - public static readonly RULE_keepCommand = 42; - public static readonly RULE_dropCommand = 43; - public static readonly RULE_renameVariable = 44; - public static readonly RULE_renameCommand = 45; - public static readonly RULE_renameClause = 46; - public static readonly RULE_dissectCommand = 47; - public static readonly RULE_grokCommand = 48; - public static readonly RULE_commandOptions = 49; - public static readonly RULE_commandOption = 50; - public static readonly RULE_booleanValue = 51; - public static readonly RULE_number = 52; - public static readonly RULE_decimalValue = 53; - public static readonly RULE_integerValue = 54; - public static readonly RULE_string = 55; - public static readonly RULE_comparisonOperator = 56; - public static readonly RULE_explainCommand = 57; - public static readonly RULE_subqueryExpression = 58; - public static readonly RULE_showCommand = 59; + public static readonly RULE_whereCommand = 4; + public static readonly RULE_booleanExpression = 5; + public static readonly RULE_regexBooleanExpression = 6; + public static readonly RULE_valueExpression = 7; + public static readonly RULE_operatorExpression = 8; + public static readonly RULE_primaryExpression = 9; + public static readonly RULE_functionExpression = 10; + public static readonly RULE_rowCommand = 11; + public static readonly RULE_fields = 12; + public static readonly RULE_field = 13; + public static readonly RULE_fromCommand = 14; + public static readonly RULE_metadata = 15; + public static readonly RULE_evalCommand = 16; + public static readonly RULE_statsCommand = 17; + public static readonly RULE_grouping = 18; + public static readonly RULE_sourceIdentifier = 19; + public static readonly RULE_qualifiedName = 20; + public static readonly RULE_identifier = 21; + public static readonly RULE_constant = 22; + public static readonly RULE_limitCommand = 23; + public static readonly RULE_sortCommand = 24; + public static readonly RULE_orderExpression = 25; + public static readonly RULE_keepCommand = 26; + public static readonly RULE_dropCommand = 27; + public static readonly RULE_renameCommand = 28; + public static readonly RULE_renameClause = 29; + public static readonly RULE_dissectCommand = 30; + public static readonly RULE_grokCommand = 31; + public static readonly RULE_mvExpandCommand = 32; + public static readonly RULE_commandOptions = 33; + public static readonly RULE_commandOption = 34; + public static readonly RULE_booleanValue = 35; + public static readonly RULE_numericValue = 36; + public static readonly RULE_decimalValue = 37; + public static readonly RULE_integerValue = 38; + public static readonly RULE_string = 39; + public static readonly RULE_comparisonOperator = 40; + public static readonly RULE_showCommand = 41; + public static readonly RULE_enrichCommand = 42; + public static readonly RULE_enrichWithClause = 43; // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ - "singleStatement", "query", "sourceCommand", "processingCommand", "enrichCommand", - "enrichWithClause", "mvExpandCommand", "whereCommand", "whereBooleanExpression", - "booleanExpression", "regexBooleanExpression", "valueExpression", "comparison", - "mathFn", "mathEvalFn", "dateExpression", "operatorExpression", "primaryExpression", - "rowCommand", "fields", "field", "enrichFieldIdentifier", "userVariable", - "fromCommand", "metadata", "evalCommand", "statsCommand", "sourceIdentifier", - "enrichIdentifier", "functionExpressionArgument", "mathFunctionExpressionArgument", - "qualifiedName", "qualifiedNames", "identifier", "mathFunctionIdentifier", - "functionIdentifier", "constant", "numericValue", "limitCommand", "sortCommand", - "orderExpression", "projectCommand", "keepCommand", "dropCommand", "renameVariable", - "renameCommand", "renameClause", "dissectCommand", "grokCommand", "commandOptions", - "commandOption", "booleanValue", "number", "decimalValue", "integerValue", - "string", "comparisonOperator", "explainCommand", "subqueryExpression", - "showCommand", + "singleStatement", "query", "sourceCommand", "processingCommand", "whereCommand", + "booleanExpression", "regexBooleanExpression", "valueExpression", "operatorExpression", + "primaryExpression", "functionExpression", "rowCommand", "fields", "field", + "fromCommand", "metadata", "evalCommand", "statsCommand", "grouping", + "sourceIdentifier", "qualifiedName", "identifier", "constant", "limitCommand", + "sortCommand", "orderExpression", "keepCommand", "dropCommand", "renameCommand", + "renameClause", "dissectCommand", "grokCommand", "mvExpandCommand", "commandOptions", + "commandOption", "booleanValue", "numericValue", "decimalValue", "integerValue", + "string", "comparisonOperator", "showCommand", "enrichCommand", "enrichWithClause", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -191,27 +165,25 @@ export class esql_parser extends Parser { undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, - "'by'", undefined, "'and'", undefined, undefined, "'.'", "'('", undefined, - "']'", undefined, undefined, undefined, undefined, undefined, undefined, - undefined, "'or'", "')'", "'_'", "'info'", "'functions'", undefined, undefined, - "'+'", "'-'", "'*'", "'/'", "'%'", "'10'", undefined, "'nulls'", + undefined, undefined, undefined, "'.'", undefined, undefined, undefined, + "'('", undefined, undefined, undefined, undefined, undefined, undefined, + undefined, "'?'", undefined, "')'", undefined, undefined, undefined, "'_'", + "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", + "'%'", undefined, "']'", ]; private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", - "WHERE", "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", - "ENRICH", "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_WS", - "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "PIPE", "STRING", - "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", "AND", "ASSIGN", - "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", "NOT", "LIKE", - "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", "INFO", "FUNCTIONS", - "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", "ASTERISK", "SLASH", - "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", - "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", - "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", - "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", - "SRC_MULTILINE_COMMENT", "SRC_WS", "ON", "WITH", "ENR_UNQUOTED_IDENTIFIER", - "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", - "ENR_WS", "EXPLAIN_PIPE", + undefined, "DISSECT", "DROP", "ENRICH", "EVAL", "FROM", "GROK", "KEEP", + "LIMIT", "MV_EXPAND", "PROJECT", "RENAME", "ROW", "SHOW", "SORT", "STATS", + "WHERE", "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", + "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", + "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", + "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "INFO", + "FUNCTIONS", "UNDERSCORE", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", + "MINUS", "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", + "EXPR_WS", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", + "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", + "SRC_WS", ]; public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(esql_parser._LITERAL_NAMES, esql_parser._SYMBOLIC_NAMES, []); @@ -242,9 +214,9 @@ export class esql_parser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 120; + this.state = 88; this.query(0); - this.state = 121; + this.state = 89; this.match(esql_parser.EOF); } } @@ -286,11 +258,11 @@ export class esql_parser extends Parser { this._ctx = _localctx; _prevctx = _localctx; - this.state = 124; + this.state = 92; this.sourceCommand(); } this._ctx._stop = this._input.tryLT(-1); - this.state = 131; + this.state = 99; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 0, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -303,18 +275,18 @@ export class esql_parser extends Parser { { _localctx = new CompositeQueryContext(new QueryContext(_parentctx, _parentState)); this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_query); - this.state = 126; + this.state = 94; if (!(this.precpred(this._ctx, 1))) { throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); } - this.state = 127; + this.state = 95; this.match(esql_parser.PIPE); - this.state = 128; + this.state = 96; this.processingCommand(); } } } - this.state = 133; + this.state = 101; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 0, this._ctx); } @@ -339,34 +311,27 @@ export class esql_parser extends Parser { let _localctx: SourceCommandContext = new SourceCommandContext(this._ctx, this.state); this.enterRule(_localctx, 4, esql_parser.RULE_sourceCommand); try { - this.state = 138; + this.state = 105; this._errHandler.sync(this); switch (this._input.LA(1)) { - case esql_parser.EXPLAIN: - this.enterOuterAlt(_localctx, 1); - { - this.state = 134; - this.explainCommand(); - } - break; case esql_parser.FROM: - this.enterOuterAlt(_localctx, 2); + this.enterOuterAlt(_localctx, 1); { - this.state = 135; + this.state = 102; this.fromCommand(); } break; case esql_parser.ROW: - this.enterOuterAlt(_localctx, 3); + this.enterOuterAlt(_localctx, 2); { - this.state = 136; + this.state = 103; this.rowCommand(); } break; case esql_parser.SHOW: - this.enterOuterAlt(_localctx, 4); + this.enterOuterAlt(_localctx, 3); { - this.state = 137; + this.state = 104; this.showCommand(); } break; @@ -393,100 +358,94 @@ export class esql_parser extends Parser { let _localctx: ProcessingCommandContext = new ProcessingCommandContext(this._ctx, this.state); this.enterRule(_localctx, 6, esql_parser.RULE_processingCommand); try { - this.state = 153; + this.state = 119; this._errHandler.sync(this); switch (this._input.LA(1)) { case esql_parser.EVAL: this.enterOuterAlt(_localctx, 1); { - this.state = 140; + this.state = 107; this.evalCommand(); } break; case esql_parser.LIMIT: this.enterOuterAlt(_localctx, 2); { - this.state = 141; + this.state = 108; this.limitCommand(); } break; + case esql_parser.KEEP: case esql_parser.PROJECT: this.enterOuterAlt(_localctx, 3); { - this.state = 142; - this.projectCommand(); + this.state = 109; + this.keepCommand(); } break; - case esql_parser.KEEP: + case esql_parser.SORT: this.enterOuterAlt(_localctx, 4); { - this.state = 143; - this.keepCommand(); + this.state = 110; + this.sortCommand(); } break; - case esql_parser.RENAME: + case esql_parser.STATS: this.enterOuterAlt(_localctx, 5); { - this.state = 144; - this.renameCommand(); + this.state = 111; + this.statsCommand(); } break; - case esql_parser.DROP: + case esql_parser.WHERE: this.enterOuterAlt(_localctx, 6); { - this.state = 145; - this.dropCommand(); + this.state = 112; + this.whereCommand(); } break; - case esql_parser.DISSECT: + case esql_parser.DROP: this.enterOuterAlt(_localctx, 7); { - this.state = 146; - this.dissectCommand(); + this.state = 113; + this.dropCommand(); } break; - case esql_parser.GROK: + case esql_parser.RENAME: this.enterOuterAlt(_localctx, 8); { - this.state = 147; - this.grokCommand(); + this.state = 114; + this.renameCommand(); } break; - case esql_parser.SORT: + case esql_parser.DISSECT: this.enterOuterAlt(_localctx, 9); { - this.state = 148; - this.sortCommand(); + this.state = 115; + this.dissectCommand(); } break; - case esql_parser.STATS: + case esql_parser.GROK: this.enterOuterAlt(_localctx, 10); { - this.state = 149; - this.statsCommand(); + this.state = 116; + this.grokCommand(); } break; - case esql_parser.WHERE: + case esql_parser.ENRICH: this.enterOuterAlt(_localctx, 11); { - this.state = 150; - this.whereCommand(); + this.state = 117; + this.enrichCommand(); } break; case esql_parser.MV_EXPAND: this.enterOuterAlt(_localctx, 12); { - this.state = 151; + this.state = 118; this.mvExpandCommand(); } break; - case esql_parser.ENRICH: - this.enterOuterAlt(_localctx, 13); - { - this.state = 152; - this.enrichCommand(); - } - break; default: throw new NoViableAltException(this); } @@ -506,150 +465,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public enrichCommand(): EnrichCommandContext { - let _localctx: EnrichCommandContext = new EnrichCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 8, esql_parser.RULE_enrichCommand); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 155; - this.match(esql_parser.ENRICH); - this.state = 156; - _localctx._policyName = this.enrichIdentifier(); - this.state = 159; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 3, this._ctx) ) { - case 1: - { - this.state = 157; - this.match(esql_parser.ON); - this.state = 158; - _localctx._matchField = this.enrichFieldIdentifier(); - } - break; - } - this.state = 170; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 5, this._ctx) ) { - case 1: - { - this.state = 161; - this.match(esql_parser.WITH); - this.state = 162; - this.enrichWithClause(); - this.state = 167; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 4, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 163; - this.match(esql_parser.COMMA); - this.state = 164; - this.enrichWithClause(); - } - } - } - this.state = 169; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 4, this._ctx); - } - } - break; - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public enrichWithClause(): EnrichWithClauseContext { - let _localctx: EnrichWithClauseContext = new EnrichWithClauseContext(this._ctx, this.state); - this.enterRule(_localctx, 10, esql_parser.RULE_enrichWithClause); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 175; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 6, this._ctx) ) { - case 1: - { - this.state = 172; - _localctx._newName = this.enrichFieldIdentifier(); - this.state = 173; - this.match(esql_parser.ASSIGN); - } - break; - } - this.state = 177; - _localctx._enrichField = this.enrichFieldIdentifier(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public mvExpandCommand(): MvExpandCommandContext { - let _localctx: MvExpandCommandContext = new MvExpandCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 12, esql_parser.RULE_mvExpandCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 179; - this.match(esql_parser.MV_EXPAND); - this.state = 180; - this.qualifiedNames(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public whereCommand(): WhereCommandContext { let _localctx: WhereCommandContext = new WhereCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 14, esql_parser.RULE_whereCommand); + this.enterRule(_localctx, 8, esql_parser.RULE_whereCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 182; + this.state = 121; this.match(esql_parser.WHERE); - this.state = 183; - this.whereBooleanExpression(0); + this.state = 122; + this.booleanExpression(0); } } catch (re) { @@ -667,164 +492,133 @@ export class esql_parser extends Parser { return _localctx; } - public whereBooleanExpression(): WhereBooleanExpressionContext; - public whereBooleanExpression(_p: number): WhereBooleanExpressionContext; + public booleanExpression(): BooleanExpressionContext; + public booleanExpression(_p: number): BooleanExpressionContext; // @RuleVersion(0) - public whereBooleanExpression(_p?: number): WhereBooleanExpressionContext { + public booleanExpression(_p?: number): BooleanExpressionContext { if (_p === undefined) { _p = 0; } let _parentctx: ParserRuleContext = this._ctx; let _parentState: number = this.state; - let _localctx: WhereBooleanExpressionContext = new WhereBooleanExpressionContext(this._ctx, _parentState); - let _prevctx: WhereBooleanExpressionContext = _localctx; - let _startState: number = 16; - this.enterRecursionRule(_localctx, 16, esql_parser.RULE_whereBooleanExpression, _p); + let _localctx: BooleanExpressionContext = new BooleanExpressionContext(this._ctx, _parentState); + let _prevctx: BooleanExpressionContext = _localctx; + let _startState: number = 10; + this.enterRecursionRule(_localctx, 10, esql_parser.RULE_booleanExpression, _p); let _la: number; try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 230; + this.state = 152; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 13, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 6, this._ctx) ) { case 1: { - this.state = 186; + _localctx = new LogicalNotContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + + this.state = 125; this.match(esql_parser.NOT); - this.state = 187; - this.whereBooleanExpression(8); + this.state = 126; + this.booleanExpression(7); } break; case 2: { - this.state = 188; + _localctx = new BooleanDefaultContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 127; this.valueExpression(); } break; case 3: { - this.state = 189; + _localctx = new RegexExpressionContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 128; this.regexBooleanExpression(); } break; case 4: { - this.state = 190; + _localctx = new LogicalInContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 129; this.valueExpression(); - this.state = 192; + this.state = 131; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === esql_parser.NOT) { { - this.state = 191; + this.state = 130; this.match(esql_parser.NOT); } } - this.state = 194; + this.state = 133; this.match(esql_parser.IN); - this.state = 195; + this.state = 134; this.match(esql_parser.LP); - this.state = 196; + this.state = 135; this.valueExpression(); - this.state = 201; + this.state = 140; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 197; + this.state = 136; this.match(esql_parser.COMMA); - this.state = 198; + this.state = 137; this.valueExpression(); } } - this.state = 203; + this.state = 142; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 204; + this.state = 143; this.match(esql_parser.RP); } break; case 5: { - this.state = 207; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === esql_parser.NOT) { - { - this.state = 206; - this.match(esql_parser.NOT); - } - } - - this.state = 209; - this.match(esql_parser.WHERE_FUNCTIONS); - this.state = 210; - this.match(esql_parser.LP); - this.state = 211; - this.qualifiedName(); - this.state = 219; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 11, this._ctx) ) { - case 1: - { - this.state = 216; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 212; - this.match(esql_parser.COMMA); - this.state = 213; - this.functionExpressionArgument(); - } - } - this.state = 218; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - break; - } - this.state = 221; - this.match(esql_parser.RP); - } - break; - - case 6: - { - this.state = 223; + _localctx = new IsNullContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 145; this.valueExpression(); - this.state = 224; + this.state = 146; this.match(esql_parser.IS); - this.state = 226; + this.state = 148; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === esql_parser.NOT) { { - this.state = 225; + this.state = 147; this.match(esql_parser.NOT); } } - this.state = 228; + this.state = 150; this.match(esql_parser.NULL); } break; } this._ctx._stop = this._input.tryLT(-1); - this.state = 240; + this.state = 162; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 8, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -832,46 +626,46 @@ export class esql_parser extends Parser { } _prevctx = _localctx; { - this.state = 238; + this.state = 160; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 7, this._ctx) ) { case 1: { - _localctx = new WhereBooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_whereBooleanExpression); - this.state = 232; - if (!(this.precpred(this._ctx, 5))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 5)"); + _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); + (_localctx as LogicalBinaryContext)._left = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); + this.state = 154; + if (!(this.precpred(this._ctx, 4))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 4)"); } - this.state = 233; - _localctx._operator = this.match(esql_parser.AND); - this.state = 234; - _localctx._right = this.whereBooleanExpression(6); + this.state = 155; + (_localctx as LogicalBinaryContext)._operator = this.match(esql_parser.AND); + this.state = 156; + (_localctx as LogicalBinaryContext)._right = this.booleanExpression(5); } break; case 2: { - _localctx = new WhereBooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_whereBooleanExpression); - this.state = 235; - if (!(this.precpred(this._ctx, 4))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 4)"); + _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); + (_localctx as LogicalBinaryContext)._left = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); + this.state = 157; + if (!(this.precpred(this._ctx, 3))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 3)"); } - this.state = 236; - _localctx._operator = this.match(esql_parser.OR); - this.state = 237; - _localctx._right = this.whereBooleanExpression(5); + this.state = 158; + (_localctx as LogicalBinaryContext)._operator = this.match(esql_parser.OR); + this.state = 159; + (_localctx as LogicalBinaryContext)._right = this.booleanExpression(4); } break; } } } - this.state = 242; + this.state = 164; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 8, this._ctx); } } } @@ -889,153 +683,33 @@ export class esql_parser extends Parser { } return _localctx; } - - public booleanExpression(): BooleanExpressionContext; - public booleanExpression(_p: number): BooleanExpressionContext; // @RuleVersion(0) - public booleanExpression(_p?: number): BooleanExpressionContext { - if (_p === undefined) { - _p = 0; - } - - let _parentctx: ParserRuleContext = this._ctx; - let _parentState: number = this.state; - let _localctx: BooleanExpressionContext = new BooleanExpressionContext(this._ctx, _parentState); - let _prevctx: BooleanExpressionContext = _localctx; - let _startState: number = 18; - this.enterRecursionRule(_localctx, 18, esql_parser.RULE_booleanExpression, _p); + public regexBooleanExpression(): RegexBooleanExpressionContext { + let _localctx: RegexBooleanExpressionContext = new RegexBooleanExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 12, esql_parser.RULE_regexBooleanExpression); + let _la: number; try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 247; + this.state = 179; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.NOT: + switch ( this.interpreter.adaptivePredict(this._input, 11, this._ctx) ) { + case 1: + this.enterOuterAlt(_localctx, 1); { - this.state = 244; - this.match(esql_parser.NOT); - this.state = 245; - this.booleanExpression(4); - } - break; - case esql_parser.STRING: - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - case esql_parser.LP: - case esql_parser.OPENING_BRACKET: - case esql_parser.NULL: - case esql_parser.BOOLEAN_VALUE: - case esql_parser.PLUS: - case esql_parser.MINUS: - case esql_parser.ASTERISK: - case esql_parser.MATH_FUNCTION: - case esql_parser.UNARY_FUNCTION: - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: - { - this.state = 246; - this.valueExpression(); - } - break; - default: - throw new NoViableAltException(this); - } - this._ctx._stop = this._input.tryLT(-1); - this.state = 257; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - if (this._parseListeners != null) { - this.triggerExitRuleEvent(); - } - _prevctx = _localctx; - { - this.state = 255; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 17, this._ctx) ) { - case 1: - { - _localctx = new BooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 249; - if (!(this.precpred(this._ctx, 2))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 2)"); - } - this.state = 250; - _localctx._operator = this.match(esql_parser.AND); - this.state = 251; - _localctx._right = this.booleanExpression(3); - } - break; - - case 2: - { - _localctx = new BooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 252; - if (!(this.precpred(this._ctx, 1))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); - } - this.state = 253; - _localctx._operator = this.match(esql_parser.OR); - this.state = 254; - _localctx._right = this.booleanExpression(2); - } - break; - } - } - } - this.state = 259; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.unrollRecursionContexts(_parentctx); - } - return _localctx; - } - // @RuleVersion(0) - public regexBooleanExpression(): RegexBooleanExpressionContext { - let _localctx: RegexBooleanExpressionContext = new RegexBooleanExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 20, esql_parser.RULE_regexBooleanExpression); - let _la: number; - try { - this.state = 274; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 21, this._ctx) ) { - case 1: - this.enterOuterAlt(_localctx, 1); - { - this.state = 260; + this.state = 165; this.valueExpression(); - this.state = 262; + this.state = 167; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === esql_parser.NOT) { { - this.state = 261; + this.state = 166; this.match(esql_parser.NOT); } } - this.state = 264; + this.state = 169; _localctx._kind = this.match(esql_parser.LIKE); - this.state = 265; + this.state = 170; _localctx._pattern = this.string(); } break; @@ -1043,21 +717,21 @@ export class esql_parser extends Parser { case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 267; + this.state = 172; this.valueExpression(); - this.state = 269; + this.state = 174; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === esql_parser.NOT) { { - this.state = 268; + this.state = 173; this.match(esql_parser.NOT); } } - this.state = 271; + this.state = 176; _localctx._kind = this.match(esql_parser.RLIKE); - this.state = 272; + this.state = 177; _localctx._pattern = this.string(); } break; @@ -1080,24 +754,30 @@ export class esql_parser extends Parser { // @RuleVersion(0) public valueExpression(): ValueExpressionContext { let _localctx: ValueExpressionContext = new ValueExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 22, esql_parser.RULE_valueExpression); + this.enterRule(_localctx, 14, esql_parser.RULE_valueExpression); try { - this.state = 278; + this.state = 186; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 22, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 12, this._ctx) ) { case 1: + _localctx = new ValueExpressionDefaultContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 276; + this.state = 181; this.operatorExpression(0); } break; case 2: + _localctx = new ComparisonContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 277; - this.comparison(); + this.state = 182; + (_localctx as ComparisonContext)._left = this.operatorExpression(0); + this.state = 183; + this.comparisonOperator(); + this.state = 184; + (_localctx as ComparisonContext)._right = this.operatorExpression(0); } break; } @@ -1116,174 +796,6 @@ export class esql_parser extends Parser { } return _localctx; } - // @RuleVersion(0) - public comparison(): ComparisonContext { - let _localctx: ComparisonContext = new ComparisonContext(this._ctx, this.state); - this.enterRule(_localctx, 24, esql_parser.RULE_comparison); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 280; - _localctx._left = this.operatorExpression(0); - this.state = 281; - this.comparisonOperator(); - this.state = 282; - _localctx._right = this.operatorExpression(0); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public mathFn(): MathFnContext { - let _localctx: MathFnContext = new MathFnContext(this._ctx, this.state); - this.enterRule(_localctx, 26, esql_parser.RULE_mathFn); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 284; - this.functionIdentifier(); - this.state = 285; - this.match(esql_parser.LP); - this.state = 294; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 53)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 53)))) !== 0)) { - { - this.state = 286; - this.functionExpressionArgument(); - this.state = 291; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 287; - this.match(esql_parser.COMMA); - this.state = 288; - this.functionExpressionArgument(); - } - } - this.state = 293; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 296; - this.match(esql_parser.RP); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public mathEvalFn(): MathEvalFnContext { - let _localctx: MathEvalFnContext = new MathEvalFnContext(this._ctx, this.state); - this.enterRule(_localctx, 28, esql_parser.RULE_mathEvalFn); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 298; - this.mathFunctionIdentifier(); - this.state = 299; - this.match(esql_parser.LP); - this.state = 308; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 34)) & ~0x1F) === 0 && ((1 << (_la - 34)) & ((1 << (esql_parser.LP - 34)) | (1 << (esql_parser.OPENING_BRACKET - 34)) | (1 << (esql_parser.NULL - 34)) | (1 << (esql_parser.BOOLEAN_VALUE - 34)) | (1 << (esql_parser.PLUS - 34)) | (1 << (esql_parser.MINUS - 34)) | (1 << (esql_parser.ASTERISK - 34)) | (1 << (esql_parser.MATH_FUNCTION - 34)) | (1 << (esql_parser.UNARY_FUNCTION - 34)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 34)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 34)))) !== 0)) { - { - this.state = 300; - this.mathFunctionExpressionArgument(); - this.state = 305; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 301; - this.match(esql_parser.COMMA); - this.state = 302; - this.mathFunctionExpressionArgument(); - } - } - this.state = 307; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 310; - this.match(esql_parser.RP); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public dateExpression(): DateExpressionContext { - let _localctx: DateExpressionContext = new DateExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 30, esql_parser.RULE_dateExpression); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 312; - _localctx._quantifier = this.number(); - this.state = 313; - this.match(esql_parser.DATE_LITERAL); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } public operatorExpression(): OperatorExpressionContext; public operatorExpression(_p: number): OperatorExpressionContext; @@ -1297,51 +809,37 @@ export class esql_parser extends Parser { let _parentState: number = this.state; let _localctx: OperatorExpressionContext = new OperatorExpressionContext(this._ctx, _parentState); let _prevctx: OperatorExpressionContext = _localctx; - let _startState: number = 32; - this.enterRecursionRule(_localctx, 32, esql_parser.RULE_operatorExpression, _p); + let _startState: number = 16; + this.enterRecursionRule(_localctx, 16, esql_parser.RULE_operatorExpression, _p); let _la: number; try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 321; + this.state = 192; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.STRING: - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - case esql_parser.LP: - case esql_parser.OPENING_BRACKET: - case esql_parser.NULL: - case esql_parser.BOOLEAN_VALUE: - case esql_parser.ASTERISK: - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: + switch ( this.interpreter.adaptivePredict(this._input, 13, this._ctx) ) { + case 1: { - this.state = 316; + _localctx = new OperatorExpressionDefaultContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + + this.state = 189; this.primaryExpression(); } break; - case esql_parser.UNARY_FUNCTION: - { - this.state = 317; - this.mathFn(); - } - break; - case esql_parser.MATH_FUNCTION: - { - this.state = 318; - this.mathEvalFn(); - } - break; - case esql_parser.PLUS: - case esql_parser.MINUS: + + case 2: { - this.state = 319; - _localctx._operator = this._input.LT(1); + _localctx = new ArithmeticUnaryContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 190; + (_localctx as ArithmeticUnaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { - _localctx._operator = this._errHandler.recoverInline(this); + (_localctx as ArithmeticUnaryContext)._operator = this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { this.matchedEOF = true; @@ -1350,17 +848,15 @@ export class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 320; + this.state = 191; this.operatorExpression(3); } break; - default: - throw new NoViableAltException(this); } this._ctx._stop = this._input.tryLT(-1); - this.state = 331; + this.state = 202; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 29, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -1368,23 +864,23 @@ export class esql_parser extends Parser { } _prevctx = _localctx; { - this.state = 329; + this.state = 200; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 28, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { case 1: { - _localctx = new OperatorExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; + _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); + (_localctx as ArithmeticBinaryContext)._left = _prevctx; this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 323; + this.state = 194; if (!(this.precpred(this._ctx, 2))) { throw new FailedPredicateException(this, "this.precpred(this._ctx, 2)"); } - this.state = 324; - _localctx._operator = this._input.LT(1); + this.state = 195; + (_localctx as ArithmeticBinaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); - if (!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.SLASH - 53)) | (1 << (esql_parser.PERCENT - 53)))) !== 0))) { - _localctx._operator = this._errHandler.recoverInline(this); + if (!(((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (esql_parser.ASTERISK - 58)) | (1 << (esql_parser.SLASH - 58)) | (1 << (esql_parser.PERCENT - 58)))) !== 0))) { + (_localctx as ArithmeticBinaryContext)._operator = this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { this.matchedEOF = true; @@ -1393,25 +889,25 @@ export class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 325; - _localctx._right = this.operatorExpression(3); + this.state = 196; + (_localctx as ArithmeticBinaryContext)._right = this.operatorExpression(3); } break; case 2: { - _localctx = new OperatorExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; + _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); + (_localctx as ArithmeticBinaryContext)._left = _prevctx; this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 326; + this.state = 197; if (!(this.precpred(this._ctx, 1))) { throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); } - this.state = 327; - _localctx._operator = this._input.LT(1); + this.state = 198; + (_localctx as ArithmeticBinaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { - _localctx._operator = this._errHandler.recoverInline(this); + (_localctx as ArithmeticBinaryContext)._operator = this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { this.matchedEOF = true; @@ -1420,16 +916,16 @@ export class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 328; - _localctx._right = this.operatorExpression(2); + this.state = 199; + (_localctx as ArithmeticBinaryContext)._right = this.operatorExpression(2); } break; } } } - this.state = 333; + this.state = 204; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 29, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); } } } @@ -1450,85 +946,131 @@ export class esql_parser extends Parser { // @RuleVersion(0) public primaryExpression(): PrimaryExpressionContext { let _localctx: PrimaryExpressionContext = new PrimaryExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 34, esql_parser.RULE_primaryExpression); - let _la: number; + this.enterRule(_localctx, 18, esql_parser.RULE_primaryExpression); try { - this.state = 355; + this.state = 212; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 32, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 16, this._ctx) ) { case 1: + _localctx = new ConstantDefaultContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 334; + this.state = 205; this.constant(); } break; case 2: + _localctx = new DereferenceContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 335; + this.state = 206; this.qualifiedName(); } break; case 3: + _localctx = new FunctionContext(_localctx); this.enterOuterAlt(_localctx, 3); { - this.state = 336; - this.dateExpression(); + this.state = 207; + this.functionExpression(); } break; case 4: + _localctx = new ParenthesizedExpressionContext(_localctx); this.enterOuterAlt(_localctx, 4); { - this.state = 337; + this.state = 208; this.match(esql_parser.LP); - this.state = 338; + this.state = 209; this.booleanExpression(0); - this.state = 339; + this.state = 210; this.match(esql_parser.RP); } break; - - case 5: - this.enterOuterAlt(_localctx, 5); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public functionExpression(): FunctionExpressionContext { + let _localctx: FunctionExpressionContext = new FunctionExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 20, esql_parser.RULE_functionExpression); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 214; + this.identifier(); + this.state = 215; + this.match(esql_parser.LP); + this.state = 225; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case esql_parser.ASTERISK: { - this.state = 341; - this.identifier(); - this.state = 342; - this.match(esql_parser.LP); - this.state = 351; + this.state = 216; + this.match(esql_parser.ASTERISK); + } + break; + case esql_parser.STRING: + case esql_parser.INTEGER_LITERAL: + case esql_parser.DECIMAL_LITERAL: + case esql_parser.FALSE: + case esql_parser.LP: + case esql_parser.NOT: + case esql_parser.NULL: + case esql_parser.PARAM: + case esql_parser.TRUE: + case esql_parser.PLUS: + case esql_parser.MINUS: + case esql_parser.OPENING_BRACKET: + case esql_parser.UNQUOTED_IDENTIFIER: + case esql_parser.QUOTED_IDENTIFIER: + { + { + this.state = 217; + this.booleanExpression(0); + this.state = 222; this._errHandler.sync(this); _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 34)) & ~0x1F) === 0 && ((1 << (_la - 34)) & ((1 << (esql_parser.LP - 34)) | (1 << (esql_parser.OPENING_BRACKET - 34)) | (1 << (esql_parser.NOT - 34)) | (1 << (esql_parser.NULL - 34)) | (1 << (esql_parser.BOOLEAN_VALUE - 34)) | (1 << (esql_parser.PLUS - 34)) | (1 << (esql_parser.MINUS - 34)) | (1 << (esql_parser.ASTERISK - 34)) | (1 << (esql_parser.MATH_FUNCTION - 34)) | (1 << (esql_parser.UNARY_FUNCTION - 34)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 34)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 34)))) !== 0)) { + while (_la === esql_parser.COMMA) { { - this.state = 343; + { + this.state = 218; + this.match(esql_parser.COMMA); + this.state = 219; this.booleanExpression(0); - this.state = 348; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 344; - this.match(esql_parser.COMMA); - this.state = 345; - this.booleanExpression(0); - } - } - this.state = 350; - this._errHandler.sync(this); - _la = this._input.LA(1); } } + this.state = 224; + this._errHandler.sync(this); + _la = this._input.LA(1); + } } - - this.state = 353; - this.match(esql_parser.RP); } break; + case esql_parser.RP: + break; + default: + break; + } + this.state = 227; + this.match(esql_parser.RP); } } catch (re) { @@ -1548,13 +1090,13 @@ export class esql_parser extends Parser { // @RuleVersion(0) public rowCommand(): RowCommandContext { let _localctx: RowCommandContext = new RowCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 36, esql_parser.RULE_rowCommand); + this.enterRule(_localctx, 22, esql_parser.RULE_rowCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 357; + this.state = 229; this.match(esql_parser.ROW); - this.state = 358; + this.state = 230; this.fields(); } } @@ -1575,30 +1117,30 @@ export class esql_parser extends Parser { // @RuleVersion(0) public fields(): FieldsContext { let _localctx: FieldsContext = new FieldsContext(this._ctx, this.state); - this.enterRule(_localctx, 38, esql_parser.RULE_fields); + this.enterRule(_localctx, 24, esql_parser.RULE_fields); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 360; + this.state = 232; this.field(); - this.state = 365; + this.state = 237; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 33, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 361; + this.state = 233; this.match(esql_parser.COMMA); - this.state = 362; + this.state = 234; this.field(); } } } - this.state = 367; + this.state = 239; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 33, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); } } } @@ -1619,15 +1161,15 @@ export class esql_parser extends Parser { // @RuleVersion(0) public field(): FieldContext { let _localctx: FieldContext = new FieldContext(this._ctx, this.state); - this.enterRule(_localctx, 40, esql_parser.RULE_field); + this.enterRule(_localctx, 26, esql_parser.RULE_field); try { - this.state = 373; + this.state = 245; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 34, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 20, this._ctx) ) { case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 368; + this.state = 240; this.booleanExpression(0); } break; @@ -1635,11 +1177,11 @@ export class esql_parser extends Parser { case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 369; - this.userVariable(); - this.state = 370; + this.state = 241; + this.qualifiedName(); + this.state = 242; this.match(esql_parser.ASSIGN); - this.state = 371; + this.state = 243; this.booleanExpression(0); } break; @@ -1660,102 +1202,41 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public enrichFieldIdentifier(): EnrichFieldIdentifierContext { - let _localctx: EnrichFieldIdentifierContext = new EnrichFieldIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 42, esql_parser.RULE_enrichFieldIdentifier); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 375; - _la = this._input.LA(1); - if (!(_la === esql_parser.ENR_UNQUOTED_IDENTIFIER || _la === esql_parser.ENR_QUOTED_IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public userVariable(): UserVariableContext { - let _localctx: UserVariableContext = new UserVariableContext(this._ctx, this.state); - this.enterRule(_localctx, 44, esql_parser.RULE_userVariable); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 377; - this.identifier(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public fromCommand(): FromCommandContext { let _localctx: FromCommandContext = new FromCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 46, esql_parser.RULE_fromCommand); + this.enterRule(_localctx, 28, esql_parser.RULE_fromCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 379; + this.state = 247; this.match(esql_parser.FROM); - this.state = 380; + this.state = 248; this.sourceIdentifier(); - this.state = 385; + this.state = 253; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 21, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 381; + this.state = 249; this.match(esql_parser.COMMA); - this.state = 382; + this.state = 250; this.sourceIdentifier(); } } } - this.state = 387; + this.state = 255; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 21, this._ctx); } - this.state = 389; + this.state = 257; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 36, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 22, this._ctx) ) { case 1: { - this.state = 388; + this.state = 256; this.metadata(); } break; @@ -1779,34 +1260,34 @@ export class esql_parser extends Parser { // @RuleVersion(0) public metadata(): MetadataContext { let _localctx: MetadataContext = new MetadataContext(this._ctx, this.state); - this.enterRule(_localctx, 48, esql_parser.RULE_metadata); + this.enterRule(_localctx, 30, esql_parser.RULE_metadata); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 391; + this.state = 259; this.match(esql_parser.OPENING_BRACKET); - this.state = 392; + this.state = 260; this.match(esql_parser.METADATA); - this.state = 393; + this.state = 261; this.sourceIdentifier(); - this.state = 398; + this.state = 266; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 394; + this.state = 262; this.match(esql_parser.COMMA); - this.state = 395; + this.state = 263; this.sourceIdentifier(); } } - this.state = 400; + this.state = 268; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 401; + this.state = 269; this.match(esql_parser.CLOSING_BRACKET); } } @@ -1827,13 +1308,13 @@ export class esql_parser extends Parser { // @RuleVersion(0) public evalCommand(): EvalCommandContext { let _localctx: EvalCommandContext = new EvalCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 50, esql_parser.RULE_evalCommand); + this.enterRule(_localctx, 32, esql_parser.RULE_evalCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 403; + this.state = 271; this.match(esql_parser.EVAL); - this.state = 404; + this.state = 272; this.fields(); } } @@ -1854,31 +1335,31 @@ export class esql_parser extends Parser { // @RuleVersion(0) public statsCommand(): StatsCommandContext { let _localctx: StatsCommandContext = new StatsCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 52, esql_parser.RULE_statsCommand); + this.enterRule(_localctx, 34, esql_parser.RULE_statsCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 406; + this.state = 274; this.match(esql_parser.STATS); - this.state = 408; + this.state = 276; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 38, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 24, this._ctx) ) { case 1: { - this.state = 407; + this.state = 275; this.fields(); } break; } - this.state = 412; + this.state = 280; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 39, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 25, this._ctx) ) { case 1: { - this.state = 410; + this.state = 278; this.match(esql_parser.BY); - this.state = 411; - this.qualifiedNames(); + this.state = 279; + this.grouping(); } break; } @@ -1899,24 +1380,32 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public sourceIdentifier(): SourceIdentifierContext { - let _localctx: SourceIdentifierContext = new SourceIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 54, esql_parser.RULE_sourceIdentifier); - let _la: number; + public grouping(): GroupingContext { + let _localctx: GroupingContext = new GroupingContext(this._ctx, this.state); + this.enterRule(_localctx, 36, esql_parser.RULE_grouping); try { + let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 414; - _la = this._input.LA(1); - if (!(_la === esql_parser.SRC_UNQUOTED_IDENTIFIER || _la === esql_parser.SRC_QUOTED_IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; + this.state = 282; + this.qualifiedName(); + this.state = 287; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 26, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 283; + this.match(esql_parser.COMMA); + this.state = 284; + this.qualifiedName(); + } + } } - - this._errHandler.reportMatch(this); - this.consume(); + this.state = 289; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 26, this._ctx); } } } @@ -1935,16 +1424,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public enrichIdentifier(): EnrichIdentifierContext { - let _localctx: EnrichIdentifierContext = new EnrichIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 56, esql_parser.RULE_enrichIdentifier); + public sourceIdentifier(): SourceIdentifierContext { + let _localctx: SourceIdentifierContext = new SourceIdentifierContext(this._ctx, this.state); + this.enterRule(_localctx, 38, esql_parser.RULE_sourceIdentifier); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 416; + this.state = 290; _la = this._input.LA(1); - if (!(_la === esql_parser.ENR_UNQUOTED_IDENTIFIER || _la === esql_parser.ENR_QUOTED_IDENTIFIER)) { + if (!(_la === esql_parser.SRC_UNQUOTED_IDENTIFIER || _la === esql_parser.SRC_QUOTED_IDENTIFIER)) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -1971,197 +1460,32 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public functionExpressionArgument(): FunctionExpressionArgumentContext { - let _localctx: FunctionExpressionArgumentContext = new FunctionExpressionArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 58, esql_parser.RULE_functionExpressionArgument); - try { - this.state = 421; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.ASTERISK: - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: - this.enterOuterAlt(_localctx, 1); - { - this.state = 418; - this.qualifiedName(); - } - break; - case esql_parser.STRING: - this.enterOuterAlt(_localctx, 2); - { - this.state = 419; - this.string(); - } - break; - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - this.enterOuterAlt(_localctx, 3); - { - this.state = 420; - this.number(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public mathFunctionExpressionArgument(): MathFunctionExpressionArgumentContext { - let _localctx: MathFunctionExpressionArgumentContext = new MathFunctionExpressionArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 60, esql_parser.RULE_mathFunctionExpressionArgument); - try { - this.state = 429; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 41, this._ctx) ) { - case 1: - this.enterOuterAlt(_localctx, 1); - { - this.state = 423; - this.qualifiedName(); - } - break; - - case 2: - this.enterOuterAlt(_localctx, 2); - { - this.state = 424; - this.string(); - } - break; - - case 3: - this.enterOuterAlt(_localctx, 3); - { - this.state = 425; - this.number(); - } - break; - - case 4: - this.enterOuterAlt(_localctx, 4); - { - this.state = 426; - this.operatorExpression(0); - } - break; - - case 5: - this.enterOuterAlt(_localctx, 5); - { - this.state = 427; - this.dateExpression(); - } - break; - - case 6: - this.enterOuterAlt(_localctx, 6); - { - this.state = 428; - this.comparison(); - } - break; - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public qualifiedName(): QualifiedNameContext { let _localctx: QualifiedNameContext = new QualifiedNameContext(this._ctx, this.state); - this.enterRule(_localctx, 62, esql_parser.RULE_qualifiedName); + this.enterRule(_localctx, 40, esql_parser.RULE_qualifiedName); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 431; + this.state = 292; this.identifier(); - this.state = 436; + this.state = 297; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 42, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 27, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 432; + this.state = 293; this.match(esql_parser.DOT); - this.state = 433; + this.state = 294; this.identifier(); } } } - this.state = 438; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 42, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public qualifiedNames(): QualifiedNamesContext { - let _localctx: QualifiedNamesContext = new QualifiedNamesContext(this._ctx, this.state); - this.enterRule(_localctx, 64, esql_parser.RULE_qualifiedNames); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 439; - this.qualifiedName(); - this.state = 444; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 43, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 440; - this.match(esql_parser.COMMA); - this.state = 441; - this.qualifiedName(); - } - } - } - this.state = 446; + this.state = 299; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 43, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 27, this._ctx); } } } @@ -2182,14 +1506,14 @@ export class esql_parser extends Parser { // @RuleVersion(0) public identifier(): IdentifierContext { let _localctx: IdentifierContext = new IdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 66, esql_parser.RULE_identifier); + this.enterRule(_localctx, 42, esql_parser.RULE_identifier); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 447; + this.state = 300; _la = this._input.LA(1); - if (!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 53)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 53)))) !== 0))) { + if (!(_la === esql_parser.UNQUOTED_IDENTIFIER || _la === esql_parser.QUOTED_IDENTIFIER)) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -2216,176 +1540,162 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public mathFunctionIdentifier(): MathFunctionIdentifierContext { - let _localctx: MathFunctionIdentifierContext = new MathFunctionIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 68, esql_parser.RULE_mathFunctionIdentifier); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 449; - this.match(esql_parser.MATH_FUNCTION); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public functionIdentifier(): FunctionIdentifierContext { - let _localctx: FunctionIdentifierContext = new FunctionIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 70, esql_parser.RULE_functionIdentifier); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 451; - this.match(esql_parser.UNARY_FUNCTION); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public constant(): ConstantContext { let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 72, esql_parser.RULE_constant); + this.enterRule(_localctx, 44, esql_parser.RULE_constant); let _la: number; try { - this.state = 490; + this.state = 344; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 47, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 31, this._ctx) ) { case 1: + _localctx = new NullLiteralContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 453; + this.state = 302; this.match(esql_parser.NULL); } break; case 2: + _localctx = new QualifiedIntegerLiteralContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 454; - this.numericValue(); + this.state = 303; + this.integerValue(); + this.state = 304; + this.match(esql_parser.UNQUOTED_IDENTIFIER); } break; case 3: + _localctx = new DecimalLiteralContext(_localctx); this.enterOuterAlt(_localctx, 3); { - this.state = 455; - this.booleanValue(); + this.state = 306; + this.decimalValue(); } break; case 4: + _localctx = new IntegerLiteralContext(_localctx); this.enterOuterAlt(_localctx, 4); { - this.state = 456; + this.state = 307; + this.integerValue(); + } + break; + + case 5: + _localctx = new BooleanLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 5); + { + this.state = 308; + this.booleanValue(); + } + break; + + case 6: + _localctx = new InputParamContext(_localctx); + this.enterOuterAlt(_localctx, 6); + { + this.state = 309; + this.match(esql_parser.PARAM); + } + break; + + case 7: + _localctx = new StringLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 7); + { + this.state = 310; this.string(); } break; - case 5: - this.enterOuterAlt(_localctx, 5); + case 8: + _localctx = new NumericArrayLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 8); { - this.state = 457; + this.state = 311; this.match(esql_parser.OPENING_BRACKET); - this.state = 458; + this.state = 312; this.numericValue(); - this.state = 463; + this.state = 317; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 459; + this.state = 313; this.match(esql_parser.COMMA); - this.state = 460; + this.state = 314; this.numericValue(); } } - this.state = 465; + this.state = 319; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 466; + this.state = 320; this.match(esql_parser.CLOSING_BRACKET); } break; - case 6: - this.enterOuterAlt(_localctx, 6); + case 9: + _localctx = new BooleanArrayLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 9); { - this.state = 468; + this.state = 322; this.match(esql_parser.OPENING_BRACKET); - this.state = 469; + this.state = 323; this.booleanValue(); - this.state = 474; + this.state = 328; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 470; + this.state = 324; this.match(esql_parser.COMMA); - this.state = 471; + this.state = 325; this.booleanValue(); } } - this.state = 476; + this.state = 330; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 477; + this.state = 331; this.match(esql_parser.CLOSING_BRACKET); } break; - case 7: - this.enterOuterAlt(_localctx, 7); + case 10: + _localctx = new StringArrayLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 10); { - this.state = 479; + this.state = 333; this.match(esql_parser.OPENING_BRACKET); - this.state = 480; + this.state = 334; this.string(); - this.state = 485; + this.state = 339; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 481; + this.state = 335; this.match(esql_parser.COMMA); - this.state = 482; + this.state = 336; this.string(); } } - this.state = 487; + this.state = 341; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 488; + this.state = 342; this.match(esql_parser.CLOSING_BRACKET); } break; @@ -2406,55 +1716,15 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public numericValue(): NumericValueContext { - let _localctx: NumericValueContext = new NumericValueContext(this._ctx, this.state); - this.enterRule(_localctx, 74, esql_parser.RULE_numericValue); - try { - this.state = 494; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.DECIMAL_LITERAL: - this.enterOuterAlt(_localctx, 1); - { - this.state = 492; - this.decimalValue(); - } - break; - case esql_parser.INTEGER_LITERAL: - this.enterOuterAlt(_localctx, 2); - { - this.state = 493; - this.integerValue(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public limitCommand(): LimitCommandContext { let _localctx: LimitCommandContext = new LimitCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 76, esql_parser.RULE_limitCommand); + this.enterRule(_localctx, 46, esql_parser.RULE_limitCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 496; + this.state = 346; this.match(esql_parser.LIMIT); - this.state = 497; + this.state = 347; this.match(esql_parser.INTEGER_LITERAL); } } @@ -2475,32 +1745,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public sortCommand(): SortCommandContext { let _localctx: SortCommandContext = new SortCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 78, esql_parser.RULE_sortCommand); + this.enterRule(_localctx, 48, esql_parser.RULE_sortCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 499; + this.state = 349; this.match(esql_parser.SORT); - this.state = 500; + this.state = 350; this.orderExpression(); - this.state = 505; + this.state = 355; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 49, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 32, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 501; + this.state = 351; this.match(esql_parser.COMMA); - this.state = 502; + this.state = 352; this.orderExpression(); } } } - this.state = 507; + this.state = 357; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 49, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 32, this._ctx); } } } @@ -2521,32 +1791,53 @@ export class esql_parser extends Parser { // @RuleVersion(0) public orderExpression(): OrderExpressionContext { let _localctx: OrderExpressionContext = new OrderExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 80, esql_parser.RULE_orderExpression); + this.enterRule(_localctx, 50, esql_parser.RULE_orderExpression); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 508; + this.state = 358; this.booleanExpression(0); - this.state = 510; + this.state = 360; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 50, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 33, this._ctx) ) { case 1: { - this.state = 509; - this.match(esql_parser.ORDERING); + this.state = 359; + _localctx._ordering = this._input.LT(1); + _la = this._input.LA(1); + if (!(_la === esql_parser.ASC || _la === esql_parser.DESC)) { + _localctx._ordering = this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } } break; } - this.state = 514; + this.state = 364; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 51, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 34, this._ctx) ) { case 1: { - this.state = 512; - this.match(esql_parser.NULLS_ORDERING); - { - this.state = 513; - this.match(esql_parser.NULLS_ORDERING_DIRECTION); + this.state = 362; + this.match(esql_parser.NULLS); + this.state = 363; + _localctx._nullOrdering = this._input.LT(1); + _la = this._input.LA(1); + if (!(_la === esql_parser.FIRST || _la === esql_parser.LAST)) { + _localctx._nullOrdering = this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); } } break; @@ -2568,43 +1859,70 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public projectCommand(): ProjectCommandContext { - let _localctx: ProjectCommandContext = new ProjectCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 82, esql_parser.RULE_projectCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 516; - this.match(esql_parser.PROJECT); - this.state = 517; - this.qualifiedNames(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public keepCommand(): KeepCommandContext { let _localctx: KeepCommandContext = new KeepCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 84, esql_parser.RULE_keepCommand); + this.enterRule(_localctx, 52, esql_parser.RULE_keepCommand); try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 519; - this.match(esql_parser.KEEP); - this.state = 520; - this.qualifiedNames(); + let _alt: number; + this.state = 384; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case esql_parser.KEEP: + this.enterOuterAlt(_localctx, 1); + { + this.state = 366; + this.match(esql_parser.KEEP); + this.state = 367; + this.sourceIdentifier(); + this.state = 372; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 368; + this.match(esql_parser.COMMA); + this.state = 369; + this.sourceIdentifier(); + } + } + } + this.state = 374; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + } + } + break; + case esql_parser.PROJECT: + this.enterOuterAlt(_localctx, 2); + { + this.state = 375; + this.match(esql_parser.PROJECT); + this.state = 376; + this.sourceIdentifier(); + this.state = 381; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 36, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 377; + this.match(esql_parser.COMMA); + this.state = 378; + this.sourceIdentifier(); + } + } + } + this.state = 383; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 36, this._ctx); + } + } + break; + default: + throw new NoViableAltException(this); } } catch (re) { @@ -2624,57 +1942,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public dropCommand(): DropCommandContext { let _localctx: DropCommandContext = new DropCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 86, esql_parser.RULE_dropCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 522; - this.match(esql_parser.DROP); - this.state = 523; - this.qualifiedNames(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public renameVariable(): RenameVariableContext { - let _localctx: RenameVariableContext = new RenameVariableContext(this._ctx, this.state); - this.enterRule(_localctx, 88, esql_parser.RULE_renameVariable); + this.enterRule(_localctx, 54, esql_parser.RULE_dropCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 525; - this.identifier(); - this.state = 530; + this.state = 386; + this.match(esql_parser.DROP); + this.state = 387; + this.sourceIdentifier(); + this.state = 392; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 52, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 38, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 526; - this.match(esql_parser.DOT); - this.state = 527; - this.identifier(); + this.state = 388; + this.match(esql_parser.COMMA); + this.state = 389; + this.sourceIdentifier(); } } } - this.state = 532; + this.state = 394; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 52, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 38, this._ctx); } } } @@ -2695,32 +1988,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public renameCommand(): RenameCommandContext { let _localctx: RenameCommandContext = new RenameCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 90, esql_parser.RULE_renameCommand); + this.enterRule(_localctx, 56, esql_parser.RULE_renameCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 533; + this.state = 395; this.match(esql_parser.RENAME); - this.state = 534; + this.state = 396; this.renameClause(); - this.state = 539; + this.state = 401; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 53, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 39, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 535; + this.state = 397; this.match(esql_parser.COMMA); - this.state = 536; + this.state = 398; this.renameClause(); } } } - this.state = 541; + this.state = 403; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 53, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 39, this._ctx); } } } @@ -2741,16 +2034,16 @@ export class esql_parser extends Parser { // @RuleVersion(0) public renameClause(): RenameClauseContext { let _localctx: RenameClauseContext = new RenameClauseContext(this._ctx, this.state); - this.enterRule(_localctx, 92, esql_parser.RULE_renameClause); + this.enterRule(_localctx, 58, esql_parser.RULE_renameClause); try { this.enterOuterAlt(_localctx, 1); { - this.state = 542; - this.qualifiedName(); - this.state = 543; + this.state = 404; + _localctx._oldName = this.sourceIdentifier(); + this.state = 405; this.match(esql_parser.AS); - this.state = 544; - this.renameVariable(); + this.state = 406; + _localctx._newName = this.sourceIdentifier(); } } catch (re) { @@ -2770,22 +2063,22 @@ export class esql_parser extends Parser { // @RuleVersion(0) public dissectCommand(): DissectCommandContext { let _localctx: DissectCommandContext = new DissectCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 94, esql_parser.RULE_dissectCommand); + this.enterRule(_localctx, 60, esql_parser.RULE_dissectCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 546; + this.state = 408; this.match(esql_parser.DISSECT); - this.state = 547; - this.qualifiedNames(); - this.state = 548; + this.state = 409; + this.primaryExpression(); + this.state = 410; this.string(); - this.state = 550; + this.state = 412; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 54, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 40, this._ctx) ) { case 1: { - this.state = 549; + this.state = 411; this.commandOptions(); } break; @@ -2809,15 +2102,15 @@ export class esql_parser extends Parser { // @RuleVersion(0) public grokCommand(): GrokCommandContext { let _localctx: GrokCommandContext = new GrokCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 96, esql_parser.RULE_grokCommand); + this.enterRule(_localctx, 62, esql_parser.RULE_grokCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 552; + this.state = 414; this.match(esql_parser.GROK); - this.state = 553; - this.qualifiedNames(); - this.state = 554; + this.state = 415; + this.primaryExpression(); + this.state = 416; this.string(); } } @@ -2836,32 +2129,59 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) + public mvExpandCommand(): MvExpandCommandContext { + let _localctx: MvExpandCommandContext = new MvExpandCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 64, esql_parser.RULE_mvExpandCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 418; + this.match(esql_parser.MV_EXPAND); + this.state = 419; + this.sourceIdentifier(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) public commandOptions(): CommandOptionsContext { let _localctx: CommandOptionsContext = new CommandOptionsContext(this._ctx, this.state); - this.enterRule(_localctx, 98, esql_parser.RULE_commandOptions); + this.enterRule(_localctx, 66, esql_parser.RULE_commandOptions); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 556; + this.state = 421; this.commandOption(); - this.state = 561; + this.state = 426; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 55, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 41, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 557; + this.state = 422; this.match(esql_parser.COMMA); - this.state = 558; + this.state = 423; this.commandOption(); } } } - this.state = 563; + this.state = 428; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 55, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 41, this._ctx); } } } @@ -2882,15 +2202,15 @@ export class esql_parser extends Parser { // @RuleVersion(0) public commandOption(): CommandOptionContext { let _localctx: CommandOptionContext = new CommandOptionContext(this._ctx, this.state); - this.enterRule(_localctx, 100, esql_parser.RULE_commandOption); + this.enterRule(_localctx, 68, esql_parser.RULE_commandOption); try { this.enterOuterAlt(_localctx, 1); { - this.state = 564; + this.state = 429; this.identifier(); - this.state = 565; + this.state = 430; this.match(esql_parser.ASSIGN); - this.state = 566; + this.state = 431; this.constant(); } } @@ -2911,12 +2231,23 @@ export class esql_parser extends Parser { // @RuleVersion(0) public booleanValue(): BooleanValueContext { let _localctx: BooleanValueContext = new BooleanValueContext(this._ctx, this.state); - this.enterRule(_localctx, 102, esql_parser.RULE_booleanValue); + this.enterRule(_localctx, 70, esql_parser.RULE_booleanValue); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 568; - this.match(esql_parser.BOOLEAN_VALUE); + this.state = 433; + _la = this._input.LA(1); + if (!(_la === esql_parser.FALSE || _la === esql_parser.TRUE)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -2934,31 +2265,28 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public number(): NumberContext { - let _localctx: NumberContext = new NumberContext(this._ctx, this.state); - this.enterRule(_localctx, 104, esql_parser.RULE_number); + public numericValue(): NumericValueContext { + let _localctx: NumericValueContext = new NumericValueContext(this._ctx, this.state); + this.enterRule(_localctx, 72, esql_parser.RULE_numericValue); try { - this.state = 572; + this.state = 437; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.DECIMAL_LITERAL: - _localctx = new DecimalLiteralContext(_localctx); + switch ( this.interpreter.adaptivePredict(this._input, 42, this._ctx) ) { + case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 570; - this.match(esql_parser.DECIMAL_LITERAL); + this.state = 435; + this.decimalValue(); } break; - case esql_parser.INTEGER_LITERAL: - _localctx = new IntegerLiteralContext(_localctx); + + case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 571; - this.match(esql_parser.INTEGER_LITERAL); + this.state = 436; + this.integerValue(); } break; - default: - throw new NoViableAltException(this); } } catch (re) { @@ -2978,11 +2306,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public decimalValue(): DecimalValueContext { let _localctx: DecimalValueContext = new DecimalValueContext(this._ctx, this.state); - this.enterRule(_localctx, 106, esql_parser.RULE_decimalValue); + this.enterRule(_localctx, 74, esql_parser.RULE_decimalValue); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 574; + this.state = 440; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === esql_parser.PLUS || _la === esql_parser.MINUS) { + { + this.state = 439; + _la = this._input.LA(1); + if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + + this.state = 442; this.match(esql_parser.DECIMAL_LITERAL); } } @@ -3003,11 +2352,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public integerValue(): IntegerValueContext { let _localctx: IntegerValueContext = new IntegerValueContext(this._ctx, this.state); - this.enterRule(_localctx, 108, esql_parser.RULE_integerValue); + this.enterRule(_localctx, 76, esql_parser.RULE_integerValue); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 576; + this.state = 445; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === esql_parser.PLUS || _la === esql_parser.MINUS) { + { + this.state = 444; + _la = this._input.LA(1); + if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + + this.state = 447; this.match(esql_parser.INTEGER_LITERAL); } } @@ -3028,11 +2398,11 @@ export class esql_parser extends Parser { // @RuleVersion(0) public string(): StringContext { let _localctx: StringContext = new StringContext(this._ctx, this.state); - this.enterRule(_localctx, 110, esql_parser.RULE_string); + this.enterRule(_localctx, 78, esql_parser.RULE_string); try { this.enterOuterAlt(_localctx, 1); { - this.state = 578; + this.state = 449; this.match(esql_parser.STRING); } } @@ -3053,12 +2423,23 @@ export class esql_parser extends Parser { // @RuleVersion(0) public comparisonOperator(): ComparisonOperatorContext { let _localctx: ComparisonOperatorContext = new ComparisonOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 112, esql_parser.RULE_comparisonOperator); + this.enterRule(_localctx, 80, esql_parser.RULE_comparisonOperator); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 580; - this.match(esql_parser.COMPARISON_OPERATOR); + this.state = 451; + _la = this._input.LA(1); + if (!(((((_la - 50)) & ~0x1F) === 0 && ((1 << (_la - 50)) & ((1 << (esql_parser.EQ - 50)) | (1 << (esql_parser.NEQ - 50)) | (1 << (esql_parser.LT - 50)) | (1 << (esql_parser.LTE - 50)) | (1 << (esql_parser.GT - 50)) | (1 << (esql_parser.GTE - 50)))) !== 0))) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -3076,16 +2457,34 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public explainCommand(): ExplainCommandContext { - let _localctx: ExplainCommandContext = new ExplainCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 114, esql_parser.RULE_explainCommand); + public showCommand(): ShowCommandContext { + let _localctx: ShowCommandContext = new ShowCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 82, esql_parser.RULE_showCommand); try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 582; - this.match(esql_parser.EXPLAIN); - this.state = 583; - this.subqueryExpression(); + this.state = 457; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 45, this._ctx) ) { + case 1: + _localctx = new ShowInfoContext(_localctx); + this.enterOuterAlt(_localctx, 1); + { + this.state = 453; + this.match(esql_parser.SHOW); + this.state = 454; + this.match(esql_parser.INFO); + } + break; + + case 2: + _localctx = new ShowFunctionsContext(_localctx); + this.enterOuterAlt(_localctx, 2); + { + this.state = 455; + this.match(esql_parser.SHOW); + this.state = 456; + this.match(esql_parser.FUNCTIONS); + } + break; } } catch (re) { @@ -3103,18 +2502,59 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public subqueryExpression(): SubqueryExpressionContext { - let _localctx: SubqueryExpressionContext = new SubqueryExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 116, esql_parser.RULE_subqueryExpression); + public enrichCommand(): EnrichCommandContext { + let _localctx: EnrichCommandContext = new EnrichCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 84, esql_parser.RULE_enrichCommand); try { + let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 585; - this.match(esql_parser.OPENING_BRACKET); - this.state = 586; - this.query(0); - this.state = 587; - this.match(esql_parser.CLOSING_BRACKET); + this.state = 459; + this.match(esql_parser.ENRICH); + this.state = 460; + _localctx._policyName = this.sourceIdentifier(); + this.state = 463; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 46, this._ctx) ) { + case 1: + { + this.state = 461; + this.match(esql_parser.ON); + this.state = 462; + _localctx._matchField = this.sourceIdentifier(); + } + break; + } + this.state = 474; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 48, this._ctx) ) { + case 1: + { + this.state = 465; + this.match(esql_parser.WITH); + this.state = 466; + this.enrichWithClause(); + this.state = 471; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 47, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 467; + this.match(esql_parser.COMMA); + this.state = 468; + this.enrichWithClause(); + } + } + } + this.state = 473; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 47, this._ctx); + } + } + break; + } } } catch (re) { @@ -3132,33 +2572,27 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public showCommand(): ShowCommandContext { - let _localctx: ShowCommandContext = new ShowCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 118, esql_parser.RULE_showCommand); + public enrichWithClause(): EnrichWithClauseContext { + let _localctx: EnrichWithClauseContext = new EnrichWithClauseContext(this._ctx, this.state); + this.enterRule(_localctx, 86, esql_parser.RULE_enrichWithClause); try { - this.state = 593; + this.enterOuterAlt(_localctx, 1); + { + this.state = 479; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 57, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 49, this._ctx) ) { case 1: - this.enterOuterAlt(_localctx, 1); - { - this.state = 589; - this.match(esql_parser.SHOW); - this.state = 590; - this.match(esql_parser.INFO); - } - break; - - case 2: - this.enterOuterAlt(_localctx, 2); { - this.state = 591; - this.match(esql_parser.SHOW); - this.state = 592; - this.match(esql_parser.FUNCTIONS); + this.state = 476; + _localctx._newName = this.sourceIdentifier(); + this.state = 477; + this.match(esql_parser.ASSIGN); } break; } + this.state = 481; + _localctx._enrichField = this.sourceIdentifier(); + } } catch (re) { if (re instanceof RecognitionException) { @@ -3180,13 +2614,10 @@ export class esql_parser extends Parser { case 1: return this.query_sempred(_localctx as QueryContext, predIndex); - case 8: - return this.whereBooleanExpression_sempred(_localctx as WhereBooleanExpressionContext, predIndex); - - case 9: + case 5: return this.booleanExpression_sempred(_localctx as BooleanExpressionContext, predIndex); - case 16: + case 8: return this.operatorExpression_sempred(_localctx as OperatorExpressionContext, predIndex); } return true; @@ -3198,17 +2629,17 @@ export class esql_parser extends Parser { } return true; } - private whereBooleanExpression_sempred(_localctx: WhereBooleanExpressionContext, predIndex: number): boolean { + private booleanExpression_sempred(_localctx: BooleanExpressionContext, predIndex: number): boolean { switch (predIndex) { case 1: - return this.precpred(this._ctx, 5); + return this.precpred(this._ctx, 4); case 2: - return this.precpred(this._ctx, 4); + return this.precpred(this._ctx, 3); } return true; } - private booleanExpression_sempred(_localctx: BooleanExpressionContext, predIndex: number): boolean { + private operatorExpression_sempred(_localctx: OperatorExpressionContext, predIndex: number): boolean { switch (predIndex) { case 3: return this.precpred(this._ctx, 2); @@ -3218,20 +2649,9 @@ export class esql_parser extends Parser { } return true; } - private operatorExpression_sempred(_localctx: OperatorExpressionContext, predIndex: number): boolean { - switch (predIndex) { - case 5: - return this.precpred(this._ctx, 2); - - case 6: - return this.precpred(this._ctx, 1); - } - return true; - } - private static readonly _serializedATNSegments: number = 2; - private static readonly _serializedATNSegment0: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03S\u0256\x04\x02" + + public static readonly _serializedATN: string = + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03N\u01E6\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + @@ -3239,293 +2659,233 @@ export class esql_parser extends Parser { "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + "\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x04)\t)\x04*\t*\x04+\t+" + - "\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x041\t1\x042\t2\x043\t3\x044" + - "\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04:\t:\x04;\t;\x04<\t<\x04" + - "=\t=\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" + - "\x03\x07\x03\x84\n\x03\f\x03\x0E\x03\x87\v\x03\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x05\x04\x8D\n\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05\x9C" + - "\n\x05\x03\x06\x03\x06\x03\x06\x03\x06\x05\x06\xA2\n\x06\x03\x06\x03\x06" + - "\x03\x06\x03\x06\x07\x06\xA8\n\x06\f\x06\x0E\x06\xAB\v\x06\x05\x06\xAD" + - "\n\x06\x03\x07\x03\x07\x03\x07\x05\x07\xB2\n\x07\x03\x07\x03\x07\x03\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03" + - "\n\x05\n\xC3\n\n\x03\n\x03\n\x03\n\x03\n\x03\n\x07\n\xCA\n\n\f\n\x0E\n" + - "\xCD\v\n\x03\n\x03\n\x03\n\x05\n\xD2\n\n\x03\n\x03\n\x03\n\x03\n\x03\n" + - "\x07\n\xD9\n\n\f\n\x0E\n\xDC\v\n\x05\n\xDE\n\n\x03\n\x03\n\x03\n\x03\n" + - "\x03\n\x05\n\xE5\n\n\x03\n\x03\n\x05\n\xE9\n\n\x03\n\x03\n\x03\n\x03\n" + - "\x03\n\x03\n\x07\n\xF1\n\n\f\n\x0E\n\xF4\v\n\x03\v\x03\v\x03\v\x03\v\x05" + - "\v\xFA\n\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x07\v\u0102\n\v\f\v\x0E" + - "\v\u0105\v\v\x03\f\x03\f\x05\f\u0109\n\f\x03\f\x03\f\x03\f\x03\f\x03\f" + - "\x05\f\u0110\n\f\x03\f\x03\f\x03\f\x05\f\u0115\n\f\x03\r\x03\r\x05\r\u0119" + - "\n\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03" + - "\x0F\x07\x0F\u0124\n\x0F\f\x0F\x0E\x0F\u0127\v\x0F\x05\x0F\u0129\n\x0F" + - "\x03\x0F\x03\x0F\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x07\x10\u0132" + - "\n\x10\f\x10\x0E\x10\u0135\v\x10\x05\x10\u0137\n\x10\x03\x10\x03\x10\x03" + - "\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x05" + - "\x12\u0144\n\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x07\x12" + - "\u014C\n\x12\f\x12\x0E\x12\u014F\v\x12\x03\x13\x03\x13\x03\x13\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13\x07\x13" + - "\u015D\n\x13\f\x13\x0E\x13\u0160\v\x13\x05\x13\u0162\n\x13\x03\x13\x03" + - "\x13\x05\x13\u0166\n\x13\x03\x14\x03\x14\x03\x14\x03\x15\x03\x15\x03\x15" + - "\x07\x15\u016E\n\x15\f\x15\x0E\x15\u0171\v\x15\x03\x16\x03\x16\x03\x16" + - "\x03\x16\x03\x16\x05\x16\u0178\n\x16\x03\x17\x03\x17\x03\x18\x03\x18\x03" + - "\x19\x03\x19\x03\x19\x03\x19\x07\x19\u0182\n\x19\f\x19\x0E\x19\u0185\v" + - "\x19\x03\x19\x05\x19\u0188\n\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A" + - "\x07\x1A\u018F\n\x1A\f\x1A\x0E\x1A\u0192\v\x1A\x03\x1A\x03\x1A\x03\x1B" + - "\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x05\x1C\u019B\n\x1C\x03\x1C\x03\x1C\x05" + - "\x1C\u019F\n\x1C\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03\x1F" + - "\x05\x1F\u01A8\n\x1F\x03 \x03 \x03 \x03 \x03 \x03 \x05 \u01B0\n \x03!" + - "\x03!\x03!\x07!\u01B5\n!\f!\x0E!\u01B8\v!\x03\"\x03\"\x03\"\x07\"\u01BD" + - "\n\"\f\"\x0E\"\u01C0\v\"\x03#\x03#\x03$\x03$\x03%\x03%\x03&\x03&\x03&" + - "\x03&\x03&\x03&\x03&\x03&\x07&\u01D0\n&\f&\x0E&\u01D3\v&\x03&\x03&\x03" + - "&\x03&\x03&\x03&\x07&\u01DB\n&\f&\x0E&\u01DE\v&\x03&\x03&\x03&\x03&\x03" + - "&\x03&\x07&\u01E6\n&\f&\x0E&\u01E9\v&\x03&\x03&\x05&\u01ED\n&\x03\'\x03" + - "\'\x05\'\u01F1\n\'\x03(\x03(\x03(\x03)\x03)\x03)\x03)\x07)\u01FA\n)\f" + - ")\x0E)\u01FD\v)\x03*\x03*\x05*\u0201\n*\x03*\x03*\x05*\u0205\n*\x03+\x03" + - "+\x03+\x03,\x03,\x03,\x03-\x03-\x03-\x03.\x03.\x03.\x07.\u0213\n.\f.\x0E" + - ".\u0216\v.\x03/\x03/\x03/\x03/\x07/\u021C\n/\f/\x0E/\u021F\v/\x030\x03" + - "0\x030\x030\x031\x031\x031\x031\x051\u0229\n1\x032\x032\x032\x032\x03" + - "3\x033\x033\x073\u0232\n3\f3\x0E3\u0235\v3\x034\x034\x034\x034\x035\x03" + - "5\x036\x036\x056\u023F\n6\x037\x037\x038\x038\x039\x039\x03:\x03:\x03" + - ";\x03;\x03;\x03<\x03<\x03<\x03<\x03=\x03=\x03=\x03=\x05=\u0254\n=\x03" + - "=\x02\x02\x06\x04\x12\x14\">\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02" + - "\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02" + - " \x02\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02" + - "<\x02>\x02@\x02B\x02D\x02F\x02H\x02J\x02L\x02N\x02P\x02R\x02T\x02V\x02" + - "X\x02Z\x02\\\x02^\x02`\x02b\x02d\x02f\x02h\x02j\x02l\x02n\x02p\x02r\x02" + - "t\x02v\x02x\x02\x02\x07\x03\x0256\x03\x0279\x03\x02NO\x03\x02GH\x04\x02" + - "77AB\x02\u0273\x02z\x03\x02\x02\x02\x04}\x03\x02\x02\x02\x06\x8C\x03\x02" + - "\x02\x02\b\x9B\x03\x02\x02\x02\n\x9D\x03\x02\x02\x02\f\xB1\x03\x02\x02" + - "\x02\x0E\xB5\x03\x02\x02\x02\x10\xB8\x03\x02\x02\x02\x12\xE8\x03\x02\x02" + - "\x02\x14\xF9\x03\x02\x02\x02\x16\u0114\x03\x02\x02\x02\x18\u0118\x03\x02" + - "\x02\x02\x1A\u011A\x03\x02\x02\x02\x1C\u011E\x03\x02\x02\x02\x1E\u012C" + - "\x03\x02\x02\x02 \u013A\x03\x02\x02\x02\"\u0143\x03\x02\x02\x02$\u0165" + - "\x03\x02\x02\x02&\u0167\x03\x02\x02\x02(\u016A\x03\x02\x02\x02*\u0177" + - "\x03\x02\x02\x02,\u0179\x03\x02\x02\x02.\u017B\x03\x02\x02\x020\u017D" + - "\x03\x02\x02\x022\u0189\x03\x02\x02\x024\u0195\x03\x02\x02\x026\u0198" + - "\x03\x02\x02\x028\u01A0\x03\x02\x02\x02:\u01A2\x03\x02\x02\x02<\u01A7" + - "\x03\x02\x02\x02>\u01AF\x03\x02\x02\x02@\u01B1\x03\x02\x02\x02B\u01B9" + - "\x03\x02\x02\x02D\u01C1\x03\x02\x02\x02F\u01C3\x03\x02\x02\x02H\u01C5" + - "\x03\x02\x02\x02J\u01EC\x03\x02\x02\x02L\u01F0\x03\x02\x02\x02N\u01F2" + - "\x03\x02\x02\x02P\u01F5\x03\x02\x02\x02R\u01FE\x03\x02\x02\x02T\u0206" + - "\x03\x02\x02\x02V\u0209\x03\x02\x02\x02X\u020C\x03\x02\x02\x02Z\u020F" + - "\x03\x02\x02\x02\\\u0217\x03\x02\x02\x02^\u0220\x03\x02\x02\x02`\u0224" + - "\x03\x02\x02\x02b\u022A\x03\x02\x02\x02d\u022E\x03\x02\x02\x02f\u0236" + - "\x03\x02\x02\x02h\u023A\x03\x02\x02\x02j\u023E\x03\x02\x02\x02l\u0240" + - "\x03\x02\x02\x02n\u0242\x03\x02\x02\x02p\u0244\x03\x02\x02\x02r\u0246" + - "\x03\x02\x02\x02t\u0248\x03\x02\x02\x02v\u024B\x03\x02\x02\x02x\u0253" + - "\x03\x02\x02\x02z{\x05\x04\x03\x02{|\x07\x02\x02\x03|\x03\x03\x02\x02" + - "\x02}~\b\x03\x01\x02~\x7F\x05\x06\x04\x02\x7F\x85\x03\x02\x02\x02\x80" + - "\x81\f\x03\x02\x02\x81\x82\x07\x1A\x02\x02\x82\x84\x05\b\x05\x02\x83\x80" + - "\x03\x02\x02\x02\x84\x87\x03\x02\x02\x02\x85\x83\x03\x02\x02\x02\x85\x86" + - "\x03\x02\x02\x02\x86\x05\x03\x02\x02\x02\x87\x85\x03\x02\x02\x02\x88\x8D" + - "\x05t;\x02\x89\x8D\x050\x19\x02\x8A\x8D\x05&\x14\x02\x8B\x8D\x05x=\x02" + - "\x8C\x88\x03\x02\x02\x02\x8C\x89\x03\x02\x02\x02\x8C\x8A\x03\x02\x02\x02" + - "\x8C\x8B\x03\x02\x02\x02\x8D\x07\x03\x02\x02\x02\x8E\x9C\x054\x1B\x02" + - "\x8F\x9C\x05N(\x02\x90\x9C\x05T+\x02\x91\x9C\x05V,\x02\x92\x9C\x05\\/" + - "\x02\x93\x9C\x05X-\x02\x94\x9C\x05`1\x02\x95\x9C\x05b2\x02\x96\x9C\x05" + - "P)\x02\x97\x9C\x056\x1C\x02\x98\x9C\x05\x10\t\x02\x99\x9C\x05\x0E\b\x02" + - "\x9A\x9C\x05\n\x06\x02\x9B\x8E\x03\x02\x02\x02\x9B\x8F\x03\x02\x02\x02" + - "\x9B\x90\x03\x02\x02\x02\x9B\x91\x03\x02\x02\x02\x9B\x92\x03\x02\x02\x02" + - "\x9B\x93\x03\x02\x02\x02\x9B\x94\x03\x02\x02\x02\x9B\x95\x03\x02\x02\x02" + - "\x9B\x96\x03\x02\x02\x02\x9B\x97\x03\x02\x02\x02\x9B\x98\x03\x02\x02\x02" + - "\x9B\x99\x03\x02\x02\x02\x9B\x9A\x03\x02\x02\x02\x9C\t\x03\x02\x02\x02" + - "\x9D\x9E\x07\x12\x02\x02\x9E\xA1\x05:\x1E\x02\x9F\xA0\x07L\x02\x02\xA0" + - "\xA2\x05,\x17\x02\xA1\x9F\x03\x02\x02\x02\xA1\xA2\x03\x02\x02\x02\xA2" + - "\xAC\x03\x02\x02\x02\xA3\xA4\x07M\x02\x02\xA4\xA9\x05\f\x07\x02\xA5\xA6" + - "\x07\"\x02\x02\xA6\xA8\x05\f\x07\x02\xA7\xA5\x03\x02\x02\x02\xA8\xAB\x03" + - "\x02\x02\x02\xA9\xA7\x03\x02\x02\x02\xA9\xAA\x03\x02\x02\x02\xAA\xAD\x03" + - "\x02\x02\x02\xAB\xA9\x03\x02\x02\x02\xAC\xA3\x03\x02\x02\x02\xAC\xAD\x03" + - "\x02\x02\x02\xAD\v\x03\x02\x02\x02\xAE\xAF\x05,\x17\x02\xAF\xB0\x07!\x02" + - "\x02\xB0\xB2\x03\x02\x02\x02\xB1\xAE\x03\x02\x02\x02\xB1\xB2\x03\x02\x02" + - "\x02\xB2\xB3\x03\x02\x02\x02\xB3\xB4\x05,\x17\x02\xB4\r\x03\x02\x02\x02" + - "\xB5\xB6\x07\f\x02\x02\xB6\xB7\x05B\"\x02\xB7\x0F\x03\x02\x02\x02\xB8" + - "\xB9\x07\n\x02\x02\xB9\xBA\x05\x12\n\x02\xBA\x11\x03\x02\x02\x02\xBB\xBC" + - "\b\n\x01\x02\xBC\xBD\x07\'\x02\x02\xBD\xE9\x05\x12\n\n\xBE\xE9\x05\x18" + - "\r\x02\xBF\xE9\x05\x16\f\x02\xC0\xC2\x05\x18\r\x02\xC1\xC3\x07\'\x02\x02" + - "\xC2\xC1\x03\x02\x02\x02\xC2\xC3\x03\x02\x02\x02\xC3\xC4\x03\x02\x02\x02" + - "\xC4\xC5\x07*\x02\x02\xC5\xC6\x07$\x02\x02\xC6\xCB\x05\x18\r\x02\xC7\xC8" + - "\x07\"\x02\x02\xC8\xCA\x05\x18\r\x02\xC9\xC7\x03\x02\x02\x02\xCA\xCD\x03" + - "\x02\x02\x02\xCB\xC9\x03\x02\x02\x02\xCB\xCC\x03\x02\x02\x02\xCC\xCE\x03" + - "\x02\x02\x02\xCD\xCB\x03\x02\x02\x02\xCE\xCF\x07/\x02\x02\xCF\xE9\x03" + - "\x02\x02\x02\xD0\xD2\x07\'\x02\x02\xD1\xD0\x03\x02\x02\x02\xD1\xD2\x03" + - "\x02\x02\x02\xD2\xD3\x03\x02\x02\x02\xD3\xD4\x07@\x02\x02\xD4\xD5\x07" + - "$\x02\x02\xD5\xDD\x05@!\x02\xD6\xD7\x07\"\x02\x02\xD7\xD9\x05<\x1F\x02" + - "\xD8\xD6\x03\x02\x02\x02\xD9\xDC\x03\x02\x02\x02\xDA\xD8\x03\x02\x02\x02" + - "\xDA\xDB\x03\x02\x02\x02\xDB\xDE\x03\x02\x02\x02\xDC\xDA\x03\x02\x02\x02" + - "\xDD\xDA\x03\x02\x02\x02\xDD\xDE\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02" + - "\xDF\xE0\x07/\x02\x02\xE0\xE9\x03\x02\x02\x02\xE1\xE2\x05\x18\r\x02\xE2" + - "\xE4\x07+\x02\x02\xE3\xE5\x07\'\x02\x02\xE4\xE3\x03\x02\x02\x02\xE4\xE5" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE7\x07-\x02\x02\xE7\xE9" + - "\x03\x02\x02\x02\xE8\xBB\x03\x02\x02\x02\xE8\xBE\x03\x02\x02\x02\xE8\xBF" + - "\x03\x02\x02\x02\xE8\xC0\x03\x02\x02\x02\xE8\xD1\x03\x02\x02\x02\xE8\xE1" + - "\x03\x02\x02\x02\xE9\xF2\x03\x02\x02\x02\xEA\xEB\f\x07\x02\x02\xEB\xEC" + - "\x07 \x02\x02\xEC\xF1\x05\x12\n\b\xED\xEE\f\x06\x02\x02\xEE\xEF\x07.\x02" + - "\x02\xEF\xF1\x05\x12\n\x07\xF0\xEA\x03\x02\x02\x02\xF0\xED\x03\x02\x02" + - "\x02\xF1\xF4\x03\x02\x02\x02\xF2\xF0\x03\x02\x02\x02\xF2\xF3\x03\x02\x02" + - "\x02\xF3\x13\x03\x02\x02\x02\xF4\xF2\x03\x02\x02\x02\xF5\xF6\b\v\x01\x02" + - "\xF6\xF7\x07\'\x02\x02\xF7\xFA\x05\x14\v\x06\xF8\xFA\x05\x18\r\x02\xF9" + - "\xF5\x03\x02\x02\x02\xF9\xF8\x03\x02\x02\x02\xFA\u0103\x03\x02\x02\x02" + - "\xFB\xFC\f\x04\x02\x02\xFC\xFD\x07 \x02\x02\xFD\u0102\x05\x14\v\x05\xFE" + - "\xFF\f\x03\x02\x02\xFF\u0100\x07.\x02\x02\u0100\u0102\x05\x14\v\x04\u0101" + - "\xFB\x03\x02\x02\x02\u0101\xFE\x03\x02\x02\x02\u0102\u0105\x03\x02\x02" + - "\x02\u0103\u0101\x03\x02\x02\x02\u0103\u0104\x03\x02\x02\x02\u0104\x15" + - "\x03\x02\x02\x02\u0105\u0103\x03\x02\x02\x02\u0106\u0108\x05\x18\r\x02" + - "\u0107\u0109\x07\'\x02\x02\u0108\u0107\x03\x02\x02\x02\u0108\u0109\x03" + - "\x02\x02\x02\u0109\u010A\x03\x02\x02\x02\u010A\u010B\x07(\x02\x02\u010B" + - "\u010C\x05p9\x02\u010C\u0115\x03\x02\x02\x02\u010D\u010F\x05\x18\r\x02" + - "\u010E\u0110\x07\'\x02\x02\u010F\u010E\x03\x02\x02\x02\u010F\u0110\x03" + - "\x02\x02\x02\u0110\u0111\x03\x02\x02\x02\u0111\u0112\x07)\x02\x02\u0112" + - "\u0113\x05p9\x02\u0113\u0115\x03\x02\x02\x02\u0114\u0106\x03\x02\x02\x02" + - "\u0114\u010D\x03\x02\x02\x02\u0115\x17\x03\x02\x02\x02\u0116\u0119\x05" + - "\"\x12\x02\u0117\u0119\x05\x1A\x0E\x02\u0118\u0116\x03\x02\x02\x02\u0118" + - "\u0117\x03\x02\x02\x02\u0119\x19\x03\x02\x02\x02\u011A\u011B\x05\"\x12" + - "\x02\u011B\u011C\x05r:\x02\u011C\u011D\x05\"\x12\x02\u011D\x1B\x03\x02" + - "\x02\x02\u011E\u011F\x05H%\x02\u011F\u0128\x07$\x02\x02\u0120\u0125\x05" + - "<\x1F\x02\u0121\u0122\x07\"\x02\x02\u0122\u0124\x05<\x1F\x02\u0123\u0121" + - "\x03\x02\x02\x02\u0124\u0127\x03\x02\x02\x02\u0125\u0123\x03\x02\x02\x02" + - "\u0125\u0126\x03\x02\x02\x02\u0126\u0129\x03\x02\x02\x02\u0127\u0125\x03" + - "\x02\x02\x02\u0128\u0120\x03\x02\x02\x02\u0128\u0129\x03\x02\x02\x02\u0129" + - "\u012A\x03\x02\x02\x02\u012A\u012B\x07/\x02\x02\u012B\x1D\x03\x02\x02" + - "\x02\u012C\u012D\x05F$\x02\u012D\u0136\x07$\x02\x02\u012E\u0133\x05> " + - "\x02\u012F\u0130\x07\"\x02\x02\u0130\u0132\x05> \x02\u0131\u012F\x03\x02" + - "\x02\x02\u0132\u0135\x03\x02\x02\x02\u0133\u0131\x03\x02\x02\x02\u0133" + - "\u0134\x03\x02\x02\x02\u0134\u0137\x03\x02\x02\x02\u0135\u0133\x03\x02" + - "\x02\x02\u0136\u012E\x03\x02\x02\x02\u0136\u0137\x03\x02\x02\x02\u0137" + - "\u0138\x03\x02\x02\x02\u0138\u0139\x07/\x02\x02\u0139\x1F\x03\x02\x02" + - "\x02\u013A\u013B\x05j6\x02\u013B\u013C\x07\x1F\x02\x02\u013C!\x03\x02" + - "\x02\x02\u013D\u013E\b\x12\x01\x02\u013E\u0144\x05$\x13\x02\u013F\u0144" + - "\x05\x1C\x0F\x02\u0140\u0144\x05\x1E\x10\x02\u0141\u0142\t\x02\x02\x02" + - "\u0142\u0144\x05\"\x12\x05\u0143\u013D\x03\x02\x02\x02\u0143\u013F\x03" + - "\x02\x02\x02\u0143\u0140\x03\x02\x02\x02\u0143\u0141\x03\x02\x02\x02\u0144" + - "\u014D\x03\x02\x02\x02\u0145\u0146\f\x04\x02\x02\u0146\u0147\t\x03\x02" + - "\x02\u0147\u014C\x05\"\x12\x05\u0148\u0149\f\x03\x02\x02\u0149\u014A\t" + - "\x02\x02\x02\u014A\u014C\x05\"\x12\x04\u014B\u0145\x03\x02\x02\x02\u014B" + - "\u0148\x03\x02\x02\x02\u014C\u014F\x03\x02\x02\x02\u014D\u014B\x03\x02" + - "\x02\x02\u014D\u014E\x03\x02\x02\x02\u014E#\x03\x02\x02\x02\u014F\u014D" + - "\x03\x02\x02\x02\u0150\u0166\x05J&\x02\u0151\u0166\x05@!\x02\u0152\u0166" + - "\x05 \x11\x02\u0153\u0154\x07$\x02\x02\u0154\u0155\x05\x14\v\x02\u0155" + - "\u0156\x07/\x02\x02\u0156\u0166\x03\x02\x02\x02\u0157\u0158\x05D#\x02" + - "\u0158\u0161\x07$\x02\x02\u0159\u015E\x05\x14\v\x02\u015A\u015B\x07\"" + - "\x02\x02\u015B\u015D\x05\x14\v\x02\u015C\u015A\x03\x02\x02\x02\u015D\u0160" + - "\x03\x02\x02\x02\u015E\u015C\x03\x02\x02\x02\u015E\u015F\x03\x02\x02\x02" + - "\u015F\u0162\x03\x02\x02\x02\u0160\u015E\x03\x02\x02\x02\u0161\u0159\x03" + - "\x02\x02\x02\u0161\u0162\x03\x02\x02\x02\u0162\u0163\x03\x02\x02\x02\u0163" + - "\u0164\x07/\x02\x02\u0164\u0166\x03\x02\x02\x02\u0165\u0150\x03\x02\x02" + - "\x02\u0165\u0151\x03\x02\x02\x02\u0165\u0152\x03\x02\x02\x02\u0165\u0153" + - "\x03\x02\x02\x02\u0165\u0157\x03\x02\x02\x02\u0166%\x03\x02\x02\x02\u0167" + - "\u0168\x07\b\x02\x02\u0168\u0169\x05(\x15\x02\u0169\'\x03\x02\x02\x02" + - "\u016A\u016F\x05*\x16\x02\u016B\u016C\x07\"\x02\x02\u016C\u016E\x05*\x16" + - "\x02\u016D\u016B\x03\x02\x02\x02\u016E\u0171\x03\x02\x02\x02\u016F\u016D" + - "\x03\x02\x02\x02\u016F\u0170\x03\x02\x02\x02\u0170)\x03\x02\x02\x02\u0171" + - "\u016F\x03\x02\x02\x02\u0172\u0178\x05\x14\v\x02\u0173\u0174\x05.\x18" + - "\x02\u0174\u0175\x07!\x02\x02\u0175\u0176\x05\x14\v\x02\u0176\u0178\x03" + - "\x02\x02\x02\u0177\u0172\x03\x02\x02\x02\u0177\u0173\x03\x02\x02\x02\u0178" + - "+\x03\x02\x02\x02\u0179\u017A\t\x04\x02\x02\u017A-\x03\x02\x02\x02\u017B" + - "\u017C\x05D#\x02\u017C/\x03\x02\x02\x02\u017D\u017E\x07\x07\x02\x02\u017E" + - "\u0183\x058\x1D\x02\u017F\u0180\x07\"\x02\x02\u0180\u0182\x058\x1D\x02" + - "\u0181\u017F\x03\x02\x02\x02\u0182\u0185\x03\x02\x02\x02\u0183\u0181\x03" + - "\x02\x02\x02\u0183\u0184\x03\x02\x02\x02\u0184\u0187\x03\x02\x02\x02\u0185" + - "\u0183\x03\x02\x02\x02\u0186\u0188\x052\x1A\x02\u0187\u0186\x03\x02\x02" + - "\x02\u0187\u0188\x03\x02\x02\x02\u01881\x03\x02\x02\x02\u0189\u018A\x07" + - "%\x02\x02\u018A\u018B\x07F\x02\x02\u018B\u0190\x058\x1D\x02\u018C\u018D" + - "\x07\"\x02\x02\u018D\u018F\x058\x1D\x02\u018E\u018C\x03\x02\x02\x02\u018F" + - "\u0192\x03\x02\x02\x02\u0190\u018E\x03\x02\x02\x02\u0190\u0191\x03\x02" + - "\x02\x02\u0191\u0193\x03\x02\x02\x02\u0192\u0190\x03\x02\x02\x02\u0193" + - "\u0194\x07&\x02\x02\u01943\x03\x02\x02\x02\u0195\u0196\x07\x05\x02\x02" + - "\u0196\u0197\x05(\x15\x02\u01975\x03\x02\x02\x02\u0198\u019A\x07\t\x02" + - "\x02\u0199\u019B\x05(\x15\x02\u019A\u0199\x03\x02\x02\x02\u019A\u019B" + - "\x03\x02\x02\x02\u019B\u019E\x03\x02\x02\x02\u019C\u019D\x07\x1E\x02\x02" + - "\u019D\u019F\x05B\"\x02\u019E\u019C\x03\x02\x02\x02\u019E\u019F\x03\x02" + - "\x02\x02\u019F7\x03\x02\x02\x02\u01A0\u01A1\t\x05\x02\x02\u01A19\x03\x02" + - "\x02\x02\u01A2\u01A3\t\x04\x02\x02\u01A3;\x03\x02\x02\x02\u01A4\u01A8" + - "\x05@!\x02\u01A5\u01A8\x05p9\x02\u01A6\u01A8\x05j6\x02\u01A7\u01A4\x03" + - "\x02\x02\x02\u01A7\u01A5\x03\x02\x02\x02\u01A7\u01A6\x03\x02\x02\x02\u01A8" + - "=\x03\x02\x02\x02\u01A9\u01B0\x05@!\x02\u01AA\u01B0\x05p9\x02\u01AB\u01B0" + - "\x05j6\x02\u01AC\u01B0\x05\"\x12\x02\u01AD\u01B0\x05 \x11\x02\u01AE\u01B0" + - "\x05\x1A\x0E\x02\u01AF\u01A9\x03\x02\x02\x02\u01AF\u01AA\x03\x02\x02\x02" + - "\u01AF\u01AB\x03\x02\x02\x02\u01AF\u01AC\x03\x02\x02\x02\u01AF\u01AD\x03" + - "\x02\x02\x02\u01AF\u01AE\x03\x02\x02\x02\u01B0?\x03\x02\x02\x02\u01B1" + - "\u01B6\x05D#\x02\u01B2\u01B3\x07#\x02\x02\u01B3\u01B5\x05D#\x02\u01B4" + - "\u01B2\x03\x02\x02\x02\u01B5\u01B8\x03\x02\x02\x02\u01B6\u01B4\x03\x02" + - "\x02\x02\u01B6\u01B7\x03\x02\x02\x02\u01B7A\x03\x02\x02\x02\u01B8\u01B6" + - "\x03\x02\x02\x02\u01B9\u01BE\x05@!\x02\u01BA\u01BB\x07\"\x02\x02\u01BB" + - "\u01BD\x05@!\x02\u01BC\u01BA\x03\x02\x02\x02\u01BD\u01C0\x03\x02\x02\x02" + - "\u01BE\u01BC\x03\x02\x02\x02\u01BE\u01BF\x03\x02\x02\x02\u01BFC\x03\x02" + - "\x02\x02\u01C0\u01BE\x03\x02\x02\x02\u01C1\u01C2\t\x06\x02\x02\u01C2E" + - "\x03\x02\x02\x02\u01C3\u01C4\x07>\x02\x02\u01C4G\x03\x02\x02\x02\u01C5" + - "\u01C6\x07?\x02\x02\u01C6I\x03\x02\x02\x02\u01C7\u01ED\x07-\x02\x02\u01C8" + - "\u01ED\x05L\'\x02\u01C9\u01ED\x05h5\x02\u01CA\u01ED\x05p9\x02\u01CB\u01CC" + - "\x07%\x02\x02\u01CC\u01D1\x05L\'\x02\u01CD\u01CE\x07\"\x02\x02\u01CE\u01D0" + - "\x05L\'\x02\u01CF\u01CD\x03\x02\x02\x02\u01D0\u01D3\x03\x02\x02\x02\u01D1" + - "\u01CF\x03\x02\x02\x02\u01D1\u01D2\x03\x02\x02\x02\u01D2\u01D4\x03\x02" + - "\x02\x02\u01D3\u01D1\x03\x02\x02\x02\u01D4\u01D5\x07&\x02\x02\u01D5\u01ED" + - "\x03\x02\x02\x02\u01D6\u01D7\x07%\x02\x02\u01D7\u01DC\x05h5\x02\u01D8" + - "\u01D9\x07\"\x02\x02\u01D9\u01DB\x05h5\x02\u01DA\u01D8\x03\x02\x02\x02" + - "\u01DB\u01DE\x03\x02\x02\x02\u01DC\u01DA\x03\x02\x02\x02\u01DC\u01DD\x03" + - "\x02\x02\x02\u01DD\u01DF\x03\x02\x02\x02\u01DE\u01DC\x03\x02\x02\x02\u01DF" + - "\u01E0\x07&\x02\x02\u01E0\u01ED\x03\x02\x02\x02\u01E1\u01E2\x07%\x02\x02" + - "\u01E2\u01E7\x05p9\x02\u01E3\u01E4\x07\"\x02\x02\u01E4\u01E6\x05p9\x02" + - "\u01E5\u01E3\x03\x02\x02\x02\u01E6\u01E9\x03\x02\x02\x02\u01E7\u01E5\x03" + - "\x02\x02\x02\u01E7\u01E8\x03\x02\x02\x02\u01E8\u01EA\x03\x02\x02\x02\u01E9" + - "\u01E7\x03\x02\x02\x02\u01EA\u01EB\x07&\x02\x02\u01EB\u01ED\x03\x02\x02" + - "\x02\u01EC\u01C7\x03\x02\x02\x02\u01EC\u01C8\x03\x02\x02\x02\u01EC\u01C9" + - "\x03\x02\x02\x02\u01EC\u01CA\x03\x02\x02\x02\u01EC\u01CB\x03\x02\x02\x02" + - "\u01EC\u01D6\x03\x02\x02\x02\u01EC\u01E1\x03\x02\x02\x02\u01EDK\x03\x02" + - "\x02\x02\u01EE\u01F1\x05l7\x02\u01EF\u01F1\x05n8\x02\u01F0\u01EE\x03\x02" + - "\x02\x02\u01F0\u01EF\x03\x02\x02\x02\u01F1M\x03\x02\x02\x02\u01F2\u01F3" + - "\x07\r\x02\x02\u01F3\u01F4\x07\x1C\x02\x02\u01F4O\x03\x02\x02\x02\u01F5" + - "\u01F6\x07\v\x02\x02\u01F6\u01FB\x05R*\x02\u01F7\u01F8\x07\"\x02\x02\u01F8" + - "\u01FA\x05R*\x02\u01F9\u01F7\x03\x02\x02\x02\u01FA\u01FD\x03\x02\x02\x02" + - "\u01FB\u01F9\x03\x02\x02\x02\u01FB\u01FC\x03\x02\x02\x02\u01FCQ\x03\x02" + - "\x02\x02\u01FD\u01FB\x03\x02\x02\x02\u01FE\u0200\x05\x14\v\x02\u01FF\u0201" + - "\x07;\x02\x02\u0200\u01FF\x03\x02\x02\x02\u0200\u0201\x03\x02\x02\x02" + - "\u0201\u0204\x03\x02\x02\x02\u0202\u0203\x07<\x02\x02\u0203\u0205\x07" + - "=\x02\x02\u0204\u0202\x03\x02\x02\x02\u0204\u0205\x03\x02\x02\x02\u0205" + - "S\x03\x02\x02\x02\u0206\u0207\x07\x0E\x02\x02\u0207\u0208\x05B\"\x02\u0208" + - "U\x03\x02\x02\x02\u0209\u020A\x07\x13\x02\x02\u020A\u020B\x05B\"\x02\u020B" + - "W\x03\x02\x02\x02\u020C\u020D\x07\x0F\x02\x02\u020D\u020E\x05B\"\x02\u020E" + - "Y\x03\x02\x02\x02\u020F\u0214\x05D#\x02\u0210\u0211\x07#\x02\x02\u0211" + - "\u0213\x05D#\x02\u0212\u0210\x03\x02\x02\x02\u0213\u0216\x03\x02\x02\x02" + - "\u0214\u0212\x03\x02\x02\x02\u0214\u0215\x03\x02\x02\x02\u0215[\x03\x02" + - "\x02\x02\u0216\u0214\x03\x02\x02\x02\u0217\u0218\x07\x10\x02\x02\u0218" + - "\u021D\x05^0\x02\u0219\u021A\x07\"\x02\x02\u021A\u021C\x05^0\x02\u021B" + - "\u0219\x03\x02\x02\x02\u021C\u021F\x03\x02\x02\x02\u021D\u021B\x03\x02" + - "\x02\x02\u021D\u021E\x03\x02\x02\x02\u021E]\x03\x02\x02\x02\u021F\u021D" + - "\x03\x02\x02\x02\u0220\u0221\x05@!\x02\u0221\u0222\x07,\x02\x02\u0222" + - "\u0223\x05Z.\x02\u0223_\x03\x02\x02\x02\u0224\u0225\x07\x03\x02\x02\u0225" + - "\u0226\x05B\"\x02\u0226\u0228\x05p9\x02\u0227\u0229\x05d3\x02\u0228\u0227" + - "\x03\x02\x02\x02\u0228\u0229\x03\x02\x02\x02\u0229a\x03\x02\x02\x02\u022A" + - "\u022B\x07\x04\x02\x02\u022B\u022C\x05B\"\x02\u022C\u022D\x05p9\x02\u022D" + - "c\x03\x02\x02\x02\u022E\u0233\x05f4\x02\u022F\u0230\x07\"\x02\x02\u0230" + - "\u0232\x05f4\x02\u0231\u022F\x03\x02\x02\x02\u0232\u0235\x03\x02\x02\x02" + - "\u0233\u0231\x03\x02\x02\x02\u0233\u0234\x03\x02\x02\x02\u0234e\x03\x02" + - "\x02\x02\u0235\u0233\x03\x02\x02\x02\u0236\u0237\x05D#\x02\u0237\u0238" + - "\x07!\x02\x02\u0238"; - private static readonly _serializedATNSegment1: string = - "\u0239\x05J&\x02\u0239g\x03\x02\x02\x02\u023A\u023B\x073\x02\x02\u023B" + - "i\x03\x02\x02\x02\u023C\u023F\x07\x1D\x02\x02\u023D\u023F\x07\x1C\x02" + - "\x02\u023E\u023C\x03\x02\x02\x02\u023E\u023D\x03\x02\x02\x02\u023Fk\x03" + - "\x02\x02\x02\u0240\u0241\x07\x1D\x02\x02\u0241m\x03\x02\x02\x02\u0242" + - "\u0243\x07\x1C\x02\x02\u0243o\x03\x02\x02\x02\u0244\u0245\x07\x1B\x02" + - "\x02\u0245q\x03\x02\x02\x02\u0246\u0247\x074\x02\x02\u0247s\x03\x02\x02" + - "\x02\u0248\u0249\x07\x06\x02\x02\u0249\u024A\x05v<\x02\u024Au\x03\x02" + - "\x02\x02\u024B\u024C\x07%\x02\x02\u024C\u024D\x05\x04\x03\x02\u024D\u024E" + - "\x07&\x02\x02\u024Ew\x03\x02\x02\x02\u024F\u0250\x07\x11\x02\x02\u0250" + - "\u0254\x071\x02\x02\u0251\u0252\x07\x11\x02\x02\u0252\u0254\x072\x02\x02" + - "\u0253\u024F\x03\x02\x02\x02\u0253\u0251\x03\x02\x02\x02\u0254y\x03\x02" + - "\x02\x02<\x85\x8C\x9B\xA1\xA9\xAC\xB1\xC2\xCB\xD1\xDA\xDD\xE4\xE8\xF0" + - "\xF2\xF9\u0101\u0103\u0108\u010F\u0114\u0118\u0125\u0128\u0133\u0136\u0143" + - "\u014B\u014D\u015E\u0161\u0165\u016F\u0177\u0183\u0187\u0190\u019A\u019E" + - "\u01A7\u01AF\u01B6\u01BE\u01D1\u01DC\u01E7\u01EC\u01F0\u01FB\u0200\u0204" + - "\u0214\u021D\u0228\u0233\u023E\u0253"; - public static readonly _serializedATN: string = Utils.join( - [ - esql_parser._serializedATNSegment0, - esql_parser._serializedATNSegment1, - ], - "", - ); + "\x04,\t,\x04-\t-\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03" + + "\x03\x03\x03\x03\x07\x03d\n\x03\f\x03\x0E\x03g\v\x03\x03\x04\x03\x04\x03" + + "\x04\x05\x04l\n\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05z\n\x05\x03\x06\x03" + + "\x06\x03\x06\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x05" + + "\x07\x86\n\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x07\x07\x8D\n\x07" + + "\f\x07\x0E\x07\x90\v\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x05\x07" + + "\x97\n\x07\x03\x07\x03\x07\x05\x07\x9B\n\x07\x03\x07\x03\x07\x03\x07\x03" + + "\x07\x03\x07\x03\x07\x07\x07\xA3\n\x07\f\x07\x0E\x07\xA6\v\x07\x03\b\x03" + + "\b\x05\b\xAA\n\b\x03\b\x03\b\x03\b\x03\b\x03\b\x05\b\xB1\n\b\x03\b\x03" + + "\b\x03\b\x05\b\xB6\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x05\t\xBD\n\t\x03" + + "\n\x03\n\x03\n\x03\n\x05\n\xC3\n\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n" + + "\x07\n\xCB\n\n\f\n\x0E\n\xCE\v\n\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03" + + "\v\x05\v\xD7\n\v\x03\f\x03\f\x03\f\x03\f\x03\f\x03\f\x07\f\xDF\n\f\f\f" + + "\x0E\f\xE2\v\f\x05\f\xE4\n\f\x03\f\x03\f\x03\r\x03\r\x03\r\x03\x0E\x03" + + "\x0E\x03\x0E\x07\x0E\xEE\n\x0E\f\x0E\x0E\x0E\xF1\v\x0E\x03\x0F\x03\x0F" + + "\x03\x0F\x03\x0F\x03\x0F\x05\x0F\xF8\n\x0F\x03\x10\x03\x10\x03\x10\x03" + + "\x10\x07\x10\xFE\n\x10\f\x10\x0E\x10\u0101\v\x10\x03\x10\x05\x10\u0104" + + "\n\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x07\x11\u010B\n\x11\f\x11" + + "\x0E\x11\u010E\v\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x13\x03" + + "\x13\x05\x13\u0117\n\x13\x03\x13\x03\x13\x05\x13\u011B\n\x13\x03\x14\x03" + + "\x14\x03\x14\x07\x14\u0120\n\x14\f\x14\x0E\x14\u0123\v\x14\x03\x15\x03" + + "\x15\x03\x16\x03\x16\x03\x16\x07\x16\u012A\n\x16\f\x16\x0E\x16\u012D\v" + + "\x16\x03\x17\x03\x17\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03" + + "\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x07\x18\u013E\n\x18" + + "\f\x18\x0E\x18\u0141\v\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03" + + "\x18\x07\x18\u0149\n\x18\f\x18\x0E\x18\u014C\v\x18\x03\x18\x03\x18\x03" + + "\x18\x03\x18\x03\x18\x03\x18\x07\x18\u0154\n\x18\f\x18\x0E\x18\u0157\v" + + "\x18\x03\x18\x03\x18\x05\x18\u015B\n\x18\x03\x19\x03\x19\x03\x19\x03\x1A" + + "\x03\x1A\x03\x1A\x03\x1A\x07\x1A\u0164\n\x1A\f\x1A\x0E\x1A\u0167\v\x1A" + + "\x03\x1B\x03\x1B\x05\x1B\u016B\n\x1B\x03\x1B\x03\x1B\x05\x1B\u016F\n\x1B" + + "\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u0175\n\x1C\f\x1C\x0E\x1C\u0178" + + "\v\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u017E\n\x1C\f\x1C\x0E\x1C" + + "\u0181\v\x1C\x05\x1C\u0183\n\x1C\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x07\x1D" + + "\u0189\n\x1D\f\x1D\x0E\x1D\u018C\v\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E" + + "\x07\x1E\u0192\n\x1E\f\x1E\x0E\x1E\u0195\v\x1E\x03\x1F\x03\x1F\x03\x1F" + + "\x03\x1F\x03 \x03 \x03 \x03 \x05 \u019F\n \x03!\x03!\x03!\x03!\x03\"\x03" + + "\"\x03\"\x03#\x03#\x03#\x07#\u01AB\n#\f#\x0E#\u01AE\v#\x03$\x03$\x03$" + + "\x03$\x03%\x03%\x03&\x03&\x05&\u01B8\n&\x03\'\x05\'\u01BB\n\'\x03\'\x03" + + "\'\x03(\x05(\u01C0\n(\x03(\x03(\x03)\x03)\x03*\x03*\x03+\x03+\x03+\x03" + + "+\x05+\u01CC\n+\x03,\x03,\x03,\x03,\x05,\u01D2\n,\x03,\x03,\x03,\x03," + + "\x07,\u01D8\n,\f,\x0E,\u01DB\v,\x05,\u01DD\n,\x03-\x03-\x03-\x05-\u01E2" + + "\n-\x03-\x03-\x03-\x02\x02\x05\x04\f\x12.\x02\x02\x04\x02\x06\x02\b\x02" + + "\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C" + + "\x02\x1E\x02 \x02\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x022\x024\x026" + + "\x028\x02:\x02<\x02>\x02@\x02B\x02D\x02F\x02H\x02J\x02L\x02N\x02P\x02" + + "R\x02T\x02V\x02X\x02\x02\n\x03\x02:;\x03\x02<>\x03\x02JK\x03\x02AB\x04" + + "\x02\x1D\x1D \x03\x02#$\x04\x02\"\"00\x03\x0249\x02\u0204\x02Z\x03\x02" + + "\x02\x02\x04]\x03\x02\x02\x02\x06k\x03\x02\x02\x02\by\x03\x02\x02\x02" + + "\n{\x03\x02\x02\x02\f\x9A\x03\x02\x02\x02\x0E\xB5\x03\x02\x02\x02\x10" + + "\xBC\x03\x02\x02\x02\x12\xC2\x03\x02\x02\x02\x14\xD6\x03\x02\x02\x02\x16" + + "\xD8\x03\x02\x02\x02\x18\xE7\x03\x02\x02\x02\x1A\xEA\x03\x02\x02\x02\x1C" + + "\xF7\x03\x02\x02\x02\x1E\xF9\x03\x02\x02\x02 \u0105\x03\x02\x02\x02\"" + + "\u0111\x03\x02\x02\x02$\u0114\x03\x02\x02\x02&\u011C\x03\x02\x02\x02(" + + "\u0124\x03\x02\x02\x02*\u0126\x03\x02\x02\x02,\u012E\x03\x02\x02\x02." + + "\u015A\x03\x02\x02\x020\u015C\x03\x02\x02\x022\u015F\x03\x02\x02\x024" + + "\u0168\x03\x02\x02\x026\u0182\x03\x02\x02\x028\u0184\x03\x02\x02\x02:" + + "\u018D\x03\x02\x02\x02<\u0196\x03\x02\x02\x02>\u019A\x03\x02\x02\x02@" + + "\u01A0\x03\x02\x02\x02B\u01A4\x03\x02\x02\x02D\u01A7\x03\x02\x02\x02F" + + "\u01AF\x03\x02\x02\x02H\u01B3\x03\x02\x02\x02J\u01B7\x03\x02\x02\x02L" + + "\u01BA\x03\x02\x02\x02N\u01BF\x03\x02\x02\x02P\u01C3\x03\x02\x02\x02R" + + "\u01C5\x03\x02\x02\x02T\u01CB\x03\x02\x02\x02V\u01CD\x03\x02\x02\x02X" + + "\u01E1\x03\x02\x02\x02Z[\x05\x04\x03\x02[\\\x07\x02\x02\x03\\\x03\x03" + + "\x02\x02\x02]^\b\x03\x01\x02^_\x05\x06\x04\x02_e\x03\x02\x02\x02`a\f\x03" + + "\x02\x02ab\x07\x17\x02\x02bd\x05\b\x05\x02c`\x03\x02\x02\x02dg\x03\x02" + + "\x02\x02ec\x03\x02\x02\x02ef\x03\x02\x02\x02f\x05\x03\x02\x02\x02ge\x03" + + "\x02\x02\x02hl\x05\x1E\x10\x02il\x05\x18\r\x02jl\x05T+\x02kh\x03\x02\x02" + + "\x02ki\x03\x02\x02\x02kj\x03\x02\x02\x02l\x07\x03\x02\x02\x02mz\x05\"" + + "\x12\x02nz\x050\x19\x02oz\x056\x1C\x02pz\x052\x1A\x02qz\x05$\x13\x02r" + + "z\x05\n\x06\x02sz\x058\x1D\x02tz\x05:\x1E\x02uz\x05> \x02vz\x05@!\x02" + + "wz\x05V,\x02xz\x05B\"\x02ym\x03\x02\x02\x02yn\x03\x02\x02\x02yo\x03\x02" + + "\x02\x02yp\x03\x02\x02\x02yq\x03\x02\x02\x02yr\x03\x02\x02\x02ys\x03\x02" + + "\x02\x02yt\x03\x02\x02\x02yu\x03\x02\x02\x02yv\x03\x02\x02\x02yw\x03\x02" + + "\x02\x02yx\x03\x02\x02\x02z\t\x03\x02\x02\x02{|\x07\x12\x02\x02|}\x05" + + "\f\x07\x02}\v\x03\x02\x02\x02~\x7F\b\x07\x01\x02\x7F\x80\x07)\x02\x02" + + "\x80\x9B\x05\f\x07\t\x81\x9B\x05\x10\t\x02\x82\x9B\x05\x0E\b\x02\x83\x85" + + "\x05\x10\t\x02\x84\x86\x07)\x02\x02\x85\x84\x03\x02\x02\x02\x85\x86\x03" + + "\x02\x02\x02\x86\x87\x03\x02\x02\x02\x87\x88\x07&\x02\x02\x88\x89\x07" + + "%\x02\x02\x89\x8E\x05\x10\t\x02\x8A\x8B\x07\x1F\x02\x02\x8B\x8D\x05\x10" + + "\t\x02\x8C\x8A\x03\x02\x02\x02\x8D\x90\x03\x02\x02\x02\x8E\x8C\x03\x02" + + "\x02\x02\x8E\x8F\x03\x02\x02\x02\x8F\x91\x03\x02\x02\x02\x90\x8E\x03\x02" + + "\x02\x02\x91\x92\x07/\x02\x02\x92\x9B\x03\x02\x02\x02\x93\x94\x05\x10" + + "\t\x02\x94\x96\x07\'\x02\x02\x95\x97\x07)\x02\x02\x96\x95\x03\x02\x02" + + "\x02\x96\x97\x03\x02\x02\x02\x97\x98\x03\x02\x02\x02\x98\x99\x07*\x02" + + "\x02\x99\x9B\x03\x02\x02\x02\x9A~\x03\x02\x02\x02\x9A\x81\x03\x02\x02" + + "\x02\x9A\x82\x03\x02\x02\x02\x9A\x83\x03\x02\x02\x02\x9A\x93\x03\x02\x02" + + "\x02\x9B\xA4\x03\x02\x02\x02\x9C\x9D\f\x06\x02\x02\x9D\x9E\x07\x1C\x02" + + "\x02\x9E\xA3\x05\f\x07\x07\x9F\xA0\f\x05\x02\x02\xA0\xA1\x07,\x02\x02" + + "\xA1\xA3\x05\f\x07\x06\xA2\x9C\x03\x02\x02\x02\xA2\x9F\x03\x02\x02\x02" + + "\xA3\xA6\x03\x02\x02\x02\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02" + + "\xA5\r\x03\x02\x02\x02\xA6\xA4\x03\x02\x02\x02\xA7\xA9\x05\x10\t\x02\xA8" + + "\xAA\x07)\x02\x02\xA9\xA8\x03\x02\x02\x02\xA9\xAA\x03\x02\x02\x02\xAA" + + "\xAB\x03\x02\x02\x02\xAB\xAC\x07(\x02\x02\xAC\xAD\x05P)\x02\xAD\xB6\x03" + + "\x02\x02\x02\xAE\xB0\x05\x10\t\x02\xAF\xB1\x07)\x02\x02\xB0\xAF\x03\x02" + + "\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2\x03\x02\x02\x02\xB2\xB3\x07." + + "\x02\x02\xB3\xB4\x05P)\x02\xB4\xB6\x03\x02\x02\x02\xB5\xA7\x03\x02\x02" + + "\x02\xB5\xAE\x03\x02\x02\x02\xB6\x0F\x03\x02\x02\x02\xB7\xBD\x05\x12\n" + + "\x02\xB8\xB9\x05\x12\n\x02\xB9\xBA\x05R*\x02\xBA\xBB\x05\x12\n\x02\xBB" + + "\xBD\x03\x02\x02\x02\xBC\xB7\x03\x02\x02\x02\xBC\xB8\x03\x02\x02\x02\xBD" + + "\x11\x03\x02\x02\x02\xBE\xBF\b\n\x01\x02\xBF\xC3\x05\x14\v\x02\xC0\xC1" + + "\t\x02\x02\x02\xC1\xC3\x05\x12\n\x05\xC2\xBE\x03\x02\x02\x02\xC2\xC0\x03" + + "\x02\x02\x02\xC3\xCC\x03\x02\x02\x02\xC4\xC5\f\x04\x02\x02\xC5\xC6\t\x03" + + "\x02\x02\xC6\xCB\x05\x12\n\x05\xC7\xC8\f\x03\x02\x02\xC8\xC9\t\x02\x02" + + "\x02\xC9\xCB\x05\x12\n\x04\xCA\xC4\x03\x02\x02\x02\xCA\xC7\x03\x02\x02" + + "\x02\xCB\xCE\x03\x02\x02\x02\xCC\xCA\x03\x02\x02\x02\xCC\xCD\x03\x02\x02" + + "\x02\xCD\x13\x03\x02\x02\x02\xCE\xCC\x03\x02\x02\x02\xCF\xD7\x05.\x18" + + "\x02\xD0\xD7\x05*\x16\x02\xD1\xD7\x05\x16\f\x02\xD2\xD3\x07%\x02\x02\xD3" + + "\xD4\x05\f\x07\x02\xD4\xD5\x07/\x02\x02\xD5\xD7\x03\x02\x02\x02\xD6\xCF" + + "\x03\x02\x02\x02\xD6\xD0\x03\x02\x02\x02\xD6\xD1\x03\x02\x02\x02\xD6\xD2" + + "\x03\x02\x02\x02\xD7\x15\x03\x02\x02\x02\xD8\xD9\x05,\x17\x02\xD9\xE3" + + "\x07%\x02\x02\xDA\xE4\x07<\x02\x02\xDB\xE0\x05\f\x07\x02\xDC\xDD\x07\x1F" + + "\x02\x02\xDD\xDF\x05\f\x07\x02\xDE\xDC\x03\x02\x02\x02\xDF\xE2\x03\x02" + + "\x02\x02\xE0\xDE\x03\x02\x02\x02\xE0\xE1\x03\x02\x02\x02\xE1\xE4\x03\x02" + + "\x02\x02\xE2\xE0\x03\x02\x02\x02\xE3\xDA\x03\x02\x02\x02\xE3\xDB\x03\x02" + + "\x02\x02\xE3\xE4\x03\x02\x02\x02\xE4\xE5\x03\x02\x02\x02\xE5\xE6\x07/" + + "\x02\x02\xE6\x17\x03\x02\x02\x02\xE7\xE8\x07\x0E\x02\x02\xE8\xE9\x05\x1A" + + "\x0E\x02\xE9\x19\x03\x02\x02\x02\xEA\xEF\x05\x1C\x0F\x02\xEB\xEC\x07\x1F" + + "\x02\x02\xEC\xEE\x05\x1C\x0F\x02\xED\xEB\x03\x02\x02\x02\xEE\xF1\x03\x02" + + "\x02\x02\xEF\xED\x03\x02\x02\x02\xEF\xF0\x03\x02\x02\x02\xF0\x1B\x03\x02" + + "\x02\x02\xF1\xEF\x03\x02\x02\x02\xF2\xF8\x05\f\x07\x02\xF3\xF4\x05*\x16" + + "\x02\xF4\xF5\x07\x1E\x02\x02\xF5\xF6\x05\f\x07\x02\xF6\xF8\x03\x02\x02" + + "\x02\xF7\xF2\x03\x02\x02\x02\xF7\xF3\x03\x02\x02\x02\xF8\x1D\x03\x02\x02" + + "\x02\xF9\xFA\x07\x07\x02\x02\xFA\xFF\x05(\x15\x02\xFB\xFC\x07\x1F\x02" + + "\x02\xFC\xFE\x05(\x15\x02\xFD\xFB\x03\x02\x02\x02\xFE\u0101\x03\x02\x02" + + "\x02\xFF\xFD\x03\x02\x02\x02\xFF\u0100\x03\x02\x02\x02\u0100\u0103\x03" + + "\x02\x02\x02\u0101\xFF\x03\x02\x02\x02\u0102\u0104\x05 \x11\x02\u0103" + + "\u0102\x03\x02\x02\x02\u0103\u0104\x03\x02\x02\x02\u0104\x1F\x03\x02\x02" + + "\x02\u0105\u0106\x07?\x02\x02\u0106\u0107\x07G\x02\x02\u0107\u010C\x05" + + "(\x15\x02\u0108\u0109\x07\x1F\x02\x02\u0109\u010B\x05(\x15\x02\u010A\u0108" + + "\x03\x02\x02\x02\u010B\u010E\x03\x02\x02\x02\u010C\u010A\x03\x02\x02\x02" + + "\u010C\u010D\x03\x02\x02\x02\u010D\u010F\x03\x02\x02\x02\u010E\u010C\x03" + + "\x02\x02\x02\u010F\u0110\x07@\x02\x02\u0110!\x03\x02\x02\x02\u0111\u0112" + + "\x07\x06\x02\x02\u0112\u0113\x05\x1A\x0E\x02\u0113#\x03\x02\x02\x02\u0114" + + "\u0116\x07\x11\x02\x02\u0115\u0117\x05\x1A\x0E\x02\u0116\u0115\x03\x02" + + "\x02\x02\u0116\u0117\x03\x02\x02\x02\u0117\u011A\x03\x02\x02\x02\u0118" + + "\u0119\x07\x1B\x02\x02\u0119\u011B\x05&\x14\x02\u011A\u0118\x03\x02\x02" + + "\x02\u011A\u011B\x03\x02\x02\x02\u011B%\x03\x02\x02\x02\u011C\u0121\x05" + + "*\x16\x02\u011D\u011E\x07\x1F\x02\x02\u011E\u0120\x05*\x16\x02\u011F\u011D" + + "\x03\x02\x02\x02\u0120\u0123\x03\x02\x02\x02\u0121\u011F\x03\x02\x02\x02" + + "\u0121\u0122\x03\x02\x02\x02\u0122\'\x03\x02\x02\x02\u0123\u0121\x03\x02" + + "\x02\x02\u0124\u0125\t\x04\x02\x02\u0125)\x03\x02\x02\x02\u0126\u012B" + + "\x05,\x17\x02\u0127\u0128\x07!\x02\x02\u0128\u012A\x05,\x17\x02\u0129" + + "\u0127\x03\x02\x02\x02\u012A\u012D\x03\x02\x02\x02\u012B\u0129\x03\x02" + + "\x02\x02\u012B\u012C\x03\x02\x02\x02\u012C+\x03\x02\x02\x02\u012D\u012B" + + "\x03\x02\x02\x02\u012E\u012F\t\x05\x02\x02\u012F-\x03\x02\x02\x02\u0130" + + "\u015B\x07*\x02\x02\u0131\u0132\x05N(\x02\u0132\u0133\x07A\x02\x02\u0133" + + "\u015B\x03\x02\x02\x02\u0134\u015B\x05L\'\x02\u0135\u015B\x05N(\x02\u0136" + + "\u015B\x05H%\x02\u0137\u015B\x07-\x02\x02\u0138\u015B\x05P)\x02\u0139" + + "\u013A\x07?\x02\x02\u013A\u013F\x05J&\x02\u013B\u013C\x07\x1F\x02\x02" + + "\u013C\u013E\x05J&\x02\u013D\u013B\x03\x02\x02\x02\u013E\u0141\x03\x02" + + "\x02\x02\u013F\u013D\x03\x02\x02\x02\u013F\u0140\x03\x02\x02\x02\u0140" + + "\u0142\x03\x02\x02\x02\u0141\u013F\x03\x02\x02\x02\u0142\u0143\x07@\x02" + + "\x02\u0143\u015B\x03\x02\x02\x02\u0144\u0145\x07?\x02\x02\u0145\u014A" + + "\x05H%\x02\u0146\u0147\x07\x1F\x02\x02\u0147\u0149\x05H%\x02\u0148\u0146" + + "\x03\x02\x02\x02\u0149\u014C\x03\x02\x02\x02\u014A\u0148\x03\x02\x02\x02" + + "\u014A\u014B\x03\x02\x02\x02\u014B\u014D\x03\x02\x02\x02\u014C\u014A\x03" + + "\x02\x02\x02\u014D\u014E\x07@\x02\x02\u014E\u015B\x03\x02\x02\x02\u014F" + + "\u0150\x07?\x02\x02\u0150\u0155\x05P)\x02\u0151\u0152\x07\x1F\x02\x02" + + "\u0152\u0154\x05P)\x02\u0153\u0151\x03\x02\x02\x02\u0154\u0157\x03\x02" + + "\x02\x02\u0155\u0153\x03\x02\x02\x02\u0155\u0156\x03\x02\x02\x02\u0156" + + "\u0158\x03\x02\x02\x02\u0157\u0155\x03\x02\x02\x02\u0158\u0159\x07@\x02" + + "\x02\u0159\u015B\x03\x02\x02\x02\u015A\u0130\x03\x02\x02\x02\u015A\u0131" + + "\x03\x02\x02\x02\u015A\u0134\x03\x02\x02\x02\u015A\u0135\x03\x02\x02\x02" + + "\u015A\u0136\x03\x02\x02\x02\u015A\u0137\x03\x02\x02\x02\u015A\u0138\x03" + + "\x02\x02\x02\u015A\u0139\x03\x02\x02\x02\u015A\u0144\x03\x02\x02\x02\u015A" + + "\u014F\x03\x02\x02\x02\u015B/\x03\x02\x02\x02\u015C\u015D\x07\n\x02\x02" + + "\u015D\u015E\x07\x19\x02\x02\u015E1\x03\x02\x02\x02\u015F\u0160\x07\x10" + + "\x02\x02\u0160\u0165\x054\x1B\x02\u0161\u0162\x07\x1F\x02\x02\u0162\u0164" + + "\x054\x1B\x02\u0163\u0161\x03\x02\x02\x02\u0164\u0167\x03\x02\x02\x02" + + "\u0165\u0163\x03\x02\x02\x02\u0165\u0166\x03\x02\x02\x02\u01663\x03\x02" + + "\x02\x02\u0167\u0165\x03\x02\x02\x02\u0168\u016A\x05\f\x07\x02\u0169\u016B" + + "\t\x06\x02\x02\u016A\u0169\x03\x02\x02\x02\u016A\u016B\x03\x02\x02\x02" + + "\u016B\u016E\x03\x02\x02\x02\u016C\u016D\x07+\x02\x02\u016D\u016F\t\x07" + + "\x02\x02\u016E\u016C\x03\x02\x02\x02\u016E\u016F\x03\x02\x02\x02\u016F" + + "5\x03\x02\x02\x02\u0170\u0171\x07\t\x02\x02\u0171\u0176\x05(\x15\x02\u0172" + + "\u0173\x07\x1F\x02\x02\u0173\u0175\x05(\x15\x02\u0174\u0172\x03\x02\x02" + + "\x02\u0175\u0178\x03\x02\x02\x02\u0176\u0174\x03\x02\x02\x02\u0176\u0177" + + "\x03\x02\x02\x02\u0177\u0183\x03\x02\x02\x02\u0178\u0176\x03\x02\x02\x02" + + "\u0179\u017A\x07\f\x02\x02\u017A\u017F\x05(\x15\x02\u017B\u017C\x07\x1F" + + "\x02\x02\u017C\u017E\x05(\x15\x02\u017D\u017B\x03\x02\x02\x02\u017E\u0181" + + "\x03\x02\x02\x02\u017F\u017D\x03\x02\x02\x02\u017F\u0180\x03\x02\x02\x02" + + "\u0180\u0183\x03\x02\x02\x02\u0181\u017F\x03\x02\x02\x02\u0182\u0170\x03" + + "\x02\x02\x02\u0182\u0179\x03\x02\x02\x02\u01837\x03\x02\x02\x02\u0184" + + "\u0185\x07\x04\x02\x02\u0185\u018A\x05(\x15\x02\u0186\u0187\x07\x1F\x02" + + "\x02\u0187\u0189\x05(\x15\x02\u0188\u0186\x03\x02\x02\x02\u0189\u018C" + + "\x03\x02\x02\x02\u018A\u0188\x03\x02\x02\x02\u018A\u018B\x03\x02\x02\x02" + + "\u018B9\x03\x02\x02\x02\u018C\u018A\x03\x02\x02\x02\u018D\u018E\x07\r" + + "\x02\x02\u018E\u0193\x05<\x1F\x02\u018F\u0190\x07\x1F\x02\x02\u0190\u0192" + + "\x05<\x1F\x02\u0191\u018F\x03\x02\x02\x02\u0192\u0195\x03\x02\x02\x02" + + "\u0193\u0191\x03\x02\x02\x02\u0193\u0194\x03\x02\x02\x02\u0194;\x03\x02" + + "\x02\x02\u0195\u0193\x03\x02\x02\x02\u0196\u0197\x05(\x15\x02\u0197\u0198" + + "\x07F\x02\x02\u0198\u0199\x05(\x15\x02\u0199=\x03\x02\x02\x02\u019A\u019B" + + "\x07\x03\x02\x02\u019B\u019C\x05\x14\v\x02\u019C\u019E\x05P)\x02\u019D" + + "\u019F\x05D#\x02\u019E\u019D\x03\x02\x02\x02\u019E\u019F\x03\x02\x02\x02" + + "\u019F?\x03\x02\x02\x02\u01A0\u01A1\x07\b\x02\x02\u01A1\u01A2\x05\x14" + + "\v\x02\u01A2\u01A3\x05P)\x02\u01A3A\x03\x02\x02\x02\u01A4\u01A5\x07\v" + + "\x02\x02\u01A5\u01A6\x05(\x15\x02\u01A6C\x03\x02\x02\x02\u01A7\u01AC\x05" + + "F$\x02\u01A8\u01A9\x07\x1F\x02\x02\u01A9\u01AB\x05F$\x02\u01AA\u01A8\x03" + + "\x02\x02\x02\u01AB\u01AE\x03\x02\x02\x02\u01AC\u01AA\x03\x02\x02\x02\u01AC" + + "\u01AD\x03\x02\x02\x02\u01ADE\x03\x02\x02\x02\u01AE\u01AC\x03\x02\x02" + + "\x02\u01AF\u01B0\x05,\x17\x02\u01B0\u01B1\x07\x1E\x02\x02\u01B1\u01B2" + + "\x05.\x18\x02\u01B2G\x03\x02\x02\x02\u01B3\u01B4\t\b\x02\x02\u01B4I\x03" + + "\x02\x02\x02\u01B5\u01B8\x05L\'\x02\u01B6\u01B8\x05N(\x02\u01B7\u01B5" + + "\x03\x02\x02\x02\u01B7\u01B6\x03\x02\x02\x02\u01B8K\x03\x02\x02\x02\u01B9" + + "\u01BB\t\x02\x02\x02\u01BA\u01B9\x03\x02\x02\x02\u01BA\u01BB\x03\x02\x02" + + "\x02\u01BB\u01BC\x03\x02\x02\x02\u01BC\u01BD\x07\x1A\x02\x02\u01BDM\x03" + + "\x02\x02\x02\u01BE\u01C0\t\x02\x02\x02\u01BF\u01BE\x03\x02\x02\x02\u01BF" + + "\u01C0\x03\x02\x02\x02\u01C0\u01C1\x03\x02\x02\x02\u01C1\u01C2\x07\x19" + + "\x02\x02\u01C2O\x03\x02\x02\x02\u01C3\u01C4\x07\x18\x02\x02\u01C4Q\x03" + + "\x02\x02\x02\u01C5\u01C6\t\t\x02\x02\u01C6S\x03\x02\x02\x02\u01C7\u01C8" + + "\x07\x0F\x02\x02\u01C8\u01CC\x071\x02\x02\u01C9\u01CA\x07\x0F\x02\x02" + + "\u01CA\u01CC\x072\x02\x02\u01CB\u01C7\x03\x02\x02\x02\u01CB\u01C9\x03" + + "\x02\x02\x02\u01CCU\x03\x02\x02\x02\u01CD\u01CE\x07\x05\x02\x02\u01CE" + + "\u01D1\x05(\x15\x02\u01CF\u01D0\x07H\x02\x02\u01D0\u01D2\x05(\x15\x02" + + "\u01D1\u01CF\x03\x02\x02\x02\u01D1\u01D2\x03\x02\x02\x02\u01D2\u01DC\x03" + + "\x02\x02\x02\u01D3\u01D4\x07I\x02\x02\u01D4\u01D9\x05X-\x02\u01D5\u01D6" + + "\x07\x1F\x02\x02\u01D6\u01D8\x05X-\x02\u01D7\u01D5\x03\x02\x02\x02\u01D8" + + "\u01DB\x03\x02\x02\x02\u01D9\u01D7\x03\x02\x02\x02\u01D9\u01DA\x03\x02" + + "\x02\x02\u01DA\u01DD\x03\x02\x02\x02\u01DB\u01D9\x03\x02\x02\x02\u01DC" + + "\u01D3\x03\x02\x02\x02\u01DC\u01DD\x03\x02\x02\x02\u01DDW\x03\x02\x02" + + "\x02\u01DE\u01DF\x05(\x15\x02\u01DF\u01E0\x07\x1E\x02\x02\u01E0\u01E2" + + "\x03\x02\x02\x02\u01E1\u01DE\x03\x02\x02\x02\u01E1\u01E2\x03\x02\x02\x02" + + "\u01E2\u01E3\x03\x02\x02\x02\u01E3\u01E4\x05(\x15\x02\u01E4Y\x03\x02\x02" + + "\x024eky\x85\x8E\x96\x9A\xA2\xA4\xA9\xB0\xB5\xBC\xC2\xCA\xCC\xD6\xE0\xE3" + + "\xEF\xF7\xFF\u0103\u010C\u0116\u011A\u0121\u012B\u013F\u014A\u0155\u015A" + + "\u0165\u016A\u016E\u0176\u017F\u0182\u018A\u0193\u019E\u01AC\u01B7\u01BA" + + "\u01BF\u01CB\u01D1\u01D9\u01DC\u01E1"; public static __ATN: ATN; public static get _ATN(): ATN { if (!esql_parser.__ATN) { @@ -3621,9 +2981,6 @@ export class CompositeQueryContext extends QueryContext { export class SourceCommandContext extends ParserRuleContext { - public explainCommand(): ExplainCommandContext | undefined { - return this.tryGetRuleContext(0, ExplainCommandContext); - } public fromCommand(): FromCommandContext | undefined { return this.tryGetRuleContext(0, FromCommandContext); } @@ -3660,39 +3017,36 @@ export class ProcessingCommandContext extends ParserRuleContext { public limitCommand(): LimitCommandContext | undefined { return this.tryGetRuleContext(0, LimitCommandContext); } - public projectCommand(): ProjectCommandContext | undefined { - return this.tryGetRuleContext(0, ProjectCommandContext); - } public keepCommand(): KeepCommandContext | undefined { return this.tryGetRuleContext(0, KeepCommandContext); } - public renameCommand(): RenameCommandContext | undefined { - return this.tryGetRuleContext(0, RenameCommandContext); + public sortCommand(): SortCommandContext | undefined { + return this.tryGetRuleContext(0, SortCommandContext); + } + public statsCommand(): StatsCommandContext | undefined { + return this.tryGetRuleContext(0, StatsCommandContext); + } + public whereCommand(): WhereCommandContext | undefined { + return this.tryGetRuleContext(0, WhereCommandContext); } public dropCommand(): DropCommandContext | undefined { return this.tryGetRuleContext(0, DropCommandContext); } + public renameCommand(): RenameCommandContext | undefined { + return this.tryGetRuleContext(0, RenameCommandContext); + } public dissectCommand(): DissectCommandContext | undefined { return this.tryGetRuleContext(0, DissectCommandContext); } public grokCommand(): GrokCommandContext | undefined { return this.tryGetRuleContext(0, GrokCommandContext); } - public sortCommand(): SortCommandContext | undefined { - return this.tryGetRuleContext(0, SortCommandContext); - } - public statsCommand(): StatsCommandContext | undefined { - return this.tryGetRuleContext(0, StatsCommandContext); - } - public whereCommand(): WhereCommandContext | undefined { - return this.tryGetRuleContext(0, WhereCommandContext); + public enrichCommand(): EnrichCommandContext | undefined { + return this.tryGetRuleContext(0, EnrichCommandContext); } public mvExpandCommand(): MvExpandCommandContext | undefined { return this.tryGetRuleContext(0, MvExpandCommandContext); } - public enrichCommand(): EnrichCommandContext | undefined { - return this.tryGetRuleContext(0, EnrichCommandContext); - } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -3713,153 +3067,138 @@ export class ProcessingCommandContext extends ParserRuleContext { } -export class EnrichCommandContext extends ParserRuleContext { - public _policyName: EnrichIdentifierContext; - public _matchField: EnrichFieldIdentifierContext; - public ENRICH(): TerminalNode { return this.getToken(esql_parser.ENRICH, 0); } - public enrichIdentifier(): EnrichIdentifierContext { - return this.getRuleContext(0, EnrichIdentifierContext); - } - public ON(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ON, 0); } - public WITH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.WITH, 0); } - public enrichWithClause(): EnrichWithClauseContext[]; - public enrichWithClause(i: number): EnrichWithClauseContext; - public enrichWithClause(i?: number): EnrichWithClauseContext | EnrichWithClauseContext[] { - if (i === undefined) { - return this.getRuleContexts(EnrichWithClauseContext); - } else { - return this.getRuleContext(i, EnrichWithClauseContext); - } - } - public enrichFieldIdentifier(): EnrichFieldIdentifierContext | undefined { - return this.tryGetRuleContext(0, EnrichFieldIdentifierContext); - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); - } +export class WhereCommandContext extends ParserRuleContext { + public WHERE(): TerminalNode { return this.getToken(esql_parser.WHERE, 0); } + public booleanExpression(): BooleanExpressionContext { + return this.getRuleContext(0, BooleanExpressionContext); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_enrichCommand; } + public get ruleIndex(): number { return esql_parser.RULE_whereCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterEnrichCommand) { - listener.enterEnrichCommand(this); + if (listener.enterWhereCommand) { + listener.enterWhereCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitEnrichCommand) { - listener.exitEnrichCommand(this); + if (listener.exitWhereCommand) { + listener.exitWhereCommand(this); } } } -export class EnrichWithClauseContext extends ParserRuleContext { - public _newName: EnrichFieldIdentifierContext; - public _enrichField: EnrichFieldIdentifierContext; - public enrichFieldIdentifier(): EnrichFieldIdentifierContext[]; - public enrichFieldIdentifier(i: number): EnrichFieldIdentifierContext; - public enrichFieldIdentifier(i?: number): EnrichFieldIdentifierContext | EnrichFieldIdentifierContext[] { - if (i === undefined) { - return this.getRuleContexts(EnrichFieldIdentifierContext); - } else { - return this.getRuleContext(i, EnrichFieldIdentifierContext); - } - } - public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } +export class BooleanExpressionContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_enrichWithClause; } + public get ruleIndex(): number { return esql_parser.RULE_booleanExpression; } + public copyFrom(ctx: BooleanExpressionContext): void { + super.copyFrom(ctx); + } +} +export class LogicalNotContext extends BooleanExpressionContext { + public NOT(): TerminalNode { return this.getToken(esql_parser.NOT, 0); } + public booleanExpression(): BooleanExpressionContext { + return this.getRuleContext(0, BooleanExpressionContext); + } + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterEnrichWithClause) { - listener.enterEnrichWithClause(this); + if (listener.enterLogicalNot) { + listener.enterLogicalNot(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitEnrichWithClause) { - listener.exitEnrichWithClause(this); + if (listener.exitLogicalNot) { + listener.exitLogicalNot(this); } } } - - -export class MvExpandCommandContext extends ParserRuleContext { - public MV_EXPAND(): TerminalNode { return this.getToken(esql_parser.MV_EXPAND, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); +export class BooleanDefaultContext extends BooleanExpressionContext { + public valueExpression(): ValueExpressionContext { + return this.getRuleContext(0, ValueExpressionContext); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mvExpandCommand; } + public enterRule(listener: esql_parserListener): void { + if (listener.enterBooleanDefault) { + listener.enterBooleanDefault(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitBooleanDefault) { + listener.exitBooleanDefault(this); + } + } +} +export class RegexExpressionContext extends BooleanExpressionContext { + public regexBooleanExpression(): RegexBooleanExpressionContext { + return this.getRuleContext(0, RegexBooleanExpressionContext); + } + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMvExpandCommand) { - listener.enterMvExpandCommand(this); + if (listener.enterRegexExpression) { + listener.enterRegexExpression(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMvExpandCommand) { - listener.exitMvExpandCommand(this); + if (listener.exitRegexExpression) { + listener.exitRegexExpression(this); } } } - - -export class WhereCommandContext extends ParserRuleContext { - public WHERE(): TerminalNode { return this.getToken(esql_parser.WHERE, 0); } - public whereBooleanExpression(): WhereBooleanExpressionContext { - return this.getRuleContext(0, WhereBooleanExpressionContext); +export class LogicalBinaryContext extends BooleanExpressionContext { + public _left: BooleanExpressionContext; + public _operator: Token; + public _right: BooleanExpressionContext; + public booleanExpression(): BooleanExpressionContext[]; + public booleanExpression(i: number): BooleanExpressionContext; + public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(BooleanExpressionContext); + } else { + return this.getRuleContext(i, BooleanExpressionContext); + } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } + public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_whereCommand; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterWhereCommand) { - listener.enterWhereCommand(this); + if (listener.enterLogicalBinary) { + listener.enterLogicalBinary(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitWhereCommand) { - listener.exitWhereCommand(this); + if (listener.exitLogicalBinary) { + listener.exitLogicalBinary(this); } } } - - -export class WhereBooleanExpressionContext extends ParserRuleContext { - public _left: WhereBooleanExpressionContext; - public _operator: Token; - public _right: WhereBooleanExpressionContext; - public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } - public whereBooleanExpression(): WhereBooleanExpressionContext[]; - public whereBooleanExpression(i: number): WhereBooleanExpressionContext; - public whereBooleanExpression(i?: number): WhereBooleanExpressionContext | WhereBooleanExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(WhereBooleanExpressionContext); - } else { - return this.getRuleContext(i, WhereBooleanExpressionContext); - } - } +export class LogicalInContext extends BooleanExpressionContext { public valueExpression(): ValueExpressionContext[]; public valueExpression(i: number): ValueExpressionContext; public valueExpression(i?: number): ValueExpressionContext | ValueExpressionContext[] { @@ -3869,14 +3208,10 @@ export class WhereBooleanExpressionContext extends ParserRuleContext { return this.getRuleContext(i, ValueExpressionContext); } } - public regexBooleanExpression(): RegexBooleanExpressionContext | undefined { - return this.tryGetRuleContext(0, RegexBooleanExpressionContext); - } - public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } - public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } - public IN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.IN, 0); } - public LP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LP, 0); } - public RP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.RP, 0); } + public IN(): TerminalNode { return this.getToken(esql_parser.IN, 0); } + public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } + public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } + public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } public COMMA(): TerminalNode[]; public COMMA(i: number): TerminalNode; public COMMA(i?: number): TerminalNode | TerminalNode[] { @@ -3886,75 +3221,44 @@ export class WhereBooleanExpressionContext extends ParserRuleContext { return this.getToken(esql_parser.COMMA, i); } } - public WHERE_FUNCTIONS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.WHERE_FUNCTIONS, 0); } - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public functionExpressionArgument(): FunctionExpressionArgumentContext[]; - public functionExpressionArgument(i: number): FunctionExpressionArgumentContext; - public functionExpressionArgument(i?: number): FunctionExpressionArgumentContext | FunctionExpressionArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionExpressionArgumentContext); - } else { - return this.getRuleContext(i, FunctionExpressionArgumentContext); - } - } - public IS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.IS, 0); } - public NULL(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULL, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_whereBooleanExpression; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterWhereBooleanExpression) { - listener.enterWhereBooleanExpression(this); + if (listener.enterLogicalIn) { + listener.enterLogicalIn(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitWhereBooleanExpression) { - listener.exitWhereBooleanExpression(this); + if (listener.exitLogicalIn) { + listener.exitLogicalIn(this); } } } - - -export class BooleanExpressionContext extends ParserRuleContext { - public _left: BooleanExpressionContext; - public _operator: Token; - public _right: BooleanExpressionContext; - public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } - public booleanExpression(): BooleanExpressionContext[]; - public booleanExpression(i: number): BooleanExpressionContext; - public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(BooleanExpressionContext); - } else { - return this.getRuleContext(i, BooleanExpressionContext); - } - } - public valueExpression(): ValueExpressionContext | undefined { - return this.tryGetRuleContext(0, ValueExpressionContext); +export class IsNullContext extends BooleanExpressionContext { + public valueExpression(): ValueExpressionContext { + return this.getRuleContext(0, ValueExpressionContext); } - public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } - public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + public IS(): TerminalNode { return this.getToken(esql_parser.IS, 0); } + public NULL(): TerminalNode { return this.getToken(esql_parser.NULL, 0); } + public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_booleanExpression; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterBooleanExpression) { - listener.enterBooleanExpression(this); + if (listener.enterIsNull) { + listener.enterIsNull(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitBooleanExpression) { - listener.exitBooleanExpression(this); + if (listener.exitIsNull) { + listener.exitIsNull(this); } } } @@ -3993,33 +3297,37 @@ export class RegexBooleanExpressionContext extends ParserRuleContext { export class ValueExpressionContext extends ParserRuleContext { - public operatorExpression(): OperatorExpressionContext | undefined { - return this.tryGetRuleContext(0, OperatorExpressionContext); - } - public comparison(): ComparisonContext | undefined { - return this.tryGetRuleContext(0, ComparisonContext); - } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override public get ruleIndex(): number { return esql_parser.RULE_valueExpression; } + public copyFrom(ctx: ValueExpressionContext): void { + super.copyFrom(ctx); + } +} +export class ValueExpressionDefaultContext extends ValueExpressionContext { + public operatorExpression(): OperatorExpressionContext { + return this.getRuleContext(0, OperatorExpressionContext); + } + constructor(ctx: ValueExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterValueExpression) { - listener.enterValueExpression(this); + if (listener.enterValueExpressionDefault) { + listener.enterValueExpressionDefault(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitValueExpression) { - listener.exitValueExpression(this); + if (listener.exitValueExpressionDefault) { + listener.exitValueExpressionDefault(this); } } } - - -export class ComparisonContext extends ParserRuleContext { +export class ComparisonContext extends ValueExpressionContext { public _left: OperatorExpressionContext; public _right: OperatorExpressionContext; public comparisonOperator(): ComparisonOperatorContext { @@ -4034,12 +3342,11 @@ export class ComparisonContext extends ParserRuleContext { return this.getRuleContext(i, OperatorExpressionContext); } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: ValueExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_comparison; } - // @Override public enterRule(listener: esql_parserListener): void { if (listener.enterComparison) { listener.enterComparison(this); @@ -4054,178 +3361,203 @@ export class ComparisonContext extends ParserRuleContext { } -export class MathFnContext extends ParserRuleContext { - public functionIdentifier(): FunctionIdentifierContext { - return this.getRuleContext(0, FunctionIdentifierContext); - } - public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } - public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } - public functionExpressionArgument(): FunctionExpressionArgumentContext[]; - public functionExpressionArgument(i: number): FunctionExpressionArgumentContext; - public functionExpressionArgument(i?: number): FunctionExpressionArgumentContext | FunctionExpressionArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionExpressionArgumentContext); - } else { - return this.getRuleContext(i, FunctionExpressionArgumentContext); - } - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); - } - } +export class OperatorExpressionContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathFn; } + public get ruleIndex(): number { return esql_parser.RULE_operatorExpression; } + public copyFrom(ctx: OperatorExpressionContext): void { + super.copyFrom(ctx); + } +} +export class OperatorExpressionDefaultContext extends OperatorExpressionContext { + public primaryExpression(): PrimaryExpressionContext { + return this.getRuleContext(0, PrimaryExpressionContext); + } + constructor(ctx: OperatorExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathFn) { - listener.enterMathFn(this); + if (listener.enterOperatorExpressionDefault) { + listener.enterOperatorExpressionDefault(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathFn) { - listener.exitMathFn(this); + if (listener.exitOperatorExpressionDefault) { + listener.exitOperatorExpressionDefault(this); } } } - - -export class MathEvalFnContext extends ParserRuleContext { - public mathFunctionIdentifier(): MathFunctionIdentifierContext { - return this.getRuleContext(0, MathFunctionIdentifierContext); +export class ArithmeticUnaryContext extends OperatorExpressionContext { + public _operator: Token; + public operatorExpression(): OperatorExpressionContext { + return this.getRuleContext(0, OperatorExpressionContext); } - public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } - public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } - public mathFunctionExpressionArgument(): MathFunctionExpressionArgumentContext[]; - public mathFunctionExpressionArgument(i: number): MathFunctionExpressionArgumentContext; - public mathFunctionExpressionArgument(i?: number): MathFunctionExpressionArgumentContext | MathFunctionExpressionArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(MathFunctionExpressionArgumentContext); - } else { - return this.getRuleContext(i, MathFunctionExpressionArgumentContext); + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + constructor(ctx: OperatorExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterArithmeticUnary) { + listener.enterArithmeticUnary(this); } } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitArithmeticUnary) { + listener.exitArithmeticUnary(this); + } + } +} +export class ArithmeticBinaryContext extends OperatorExpressionContext { + public _left: OperatorExpressionContext; + public _operator: Token; + public _right: OperatorExpressionContext; + public operatorExpression(): OperatorExpressionContext[]; + public operatorExpression(i: number): OperatorExpressionContext; + public operatorExpression(i?: number): OperatorExpressionContext | OperatorExpressionContext[] { if (i === undefined) { - return this.getTokens(esql_parser.COMMA); + return this.getRuleContexts(OperatorExpressionContext); } else { - return this.getToken(esql_parser.COMMA, i); + return this.getRuleContext(i, OperatorExpressionContext); } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } + public SLASH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SLASH, 0); } + public PERCENT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PERCENT, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } + constructor(ctx: OperatorExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathEvalFn; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathEvalFn) { - listener.enterMathEvalFn(this); + if (listener.enterArithmeticBinary) { + listener.enterArithmeticBinary(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathEvalFn) { - listener.exitMathEvalFn(this); + if (listener.exitArithmeticBinary) { + listener.exitArithmeticBinary(this); } } } -export class DateExpressionContext extends ParserRuleContext { - public _quantifier: NumberContext; - public DATE_LITERAL(): TerminalNode { return this.getToken(esql_parser.DATE_LITERAL, 0); } - public number(): NumberContext { - return this.getRuleContext(0, NumberContext); - } +export class PrimaryExpressionContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_dateExpression; } + public get ruleIndex(): number { return esql_parser.RULE_primaryExpression; } + public copyFrom(ctx: PrimaryExpressionContext): void { + super.copyFrom(ctx); + } +} +export class ConstantDefaultContext extends PrimaryExpressionContext { + public constant(): ConstantContext { + return this.getRuleContext(0, ConstantContext); + } + constructor(ctx: PrimaryExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterDateExpression) { - listener.enterDateExpression(this); + if (listener.enterConstantDefault) { + listener.enterConstantDefault(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitDateExpression) { - listener.exitDateExpression(this); + if (listener.exitConstantDefault) { + listener.exitConstantDefault(this); } } } - - -export class OperatorExpressionContext extends ParserRuleContext { - public _left: OperatorExpressionContext; - public _operator: Token; - public _right: OperatorExpressionContext; - public primaryExpression(): PrimaryExpressionContext | undefined { - return this.tryGetRuleContext(0, PrimaryExpressionContext); +export class DereferenceContext extends PrimaryExpressionContext { + public qualifiedName(): QualifiedNameContext { + return this.getRuleContext(0, QualifiedNameContext); } - public mathFn(): MathFnContext | undefined { - return this.tryGetRuleContext(0, MathFnContext); + constructor(ctx: PrimaryExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } - public mathEvalFn(): MathEvalFnContext | undefined { - return this.tryGetRuleContext(0, MathEvalFnContext); + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterDereference) { + listener.enterDereference(this); + } } - public operatorExpression(): OperatorExpressionContext[]; - public operatorExpression(i: number): OperatorExpressionContext; - public operatorExpression(i?: number): OperatorExpressionContext | OperatorExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(OperatorExpressionContext); - } else { - return this.getRuleContext(i, OperatorExpressionContext); + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitDereference) { + listener.exitDereference(this); } } - public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } - public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } - public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } - public SLASH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SLASH, 0); } - public PERCENT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PERCENT, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); +} +export class FunctionContext extends PrimaryExpressionContext { + public functionExpression(): FunctionExpressionContext { + return this.getRuleContext(0, FunctionExpressionContext); + } + constructor(ctx: PrimaryExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_operatorExpression; } + public enterRule(listener: esql_parserListener): void { + if (listener.enterFunction) { + listener.enterFunction(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitFunction) { + listener.exitFunction(this); + } + } +} +export class ParenthesizedExpressionContext extends PrimaryExpressionContext { + public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } + public booleanExpression(): BooleanExpressionContext { + return this.getRuleContext(0, BooleanExpressionContext); + } + public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } + constructor(ctx: PrimaryExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterOperatorExpression) { - listener.enterOperatorExpression(this); + if (listener.enterParenthesizedExpression) { + listener.enterParenthesizedExpression(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitOperatorExpression) { - listener.exitOperatorExpression(this); + if (listener.exitParenthesizedExpression) { + listener.exitParenthesizedExpression(this); } } } -export class PrimaryExpressionContext extends ParserRuleContext { - public constant(): ConstantContext | undefined { - return this.tryGetRuleContext(0, ConstantContext); - } - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public dateExpression(): DateExpressionContext | undefined { - return this.tryGetRuleContext(0, DateExpressionContext); +export class FunctionExpressionContext extends ParserRuleContext { + public identifier(): IdentifierContext { + return this.getRuleContext(0, IdentifierContext); } - public LP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LP, 0); } + public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } + public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } + public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } public booleanExpression(): BooleanExpressionContext[]; public booleanExpression(i: number): BooleanExpressionContext; public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { @@ -4235,10 +3567,6 @@ export class PrimaryExpressionContext extends ParserRuleContext { return this.getRuleContext(i, BooleanExpressionContext); } } - public RP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.RP, 0); } - public identifier(): IdentifierContext | undefined { - return this.tryGetRuleContext(0, IdentifierContext); - } public COMMA(): TerminalNode[]; public COMMA(i: number): TerminalNode; public COMMA(i?: number): TerminalNode | TerminalNode[] { @@ -4252,17 +3580,17 @@ export class PrimaryExpressionContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_primaryExpression; } + public get ruleIndex(): number { return esql_parser.RULE_functionExpression; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterPrimaryExpression) { - listener.enterPrimaryExpression(this); + if (listener.enterFunctionExpression) { + listener.enterFunctionExpression(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitPrimaryExpression) { - listener.exitPrimaryExpression(this); + if (listener.exitFunctionExpression) { + listener.exitFunctionExpression(this); } } } @@ -4336,72 +3664,25 @@ export class FieldContext extends ParserRuleContext { public booleanExpression(): BooleanExpressionContext { return this.getRuleContext(0, BooleanExpressionContext); } - public userVariable(): UserVariableContext | undefined { - return this.tryGetRuleContext(0, UserVariableContext); - } - public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_field; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterField) { - listener.enterField(this); - } - } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitField) { - listener.exitField(this); - } - } -} - - -export class EnrichFieldIdentifierContext extends ParserRuleContext { - public ENR_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_UNQUOTED_IDENTIFIER, 0); } - public ENR_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_QUOTED_IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_enrichFieldIdentifier; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterEnrichFieldIdentifier) { - listener.enterEnrichFieldIdentifier(this); - } - } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitEnrichFieldIdentifier) { - listener.exitEnrichFieldIdentifier(this); - } - } -} - - -export class UserVariableContext extends ParserRuleContext { - public identifier(): IdentifierContext { - return this.getRuleContext(0, IdentifierContext); + public qualifiedName(): QualifiedNameContext | undefined { + return this.tryGetRuleContext(0, QualifiedNameContext); } + public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_userVariable; } + public get ruleIndex(): number { return esql_parser.RULE_field; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterUserVariable) { - listener.enterUserVariable(this); + if (listener.enterField) { + listener.enterField(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitUserVariable) { - listener.exitUserVariable(this); + if (listener.exitField) { + listener.exitField(this); } } } @@ -4523,8 +3804,8 @@ export class StatsCommandContext extends ParserRuleContext { return this.tryGetRuleContext(0, FieldsContext); } public BY(): TerminalNode | undefined { return this.tryGetToken(esql_parser.BY, 0); } - public qualifiedNames(): QualifiedNamesContext | undefined { - return this.tryGetRuleContext(0, QualifiedNamesContext); + public grouping(): GroupingContext | undefined { + return this.tryGetRuleContext(0, GroupingContext); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); @@ -4546,116 +3827,63 @@ export class StatsCommandContext extends ParserRuleContext { } -export class SourceIdentifierContext extends ParserRuleContext { - public SRC_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_UNQUOTED_IDENTIFIER, 0); } - public SRC_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_QUOTED_IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_sourceIdentifier; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterSourceIdentifier) { - listener.enterSourceIdentifier(this); - } - } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitSourceIdentifier) { - listener.exitSourceIdentifier(this); - } - } -} - - -export class EnrichIdentifierContext extends ParserRuleContext { - public ENR_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_UNQUOTED_IDENTIFIER, 0); } - public ENR_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_QUOTED_IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_enrichIdentifier; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterEnrichIdentifier) { - listener.enterEnrichIdentifier(this); +export class GroupingContext extends ParserRuleContext { + public qualifiedName(): QualifiedNameContext[]; + public qualifiedName(i: number): QualifiedNameContext; + public qualifiedName(i?: number): QualifiedNameContext | QualifiedNameContext[] { + if (i === undefined) { + return this.getRuleContexts(QualifiedNameContext); + } else { + return this.getRuleContext(i, QualifiedNameContext); } } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitEnrichIdentifier) { - listener.exitEnrichIdentifier(this); + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); } } -} - - -export class FunctionExpressionArgumentContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public string(): StringContext | undefined { - return this.tryGetRuleContext(0, StringContext); - } - public number(): NumberContext | undefined { - return this.tryGetRuleContext(0, NumberContext); - } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_functionExpressionArgument; } + public get ruleIndex(): number { return esql_parser.RULE_grouping; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterFunctionExpressionArgument) { - listener.enterFunctionExpressionArgument(this); + if (listener.enterGrouping) { + listener.enterGrouping(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitFunctionExpressionArgument) { - listener.exitFunctionExpressionArgument(this); + if (listener.exitGrouping) { + listener.exitGrouping(this); } } } -export class MathFunctionExpressionArgumentContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public string(): StringContext | undefined { - return this.tryGetRuleContext(0, StringContext); - } - public number(): NumberContext | undefined { - return this.tryGetRuleContext(0, NumberContext); - } - public operatorExpression(): OperatorExpressionContext | undefined { - return this.tryGetRuleContext(0, OperatorExpressionContext); - } - public dateExpression(): DateExpressionContext | undefined { - return this.tryGetRuleContext(0, DateExpressionContext); - } - public comparison(): ComparisonContext | undefined { - return this.tryGetRuleContext(0, ComparisonContext); - } +export class SourceIdentifierContext extends ParserRuleContext { + public SRC_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_UNQUOTED_IDENTIFIER, 0); } + public SRC_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_QUOTED_IDENTIFIER, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathFunctionExpressionArgument; } + public get ruleIndex(): number { return esql_parser.RULE_sourceIdentifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathFunctionExpressionArgument) { - listener.enterMathFunctionExpressionArgument(this); + if (listener.enterSourceIdentifier) { + listener.enterSourceIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathFunctionExpressionArgument) { - listener.exitMathFunctionExpressionArgument(this); + if (listener.exitSourceIdentifier) { + listener.exitSourceIdentifier(this); } } } @@ -4700,115 +3928,185 @@ export class QualifiedNameContext extends ParserRuleContext { } -export class QualifiedNamesContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext[]; - public qualifiedName(i: number): QualifiedNameContext; - public qualifiedName(i?: number): QualifiedNameContext | QualifiedNameContext[] { - if (i === undefined) { - return this.getRuleContexts(QualifiedNameContext); - } else { - return this.getRuleContext(i, QualifiedNameContext); - } - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); - } - } +export class IdentifierContext extends ParserRuleContext { + public UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.UNQUOTED_IDENTIFIER, 0); } + public QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.QUOTED_IDENTIFIER, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_qualifiedNames; } + public get ruleIndex(): number { return esql_parser.RULE_identifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterQualifiedNames) { - listener.enterQualifiedNames(this); + if (listener.enterIdentifier) { + listener.enterIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitQualifiedNames) { - listener.exitQualifiedNames(this); + if (listener.exitIdentifier) { + listener.exitIdentifier(this); } } } -export class IdentifierContext extends ParserRuleContext { - public UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.UNQUOTED_IDENTIFIER, 0); } - public QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.QUOTED_IDENTIFIER, 0); } - public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } +export class ConstantContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_identifier; } + public get ruleIndex(): number { return esql_parser.RULE_constant; } + public copyFrom(ctx: ConstantContext): void { + super.copyFrom(ctx); + } +} +export class NullLiteralContext extends ConstantContext { + public NULL(): TerminalNode { return this.getToken(esql_parser.NULL, 0); } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterIdentifier) { - listener.enterIdentifier(this); + if (listener.enterNullLiteral) { + listener.enterNullLiteral(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitIdentifier) { - listener.exitIdentifier(this); + if (listener.exitNullLiteral) { + listener.exitNullLiteral(this); } } } - - -export class MathFunctionIdentifierContext extends ParserRuleContext { - public MATH_FUNCTION(): TerminalNode { return this.getToken(esql_parser.MATH_FUNCTION, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); +export class QualifiedIntegerLiteralContext extends ConstantContext { + public integerValue(): IntegerValueContext { + return this.getRuleContext(0, IntegerValueContext); + } + public UNQUOTED_IDENTIFIER(): TerminalNode { return this.getToken(esql_parser.UNQUOTED_IDENTIFIER, 0); } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathFunctionIdentifier; } + public enterRule(listener: esql_parserListener): void { + if (listener.enterQualifiedIntegerLiteral) { + listener.enterQualifiedIntegerLiteral(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitQualifiedIntegerLiteral) { + listener.exitQualifiedIntegerLiteral(this); + } + } +} +export class DecimalLiteralContext extends ConstantContext { + public decimalValue(): DecimalValueContext { + return this.getRuleContext(0, DecimalValueContext); + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathFunctionIdentifier) { - listener.enterMathFunctionIdentifier(this); + if (listener.enterDecimalLiteral) { + listener.enterDecimalLiteral(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathFunctionIdentifier) { - listener.exitMathFunctionIdentifier(this); + if (listener.exitDecimalLiteral) { + listener.exitDecimalLiteral(this); } } } - - -export class FunctionIdentifierContext extends ParserRuleContext { - public UNARY_FUNCTION(): TerminalNode { return this.getToken(esql_parser.UNARY_FUNCTION, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); +export class IntegerLiteralContext extends ConstantContext { + public integerValue(): IntegerValueContext { + return this.getRuleContext(0, IntegerValueContext); + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterIntegerLiteral) { + listener.enterIntegerLiteral(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitIntegerLiteral) { + listener.exitIntegerLiteral(this); + } + } +} +export class BooleanLiteralContext extends ConstantContext { + public booleanValue(): BooleanValueContext { + return this.getRuleContext(0, BooleanValueContext); + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterBooleanLiteral) { + listener.enterBooleanLiteral(this); + } } // @Override - public get ruleIndex(): number { return esql_parser.RULE_functionIdentifier; } + public exitRule(listener: esql_parserListener): void { + if (listener.exitBooleanLiteral) { + listener.exitBooleanLiteral(this); + } + } +} +export class InputParamContext extends ConstantContext { + public PARAM(): TerminalNode { return this.getToken(esql_parser.PARAM, 0); } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterFunctionIdentifier) { - listener.enterFunctionIdentifier(this); + if (listener.enterInputParam) { + listener.enterInputParam(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitFunctionIdentifier) { - listener.exitFunctionIdentifier(this); + if (listener.exitInputParam) { + listener.exitInputParam(this); } } } - - -export class ConstantContext extends ParserRuleContext { - public NULL(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULL, 0); } +export class StringLiteralContext extends ConstantContext { + public string(): StringContext { + return this.getRuleContext(0, StringContext); + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterStringLiteral) { + listener.enterStringLiteral(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitStringLiteral) { + listener.exitStringLiteral(this); + } + } +} +export class NumericArrayLiteralContext extends ConstantContext { + public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } public numericValue(): NumericValueContext[]; public numericValue(i: number): NumericValueContext; public numericValue(i?: number): NumericValueContext | NumericValueContext[] { @@ -4818,6 +4116,35 @@ export class ConstantContext extends ParserRuleContext { return this.getRuleContext(i, NumericValueContext); } } + public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterNumericArrayLiteral) { + listener.enterNumericArrayLiteral(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitNumericArrayLiteral) { + listener.exitNumericArrayLiteral(this); + } + } +} +export class BooleanArrayLiteralContext extends ConstantContext { + public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } public booleanValue(): BooleanValueContext[]; public booleanValue(i: number): BooleanValueContext; public booleanValue(i?: number): BooleanValueContext | BooleanValueContext[] { @@ -4827,17 +4154,7 @@ export class ConstantContext extends ParserRuleContext { return this.getRuleContext(i, BooleanValueContext); } } - public string(): StringContext[]; - public string(i: number): StringContext; - public string(i?: number): StringContext | StringContext[] { - if (i === undefined) { - return this.getRuleContexts(StringContext); - } else { - return this.getRuleContext(i, StringContext); - } - } - public OPENING_BRACKET(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OPENING_BRACKET, 0); } - public CLOSING_BRACKET(): TerminalNode | undefined { return this.tryGetToken(esql_parser.CLOSING_BRACKET, 0); } + public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } public COMMA(): TerminalNode[]; public COMMA(i: number): TerminalNode; public COMMA(i?: number): TerminalNode | TerminalNode[] { @@ -4847,48 +4164,58 @@ export class ConstantContext extends ParserRuleContext { return this.getToken(esql_parser.COMMA, i); } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_constant; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterConstant) { - listener.enterConstant(this); + if (listener.enterBooleanArrayLiteral) { + listener.enterBooleanArrayLiteral(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitConstant) { - listener.exitConstant(this); + if (listener.exitBooleanArrayLiteral) { + listener.exitBooleanArrayLiteral(this); } } } - - -export class NumericValueContext extends ParserRuleContext { - public decimalValue(): DecimalValueContext | undefined { - return this.tryGetRuleContext(0, DecimalValueContext); +export class StringArrayLiteralContext extends ConstantContext { + public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } + public string(): StringContext[]; + public string(i: number): StringContext; + public string(i?: number): StringContext | StringContext[] { + if (i === undefined) { + return this.getRuleContexts(StringContext); + } else { + return this.getRuleContext(i, StringContext); + } } - public integerValue(): IntegerValueContext | undefined { - return this.tryGetRuleContext(0, IntegerValueContext); + public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_numericValue; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterNumericValue) { - listener.enterNumericValue(this); + if (listener.enterStringArrayLiteral) { + listener.enterStringArrayLiteral(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitNumericValue) { - listener.exitNumericValue(this); + if (listener.exitStringArrayLiteral) { + listener.exitStringArrayLiteral(this); } } } @@ -4958,12 +4285,16 @@ export class SortCommandContext extends ParserRuleContext { export class OrderExpressionContext extends ParserRuleContext { + public _ordering: Token; + public _nullOrdering: Token; public booleanExpression(): BooleanExpressionContext { return this.getRuleContext(0, BooleanExpressionContext); } - public ORDERING(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ORDERING, 0); } - public NULLS_ORDERING(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS_ORDERING, 0); } - public NULLS_ORDERING_DIRECTION(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS_ORDERING_DIRECTION, 0); } + public NULLS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS, 0); } + public ASC(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASC, 0); } + public DESC(): TerminalNode | undefined { return this.tryGetToken(esql_parser.DESC, 0); } + public FIRST(): TerminalNode | undefined { return this.tryGetToken(esql_parser.FIRST, 0); } + public LAST(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LAST, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -4984,36 +4315,27 @@ export class OrderExpressionContext extends ParserRuleContext { } -export class ProjectCommandContext extends ParserRuleContext { - public PROJECT(): TerminalNode { return this.getToken(esql_parser.PROJECT, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_projectCommand; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterProjectCommand) { - listener.enterProjectCommand(this); +export class KeepCommandContext extends ParserRuleContext { + public KEEP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.KEEP, 0); } + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); } } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitProjectCommand) { - listener.exitProjectCommand(this); + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); } } -} - - -export class KeepCommandContext extends ParserRuleContext { - public KEEP(): TerminalNode { return this.getToken(esql_parser.KEEP, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); - } + public PROJECT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PROJECT, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5036,63 +4358,39 @@ export class KeepCommandContext extends ParserRuleContext { export class DropCommandContext extends ParserRuleContext { public DROP(): TerminalNode { return this.getToken(esql_parser.DROP, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_dropCommand; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterDropCommand) { - listener.enterDropCommand(this); - } - } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitDropCommand) { - listener.exitDropCommand(this); - } - } -} - - -export class RenameVariableContext extends ParserRuleContext { - public identifier(): IdentifierContext[]; - public identifier(i: number): IdentifierContext; - public identifier(i?: number): IdentifierContext | IdentifierContext[] { + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { if (i === undefined) { - return this.getRuleContexts(IdentifierContext); + return this.getRuleContexts(SourceIdentifierContext); } else { - return this.getRuleContext(i, IdentifierContext); + return this.getRuleContext(i, SourceIdentifierContext); } } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { if (i === undefined) { - return this.getTokens(esql_parser.DOT); + return this.getTokens(esql_parser.COMMA); } else { - return this.getToken(esql_parser.DOT, i); + return this.getToken(esql_parser.COMMA, i); } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_renameVariable; } + public get ruleIndex(): number { return esql_parser.RULE_dropCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterRenameVariable) { - listener.enterRenameVariable(this); + if (listener.enterDropCommand) { + listener.enterDropCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitRenameVariable) { - listener.exitRenameVariable(this); + if (listener.exitDropCommand) { + listener.exitDropCommand(this); } } } @@ -5139,12 +4437,17 @@ export class RenameCommandContext extends ParserRuleContext { export class RenameClauseContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext { - return this.getRuleContext(0, QualifiedNameContext); - } + public _oldName: SourceIdentifierContext; + public _newName: SourceIdentifierContext; public AS(): TerminalNode { return this.getToken(esql_parser.AS, 0); } - public renameVariable(): RenameVariableContext { - return this.getRuleContext(0, RenameVariableContext); + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); + } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); @@ -5168,8 +4471,8 @@ export class RenameClauseContext extends ParserRuleContext { export class DissectCommandContext extends ParserRuleContext { public DISSECT(): TerminalNode { return this.getToken(esql_parser.DISSECT, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); + public primaryExpression(): PrimaryExpressionContext { + return this.getRuleContext(0, PrimaryExpressionContext); } public string(): StringContext { return this.getRuleContext(0, StringContext); @@ -5199,8 +4502,8 @@ export class DissectCommandContext extends ParserRuleContext { export class GrokCommandContext extends ParserRuleContext { public GROK(): TerminalNode { return this.getToken(esql_parser.GROK, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); + public primaryExpression(): PrimaryExpressionContext { + return this.getRuleContext(0, PrimaryExpressionContext); } public string(): StringContext { return this.getRuleContext(0, StringContext); @@ -5225,6 +4528,31 @@ export class GrokCommandContext extends ParserRuleContext { } +export class MvExpandCommandContext extends ParserRuleContext { + public MV_EXPAND(): TerminalNode { return this.getToken(esql_parser.MV_EXPAND, 0); } + public sourceIdentifier(): SourceIdentifierContext { + return this.getRuleContext(0, SourceIdentifierContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_mvExpandCommand; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterMvExpandCommand) { + listener.enterMvExpandCommand(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitMvExpandCommand) { + listener.exitMvExpandCommand(this); + } + } +} + + export class CommandOptionsContext extends ParserRuleContext { public commandOption(): CommandOptionContext[]; public commandOption(i: number): CommandOptionContext; @@ -5293,7 +4621,8 @@ export class CommandOptionContext extends ParserRuleContext { export class BooleanValueContext extends ParserRuleContext { - public BOOLEAN_VALUE(): TerminalNode { return this.getToken(esql_parser.BOOLEAN_VALUE, 0); } + public TRUE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.TRUE, 0); } + public FALSE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.FALSE, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5314,51 +4643,28 @@ export class BooleanValueContext extends ParserRuleContext { } -export class NumberContext extends ParserRuleContext { - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_number; } - public copyFrom(ctx: NumberContext): void { - super.copyFrom(ctx); +export class NumericValueContext extends ParserRuleContext { + public decimalValue(): DecimalValueContext | undefined { + return this.tryGetRuleContext(0, DecimalValueContext); } -} -export class DecimalLiteralContext extends NumberContext { - public DECIMAL_LITERAL(): TerminalNode { return this.getToken(esql_parser.DECIMAL_LITERAL, 0); } - constructor(ctx: NumberContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); + public integerValue(): IntegerValueContext | undefined { + return this.tryGetRuleContext(0, IntegerValueContext); } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterDecimalLiteral) { - listener.enterDecimalLiteral(this); - } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); } // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitDecimalLiteral) { - listener.exitDecimalLiteral(this); - } - } -} -export class IntegerLiteralContext extends NumberContext { - public INTEGER_LITERAL(): TerminalNode { return this.getToken(esql_parser.INTEGER_LITERAL, 0); } - constructor(ctx: NumberContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); - } + public get ruleIndex(): number { return esql_parser.RULE_numericValue; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterIntegerLiteral) { - listener.enterIntegerLiteral(this); + if (listener.enterNumericValue) { + listener.enterNumericValue(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitIntegerLiteral) { - listener.exitIntegerLiteral(this); + if (listener.exitNumericValue) { + listener.exitNumericValue(this); } } } @@ -5366,6 +4672,8 @@ export class IntegerLiteralContext extends NumberContext { export class DecimalValueContext extends ParserRuleContext { public DECIMAL_LITERAL(): TerminalNode { return this.getToken(esql_parser.DECIMAL_LITERAL, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5388,6 +4696,8 @@ export class DecimalValueContext extends ParserRuleContext { export class IntegerValueContext extends ParserRuleContext { public INTEGER_LITERAL(): TerminalNode { return this.getToken(esql_parser.INTEGER_LITERAL, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5431,7 +4741,12 @@ export class StringContext extends ParserRuleContext { export class ComparisonOperatorContext extends ParserRuleContext { - public COMPARISON_OPERATOR(): TerminalNode { return this.getToken(esql_parser.COMPARISON_OPERATOR, 0); } + public EQ(): TerminalNode | undefined { return this.tryGetToken(esql_parser.EQ, 0); } + public NEQ(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NEQ, 0); } + public LT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LT, 0); } + public LTE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LTE, 0); } + public GT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.GT, 0); } + public GTE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.GTE, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5452,76 +4767,139 @@ export class ComparisonOperatorContext extends ParserRuleContext { } -export class ExplainCommandContext extends ParserRuleContext { - public EXPLAIN(): TerminalNode { return this.getToken(esql_parser.EXPLAIN, 0); } - public subqueryExpression(): SubqueryExpressionContext { - return this.getRuleContext(0, SubqueryExpressionContext); - } +export class ShowCommandContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_explainCommand; } + public get ruleIndex(): number { return esql_parser.RULE_showCommand; } + public copyFrom(ctx: ShowCommandContext): void { + super.copyFrom(ctx); + } +} +export class ShowInfoContext extends ShowCommandContext { + public SHOW(): TerminalNode { return this.getToken(esql_parser.SHOW, 0); } + public INFO(): TerminalNode { return this.getToken(esql_parser.INFO, 0); } + constructor(ctx: ShowCommandContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterShowInfo) { + listener.enterShowInfo(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitShowInfo) { + listener.exitShowInfo(this); + } + } +} +export class ShowFunctionsContext extends ShowCommandContext { + public SHOW(): TerminalNode { return this.getToken(esql_parser.SHOW, 0); } + public FUNCTIONS(): TerminalNode { return this.getToken(esql_parser.FUNCTIONS, 0); } + constructor(ctx: ShowCommandContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterExplainCommand) { - listener.enterExplainCommand(this); + if (listener.enterShowFunctions) { + listener.enterShowFunctions(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitExplainCommand) { - listener.exitExplainCommand(this); + if (listener.exitShowFunctions) { + listener.exitShowFunctions(this); } } } -export class SubqueryExpressionContext extends ParserRuleContext { - public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } - public query(): QueryContext { - return this.getRuleContext(0, QueryContext); +export class EnrichCommandContext extends ParserRuleContext { + public _policyName: SourceIdentifierContext; + public _matchField: SourceIdentifierContext; + public ENRICH(): TerminalNode { return this.getToken(esql_parser.ENRICH, 0); } + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); + } + } + public ON(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ON, 0); } + public WITH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.WITH, 0); } + public enrichWithClause(): EnrichWithClauseContext[]; + public enrichWithClause(i: number): EnrichWithClauseContext; + public enrichWithClause(i?: number): EnrichWithClauseContext | EnrichWithClauseContext[] { + if (i === undefined) { + return this.getRuleContexts(EnrichWithClauseContext); + } else { + return this.getRuleContext(i, EnrichWithClauseContext); + } + } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } } - public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_subqueryExpression; } + public get ruleIndex(): number { return esql_parser.RULE_enrichCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterSubqueryExpression) { - listener.enterSubqueryExpression(this); + if (listener.enterEnrichCommand) { + listener.enterEnrichCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitSubqueryExpression) { - listener.exitSubqueryExpression(this); + if (listener.exitEnrichCommand) { + listener.exitEnrichCommand(this); } } } -export class ShowCommandContext extends ParserRuleContext { - public SHOW(): TerminalNode { return this.getToken(esql_parser.SHOW, 0); } - public INFO(): TerminalNode | undefined { return this.tryGetToken(esql_parser.INFO, 0); } - public FUNCTIONS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.FUNCTIONS, 0); } +export class EnrichWithClauseContext extends ParserRuleContext { + public _newName: SourceIdentifierContext; + public _enrichField: SourceIdentifierContext; + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); + } + } + public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_showCommand; } + public get ruleIndex(): number { return esql_parser.RULE_enrichWithClause; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterShowCommand) { - listener.enterShowCommand(this); + if (listener.enterEnrichWithClause) { + listener.enterEnrichWithClause(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitShowCommand) { - listener.exitShowCommand(this); + if (listener.exitEnrichWithClause) { + listener.exitEnrichWithClause(this); } } } diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts b/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts index f131d4072b773..ff67f81aeab09 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts @@ -4,70 +4,79 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { ValueExpressionDefaultContext } from "./esql_parser"; +import { ComparisonContext } from "./esql_parser"; +import { NullLiteralContext } from "./esql_parser"; +import { QualifiedIntegerLiteralContext } from "./esql_parser"; import { DecimalLiteralContext } from "./esql_parser"; import { IntegerLiteralContext } from "./esql_parser"; +import { BooleanLiteralContext } from "./esql_parser"; +import { InputParamContext } from "./esql_parser"; +import { StringLiteralContext } from "./esql_parser"; +import { NumericArrayLiteralContext } from "./esql_parser"; +import { BooleanArrayLiteralContext } from "./esql_parser"; +import { StringArrayLiteralContext } from "./esql_parser"; +import { ShowInfoContext } from "./esql_parser"; +import { ShowFunctionsContext } from "./esql_parser"; +import { ConstantDefaultContext } from "./esql_parser"; +import { DereferenceContext } from "./esql_parser"; +import { FunctionContext } from "./esql_parser"; +import { ParenthesizedExpressionContext } from "./esql_parser"; import { SingleCommandQueryContext } from "./esql_parser"; import { CompositeQueryContext } from "./esql_parser"; +import { LogicalNotContext } from "./esql_parser"; +import { BooleanDefaultContext } from "./esql_parser"; +import { RegexExpressionContext } from "./esql_parser"; +import { LogicalBinaryContext } from "./esql_parser"; +import { LogicalInContext } from "./esql_parser"; +import { IsNullContext } from "./esql_parser"; +import { OperatorExpressionDefaultContext } from "./esql_parser"; +import { ArithmeticUnaryContext } from "./esql_parser"; +import { ArithmeticBinaryContext } from "./esql_parser"; import { SingleStatementContext } from "./esql_parser"; import { QueryContext } from "./esql_parser"; import { SourceCommandContext } from "./esql_parser"; import { ProcessingCommandContext } from "./esql_parser"; -import { EnrichCommandContext } from "./esql_parser"; -import { EnrichWithClauseContext } from "./esql_parser"; -import { MvExpandCommandContext } from "./esql_parser"; import { WhereCommandContext } from "./esql_parser"; -import { WhereBooleanExpressionContext } from "./esql_parser"; import { BooleanExpressionContext } from "./esql_parser"; import { RegexBooleanExpressionContext } from "./esql_parser"; import { ValueExpressionContext } from "./esql_parser"; -import { ComparisonContext } from "./esql_parser"; -import { MathFnContext } from "./esql_parser"; -import { MathEvalFnContext } from "./esql_parser"; -import { DateExpressionContext } from "./esql_parser"; import { OperatorExpressionContext } from "./esql_parser"; import { PrimaryExpressionContext } from "./esql_parser"; +import { FunctionExpressionContext } from "./esql_parser"; import { RowCommandContext } from "./esql_parser"; import { FieldsContext } from "./esql_parser"; import { FieldContext } from "./esql_parser"; -import { EnrichFieldIdentifierContext } from "./esql_parser"; -import { UserVariableContext } from "./esql_parser"; import { FromCommandContext } from "./esql_parser"; import { MetadataContext } from "./esql_parser"; import { EvalCommandContext } from "./esql_parser"; import { StatsCommandContext } from "./esql_parser"; +import { GroupingContext } from "./esql_parser"; import { SourceIdentifierContext } from "./esql_parser"; -import { EnrichIdentifierContext } from "./esql_parser"; -import { FunctionExpressionArgumentContext } from "./esql_parser"; -import { MathFunctionExpressionArgumentContext } from "./esql_parser"; import { QualifiedNameContext } from "./esql_parser"; -import { QualifiedNamesContext } from "./esql_parser"; import { IdentifierContext } from "./esql_parser"; -import { MathFunctionIdentifierContext } from "./esql_parser"; -import { FunctionIdentifierContext } from "./esql_parser"; import { ConstantContext } from "./esql_parser"; -import { NumericValueContext } from "./esql_parser"; import { LimitCommandContext } from "./esql_parser"; import { SortCommandContext } from "./esql_parser"; import { OrderExpressionContext } from "./esql_parser"; -import { ProjectCommandContext } from "./esql_parser"; import { KeepCommandContext } from "./esql_parser"; import { DropCommandContext } from "./esql_parser"; -import { RenameVariableContext } from "./esql_parser"; import { RenameCommandContext } from "./esql_parser"; import { RenameClauseContext } from "./esql_parser"; import { DissectCommandContext } from "./esql_parser"; import { GrokCommandContext } from "./esql_parser"; +import { MvExpandCommandContext } from "./esql_parser"; import { CommandOptionsContext } from "./esql_parser"; import { CommandOptionContext } from "./esql_parser"; import { BooleanValueContext } from "./esql_parser"; -import { NumberContext } from "./esql_parser"; +import { NumericValueContext } from "./esql_parser"; import { DecimalValueContext } from "./esql_parser"; import { IntegerValueContext } from "./esql_parser"; import { StringContext } from "./esql_parser"; import { ComparisonOperatorContext } from "./esql_parser"; -import { ExplainCommandContext } from "./esql_parser"; -import { SubqueryExpressionContext } from "./esql_parser"; import { ShowCommandContext } from "./esql_parser"; +import { EnrichCommandContext } from "./esql_parser"; +import { EnrichWithClauseContext } from "./esql_parser"; /** @@ -75,32 +84,240 @@ import { ShowCommandContext } from "./esql_parser"; * `esql_parser`. */ export interface esql_parserListener extends ParseTreeListener { + /** + * Enter a parse tree produced by the `valueExpressionDefault` + * labeled alternative in `esql_parser.valueExpression`. + * @param ctx the parse tree + */ + enterValueExpressionDefault?: (ctx: ValueExpressionDefaultContext) => void; + /** + * Exit a parse tree produced by the `valueExpressionDefault` + * labeled alternative in `esql_parser.valueExpression`. + * @param ctx the parse tree + */ + exitValueExpressionDefault?: (ctx: ValueExpressionDefaultContext) => void; + + /** + * Enter a parse tree produced by the `comparison` + * labeled alternative in `esql_parser.valueExpression`. + * @param ctx the parse tree + */ + enterComparison?: (ctx: ComparisonContext) => void; + /** + * Exit a parse tree produced by the `comparison` + * labeled alternative in `esql_parser.valueExpression`. + * @param ctx the parse tree + */ + exitComparison?: (ctx: ComparisonContext) => void; + + /** + * Enter a parse tree produced by the `nullLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterNullLiteral?: (ctx: NullLiteralContext) => void; + /** + * Exit a parse tree produced by the `nullLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitNullLiteral?: (ctx: NullLiteralContext) => void; + + /** + * Enter a parse tree produced by the `qualifiedIntegerLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterQualifiedIntegerLiteral?: (ctx: QualifiedIntegerLiteralContext) => void; + /** + * Exit a parse tree produced by the `qualifiedIntegerLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitQualifiedIntegerLiteral?: (ctx: QualifiedIntegerLiteralContext) => void; + /** * Enter a parse tree produced by the `decimalLiteral` - * labeled alternative in `esql_parser.number`. + * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ enterDecimalLiteral?: (ctx: DecimalLiteralContext) => void; /** * Exit a parse tree produced by the `decimalLiteral` - * labeled alternative in `esql_parser.number`. + * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ exitDecimalLiteral?: (ctx: DecimalLiteralContext) => void; /** * Enter a parse tree produced by the `integerLiteral` - * labeled alternative in `esql_parser.number`. + * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ enterIntegerLiteral?: (ctx: IntegerLiteralContext) => void; /** * Exit a parse tree produced by the `integerLiteral` - * labeled alternative in `esql_parser.number`. + * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ exitIntegerLiteral?: (ctx: IntegerLiteralContext) => void; + /** + * Enter a parse tree produced by the `booleanLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Exit a parse tree produced by the `booleanLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + + /** + * Enter a parse tree produced by the `inputParam` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterInputParam?: (ctx: InputParamContext) => void; + /** + * Exit a parse tree produced by the `inputParam` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitInputParam?: (ctx: InputParamContext) => void; + + /** + * Enter a parse tree produced by the `stringLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterStringLiteral?: (ctx: StringLiteralContext) => void; + /** + * Exit a parse tree produced by the `stringLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitStringLiteral?: (ctx: StringLiteralContext) => void; + + /** + * Enter a parse tree produced by the `numericArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterNumericArrayLiteral?: (ctx: NumericArrayLiteralContext) => void; + /** + * Exit a parse tree produced by the `numericArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitNumericArrayLiteral?: (ctx: NumericArrayLiteralContext) => void; + + /** + * Enter a parse tree produced by the `booleanArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterBooleanArrayLiteral?: (ctx: BooleanArrayLiteralContext) => void; + /** + * Exit a parse tree produced by the `booleanArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitBooleanArrayLiteral?: (ctx: BooleanArrayLiteralContext) => void; + + /** + * Enter a parse tree produced by the `stringArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterStringArrayLiteral?: (ctx: StringArrayLiteralContext) => void; + /** + * Exit a parse tree produced by the `stringArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitStringArrayLiteral?: (ctx: StringArrayLiteralContext) => void; + + /** + * Enter a parse tree produced by the `showInfo` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + enterShowInfo?: (ctx: ShowInfoContext) => void; + /** + * Exit a parse tree produced by the `showInfo` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowInfo?: (ctx: ShowInfoContext) => void; + + /** + * Enter a parse tree produced by the `showFunctions` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + enterShowFunctions?: (ctx: ShowFunctionsContext) => void; + /** + * Exit a parse tree produced by the `showFunctions` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowFunctions?: (ctx: ShowFunctionsContext) => void; + + /** + * Enter a parse tree produced by the `constantDefault` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + enterConstantDefault?: (ctx: ConstantDefaultContext) => void; + /** + * Exit a parse tree produced by the `constantDefault` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + exitConstantDefault?: (ctx: ConstantDefaultContext) => void; + + /** + * Enter a parse tree produced by the `dereference` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + enterDereference?: (ctx: DereferenceContext) => void; + /** + * Exit a parse tree produced by the `dereference` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + exitDereference?: (ctx: DereferenceContext) => void; + + /** + * Enter a parse tree produced by the `function` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + enterFunction?: (ctx: FunctionContext) => void; + /** + * Exit a parse tree produced by the `function` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + exitFunction?: (ctx: FunctionContext) => void; + + /** + * Enter a parse tree produced by the `parenthesizedExpression` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + enterParenthesizedExpression?: (ctx: ParenthesizedExpressionContext) => void; + /** + * Exit a parse tree produced by the `parenthesizedExpression` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + exitParenthesizedExpression?: (ctx: ParenthesizedExpressionContext) => void; + /** * Enter a parse tree produced by the `singleCommandQuery` * labeled alternative in `esql_parser.query`. @@ -128,180 +345,209 @@ export interface esql_parserListener extends ParseTreeListener { exitCompositeQuery?: (ctx: CompositeQueryContext) => void; /** - * Enter a parse tree produced by `esql_parser.singleStatement`. + * Enter a parse tree produced by the `logicalNot` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterSingleStatement?: (ctx: SingleStatementContext) => void; + enterLogicalNot?: (ctx: LogicalNotContext) => void; /** - * Exit a parse tree produced by `esql_parser.singleStatement`. + * Exit a parse tree produced by the `logicalNot` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitSingleStatement?: (ctx: SingleStatementContext) => void; + exitLogicalNot?: (ctx: LogicalNotContext) => void; /** - * Enter a parse tree produced by `esql_parser.query`. + * Enter a parse tree produced by the `booleanDefault` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterQuery?: (ctx: QueryContext) => void; + enterBooleanDefault?: (ctx: BooleanDefaultContext) => void; /** - * Exit a parse tree produced by `esql_parser.query`. + * Exit a parse tree produced by the `booleanDefault` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitQuery?: (ctx: QueryContext) => void; + exitBooleanDefault?: (ctx: BooleanDefaultContext) => void; /** - * Enter a parse tree produced by `esql_parser.sourceCommand`. + * Enter a parse tree produced by the `regexExpression` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterSourceCommand?: (ctx: SourceCommandContext) => void; + enterRegexExpression?: (ctx: RegexExpressionContext) => void; /** - * Exit a parse tree produced by `esql_parser.sourceCommand`. + * Exit a parse tree produced by the `regexExpression` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitSourceCommand?: (ctx: SourceCommandContext) => void; + exitRegexExpression?: (ctx: RegexExpressionContext) => void; /** - * Enter a parse tree produced by `esql_parser.processingCommand`. + * Enter a parse tree produced by the `logicalBinary` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterProcessingCommand?: (ctx: ProcessingCommandContext) => void; + enterLogicalBinary?: (ctx: LogicalBinaryContext) => void; /** - * Exit a parse tree produced by `esql_parser.processingCommand`. + * Exit a parse tree produced by the `logicalBinary` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitProcessingCommand?: (ctx: ProcessingCommandContext) => void; + exitLogicalBinary?: (ctx: LogicalBinaryContext) => void; /** - * Enter a parse tree produced by `esql_parser.enrichCommand`. + * Enter a parse tree produced by the `logicalIn` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterEnrichCommand?: (ctx: EnrichCommandContext) => void; + enterLogicalIn?: (ctx: LogicalInContext) => void; /** - * Exit a parse tree produced by `esql_parser.enrichCommand`. + * Exit a parse tree produced by the `logicalIn` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitEnrichCommand?: (ctx: EnrichCommandContext) => void; + exitLogicalIn?: (ctx: LogicalInContext) => void; /** - * Enter a parse tree produced by `esql_parser.enrichWithClause`. + * Enter a parse tree produced by the `isNull` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; + enterIsNull?: (ctx: IsNullContext) => void; /** - * Exit a parse tree produced by `esql_parser.enrichWithClause`. + * Exit a parse tree produced by the `isNull` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; + exitIsNull?: (ctx: IsNullContext) => void; /** - * Enter a parse tree produced by `esql_parser.mvExpandCommand`. + * Enter a parse tree produced by the `operatorExpressionDefault` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - enterMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + enterOperatorExpressionDefault?: (ctx: OperatorExpressionDefaultContext) => void; /** - * Exit a parse tree produced by `esql_parser.mvExpandCommand`. + * Exit a parse tree produced by the `operatorExpressionDefault` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - exitMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + exitOperatorExpressionDefault?: (ctx: OperatorExpressionDefaultContext) => void; /** - * Enter a parse tree produced by `esql_parser.whereCommand`. + * Enter a parse tree produced by the `arithmeticUnary` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - enterWhereCommand?: (ctx: WhereCommandContext) => void; + enterArithmeticUnary?: (ctx: ArithmeticUnaryContext) => void; /** - * Exit a parse tree produced by `esql_parser.whereCommand`. + * Exit a parse tree produced by the `arithmeticUnary` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - exitWhereCommand?: (ctx: WhereCommandContext) => void; + exitArithmeticUnary?: (ctx: ArithmeticUnaryContext) => void; /** - * Enter a parse tree produced by `esql_parser.whereBooleanExpression`. + * Enter a parse tree produced by the `arithmeticBinary` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - enterWhereBooleanExpression?: (ctx: WhereBooleanExpressionContext) => void; + enterArithmeticBinary?: (ctx: ArithmeticBinaryContext) => void; /** - * Exit a parse tree produced by `esql_parser.whereBooleanExpression`. + * Exit a parse tree produced by the `arithmeticBinary` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - exitWhereBooleanExpression?: (ctx: WhereBooleanExpressionContext) => void; + exitArithmeticBinary?: (ctx: ArithmeticBinaryContext) => void; /** - * Enter a parse tree produced by `esql_parser.booleanExpression`. + * Enter a parse tree produced by `esql_parser.singleStatement`. * @param ctx the parse tree */ - enterBooleanExpression?: (ctx: BooleanExpressionContext) => void; + enterSingleStatement?: (ctx: SingleStatementContext) => void; /** - * Exit a parse tree produced by `esql_parser.booleanExpression`. + * Exit a parse tree produced by `esql_parser.singleStatement`. * @param ctx the parse tree */ - exitBooleanExpression?: (ctx: BooleanExpressionContext) => void; + exitSingleStatement?: (ctx: SingleStatementContext) => void; /** - * Enter a parse tree produced by `esql_parser.regexBooleanExpression`. + * Enter a parse tree produced by `esql_parser.query`. * @param ctx the parse tree */ - enterRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; + enterQuery?: (ctx: QueryContext) => void; /** - * Exit a parse tree produced by `esql_parser.regexBooleanExpression`. + * Exit a parse tree produced by `esql_parser.query`. * @param ctx the parse tree */ - exitRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; + exitQuery?: (ctx: QueryContext) => void; /** - * Enter a parse tree produced by `esql_parser.valueExpression`. + * Enter a parse tree produced by `esql_parser.sourceCommand`. * @param ctx the parse tree */ - enterValueExpression?: (ctx: ValueExpressionContext) => void; + enterSourceCommand?: (ctx: SourceCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.valueExpression`. + * Exit a parse tree produced by `esql_parser.sourceCommand`. * @param ctx the parse tree */ - exitValueExpression?: (ctx: ValueExpressionContext) => void; + exitSourceCommand?: (ctx: SourceCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.comparison`. + * Enter a parse tree produced by `esql_parser.processingCommand`. * @param ctx the parse tree */ - enterComparison?: (ctx: ComparisonContext) => void; + enterProcessingCommand?: (ctx: ProcessingCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.comparison`. + * Exit a parse tree produced by `esql_parser.processingCommand`. * @param ctx the parse tree */ - exitComparison?: (ctx: ComparisonContext) => void; + exitProcessingCommand?: (ctx: ProcessingCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.mathFn`. + * Enter a parse tree produced by `esql_parser.whereCommand`. + * @param ctx the parse tree + */ + enterWhereCommand?: (ctx: WhereCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.whereCommand`. + * @param ctx the parse tree + */ + exitWhereCommand?: (ctx: WhereCommandContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterMathFn?: (ctx: MathFnContext) => void; + enterBooleanExpression?: (ctx: BooleanExpressionContext) => void; /** - * Exit a parse tree produced by `esql_parser.mathFn`. + * Exit a parse tree produced by `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitMathFn?: (ctx: MathFnContext) => void; + exitBooleanExpression?: (ctx: BooleanExpressionContext) => void; /** - * Enter a parse tree produced by `esql_parser.mathEvalFn`. + * Enter a parse tree produced by `esql_parser.regexBooleanExpression`. * @param ctx the parse tree */ - enterMathEvalFn?: (ctx: MathEvalFnContext) => void; + enterRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; /** - * Exit a parse tree produced by `esql_parser.mathEvalFn`. + * Exit a parse tree produced by `esql_parser.regexBooleanExpression`. * @param ctx the parse tree */ - exitMathEvalFn?: (ctx: MathEvalFnContext) => void; + exitRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; /** - * Enter a parse tree produced by `esql_parser.dateExpression`. + * Enter a parse tree produced by `esql_parser.valueExpression`. * @param ctx the parse tree */ - enterDateExpression?: (ctx: DateExpressionContext) => void; + enterValueExpression?: (ctx: ValueExpressionContext) => void; /** - * Exit a parse tree produced by `esql_parser.dateExpression`. + * Exit a parse tree produced by `esql_parser.valueExpression`. * @param ctx the parse tree */ - exitDateExpression?: (ctx: DateExpressionContext) => void; + exitValueExpression?: (ctx: ValueExpressionContext) => void; /** * Enter a parse tree produced by `esql_parser.operatorExpression`. @@ -325,6 +571,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitPrimaryExpression?: (ctx: PrimaryExpressionContext) => void; + /** + * Enter a parse tree produced by `esql_parser.functionExpression`. + * @param ctx the parse tree + */ + enterFunctionExpression?: (ctx: FunctionExpressionContext) => void; + /** + * Exit a parse tree produced by `esql_parser.functionExpression`. + * @param ctx the parse tree + */ + exitFunctionExpression?: (ctx: FunctionExpressionContext) => void; + /** * Enter a parse tree produced by `esql_parser.rowCommand`. * @param ctx the parse tree @@ -358,28 +615,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitField?: (ctx: FieldContext) => void; - /** - * Enter a parse tree produced by `esql_parser.enrichFieldIdentifier`. - * @param ctx the parse tree - */ - enterEnrichFieldIdentifier?: (ctx: EnrichFieldIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.enrichFieldIdentifier`. - * @param ctx the parse tree - */ - exitEnrichFieldIdentifier?: (ctx: EnrichFieldIdentifierContext) => void; - - /** - * Enter a parse tree produced by `esql_parser.userVariable`. - * @param ctx the parse tree - */ - enterUserVariable?: (ctx: UserVariableContext) => void; - /** - * Exit a parse tree produced by `esql_parser.userVariable`. - * @param ctx the parse tree - */ - exitUserVariable?: (ctx: UserVariableContext) => void; - /** * Enter a parse tree produced by `esql_parser.fromCommand`. * @param ctx the parse tree @@ -425,48 +660,26 @@ export interface esql_parserListener extends ParseTreeListener { exitStatsCommand?: (ctx: StatsCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.sourceIdentifier`. - * @param ctx the parse tree - */ - enterSourceIdentifier?: (ctx: SourceIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.sourceIdentifier`. - * @param ctx the parse tree - */ - exitSourceIdentifier?: (ctx: SourceIdentifierContext) => void; - - /** - * Enter a parse tree produced by `esql_parser.enrichIdentifier`. - * @param ctx the parse tree - */ - enterEnrichIdentifier?: (ctx: EnrichIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.enrichIdentifier`. - * @param ctx the parse tree - */ - exitEnrichIdentifier?: (ctx: EnrichIdentifierContext) => void; - - /** - * Enter a parse tree produced by `esql_parser.functionExpressionArgument`. + * Enter a parse tree produced by `esql_parser.grouping`. * @param ctx the parse tree */ - enterFunctionExpressionArgument?: (ctx: FunctionExpressionArgumentContext) => void; + enterGrouping?: (ctx: GroupingContext) => void; /** - * Exit a parse tree produced by `esql_parser.functionExpressionArgument`. + * Exit a parse tree produced by `esql_parser.grouping`. * @param ctx the parse tree */ - exitFunctionExpressionArgument?: (ctx: FunctionExpressionArgumentContext) => void; + exitGrouping?: (ctx: GroupingContext) => void; /** - * Enter a parse tree produced by `esql_parser.mathFunctionExpressionArgument`. + * Enter a parse tree produced by `esql_parser.sourceIdentifier`. * @param ctx the parse tree */ - enterMathFunctionExpressionArgument?: (ctx: MathFunctionExpressionArgumentContext) => void; + enterSourceIdentifier?: (ctx: SourceIdentifierContext) => void; /** - * Exit a parse tree produced by `esql_parser.mathFunctionExpressionArgument`. + * Exit a parse tree produced by `esql_parser.sourceIdentifier`. * @param ctx the parse tree */ - exitMathFunctionExpressionArgument?: (ctx: MathFunctionExpressionArgumentContext) => void; + exitSourceIdentifier?: (ctx: SourceIdentifierContext) => void; /** * Enter a parse tree produced by `esql_parser.qualifiedName`. @@ -479,17 +692,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitQualifiedName?: (ctx: QualifiedNameContext) => void; - /** - * Enter a parse tree produced by `esql_parser.qualifiedNames`. - * @param ctx the parse tree - */ - enterQualifiedNames?: (ctx: QualifiedNamesContext) => void; - /** - * Exit a parse tree produced by `esql_parser.qualifiedNames`. - * @param ctx the parse tree - */ - exitQualifiedNames?: (ctx: QualifiedNamesContext) => void; - /** * Enter a parse tree produced by `esql_parser.identifier`. * @param ctx the parse tree @@ -501,28 +703,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitIdentifier?: (ctx: IdentifierContext) => void; - /** - * Enter a parse tree produced by `esql_parser.mathFunctionIdentifier`. - * @param ctx the parse tree - */ - enterMathFunctionIdentifier?: (ctx: MathFunctionIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.mathFunctionIdentifier`. - * @param ctx the parse tree - */ - exitMathFunctionIdentifier?: (ctx: MathFunctionIdentifierContext) => void; - - /** - * Enter a parse tree produced by `esql_parser.functionIdentifier`. - * @param ctx the parse tree - */ - enterFunctionIdentifier?: (ctx: FunctionIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.functionIdentifier`. - * @param ctx the parse tree - */ - exitFunctionIdentifier?: (ctx: FunctionIdentifierContext) => void; - /** * Enter a parse tree produced by `esql_parser.constant`. * @param ctx the parse tree @@ -534,17 +714,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitConstant?: (ctx: ConstantContext) => void; - /** - * Enter a parse tree produced by `esql_parser.numericValue`. - * @param ctx the parse tree - */ - enterNumericValue?: (ctx: NumericValueContext) => void; - /** - * Exit a parse tree produced by `esql_parser.numericValue`. - * @param ctx the parse tree - */ - exitNumericValue?: (ctx: NumericValueContext) => void; - /** * Enter a parse tree produced by `esql_parser.limitCommand`. * @param ctx the parse tree @@ -578,17 +747,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitOrderExpression?: (ctx: OrderExpressionContext) => void; - /** - * Enter a parse tree produced by `esql_parser.projectCommand`. - * @param ctx the parse tree - */ - enterProjectCommand?: (ctx: ProjectCommandContext) => void; - /** - * Exit a parse tree produced by `esql_parser.projectCommand`. - * @param ctx the parse tree - */ - exitProjectCommand?: (ctx: ProjectCommandContext) => void; - /** * Enter a parse tree produced by `esql_parser.keepCommand`. * @param ctx the parse tree @@ -611,17 +769,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitDropCommand?: (ctx: DropCommandContext) => void; - /** - * Enter a parse tree produced by `esql_parser.renameVariable`. - * @param ctx the parse tree - */ - enterRenameVariable?: (ctx: RenameVariableContext) => void; - /** - * Exit a parse tree produced by `esql_parser.renameVariable`. - * @param ctx the parse tree - */ - exitRenameVariable?: (ctx: RenameVariableContext) => void; - /** * Enter a parse tree produced by `esql_parser.renameCommand`. * @param ctx the parse tree @@ -666,6 +813,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitGrokCommand?: (ctx: GrokCommandContext) => void; + /** + * Enter a parse tree produced by `esql_parser.mvExpandCommand`. + * @param ctx the parse tree + */ + enterMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.mvExpandCommand`. + * @param ctx the parse tree + */ + exitMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + /** * Enter a parse tree produced by `esql_parser.commandOptions`. * @param ctx the parse tree @@ -700,15 +858,15 @@ export interface esql_parserListener extends ParseTreeListener { exitBooleanValue?: (ctx: BooleanValueContext) => void; /** - * Enter a parse tree produced by `esql_parser.number`. + * Enter a parse tree produced by `esql_parser.numericValue`. * @param ctx the parse tree */ - enterNumber?: (ctx: NumberContext) => void; + enterNumericValue?: (ctx: NumericValueContext) => void; /** - * Exit a parse tree produced by `esql_parser.number`. + * Exit a parse tree produced by `esql_parser.numericValue`. * @param ctx the parse tree */ - exitNumber?: (ctx: NumberContext) => void; + exitNumericValue?: (ctx: NumericValueContext) => void; /** * Enter a parse tree produced by `esql_parser.decimalValue`. @@ -755,36 +913,36 @@ export interface esql_parserListener extends ParseTreeListener { exitComparisonOperator?: (ctx: ComparisonOperatorContext) => void; /** - * Enter a parse tree produced by `esql_parser.explainCommand`. + * Enter a parse tree produced by `esql_parser.showCommand`. * @param ctx the parse tree */ - enterExplainCommand?: (ctx: ExplainCommandContext) => void; + enterShowCommand?: (ctx: ShowCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.explainCommand`. + * Exit a parse tree produced by `esql_parser.showCommand`. * @param ctx the parse tree */ - exitExplainCommand?: (ctx: ExplainCommandContext) => void; + exitShowCommand?: (ctx: ShowCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.subqueryExpression`. + * Enter a parse tree produced by `esql_parser.enrichCommand`. * @param ctx the parse tree */ - enterSubqueryExpression?: (ctx: SubqueryExpressionContext) => void; + enterEnrichCommand?: (ctx: EnrichCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.subqueryExpression`. + * Exit a parse tree produced by `esql_parser.enrichCommand`. * @param ctx the parse tree */ - exitSubqueryExpression?: (ctx: SubqueryExpressionContext) => void; + exitEnrichCommand?: (ctx: EnrichCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.showCommand`. + * Enter a parse tree produced by `esql_parser.enrichWithClause`. * @param ctx the parse tree */ - enterShowCommand?: (ctx: ShowCommandContext) => void; + enterEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; /** - * Exit a parse tree produced by `esql_parser.showCommand`. + * Exit a parse tree produced by `esql_parser.enrichWithClause`. * @param ctx the parse tree */ - exitShowCommand?: (ctx: ShowCommandContext) => void; + exitEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; } diff --git a/packages/kbn-monaco/src/esql/index.ts b/packages/kbn-monaco/src/esql/index.ts index 46ae9fe7f6bcb..a3b5f3bec666d 100644 --- a/packages/kbn-monaco/src/esql/index.ts +++ b/packages/kbn-monaco/src/esql/index.ts @@ -8,5 +8,5 @@ export { ESQL_LANG_ID, ESQL_THEME_ID } from './lib/constants'; export { ESQLLang } from './language'; -export type { ESQLCustomAutocompleteCallbacks } from './lib/autocomplete/types'; +export type { ESQLCallbacks } from './lib/ast/shared/types'; export { buildESQlTheme } from './lib/monaco/esql_theme'; diff --git a/packages/kbn-monaco/src/esql/language.ts b/packages/kbn-monaco/src/esql/language.ts index cca4cb3718f06..956baa4405e0a 100644 --- a/packages/kbn-monaco/src/esql/language.ts +++ b/packages/kbn-monaco/src/esql/language.ts @@ -15,12 +15,12 @@ import type { ESQLWorker } from './worker/esql_worker'; import { DiagnosticsAdapter } from '../common/diagnostics_adapter'; import { WorkerProxyService } from '../common/worker_proxy'; -import { ESQLCompletionAdapter } from './lib/monaco/esql_completion_provider'; -import type { ESQLCustomAutocompleteCallbacks } from './lib/autocomplete/types'; +import type { ESQLCallbacks } from './lib/ast/shared/types'; +import { ESQLAstAdapter } from './lib/monaco/esql_ast_provider'; const workerProxyService = new WorkerProxyService(); -export const ESQLLang: CustomLangModuleType = { +export const ESQLLang: CustomLangModuleType = { ID: ESQL_LANG_ID, async onLanguage() { const { ESQLTokensProvider } = await import('./lib/monaco'); @@ -29,12 +29,18 @@ export const ESQLLang: CustomLangModuleType = { monaco.languages.setTokensProvider(ESQL_LANG_ID, new ESQLTokensProvider()); + // handle syntax errors via the diagnostic adapter + // but then enrich them via the separate validate function new DiagnosticsAdapter(ESQL_LANG_ID, (...uris) => workerProxyService.getWorker(uris)); }, languageConfiguration: { - brackets: [['(', ')']], + brackets: [ + ['(', ')'], + ['[', ']'], + ], autoClosingPairs: [ { open: '(', close: ')' }, + { open: '[', close: ']' }, { open: `'`, close: `'` }, { open: '"', close: '"' }, ], @@ -44,8 +50,65 @@ export const ESQLLang: CustomLangModuleType = { { open: '"', close: '"' }, ], }, - - getSuggestionProvider(callbacks?: ESQLCustomAutocompleteCallbacks) { - return new ESQLCompletionAdapter((...uris) => workerProxyService.getWorker(uris), callbacks); + validate: async (model: monaco.editor.ITextModel, code: string, callbacks?: ESQLCallbacks) => { + const astAdapter = new ESQLAstAdapter( + (...uris) => workerProxyService.getWorker(uris), + callbacks + ); + return await astAdapter.validate(model, code); + }, + getSignatureProvider: (callbacks?: ESQLCallbacks): monaco.languages.SignatureHelpProvider => { + return { + signatureHelpTriggerCharacters: [' ', '('], + async provideSignatureHelp( + model: monaco.editor.ITextModel, + position: monaco.Position, + _token: monaco.CancellationToken, + context: monaco.languages.SignatureHelpContext + ) { + const astAdapter = new ESQLAstAdapter( + (...uris) => workerProxyService.getWorker(uris), + callbacks + ); + return astAdapter.suggestSignature(model, position, context); + }, + }; + }, + getHoverProvider: (callbacks?: ESQLCallbacks): monaco.languages.HoverProvider => { + return { + async provideHover( + model: monaco.editor.ITextModel, + position: monaco.Position, + token: monaco.CancellationToken + ) { + const astAdapter = new ESQLAstAdapter( + (...uris) => workerProxyService.getWorker(uris), + callbacks + ); + return astAdapter.getHover(model, position, token); + }, + }; + }, + getSuggestionProvider: (callbacks?: ESQLCallbacks): monaco.languages.CompletionItemProvider => { + return { + triggerCharacters: [',', '(', '=', ' ', ''], + async provideCompletionItems( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.CompletionContext + ): Promise { + const astAdapter = new ESQLAstAdapter( + (...uris) => workerProxyService.getWorker(uris), + callbacks + ); + const suggestionEntries = await astAdapter.autocomplete(model, position, context); + return { + suggestions: suggestionEntries.suggestions.map((suggestion) => ({ + ...suggestion, + range: undefined as unknown as monaco.IRange, + })), + }; + }, + }; }, }; diff --git a/packages/kbn-monaco/src/esql/lib/antlr_facade.ts b/packages/kbn-monaco/src/esql/lib/antlr_facade.ts index e6bf97e443140..ffa69ba2a8f4c 100644 --- a/packages/kbn-monaco/src/esql/lib/antlr_facade.ts +++ b/packages/kbn-monaco/src/esql/lib/antlr_facade.ts @@ -6,19 +6,17 @@ * Side Public License, v 1. */ -import { CommonTokenStream, CodePointCharStream } from 'antlr4ts'; +import { CommonTokenStream, type CodePointCharStream, type ANTLRErrorListener } from 'antlr4ts'; import { esql_lexer as ESQLLexer } from '../antlr/esql_lexer'; import { esql_parser as ESQLParser } from '../antlr/esql_parser'; import type { esql_parserListener as ESQLParserListener } from '../antlr/esql_parser_listener'; -import type { ANTLREErrorListener } from '../../common/error_listener'; - export const ROOT_STATEMENT = 'singleStatement'; export const getParser = ( inputStream: CodePointCharStream, - errorListener: ANTLREErrorListener, + errorListener: ANTLRErrorListener, parseListener?: ESQLParserListener ) => { const lexer = getLexer(inputStream, errorListener); @@ -35,7 +33,10 @@ export const getParser = ( return parser; }; -export const getLexer = (inputStream: CodePointCharStream, errorListener: ANTLREErrorListener) => { +export const getLexer = ( + inputStream: CodePointCharStream, + errorListener: ANTLRErrorListener +) => { const lexer = new ESQLLexer(inputStream); lexer.removeErrorListeners(); diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_errors.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_errors.ts new file mode 100644 index 0000000000000..01d16a46b2502 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_errors.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { RecognitionException } from 'antlr4ts'; +import { esql_parser } from '../../antlr/esql_parser'; +import { getPosition } from './ast_position_utils'; + +function getExpectedSymbols(expectedTokens: RecognitionException['expectedTokens']) { + const tokenIds = expectedTokens?.toIntegerList().toArray() || []; + const list = []; + for (const tokenId of tokenIds) { + if (esql_parser.VOCABULARY.getSymbolicName(tokenId)) { + const symbol = esql_parser.VOCABULARY.getSymbolicName(tokenId); + list.push(symbol === 'EOF' ? `<${symbol}>` : symbol); + } + } + return list; +} + +export function createError(exception: RecognitionException) { + const token = exception.getOffendingToken(); + if (token) { + const expectedSymbols = getExpectedSymbols(exception.expectedTokens); + if ( + ['ASTERISK', 'UNQUOTED_IDENTIFIER', 'QUOTED_IDENTIFIER'].every( + (s, i) => expectedSymbols[i] === s + ) + ) { + return { + type: 'error' as const, + text: `Unknown column ${token.text}`, + location: getPosition(token), + }; + } + } + return { + type: 'error' as const, + text: token + ? `SyntaxError: expected {${getExpectedSymbols(exception.expectedTokens).join( + ', ' + )}} but found "${token.text}"` + : exception.message, + location: getPosition(token), + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_factory.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_factory.ts new file mode 100644 index 0000000000000..939d6d764f513 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_factory.ts @@ -0,0 +1,249 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + type ShowInfoContext, + type ShowFunctionsContext, + type SingleStatementContext, + type RowCommandContext, + type FromCommandContext, + type EvalCommandContext, + type StatsCommandContext, + type LimitCommandContext, + type SortCommandContext, + type KeepCommandContext, + type DropCommandContext, + type RenameCommandContext, + type DissectCommandContext, + type GrokCommandContext, + type MvExpandCommandContext, + type ShowCommandContext, + type EnrichCommandContext, + type WhereCommandContext, + esql_parser, +} from '../../antlr/esql_parser'; +import { esql_parserListener as ESQLParserListener } from '../../antlr/esql_parser_listener'; +import { createCommand, createFunction, createOption, createLiteral } from './ast_helpers'; +import { getPosition } from './ast_position_utils'; +import { + collectAllSourceIdentifiers, + collectAllFieldsStatements, + visitByOption, + collectAllColumnIdentifiers, + visitRenameClauses, + visitDissect, + visitGrok, + collectBooleanExpression, + visitOrderExpression, + getPolicyName, + getMatchField, + getEnrichClauses, +} from './ast_walker'; +import type { ESQLAst } from './types'; + +export class AstListener implements ESQLParserListener { + private ast: ESQLAst = []; + + public getAst() { + return { ast: this.ast }; + } + + /** + * Exit a parse tree produced by the `showInfo` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowInfo(ctx: ShowInfoContext) { + const commandAst = createCommand('show', ctx); + + this.ast.push(commandAst); + commandAst.text = ctx.text; + commandAst?.args.push(createFunction('info', ctx, getPosition(ctx.INFO().symbol))); + } + + /** + * Exit a parse tree produced by the `showFunctions` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowFunctions(ctx: ShowFunctionsContext) { + const commandAst = createCommand('show', ctx); + this.ast.push(commandAst); + // update the text + commandAst.text = ctx.text; + commandAst?.args.push(createFunction('functions', ctx, getPosition(ctx.FUNCTIONS().symbol))); + } + + /** + * Enter a parse tree produced by `esql_parser.singleStatement`. + * @param ctx the parse tree + */ + enterSingleStatement(ctx: SingleStatementContext) { + this.ast = []; + } + + /** + * Exit a parse tree produced by `esql_parser.whereCommand`. + * @param ctx the parse tree + */ + exitWhereCommand(ctx: WhereCommandContext) { + const command = createCommand('where', ctx); + this.ast.push(command); + command.args.push(...collectBooleanExpression(ctx.booleanExpression())); + } + + /** + * Exit a parse tree produced by `esql_parser.rowCommand`. + * @param ctx the parse tree + */ + exitRowCommand(ctx: RowCommandContext) { + const command = createCommand('row', ctx); + this.ast.push(command); + command.args.push(...collectAllFieldsStatements(ctx.fields())); + } + + /** + * Exit a parse tree produced by `esql_parser.fromCommand`. + * @param ctx the parse tree + */ + exitFromCommand(ctx: FromCommandContext) { + const commandAst = createCommand('from', ctx); + this.ast.push(commandAst); + commandAst.args.push(...collectAllSourceIdentifiers(ctx)); + const metadataContext = ctx.metadata(); + if (metadataContext) { + const option = createOption(metadataContext.METADATA().text.toLowerCase(), metadataContext); + commandAst.args.push(option); + // skip for the moment as there's no easy way to get meta fields right now + // option.args.push(...collectAllColumnIdentifiers(metadataContext)); + } + } + + /** + * Exit a parse tree produced by `esql_parser.evalCommand`. + * @param ctx the parse tree + */ + exitEvalCommand(ctx: EvalCommandContext) { + const commandAst = createCommand('eval', ctx); + this.ast.push(commandAst); + commandAst.args.push(...collectAllFieldsStatements(ctx.fields())); + } + + /** + * Exit a parse tree produced by `esql_parser.statsCommand`. + * @param ctx the parse tree + */ + exitStatsCommand(ctx: StatsCommandContext) { + const command = createCommand('stats', ctx); + this.ast.push(command); + command.args.push(...collectAllFieldsStatements(ctx.fields()), ...visitByOption(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.limitCommand`. + * @param ctx the parse tree + */ + exitLimitCommand(ctx: LimitCommandContext) { + const command = createCommand('limit', ctx); + this.ast.push(command); + if (ctx.tryGetToken(esql_parser.INTEGER_LITERAL, 0)) { + const literal = createLiteral('number', ctx.INTEGER_LITERAL()); + if (literal) { + command.args.push(literal); + } + } + } + + /** + * Exit a parse tree produced by `esql_parser.sortCommand`. + * @param ctx the parse tree + */ + exitSortCommand(ctx: SortCommandContext) { + const command = createCommand('sort', ctx); + this.ast.push(command); + command.args.push(...visitOrderExpression(ctx.orderExpression())); + } + + /** + * Exit a parse tree produced by `esql_parser.keepCommand`. + * @param ctx the parse tree + */ + exitKeepCommand(ctx: KeepCommandContext) { + const command = createCommand('keep', ctx); + this.ast.push(command); + command.args.push(...collectAllColumnIdentifiers(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.dropCommand`. + * @param ctx the parse tree + */ + exitDropCommand(ctx: DropCommandContext) { + const command = createCommand('drop', ctx); + this.ast.push(command); + command.args.push(...collectAllColumnIdentifiers(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.renameCommand`. + * @param ctx the parse tree + */ + exitRenameCommand(ctx: RenameCommandContext) { + const command = createCommand('rename', ctx); + this.ast.push(command); + command.args.push(...visitRenameClauses(ctx.renameClause())); + } + + /** + * Exit a parse tree produced by `esql_parser.dissectCommand`. + * @param ctx the parse tree + */ + exitDissectCommand(ctx: DissectCommandContext) { + const command = createCommand('dissect', ctx); + this.ast.push(command); + command.args.push(...visitDissect(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.grokCommand`. + * @param ctx the parse tree + */ + exitGrokCommand(ctx: GrokCommandContext) { + const command = createCommand('grok', ctx); + this.ast.push(command); + command.args.push(...visitGrok(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.mvExpandCommand`. + * @param ctx the parse tree + */ + exitMvExpandCommand(ctx: MvExpandCommandContext) { + const command = createCommand('mv_expand', ctx); + this.ast.push(command); + command.args.push(...collectAllColumnIdentifiers(ctx)); + } + + /** + * Enter a parse tree produced by `esql_parser.showCommand`. + * @param ctx the parse tree + */ + enterShowCommand(ctx: ShowCommandContext) { + const command = createCommand('show', ctx); + this.ast.push(command); + } + /** + * Exit a parse tree produced by `esql_parser.enrichCommand`. + * @param ctx the parse tree + */ + exitEnrichCommand(ctx: EnrichCommandContext) { + const command = createCommand('enrich', ctx); + this.ast.push(command); + command.args.push(...getPolicyName(ctx), ...getMatchField(ctx), ...getEnrichClauses(ctx)); + } +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_helpers.ts new file mode 100644 index 0000000000000..d6e8ea7d0a038 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_helpers.ts @@ -0,0 +1,240 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; +import type { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import type { + ArithmeticUnaryContext, + DecimalValueContext, + IntegerValueContext, + QualifiedIntegerLiteralContext, +} from '../../antlr/esql_parser'; +import { getPosition } from './ast_position_utils'; +import type { + ESQLCommand, + ESQLLiteral, + ESQLList, + ESQLTimeInterval, + ESQLLocation, + ESQLFunction, + ESQLSource, + ESQLColumn, + ESQLCommandOption, + ESQLAstItem, +} from './types'; + +export function nonNullable(v: T): v is NonNullable { + return v != null; +} + +export function createCommand(name: string, ctx: ParserRuleContext): ESQLCommand { + return { + type: 'command', + name, + text: ctx.text, + args: [], + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + +export function createList(ctx: ParserRuleContext, values: ESQLLiteral[]): ESQLList { + return { + type: 'list', + name: ctx.text, + values, + text: ctx.text, + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + +export function createNumericLiteral(ctx: DecimalValueContext | IntegerValueContext): ESQLLiteral { + const text = ctx.text; + return { + type: 'literal', + literalType: 'number', + text, + name: text, + value: Number(text), + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + +export function createFakeMultiplyLiteral(ctx: ArithmeticUnaryContext): ESQLLiteral { + return { + type: 'literal', + literalType: 'number', + text: ctx.text, + name: ctx.text, + value: ctx.PLUS() ? 1 : -1, + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + +export function createLiteral( + type: ESQLLiteral['literalType'], + node: TerminalNode | undefined +): ESQLLiteral | undefined { + if (!node) { + return; + } + const text = node.text; + return { + type: 'literal', + literalType: type, + text, + name: text, + value: type === 'number' ? Number(text) : text, + location: getPosition(node.symbol), + incomplete: / number +) { + let nextArg: ESQLAstItem | undefined = args[getNextItemIndex(args)]; + const location = { ...initialLocation }; + while (Array.isArray(nextArg) || nextArg) { + if (Array.isArray(nextArg)) { + nextArg = nextArg[getNextItemIndex(nextArg)]; + } else { + location[prop] = Math[prop](location[prop], nextArg.location[prop]); + if (nextArg.type === 'function') { + nextArg = nextArg.args[getNextItemIndex(nextArg.args)]; + } else { + nextArg = undefined; + } + } + } + return location[prop]; +} + +export function computeLocationExtends(fn: ESQLFunction) { + const location = fn.location; + if (fn.args) { + // get min location navigating in depth keeping the left/first arg + location.min = walkFunctionStructure(fn.args, location, 'min', () => 0); + // get max location navigating in depth keeping the right/last arg + location.max = walkFunctionStructure(fn.args, location, 'max', (args) => args.length - 1); + } + return location; +} + +// Note: do not import esql_parser or bundle size will grow up by ~500 kb +function getQuotedText(ctx: ParserRuleContext) { + return ( + ctx.tryGetToken(73 /* esql_parser.SRC_QUOTED_IDENTIFIER*/, 0) || + ctx.tryGetToken(64 /* esql_parser.QUOTED_IDENTIFIER */, 0) + ); +} + +function getUnquotedText(ctx: ParserRuleContext) { + return ( + ctx.tryGetToken(72 /* esql_parser.SRC_UNQUOTED_IDENTIFIER */, 0) || + ctx.tryGetToken(63 /* esql_parser.UNQUOTED_IDENTIFIER */, 0) + ); +} + +const TICKS_REGEX = /(`)/g; + +function isQuoted(text: string | undefined) { + return text && TICKS_REGEX.test(text); +} + +export function sanifyIdentifierString(ctx: ParserRuleContext) { + return ( + getUnquotedText(ctx)?.text || + getQuotedText(ctx)?.text.replace(TICKS_REGEX, '') || + ctx.text.replace(TICKS_REGEX, '') // for some reason some quoted text is not detected correctly by the parser + ); +} + +export function createSource( + ctx: ParserRuleContext, + type: 'index' | 'policy' = 'index' +): ESQLSource { + const text = sanifyIdentifierString(ctx); + return { + type: 'source', + name: text, + sourceType: type, + text, + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception || text === ''), + }; +} + +export function createColumnStar(ctx: TerminalNode): ESQLColumn { + return { + type: 'column', + name: ctx.text, + text: ctx.text, + location: getPosition(ctx.symbol), + incomplete: ctx.text === '', + quoted: false, + }; +} + +export function createColumn(ctx: ParserRuleContext): ESQLColumn { + const text = sanifyIdentifierString(ctx); + const hasQuotes = Boolean(getQuotedText(ctx) || isQuoted(ctx.text)); + return { + type: 'column', + name: text, + text, + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception || text === ''), + quoted: hasQuotes, + }; +} + +export function createOption(name: string, ctx: ParserRuleContext): ESQLCommandOption { + return { + type: 'option', + name, + text: ctx.text, + location: getPosition(ctx.start, ctx.stop), + args: [], + incomplete: Boolean(ctx.exception || ctx.children?.some((c) => c instanceof ErrorNode)), + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_position_utils.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_position_utils.ts new file mode 100644 index 0000000000000..73745b12f4908 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_position_utils.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Token } from 'antlr4ts'; + +export function getPosition(token: Token | undefined, lastToken?: Token | undefined) { + if (!token || token.startIndex < 0) { + return { min: 0, max: 0 }; + } + const endFirstToken = + token.stopIndex > -1 ? Math.max(token.stopIndex + 1, token.startIndex) : undefined; + const endLastToken = lastToken?.stopIndex; + return { + min: token.startIndex, + max: endLastToken ?? endFirstToken ?? Infinity, + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_walker.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_walker.ts new file mode 100644 index 0000000000000..677bc4694e05a --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_walker.ts @@ -0,0 +1,544 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + ArithmeticBinaryContext, + ArithmeticUnaryContext, + BooleanArrayLiteralContext, + BooleanDefaultContext, + type BooleanExpressionContext, + BooleanLiteralContext, + BooleanValueContext, + type CommandOptionsContext, + ComparisonContext, + type ComparisonOperatorContext, + type ConstantContext, + ConstantDefaultContext, + DecimalLiteralContext, + DereferenceContext, + type DissectCommandContext, + type DropCommandContext, + type EnrichCommandContext, + esql_parser, + type FieldContext, + type FieldsContext, + type FromCommandContext, + FunctionContext, + type GrokCommandContext, + IntegerLiteralContext, + IsNullContext, + type KeepCommandContext, + LogicalBinaryContext, + LogicalInContext, + LogicalNotContext, + type MetadataContext, + type MvExpandCommandContext, + NullLiteralContext, + NumericArrayLiteralContext, + NumericValueContext, + type OperatorExpressionContext, + OperatorExpressionDefaultContext, + type OrderExpressionContext, + ParenthesizedExpressionContext, + type PrimaryExpressionContext, + QualifiedIntegerLiteralContext, + RegexBooleanExpressionContext, + type RenameClauseContext, + SourceIdentifierContext, + type StatsCommandContext, + StringArrayLiteralContext, + StringContext, + StringLiteralContext, + type ValueExpressionContext, + ValueExpressionDefaultContext, +} from '../../antlr/esql_parser'; +import { + createSource, + createColumn, + createOption, + nonNullable, + createFunction, + createLiteral, + createTimeUnit, + createFakeMultiplyLiteral, + createList, + createNumericLiteral, + sanifyIdentifierString, + computeLocationExtends, + createColumnStar, +} from './ast_helpers'; +import { getPosition } from './ast_position_utils'; +import type { + ESQLLiteral, + ESQLColumn, + ESQLFunction, + ESQLCommandOption, + ESQLAstItem, +} from './types'; + +export function collectAllSourceIdentifiers(ctx: FromCommandContext): ESQLAstItem[] { + return ctx.getRuleContexts(SourceIdentifierContext).map((sourceCtx) => createSource(sourceCtx)); +} + +export function collectAllColumnIdentifiers( + ctx: KeepCommandContext | DropCommandContext | MvExpandCommandContext | MetadataContext +): ESQLAstItem[] { + const identifiers = ( + Array.isArray(ctx.sourceIdentifier()) ? ctx.sourceIdentifier() : [ctx.sourceIdentifier()] + ) as SourceIdentifierContext[]; + const args: ESQLColumn[] = + identifiers + .filter((child) => child.text) + .map((sourceContext) => { + return createColumn(sourceContext); + }) ?? []; + return args; +} + +export function getPolicyName(ctx: EnrichCommandContext) { + if (!ctx._policyName) { + return []; + } + return [createSource(ctx._policyName, 'policy')]; +} + +export function getMatchField(ctx: EnrichCommandContext) { + if (!ctx._matchField) { + return []; + } + const identifier = ctx.sourceIdentifier(1); + if (identifier) { + const fn = createOption(ctx.ON()!.text.toLowerCase(), ctx); + if (identifier.text) { + fn.args.push(createColumn(identifier)); + } + // overwrite the location inferring the correct position + fn.location = getPosition(ctx.ON()!.symbol, ctx.WITH()?.symbol); + return [fn]; + } + return []; +} + +export function getEnrichClauses(ctx: EnrichCommandContext) { + const ast: ESQLCommandOption[] = []; + if (ctx.WITH()) { + const option = createOption(ctx.WITH()!.text.toLowerCase(), ctx); + ast.push(option); + const clauses = ctx.enrichWithClause(); + for (const clause of clauses) { + if (clause._enrichField) { + const args = [ + // if an explicit assign is not set, create a fake assign with + // both left and right value with the same column + clause.ASSIGN() ? createColumn(clause._newName) : createColumn(clause._enrichField), + createColumn(clause._enrichField), + ].filter(nonNullable); + if (args.length) { + const fn = createFunction('=', clause); + fn.args.push(args[0], [args[1]]); + option.args.push(fn); + } + } + } + option.location = getPosition(ctx.WITH()?.symbol); + } + + return ast; +} + +function visitLogicalNot(ctx: LogicalNotContext) { + const fn = createFunction('not', ctx); + fn.args.push(...collectBooleanExpression(ctx.booleanExpression())); + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return fn; +} + +function visitLogicalAndsOrs(ctx: LogicalBinaryContext) { + const fn = createFunction(ctx.AND() ? 'and' : 'or', ctx); + fn.args.push(...collectBooleanExpression(ctx._left), ...collectBooleanExpression(ctx._right)); + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return fn; +} + +function visitLogicalIns(ctx: LogicalInContext) { + const fn = createFunction(ctx.NOT() ? 'not_in' : 'in', ctx); + const [left, ...list] = ctx.valueExpression(); + const values = [visitValueExpression(left), list.map((ve) => visitValueExpression(ve))]; + for (const arg of values) { + if (arg) { + const filteredArgs = Array.isArray(arg) ? arg.filter(nonNullable) : [arg]; + fn.args.push(filteredArgs); + } + } + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return fn; +} + +function getMathOperation(ctx: ArithmeticBinaryContext) { + return ( + ctx.PLUS()?.text || + ctx.MINUS()?.text || + ctx.ASTERISK()?.text || + ctx.SLASH()?.text || + ctx.PERCENT()?.text || + '' + ); +} + +function getComparisonName(ctx: ComparisonOperatorContext) { + return ( + ctx.EQ()?.text || + ctx.NEQ()?.text || + ctx.LT()?.text || + ctx.LTE()?.text || + ctx.GT()?.text || + ctx.GTE()?.text || + '' + ); +} + +function visitValueExpression(ctx: ValueExpressionContext) { + if (ctx instanceof ValueExpressionDefaultContext) { + return visitOperatorExpression(ctx.operatorExpression()); + } + if (ctx instanceof ComparisonContext) { + const comparisonNode = ctx.comparisonOperator(); + const comparisonFn = createFunction(getComparisonName(comparisonNode), comparisonNode); + comparisonFn.args.push( + visitOperatorExpression(ctx._left)!, + visitOperatorExpression(ctx._right)! + ); + // update the location of the comparisonFn based on arguments + const argsLocationExtends = computeLocationExtends(comparisonFn); + comparisonFn.location = argsLocationExtends; + + return comparisonFn; + } +} + +function visitOperatorExpression( + ctx: OperatorExpressionContext +): ESQLAstItem | ESQLAstItem[] | undefined { + if (ctx instanceof ArithmeticUnaryContext) { + const arg = visitOperatorExpression(ctx.operatorExpression()); + // this is a number sign thing + const fn = createFunction('multiply', ctx); + fn.args.push(createFakeMultiplyLiteral(ctx)); + if (arg) { + fn.args.push(arg); + } + return fn; + } + if (ctx instanceof ArithmeticBinaryContext) { + const fn = createFunction(getMathOperation(ctx), ctx); + const args = [visitOperatorExpression(ctx._left), visitOperatorExpression(ctx._right)]; + for (const arg of args) { + if (arg) { + fn.args.push(arg); + } + } + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return fn; + } + if (ctx instanceof OperatorExpressionDefaultContext) { + return visitPrimaryExpression(ctx.primaryExpression()); + } +} + +function getBooleanValue(ctx: BooleanLiteralContext | BooleanValueContext) { + const parentNode = ctx instanceof BooleanLiteralContext ? ctx.booleanValue() : ctx; + const booleanTerminalNode = parentNode.TRUE() || parentNode.FALSE(); + return createLiteral('boolean', booleanTerminalNode!); +} + +function getConstant(ctx: ConstantContext | undefined): ESQLAstItem | undefined { + if (ctx instanceof NullLiteralContext) { + return createLiteral('string', ctx.NULL()); + } + if (ctx instanceof QualifiedIntegerLiteralContext) { + // despite the generic name, this is a date unit constant: + // e.g. 1 year, 15 months + return createTimeUnit(ctx); + } + if (ctx instanceof DecimalLiteralContext) { + return createNumericLiteral(ctx.decimalValue()); + } + if (ctx instanceof IntegerLiteralContext) { + return createNumericLiteral(ctx.integerValue()); + } + if (ctx instanceof BooleanLiteralContext) { + return getBooleanValue(ctx); + } + if (ctx instanceof StringLiteralContext) { + return createLiteral('string', ctx.string().STRING()); + } + if ( + ctx instanceof NumericArrayLiteralContext || + ctx instanceof BooleanArrayLiteralContext || + ctx instanceof StringArrayLiteralContext + ) { + const values: ESQLLiteral[] = []; + for (const numericValue of ctx.getRuleContexts(NumericValueContext)) { + const value = numericValue.decimalValue() || numericValue.integerValue(); + values.push(createNumericLiteral(value!)); + } + for (const booleanValue of ctx.getRuleContexts(BooleanValueContext)) { + values.push(getBooleanValue(booleanValue)!); + } + for (const string of ctx.getRuleContexts(StringContext)) { + const literal = createLiteral('string', string.STRING()); + if (literal) { + values.push(literal); + } + } + return createList(ctx, values); + } +} + +export function visitRenameClauses(clausesCtx: RenameClauseContext[]): ESQLAstItem[] { + return clausesCtx + .map((clause) => { + const asToken = clause.tryGetToken(esql_parser.AS, 0); + if (asToken) { + const fn = createOption(asToken.text.toLowerCase(), clause); + for (const arg of [clause._oldName, clause._newName]) { + if (arg?.text) { + fn.args.push(createColumn(arg)); + } + } + return fn; + } else if (clause._oldName?.text) { + return createColumn(clause._oldName); + } + }) + .filter(nonNullable); +} + +export function visitPrimaryExpression( + ctx: PrimaryExpressionContext +): ESQLAstItem | ESQLAstItem[] | undefined { + if (ctx instanceof ConstantDefaultContext) { + return getConstant(ctx.constant()); + } + if (ctx instanceof DereferenceContext) { + return createColumn(ctx.qualifiedName()); + } + if (ctx instanceof ParenthesizedExpressionContext) { + return collectBooleanExpression(ctx.booleanExpression()); + } + if (ctx instanceof FunctionContext) { + const functionExpressionCtx = ctx.functionExpression(); + const fn = createFunction(functionExpressionCtx.identifier().text.toLowerCase(), ctx); + const asteriskArg = functionExpressionCtx.ASTERISK() + ? createColumnStar(functionExpressionCtx.ASTERISK()!) + : undefined; + if (asteriskArg) { + fn.args.push(asteriskArg); + } + const functionArgs = functionExpressionCtx + .booleanExpression() + .flatMap(collectBooleanExpression) + .filter(nonNullable); + if (functionArgs.length) { + fn.args.push(...functionArgs); + } + return fn; + } +} + +export function collectLogicalExpression(ctx: BooleanExpressionContext) { + if (ctx instanceof LogicalNotContext) { + return [visitLogicalNot(ctx)]; + } + if (ctx instanceof LogicalBinaryContext) { + return [visitLogicalAndsOrs(ctx)]; + } + if (ctx instanceof LogicalInContext) { + return [visitLogicalIns(ctx)]; + } + return []; +} + +function collectRegexExpression(ctx: BooleanExpressionContext): ESQLFunction[] { + const regexes = ctx.getRuleContexts(RegexBooleanExpressionContext); + const ret: ESQLFunction[] = []; + return ret.concat( + regexes.map((regex) => { + const negate = regex.NOT(); + const likeType = regex._kind.text?.toLowerCase() || ''; + const fnName = `${negate ? 'not_' : ''}${likeType}`; + const fn = createFunction(fnName, regex); + const arg = visitValueExpression(regex.valueExpression()); + if (arg) { + fn.args.push(arg); + const literal = createLiteral('string', regex._pattern.STRING()); + if (literal) { + fn.args.push(literal); + } + } + return fn; + }) + ); +} + +function collectIsNullExpression(ctx: BooleanExpressionContext) { + if (!(ctx instanceof IsNullContext)) { + return []; + } + const negate = ctx.NOT(); + const fnName = `${negate ? 'not_' : ''}is_null`; + const fn = createFunction(fnName, ctx); + const arg = visitValueExpression(ctx.valueExpression()); + if (arg) { + fn.args.push(arg); + } + return [fn]; +} + +function collectDefaultExpression(ctx: BooleanExpressionContext) { + if (!(ctx instanceof BooleanDefaultContext)) { + return []; + } + const arg = visitValueExpression(ctx.valueExpression()); + return arg ? [arg] : []; +} + +export function collectBooleanExpression(ctx: BooleanExpressionContext | undefined): ESQLAstItem[] { + const ast: ESQLAstItem[] = []; + if (!ctx) { + return ast; + } + return ast.concat( + collectLogicalExpression(ctx), + collectRegexExpression(ctx), + collectIsNullExpression(ctx), + collectDefaultExpression(ctx) + ); +} + +export function visitField(ctx: FieldContext) { + if (ctx.qualifiedName() && ctx.ASSIGN()) { + const fn = createFunction(ctx.ASSIGN()!.text, ctx); + fn.args.push( + createColumn(ctx.qualifiedName()!), + collectBooleanExpression(ctx.booleanExpression()) + ); + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return [fn]; + } + return collectBooleanExpression(ctx.booleanExpression()); +} + +export function collectAllFieldsStatements(ctx: FieldsContext | undefined): ESQLAstItem[] { + const ast: ESQLAstItem[] = []; + if (!ctx) { + return ast; + } + try { + for (const field of ctx.field()) { + ast.push(...visitField(field)); + } + } catch (e) { + // do nothing + } + return ast; +} + +export function visitByOption(ctx: StatsCommandContext) { + if (!ctx.BY()) { + return []; + } + const option = createOption(ctx.BY()!.text.toLowerCase(), ctx); + for (const qnCtx of ctx.grouping()?.qualifiedName() || []) { + if (qnCtx?.text?.length) { + option.args.push(createColumn(qnCtx)); + } + } + return [option]; +} + +export function visitOrderExpression(ctx: OrderExpressionContext[]) { + const ast = []; + for (const orderCtx of ctx) { + const expression = collectBooleanExpression(orderCtx.booleanExpression()); + if (orderCtx._ordering) { + const terminalNode = + orderCtx.tryGetToken(esql_parser.ASC, 0) || orderCtx.tryGetToken(esql_parser.DESC, 0); + const literal = createLiteral('string', terminalNode); + if (literal) { + expression.push(literal); + } + } + if (orderCtx.NULLS()) { + expression.push(createLiteral('string', orderCtx.NULLS()!)!); + if (orderCtx._nullOrdering) { + const innerTerminalNode = + orderCtx.tryGetToken(esql_parser.FIRST, 0) || orderCtx.tryGetToken(esql_parser.LAST, 0); + const literal = createLiteral('string', innerTerminalNode); + if (literal) { + expression.push(literal); + } + } + } + + if (expression.length) { + ast.push(...expression); + } + } + return ast; +} + +export function visitDissect(ctx: DissectCommandContext) { + const pattern = ctx.string().tryGetToken(esql_parser.STRING, 0); + return [ + visitPrimaryExpression(ctx.primaryExpression()), + createLiteral('string', pattern), + ...visitDissectOptions(ctx.commandOptions()), + ].filter(nonNullable); +} + +export function visitGrok(ctx: GrokCommandContext) { + const pattern = ctx.string().tryGetToken(esql_parser.STRING, 0); + return [visitPrimaryExpression(ctx.primaryExpression()), createLiteral('string', pattern)].filter( + nonNullable + ); +} + +function visitDissectOptions(ctx: CommandOptionsContext | undefined) { + if (!ctx) { + return []; + } + const options: ESQLCommandOption[] = []; + for (const optionCtx of ctx.commandOption()) { + const option = createOption( + sanifyIdentifierString(optionCtx.identifier()).toLowerCase(), + optionCtx + ); + options.push(option); + // it can throw while accessing constant for incomplete commands, so try catch it + try { + const optionValue = getConstant(optionCtx.constant()); + if (optionValue != null) { + option.args.push(optionValue); + } + } catch (e) { + // do nothing here + } + } + return options; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.test.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.test.ts new file mode 100644 index 0000000000000..bfb9ecaee8d80 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.test.ts @@ -0,0 +1,780 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { monaco } from '../../../../monaco_imports'; +import { CharStreams } from 'antlr4ts'; +import { suggest } from './autocomplete'; +import { getParser, ROOT_STATEMENT } from '../../antlr_facade'; +import { ESQLErrorListener } from '../../monaco/esql_error_listener'; +import { AstListener } from '../ast_factory'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { builtinFunctions } from '../definitions/builtin'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import { chronoLiterals, timeLiterals } from '../definitions/literals'; +import { commandDefinitions } from '../definitions/commands'; + +const triggerCharacters = [',', '(', '=', ' ']; + +const fields = [ + ...['string', 'number', 'date', 'boolean', 'ip'].map((type) => ({ + name: `${type}Field`, + type, + })), + { name: 'any#Char$ field', type: 'number' }, + { name: 'kubernetes.something.something', type: 'number' }, + { + name: `listField`, + type: `list`, + }, +]; + +const indexes = ['a', 'index', 'otherIndex', '.secretIndex'].map((name) => ({ + name, + hidden: name.startsWith('.'), +})); +const policies = [ + { + name: 'policy', + sourceIndices: ['enrichIndex1'], + matchField: 'otherStringField', + enrichFields: ['otherField', 'yetAnotherField'], + }, +]; + +/** + * Utility to filter down the function list for the given type + * It is mainly driven by the return type, but it can be filtered upon with the last optional argument "paramsTypes" + * jsut make sure to pass the arguments in the right order + * @param command current command context + * @param expectedReturnType the expected type returned by the function + * @param functionCategories + * @param paramsTypes the function argument types (optional) + * @returns + */ +function getFunctionSignaturesByReturnType( + command: string, + expectedReturnType: string, + { agg, evalMath, builtin }: { agg?: boolean; evalMath?: boolean; builtin?: boolean } = {}, + paramsTypes?: string[], + ignored?: string[] +) { + const list = []; + if (agg) { + list.push(...statsAggregationFunctionDefinitions); + } + // eval functions (eval is a special keyword in JS) + if (evalMath) { + list.push(...evalFunctionsDefinitions); + } + if (builtin) { + list.push(...builtinFunctions); + } + return list + .filter(({ signatures, ignoreAsSuggestion, supportedCommands }) => { + if (ignoreAsSuggestion) { + return false; + } + if (!supportedCommands.includes(command)) { + return false; + } + const filteredByReturnType = signatures.some( + ({ returnType }) => expectedReturnType === 'any' || returnType === expectedReturnType + ); + if (!filteredByReturnType) { + return false; + } + if (paramsTypes?.length) { + return signatures.some(({ params }) => + paramsTypes.every( + (expectedType, i) => expectedType === 'any' || expectedType === params[i].type + ) + ); + } + return true; + }) + .filter(({ name }) => { + if (ignored?.length) { + return !ignored?.includes(name); + } + return true; + }) + .map(({ builtin: isBuiltinFn, name, signatures, ...defRest }) => + isBuiltinFn ? `${name} $0` : `${name}($0)` + ); +} + +function getFieldNamesByType(requestedType: string) { + return fields + .filter(({ type }) => requestedType === 'any' || type === requestedType) + .map(({ name }) => name); +} + +function getLiteralsByType(type: string) { + if (type === 'time_literal') { + // return only singular + return timeLiterals.map(({ name }) => `1 ${name}`).filter((s) => !/s$/.test(s)); + } + if (type === 'chrono_literal') { + return chronoLiterals.map(({ name }) => name); + } + return []; +} + +function createCustomCallbackMocks( + customFields: Array<{ name: string; type: string }> | undefined, + customSources: Array<{ name: string; hidden: boolean }> | undefined, + customPolicies: + | Array<{ + name: string; + sourceIndices: string[]; + matchField: string; + enrichFields: string[]; + }> + | undefined +) { + const finalFields = customFields || fields; + const finalSources = customSources || indexes; + const finalPolicies = customPolicies || policies; + return { + getFieldsFor: jest.fn(async () => finalFields), + getSources: jest.fn(async () => finalSources), + getPolicies: jest.fn(async () => finalPolicies), + }; +} + +function createModelAndPosition(text: string, offset: number) { + return { + model: { getValue: () => text } as monaco.editor.ITextModel, + position: { lineNumber: 1, column: offset } as monaco.Position, + }; +} + +function createSuggestContext(text: string, triggerCharacter?: string) { + if (triggerCharacter) { + return { triggerCharacter, triggerKind: 1 }; // any number is fine here + } + const foundTriggerCharIndexes = triggerCharacters.map((char) => text.lastIndexOf(char)); + const maxIndex = Math.max(...foundTriggerCharIndexes); + return { + triggerCharacter: text[maxIndex], + triggerKind: 1, + }; +} + +function getPolicyFields(policyName: string) { + return policies + .filter(({ name }) => name === policyName) + .flatMap(({ enrichFields }) => enrichFields); +} + +describe('autocomplete', () => { + const getAstAndErrors = async (text: string) => { + const errorListener = new ESQLErrorListener(); + const parseListener = new AstListener(); + const parser = getParser(CharStreams.fromString(text), errorListener, parseListener); + + parser[ROOT_STATEMENT](); + + return { ...parseListener.getAst(), errors: [] }; + }; + + type TestArgs = [ + string, + string[], + (string | number)?, + Parameters? + ]; + + const testSuggestionsFn = ( + statement: string, + expected: string[], + triggerCharacter: string | number = '', + customCallbacksArgs: Parameters = [ + undefined, + undefined, + undefined, + ], + { only, skip }: { only?: boolean; skip?: boolean } = {} + ) => { + const triggerCharacterString = + triggerCharacter == null || typeof triggerCharacter === 'string' + ? triggerCharacter + : statement[triggerCharacter + 1]; + const context = createSuggestContext(statement, triggerCharacterString); + const offset = + typeof triggerCharacter === 'string' + ? statement.lastIndexOf(context.triggerCharacter) + 2 + : triggerCharacter; + const testFn = only ? test.only : skip ? test.skip : test; + + testFn( + `${statement} (triggerChar: "${context.triggerCharacter}" @ ${offset})=> ["${expected.join( + '","' + )}"]`, + async () => { + const callbackMocks = createCustomCallbackMocks(...customCallbacksArgs); + const { model, position } = createModelAndPosition(statement, offset); + const suggestions = await suggest( + model, + position, + context, + async (text) => (text ? await getAstAndErrors(text) : { ast: [], errors: [] }), + callbackMocks + ); + expect(suggestions.map((i) => i.insertText)).toEqual(expected); + } + ); + }; + + // Enrich the function to work with .only and .skip as regular test function + const testSuggestions = Object.assign(testSuggestionsFn, { + skip: (...args: TestArgs) => { + const paddingArgs = ['', [undefined, undefined, undefined]].slice(args.length - 2); + return testSuggestionsFn( + ...((args.length > 1 ? [...args, ...paddingArgs] : args) as TestArgs), + { + skip: true, + } + ); + }, + only: (...args: TestArgs) => { + const paddingArgs = ['', [undefined, undefined, undefined]].slice(args.length - 2); + return testSuggestionsFn( + ...((args.length > 1 ? [...args, ...paddingArgs] : args) as TestArgs), + { + only: true, + } + ); + }, + }); + + const sourceCommands = ['row', 'from', 'show']; + + describe('New command', () => { + testSuggestions(' ', sourceCommands); + testSuggestions( + 'from a | ', + commandDefinitions + .filter(({ name }) => !sourceCommands.includes(name)) + .map(({ name }) => name) + ); + testSuggestions( + 'from a [metadata _id] | ', + commandDefinitions + .filter(({ name }) => !sourceCommands.includes(name)) + .map(({ name }) => name) + ); + testSuggestions( + 'from a | eval var0 = a | ', + commandDefinitions + .filter(({ name }) => !sourceCommands.includes(name)) + .map(({ name }) => name) + ); + testSuggestions( + 'from a [metadata _id] | eval var0 = a | ', + commandDefinitions + .filter(({ name }) => !sourceCommands.includes(name)) + .map(({ name }) => name) + ); + }); + + describe('from', () => { + const suggestedIndexes = indexes.filter(({ hidden }) => !hidden).map(({ name }) => name); + // Monaco will filter further down here + testSuggestions('f', sourceCommands); + testSuggestions('from ', suggestedIndexes); + testSuggestions('from a,', suggestedIndexes); + testSuggestions('from a, b ', ['[metadata $0 ]', '|', ',']); + testSuggestions('from *,', suggestedIndexes); + }); + + describe('where', () => { + const allEvalFns = getFunctionSignaturesByReturnType('where', 'any', { + evalMath: true, + }); + testSuggestions('from a | where ', [...getFieldNamesByType('any'), ...allEvalFns]); + testSuggestions('from a | eval var0 = 1 | where ', [ + ...getFieldNamesByType('any'), + ...allEvalFns, + 'var0', + ]); + testSuggestions('from a | where stringField ', [ + // all functions compatible with a stringField type + ...getFunctionSignaturesByReturnType( + 'where', + 'boolean', + { + builtin: true, + }, + ['string'] + ), + ]); + testSuggestions('from a | where stringField >= ', [ + ...getFieldNamesByType('string'), + ...getFunctionSignaturesByReturnType('where', 'string', { evalMath: true }), + ]); + testSuggestions('from a | where stringField >= stringField ', [ + ...getFunctionSignaturesByReturnType( + 'where', + 'boolean', + { + builtin: true, + }, + ['boolean'] + ), + '|', + ]); + for (const op of ['and', 'or']) { + testSuggestions(`from a | where stringField >= stringField ${op} `, [ + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('where', 'any', { evalMath: true }), + ]); + testSuggestions(`from a | where stringField >= stringField ${op} numberField `, [ + ...getFunctionSignaturesByReturnType('where', 'boolean', { builtin: true }, ['number']), + ]); + testSuggestions(`from a | where stringField >= stringField ${op} numberField == `, [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('where', 'number', { evalMath: true }), + ]); + } + testSuggestions('from a | stats a=avg(numberField) | where a ', [ + ...getFunctionSignaturesByReturnType('where', 'any', { builtin: true }, ['number']), + ]); + // Mind this test: suggestion is aware of previous commands when checking for fields + // in this case the numberField has been wiped by the STATS command and suggest cannot find it's type + // @TODO: verify this is the correct behaviour in this case or if we want a "generic" suggestion anyway + testSuggestions( + 'from a | stats a=avg(numberField) | where numberField ', + [], + '', + // make the fields suggest aware of the previous STATS, leave the other callbacks untouched + [[{ name: 'a', type: 'number' }], undefined, undefined] + ); + // The editor automatically inject the final bracket, so it is not useful to test with just open bracket + testSuggestions( + 'from a | where log10()', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('where', 'number', { evalMath: true }, undefined, [ + 'log10', + ]), + ], + '(' + ); + testSuggestions('from a | where log10(numberField) ', [ + ...getFunctionSignaturesByReturnType('where', 'number', { builtin: true }, ['number']), + ...getFunctionSignaturesByReturnType('where', 'boolean', { builtin: true }, ['number']), + ]); + testSuggestions( + 'from a | WHERE pow(numberField, )', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('where', 'number', { evalMath: true }, undefined, [ + 'pow', + ]), + ], + ',' + ); + }); + + describe('sort', () => { + testSuggestions('from a | sort ', getFieldNamesByType('any')); + testSuggestions('from a | sort stringField ', ['asc', 'desc', '|', ',']); + testSuggestions('from a | sort stringField desc ', ['nulls first', 'nulls last', '|', ',']); + // @TODO: improve here + // testSuggestions('from a | sort stringField desc ', ['first', 'last']); + }); + + describe('limit', () => { + testSuggestions('from a | limit ', ['10', '100', '1000']); + testSuggestions('from a | limit 4 ', ['|']); + }); + + describe('mv_expand', () => { + testSuggestions('from a | mv_expand ', ['listField']); + testSuggestions('from a | mv_expand a ', ['|']); + }); + + describe('rename', () => { + testSuggestions('from a | rename ', getFieldNamesByType('any')); + testSuggestions('from a | rename stringField ', ['as']); + testSuggestions('from a | rename stringField as ', ['var0']); + }); + + for (const command of ['keep', 'drop', 'project']) { + describe(command, () => { + testSuggestions(`from a | ${command} `, getFieldNamesByType('any')); + testSuggestions( + `from a | ${command} stringField, `, + getFieldNamesByType('any').filter((name) => name !== 'stringField') + ); + }); + } + + describe('stats', () => { + const allAggFunctions = getFunctionSignaturesByReturnType('stats', 'any', { + agg: true, + }); + testSuggestions('from a | stats ', ['var0 =', ...allAggFunctions]); + testSuggestions('from a | stats a ', ['= $0']); + testSuggestions('from a | stats a=', [...allAggFunctions]); + testSuggestions('from a | stats a=max(b) by ', getFieldNamesByType('any')); + testSuggestions('from a | stats a=max(b) BY ', getFieldNamesByType('any')); + testSuggestions('from a | stats a=c by d ', ['|', ',']); + testSuggestions('from a | stats a=c by d, ', getFieldNamesByType('any')); + testSuggestions('from a | stats a=max(b), ', ['var0 =', ...allAggFunctions]); + testSuggestions( + 'from a | stats a=min()', + fields.filter(({ type }) => type === 'number').map(({ name }) => name), + '(' + ); + testSuggestions('from a | stats a=min(b) ', ['by', '|', ',']); + testSuggestions('from a | stats a=min(b) by ', getFieldNamesByType('any')); + testSuggestions('from a | stats a=min(b),', ['var0 =', ...allAggFunctions]); + testSuggestions('from a | stats var0=min(b),var1=c,', ['var2 =', ...allAggFunctions]); + testSuggestions( + 'from a | stats a=min(b), b=max()', + fields.filter(({ type }) => type === 'number').map(({ name }) => name) + ); + // @TODO: remove last 2 suggestions if possible + testSuggestions('from a | eval var0=round(b), var1=round(c) | stats ', [ + 'var2 =', + ...allAggFunctions, + 'var0', + 'var1', + ]); + + // smoke testing with suggestions not at the end of the string + testSuggestions( + 'from a | stats a = min(b) | sort b', + ['by', '|', ','], + 27 /* " " after min(b) */ + ); + testSuggestions( + 'from a | stats avg(b) by stringField', + getFieldNamesByType('number'), + 21 /* b column in avg */ + ); + }); + + describe('enrich', () => { + for (const prevCommand of [ + '', + '| enrich other-policy ', + '| enrich other-policy on b ', + '| enrich other-policy with c ', + ]) { + testSuggestions(`from a ${prevCommand}| enrich `, ['policy']); + testSuggestions(`from a ${prevCommand}| enrich policy `, ['on', 'with', '|']); + testSuggestions(`from a ${prevCommand}| enrich policy on `, [ + 'stringField', + 'numberField', + 'dateField', + 'booleanField', + 'ipField', + 'any#Char$ field', + 'kubernetes.something.something', + 'listField', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b `, ['with', '|', ',']); + testSuggestions(`from a ${prevCommand}| enrich policy on b with `, [ + 'var0 =', + ...getPolicyFields('policy'), + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 `, ['= $0', '|', ',']); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = `, [ + ...getPolicyFields('policy'), + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = stringField `, [ + '|', + ',', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = stringField, `, [ + 'var1 =', + ...getPolicyFields('policy'), + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = stringField, var1 `, [ + '= $0', + '|', + ',', + ]); + testSuggestions( + `from a ${prevCommand}| enrich policy on b with var0 = stringField, var1 = `, + [...getPolicyFields('policy')] + ); + testSuggestions(`from a ${prevCommand}| enrich policy with `, [ + 'var0 =', + ...getPolicyFields('policy'), + ]); + testSuggestions(`from a ${prevCommand}| enrich policy with stringField `, ['= $0', '|', ',']); + } + }); + + describe('eval', () => { + testSuggestions('from a | eval ', [ + 'var0 =', + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + ]); + testSuggestions('from a | eval numberField ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + '|', + ',', + ]); + testSuggestions('from a | eval a=', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + ]); + testSuggestions('from a | eval a=abs(numberField), b= ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + ]); + testSuggestions('from a | eval a=numberField, ', [ + 'var0 =', + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + 'a', + ]); + testSuggestions( + 'from a | eval a=round()', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }, undefined, [ + 'round', + ]), + ], + '(' + ); + testSuggestions('from a | eval a=round(numberField) ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + '|', + ',', + ]); + testSuggestions('from a | eval a=round(numberField),', [ + 'var0 =', + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + 'a', + ]); + testSuggestions('from a | eval a=round(numberField) + ', [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }), + 'a', // @TODO remove this + ]); + testSuggestions( + 'from a | stats avg(numberField) by stringField | eval ', + [ + 'var0 =', + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + '`avg(numberField)`', + ], + ' ', + // make aware EVAL of the previous STATS command + [[], undefined, undefined] + ); + testSuggestions( + 'from a | eval abs(numberField) + 1 | eval ', + [ + 'var0 =', + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + // @TODO: leverage the location data to get the original text + // For now return back the trimmed version: + // the ANTLR parser trims all text so that's what it's stored in the AST + '`abs(numberField)+1`', + ], + ' ' + ); + testSuggestions( + 'from a | stats avg(numberField) by stringField | eval ', + [ + 'var0 =', + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + '`avg(numberField)`', + ], + ' ', + // make aware EVAL of the previous STATS command with the buggy field name from expression + [[{ name: 'avg_numberField_', type: 'number' }], undefined, undefined] + ); + testSuggestions( + 'from a | stats avg(numberField), avg(kubernetes.something.something) by stringField | eval ', + [ + 'var0 =', + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + '`avg(numberField)`', + '`avg(kubernetes.something.something)`', + ], + ' ', + // make aware EVAL of the previous STATS command with the buggy field name from expression + [ + [ + { name: 'avg_numberField_', type: 'number' }, + { name: 'avg_kubernetes.something.something_', type: 'number' }, + ], + undefined, + undefined, + ] + ); + testSuggestions( + 'from a | eval a=round(numberField), b=round()', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }, undefined, [ + 'round', + ]), + ], + '(' + ); + // test deep function nesting suggestions (and check that the same function is not suggested) + // round(round( + // round(round(round( + // etc... + for (const nesting of [1, 2, 3, 4]) { + testSuggestions( + `from a | eval a=${Array(nesting).fill('round(').join('')}`, + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }, undefined, [ + 'round', + ]), + ], + '(' + ); + } + + // Smoke testing for suggestions in previous position than the end of the statement + testSuggestions( + 'from a | eval var0 = abs(numberField) | eval abs(var0)', + [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + '|', + ',', + ], + 38 /* " " after abs(b) */ + ); + testSuggestions( + 'from a | eval var0 = abs(b) | eval abs(var0)', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }, undefined, [ + 'abs', + ]), + ], + 26 /* b column in abs */ + ); + + // Test suggestions for each possible param, within each signature variation, for each function + for (const fn of evalFunctionsDefinitions) { + // skip this fn for the moment as it's quite hard to test + if (fn.name !== 'auto_bucket') { + for (const signature of fn.signatures) { + signature.params.forEach((param, i) => { + if (i < signature.params.length - 1) { + const canHaveMoreArgs = + signature.params.filter(({ optional }, j) => !optional && j > i).length > i; + testSuggestions( + `from a | eval ${fn.name}(${Array(i).fill('field').join(', ')}${i ? ',' : ''} )`, + [ + ...getFieldNamesByType(param.type).map((f) => (canHaveMoreArgs ? `${f},` : f)), + ...getFunctionSignaturesByReturnType( + 'eval', + param.type, + { evalMath: true }, + undefined, + [fn.name] + ).map((l) => (canHaveMoreArgs ? `${l},` : l)), + ...getLiteralsByType(param.type).map((d) => (canHaveMoreArgs ? `${d},` : d)), + ] + ); + testSuggestions( + `from a | eval var0 = ${fn.name}(${Array(i).fill('field').join(', ')}${ + i ? ',' : '' + } )`, + [ + ...getFieldNamesByType(param.type).map((f) => (canHaveMoreArgs ? `${f},` : f)), + ...getFunctionSignaturesByReturnType( + 'eval', + param.type, + { evalMath: true }, + undefined, + [fn.name] + ).map((l) => (canHaveMoreArgs ? `${l},` : l)), + ...getLiteralsByType(param.type).map((d) => (canHaveMoreArgs ? `${d},` : d)), + ] + ); + } + }); + } + } + } + + describe('date math', () => { + const dateSuggestions = timeLiterals.map(({ name }) => name); + // If a literal number is detected then suggest also date period keywords + testSuggestions('from a | eval a = 1 ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + ...dateSuggestions, + '|', + ',', + ]); + testSuggestions('from a | eval a = 1 year ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['time_interval']), + '|', + ',', + ]); + testSuggestions('from a | eval a = 1 day + 2 ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + ...dateSuggestions, + '|', + ',', + ]); + testSuggestions( + 'from a | eval var0=date_trunc()', + [...getLiteralsByType('time_literal').map((t) => `${t},`)], + '(' + ); + testSuggestions('from a | eval var0=date_trunc(2 )', [ + ...dateSuggestions.map((t) => `${t},`), + ',', + ]); + }); + }); + + describe('callbacks', () => { + it('should send the fields query without the last command', async () => { + const callbackMocks = createCustomCallbackMocks(undefined, undefined, undefined); + const statement = 'from a | drop stringField | eval var0 = abs(numberField) '; + const triggerOffset = statement.lastIndexOf(' '); + const context = createSuggestContext(statement, statement[triggerOffset]); + const { model, position } = createModelAndPosition(statement, triggerOffset + 2); + await suggest( + model, + position, + context, + async (text) => (text ? await getAstAndErrors(text) : { ast: [], errors: [] }), + callbackMocks + ); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledWith({ + query: 'from a | drop stringField', + }); + }); + it('should send the fields query aware of the location', async () => { + const callbackMocks = createCustomCallbackMocks(undefined, undefined, undefined); + const statement = 'from a | drop | eval var0 = abs(numberField) '; + const triggerOffset = statement.lastIndexOf('p') + 1; // drop + const context = createSuggestContext(statement, statement[triggerOffset]); + const { model, position } = createModelAndPosition(statement, triggerOffset + 2); + await suggest( + model, + position, + context, + async (text) => (text ? await getAstAndErrors(text) : { ast: [], errors: [] }), + callbackMocks + ); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledWith({ query: 'from a' }); + }); + }); +}); diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.ts new file mode 100644 index 0000000000000..de1b07b39bed5 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.ts @@ -0,0 +1,1098 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import uniqBy from 'lodash/uniqBy'; +import type { monaco } from '../../../../monaco_imports'; +import type { AutocompleteCommandDefinition } from './types'; +import { nonNullable } from '../ast_helpers'; +import { + columnExists, + getColumnHit, + getCommandDefinition, + getCommandOption, + getFunctionDefinition, + isAssignment, + isAssignmentComplete, + isColumnItem, + isFunctionItem, + isIncompleteItem, + isLiteralItem, + isOptionItem, + isRestartingExpression, + isSourceItem, + isTimeIntervalItem, + monacoPositionToOffset, +} from '../shared/helpers'; +import { collectVariables, excludeVariablesFromCurrentCommand } from '../shared/variables'; +import type { + AstProviderFn, + ESQLAst, + ESQLAstItem, + ESQLCommand, + ESQLCommandOption, + ESQLFunction, + ESQLSingleAstItem, +} from '../types'; +import type { ESQLPolicy, ESQLRealField, ESQLVariable, ReferenceMaps } from '../validation/types'; +import { + commaCompleteItem, + commandAutocompleteDefinitions, + getAssignmentDefinitionCompletitionItem, + getBuiltinCompatibleFunctionDefinition, + mathCommandDefinition, + pipeCompleteItem, +} from './complete_items'; +import { + buildFieldsDefinitions, + buildPoliciesDefinitions, + buildSourcesDefinitions, + buildNewVarDefinition, + buildNoPoliciesAvailableDefinition, + getCompatibleFunctionDefinition, + buildMatchingFieldsDefinition, + getCompatibleLiterals, + buildConstantsDefinitions, + buildVariablesDefinitions, + buildOptionDefinition, + TRIGGER_SUGGESTION_COMMAND, +} from './factories'; +import { EDITOR_MARKER } from '../shared/constants'; +import { getAstContext, removeMarkerArgFromArgsList } from '../shared/context'; +import { + getFieldsByTypeHelper, + getPolicyHelper, + getSourcesHelper, +} from '../shared/resources_helpers'; +import { ESQLCallbacks } from '../shared/types'; + +type GetSourceFn = () => Promise; +type GetFieldsByTypeFn = ( + type: string | string[], + ignored?: string[] +) => Promise; +type GetFieldsMapFn = () => Promise>; +type GetPoliciesFn = () => Promise; +type GetPolicyMetadataFn = (name: string) => Promise; + +function hasSameArgBothSides(assignFn: ESQLFunction) { + if (assignFn.name === '=' && isColumnItem(assignFn.args[0]) && assignFn.args[1]) { + const assignValue = assignFn.args[1]; + if (Array.isArray(assignValue) && isColumnItem(assignValue[0])) { + return assignFn.args[0].name === assignValue[0].name; + } + } +} + +function appendEnrichFields( + fieldsMap: Map, + policyMetadata: ESQLPolicy | undefined +) { + if (!policyMetadata) { + return fieldsMap; + } + // @TODO: improve this + const newMap: Map = new Map(fieldsMap); + for (const field of policyMetadata.enrichFields) { + newMap.set(field, { name: field, type: 'number' }); + } + return newMap; +} + +function getFinalSuggestions({ comma }: { comma?: boolean } = { comma: true }) { + const finalSuggestions = [pipeCompleteItem]; + if (comma) { + finalSuggestions.push(commaCompleteItem); + } + return finalSuggestions; +} + +function isMathFunction(char: string) { + return ['+', '-', '*', '/', '%', '='].some((op) => char === op); +} + +function isComma(char: string) { + return char === ','; +} + +function isSourceCommand({ label }: AutocompleteCommandDefinition) { + return ['from', 'row', 'show'].includes(String(label)); +} +/** + * This function count the number of unclosed brackets in order to + * locally fix the queryString to generate a valid AST + * A known limitation of this is that is not aware of commas "," or pipes "|" + * so it is not yet helpful on a multiple commands errors (a workaround it to pass each command here...) + * @param bracketType + * @param text + * @returns + */ +function countBracketsUnclosed(bracketType: '(' | '[', text: string) { + const stack = []; + const closingBrackets = { '(': ')', '[': ']' }; + for (const char of text) { + if (char === bracketType) { + stack.push(bracketType); + } else if (char === closingBrackets[bracketType]) { + stack.pop(); + } + } + return stack.length; +} + +export async function suggest( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.CompletionContext, + astProvider: AstProviderFn, + resourceRetriever?: ESQLCallbacks +): Promise { + // take the full text but then slice it to the current position + const fullText = model.getValue(); + const offset = monacoPositionToOffset(fullText, position); + const innerText = fullText.substring(0, offset); + + let finalText = innerText; + + // check if all brackets are closed, otherwise close them + const unclosedBrackets = countBracketsUnclosed('(', finalText); + // if it's a comma by the user or a forced trigger by a function argument suggestion + // add a marker to make the expression still valid + if ( + context.triggerCharacter === ',' || + (context.triggerKind === 0 && unclosedBrackets === 0) || + (context.triggerCharacter === ' ' && + // make this more robust + (isMathFunction(innerText[offset - 2]) || isComma(innerText[offset - 2]))) + ) { + finalText = `${innerText.substring(0, offset)}${EDITOR_MARKER}${innerText.substring(offset)}`; + } + if (unclosedBrackets > 0) { + // inject the closing brackets + finalText += Array(unclosedBrackets).fill(')').join(''); + } + + const { ast } = await astProvider(finalText); + + const astContext = getAstContext(innerText, ast, offset); + // build the correct query to fetch the list of fields + const queryForFields = buildQueryForFields(ast, finalText); + const { getFieldsByType, getFieldsMap } = getFieldsByTypeRetriever( + queryForFields, + resourceRetriever + ); + const getSources = getSourcesRetriever(resourceRetriever); + const { getPolicies, getPolicyMetadata } = getPolicyRetriever(resourceRetriever); + + if (astContext.type === 'newCommand') { + // propose main commands here + // filter source commands if already defined + const suggestions = commandAutocompleteDefinitions; + if (!ast.length) { + return suggestions.filter(isSourceCommand); + } + return suggestions.filter((def) => !isSourceCommand(def)); + } + + if (astContext.type === 'expression') { + // suggest next possible argument, or option + // otherwise a variable + return getExpressionSuggestionsByType( + innerText, + ast, + astContext, + getSources, + getFieldsByType, + getFieldsMap, + getPolicies, + getPolicyMetadata + ); + } + if (astContext.type === 'option') { + // need this wrap/unwrap thing to make TS happy + const { option, ...rest } = astContext; + if (option && isOptionItem(option)) { + return getOptionArgsSuggestions( + innerText, + ast, + { option, ...rest }, + getFieldsByType, + getFieldsMap, + getPolicyMetadata + ); + } + } + if (astContext.type === 'function') { + return getFunctionArgsSuggestions( + innerText, + ast, + astContext, + getFieldsByType, + getFieldsMap, + getPolicyMetadata + ); + } + return []; +} + +export function buildQueryForFields(ast: ESQLAst, queryString: string) { + const prevCommand = ast[Math.max(ast.length - 2, 0)]; + return prevCommand ? queryString.substring(0, prevCommand.location.max + 1) : queryString; +} + +function getFieldsByTypeRetriever(queryString: string, resourceRetriever?: ESQLCallbacks) { + const helpers = getFieldsByTypeHelper(queryString, resourceRetriever); + return { + getFieldsByType: async (expectedType: string | string[] = 'any', ignored: string[] = []) => { + const fields = await helpers.getFieldsByType(expectedType, ignored); + return buildFieldsDefinitions(fields); + }, + getFieldsMap: helpers.getFieldsMap, + }; +} + +function getPolicyRetriever(resourceRetriever?: ESQLCallbacks) { + const helpers = getPolicyHelper(resourceRetriever); + return { + getPolicies: async () => { + const policies = await helpers.getPolicies(); + return buildPoliciesDefinitions(policies); + }, + getPolicyMetadata: helpers.getPolicyMetadata, + }; +} + +function getSourcesRetriever(resourceRetriever?: ESQLCallbacks) { + const helper = getSourcesHelper(resourceRetriever); + return async () => { + const list = (await helper()) || []; + // hide indexes that start with . + return buildSourcesDefinitions(list.filter(({ hidden }) => !hidden).map(({ name }) => name)); + }; +} + +function findNewVariable(variables: Map) { + let autoGeneratedVariableCounter = 0; + let name = `var${autoGeneratedVariableCounter++}`; + while (variables.has(name)) { + name = `var${autoGeneratedVariableCounter++}`; + } + return name; +} + +function areCurrentArgsValid( + command: ESQLCommand, + node: ESQLAstItem, + references: Pick +) { + // unfortunately here we need to bake some command-specific logic + if (command.name === 'stats') { + if (node) { + // consider the following expressions not complete yet + // ... | stats a + // ... | stats a = + if (isColumnItem(node) || (isAssignment(node) && !isAssignmentComplete(node))) { + return false; + } + } + } + if (command.name === 'eval') { + if (node) { + if (isFunctionItem(node)) { + if (isAssignment(node)) { + return isAssignmentComplete(node); + } else { + return isFunctionArgComplete(node, references).complete; + } + } + } + } + if (command.name === 'where') { + if (node) { + if ( + isColumnItem(node) || + (isFunctionItem(node) && !isFunctionArgComplete(node, references).complete) + ) { + return false; + } else { + return ( + extractFinalTypeFromArg(node, references) === + getCommandDefinition(command.name).signature.params[0].type + ); + } + } + } + if (command.name === 'rename') { + if (node) { + if (isColumnItem(node)) { + return true; + } + } + } + return true; +} + +function extractFinalTypeFromArg( + arg: ESQLAstItem, + references: Pick +): string | undefined { + if (Array.isArray(arg)) { + return extractFinalTypeFromArg(arg[0], references); + } + if (isColumnItem(arg) || isLiteralItem(arg)) { + if (isLiteralItem(arg)) { + return arg.literalType; + } + if (isColumnItem(arg)) { + const hit = getColumnHit(arg.name, references); + if (hit) { + return hit.type; + } + } + } + if (isTimeIntervalItem(arg)) { + return arg.type; + } + if (isFunctionItem(arg)) { + const fnDef = getFunctionDefinition(arg.name); + if (fnDef) { + // @TODO: improve this to better filter down the correct return type based on existing arguments + // just mind that this can be highly recursive... + return fnDef.signatures[0].returnType; + } + } +} + +// @TODO: refactor this to be shared with validation +function isFunctionArgComplete( + arg: ESQLFunction, + references: Pick +) { + const fnDefinition = getFunctionDefinition(arg.name)!; + const cleanedArgs = removeMarkerArgFromArgsList(arg)!.args; + const argLengthCheck = fnDefinition.signatures.some((def) => { + if (def.infiniteParams && cleanedArgs.length > 0) { + return true; + } + if (def.minParams && cleanedArgs.length >= def.minParams) { + return true; + } + if (cleanedArgs.length === def.params.length) { + return true; + } + return cleanedArgs.length >= def.params.filter(({ optional }) => !optional).length; + }); + if (!argLengthCheck) { + return { complete: false, reason: 'fewArgs' }; + } + const hasCorrectTypes = fnDefinition.signatures.some((def) => { + return arg.args.every((a, index) => { + if (def.infiniteParams) { + return true; + } + return def.params[index].type === extractFinalTypeFromArg(a, references); + }); + }); + if (!hasCorrectTypes) { + return { complete: false, reason: 'wrongTypes' }; + } + return { complete: true }; +} + +async function getExpressionSuggestionsByType( + innerText: string, + commands: ESQLCommand[], + { + command, + node, + }: { + command: ESQLCommand; + node: ESQLSingleAstItem | undefined; + }, + getSources: GetSourceFn, + getFieldsByType: GetFieldsByTypeFn, + getFieldsMap: GetFieldsMapFn, + getPolicies: GetPoliciesFn, + getPolicyMetadata: GetPolicyMetadataFn +) { + const commandDef = getCommandDefinition(command.name); + // get the argument position + let argIndex = command.args.length; + const prevIndex = Math.max(argIndex - 1, 0); + const lastArg = removeMarkerArgFromArgsList(command)!.args[prevIndex]; + if (isIncompleteItem(lastArg)) { + argIndex = prevIndex; + } + + // if a node is not specified use the lastArg + // mind to give priority to node as lastArg might be a function root + // => "a > b and c == d" gets translated into and( gt(a, b) , eq(c, d) ) => hence "and" is lastArg + const nodeArg = node || lastArg; + // A new expression is considered either + // * just after a command name => i.e. ... | STATS + // * or after a comma => i.e. STATS fieldA, + const isNewExpression = isRestartingExpression(innerText) || argIndex === 0; + + // Are options already declared? This is useful to suggest only new ones + const optionsAlreadyDeclared = ( + command.args.filter((arg) => isOptionItem(arg)) as ESQLCommandOption[] + ).map(({ name }) => ({ + name, + index: commandDef.options.findIndex(({ name: defName }) => defName === name), + })); + const optionsAvailable = commandDef.options.filter(({ name }, index) => { + const optArg = optionsAlreadyDeclared.find(({ name: optionName }) => optionName === name); + return (!optArg && !optionsAlreadyDeclared.length) || (optArg && index > optArg.index); + }); + // get the next definition for the given command + let argDef = commandDef.signature.params[argIndex]; + // tune it for the variadic case + if (!argDef) { + // this is the case of a comma argument + if (commandDef.signature.multipleParams) { + if (isNewExpression || (isAssignment(lastArg) && !isAssignmentComplete(lastArg))) { + // i.e. ... | a, + // i.e. ... | a = ..., b = + argDef = commandDef.signature.params[0]; + } + } + + // this is the case where there's an argument, but it's of the wrong type + // i.e. ... | WHERE numberField (WHERE wants a boolean expression!) + // i.e. ... | STATS numberfield (STATS wants a function expression!) + if (!isNewExpression && nodeArg && !Array.isArray(nodeArg)) { + const prevArg = commandDef.signature.params[prevIndex]; + // in some cases we do not want to go back as the command only accepts a literal + // i.e. LIMIT 5 -> that's it, so no argDef should be assigned + + // make an exception for STATS (STATS is the only command who accept a function type as arg) + if ( + prevArg && + (prevArg.type === 'function' || (!Array.isArray(nodeArg) && prevArg.type !== nodeArg.type)) + ) { + if (!isLiteralItem(nodeArg) || !prevArg.literalOnly) { + argDef = prevArg; + } + } + } + } + + // collect all fields + variables to suggest + const fieldsMap: Map = await (argDef ? getFieldsMap() : new Map()); + const anyVariables = collectVariables(commands, fieldsMap); + + // enrich with assignment has some special rules who are handled somewhere else + const canHaveAssignments = ['eval', 'stats', 'row'].includes(command.name); + + const references = { fields: fieldsMap, variables: anyVariables }; + + const suggestions: AutocompleteCommandDefinition[] = []; + + // in this flow there's a clear plan here from argument definitions so try to follow it + if (argDef) { + if (argDef.type === 'column' || argDef.type === 'any' || argDef.type === 'function') { + if (isNewExpression && canHaveAssignments) { + // i.e. + // ... | ROW + // ... | STATS + // ... | STATS ..., + // ... | EVAL + // ... | EVAL ..., + suggestions.push(buildNewVarDefinition(findNewVariable(anyVariables))); + } + } + // Suggest fields or variables + if (argDef.type === 'column' || argDef.type === 'any') { + // ... | + if (!nodeArg || (isNewExpression && commandDef.signature.multipleParams)) { + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + [argDef.innerType || 'any'], + command.name, + getFieldsByType, + { + functions: canHaveAssignments, + fields: true, + variables: anyVariables, + }, + { + ignoreFields: isNewExpression + ? command.args.filter(isColumnItem).map(({ name }) => name) + : [], + } + )) + ); + } + } + if (argDef.type === 'function' || argDef.type === 'any') { + if (isColumnItem(nodeArg)) { + // ... | STATS a + // ... | EVAL a + const nodeArgType = extractFinalTypeFromArg(nodeArg, references); + if (nodeArgType) { + suggestions.push(...getBuiltinCompatibleFunctionDefinition(command.name, nodeArgType)); + } else { + suggestions.push(getAssignmentDefinitionCompletitionItem()); + } + } + if (isNewExpression || (isAssignment(nodeArg) && !isAssignmentComplete(nodeArg))) { + // ... | STATS a = + // ... | EVAL a = + // ... | STATS a = ..., + // ... | EVAL a = ..., + // ... | STATS a = ..., b = + // ... | EVAL a = ..., b = + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions(['any'], command.name, getFieldsByType, { + functions: true, + fields: false, + variables: nodeArg ? undefined : anyVariables, + })) + ); + } + } + + if (argDef.type === 'any') { + // ... | EVAL var = field + // ... | EVAL var = fn(field) + // make sure we're still in the same assignment context and there's no comma (newExpression ensures that) + if (!isNewExpression) { + if (isAssignment(nodeArg) && isAssignmentComplete(nodeArg)) { + const [rightArg] = nodeArg.args[1] as [ESQLSingleAstItem]; + const nodeArgType = extractFinalTypeFromArg(rightArg, references); + suggestions.push( + ...getBuiltinCompatibleFunctionDefinition(command.name, nodeArgType || 'any') + ); + if (nodeArgType === 'number' && isLiteralItem(rightArg)) { + // ... EVAL var = 1 + suggestions.push(...getCompatibleLiterals(command.name, ['time_literal_unit'])); + } + if (isFunctionItem(rightArg)) { + if (rightArg.args.some(isTimeIntervalItem)) { + const lastFnArg = rightArg.args[rightArg.args.length - 1]; + const lastFnArgType = extractFinalTypeFromArg(lastFnArg, references); + if (lastFnArgType === 'number' && isLiteralItem(lastFnArg)) + // ... EVAL var = 1 year + 2 + suggestions.push(...getCompatibleLiterals(command.name, ['time_literal_unit'])); + } + } + } else { + if (isFunctionItem(nodeArg)) { + const nodeArgType = extractFinalTypeFromArg(nodeArg, references); + suggestions.push( + ...(await getBuiltinFunctionNextArgument( + command, + argDef, + nodeArg, + nodeArgType || 'any', + references, + getFieldsByType + )) + ); + if (nodeArg.args.some(isTimeIntervalItem)) { + const lastFnArg = nodeArg.args[nodeArg.args.length - 1]; + const lastFnArgType = extractFinalTypeFromArg(lastFnArg, references); + if (lastFnArgType === 'number' && isLiteralItem(lastFnArg)) + // ... EVAL var = 1 year + 2 + suggestions.push(...getCompatibleLiterals(command.name, ['time_literal_unit'])); + } + } + } + } + } + + // if the definition includes a list of constants, suggest them + if (argDef.values) { + // ... | ... + suggestions.push(...buildConstantsDefinitions(argDef.values)); + } + // If the type is specified try to dig deeper in the definition to suggest the best candidate + if (['string', 'number', 'boolean'].includes(argDef.type) && !argDef.values) { + // it can be just literal values (i.e. "string") + if (argDef.literalOnly) { + // ... | ... + suggestions.push(...getCompatibleLiterals(command.name, [argDef.type], [argDef.name])); + } else { + // or it can be anything else as long as it is of the right type and the end (i.e. column or function) + if (!nodeArg) { + // ... | + // In this case start suggesting something not strictly based on type + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions(['any'], command.name, getFieldsByType, { + functions: true, + fields: true, + variables: anyVariables, + })) + ); + } else { + // if something is already present, leverage its type to suggest something in context + const nodeArgType = extractFinalTypeFromArg(nodeArg, references); + // These cases can happen here, so need to identify each and provide the right suggestion + // i.e. ... | field + // i.e. ... | field + + // i.e. ... | field >= + // i.e. ... | field > 0 + // i.e. ... | field + otherN + + if (nodeArgType) { + if (isFunctionItem(nodeArg)) { + suggestions.push( + ...(await getBuiltinFunctionNextArgument( + command, + argDef, + nodeArg, + nodeArgType, + references, + getFieldsByType + )) + ); + } else { + // i.e. ... | field + suggestions.push( + ...getBuiltinCompatibleFunctionDefinition(command.name, nodeArgType) + ); + } + } + } + } + } + if (argDef.type === 'source') { + if (argDef.innerType === 'policy') { + // ... | ENRICH + const policies = await getPolicies(); + suggestions.push(...(policies.length ? policies : [buildNoPoliciesAvailableDefinition()])); + } else { + // FROM + // @TODO: filter down the suggestions here based on other existing sources defined + suggestions.push(...(await getSources())); + } + } + } + + const nonOptionArgs = command.args.filter( + (arg) => !isOptionItem(arg) && !Array.isArray(arg) && !arg.incomplete + ); + // Perform some checks on mandatory arguments + const mandatoryArgsAlreadyPresent = + (commandDef.signature.multipleParams && nonOptionArgs.length > 1) || + nonOptionArgs.length >= + commandDef.signature.params.filter(({ optional }) => !optional).length || + argDef?.type === 'function'; + + // check if declared args are fully valid for the given command + const currentArgsAreValidForCommand = areCurrentArgsValid(command, nodeArg, references); + + // latest suggestions: options and final ones + if ( + (!isNewExpression && mandatoryArgsAlreadyPresent && currentArgsAreValidForCommand) || + optionsAlreadyDeclared.length + ) { + // suggest some command options + if (optionsAvailable.length) { + suggestions.push(...optionsAvailable.map(buildOptionDefinition)); + } + + if (!optionsAvailable.length || optionsAvailable.every(({ optional }) => optional)) { + // now suggest pipe or comma + suggestions.push( + ...getFinalSuggestions({ + comma: + commandDef.signature.multipleParams && + optionsAvailable.length === commandDef.options.length, + }) + ); + } + } + // Due to some logic overlapping functions can be repeated + // so dedupe here based on insertText string (it can differ from name) + return uniqBy(suggestions, (suggestion) => suggestion.insertText); +} + +async function getBuiltinFunctionNextArgument( + command: ESQLCommand, + argDef: { type: string }, + nodeArg: ESQLFunction, + nodeArgType: string, + references: Pick, + getFieldsByType: GetFieldsByTypeFn +) { + const suggestions = []; + const isFnComplete = isFunctionArgComplete(nodeArg, references); + if (isFnComplete.complete) { + // i.e. ... | field > 0 + // i.e. ... | field + otherN + suggestions.push(...getBuiltinCompatibleFunctionDefinition(command.name, nodeArgType || 'any')); + } else { + // i.e. ... | field >= + // i.e. ... | field + + // i.e. ... | field and + + // Because it's an incomplete function, need to extract the type of the current argument + // and suggest the next argument based on types + + // pick the last arg and check its type to verify whether is incomplete for the given function + const cleanedArgs = removeMarkerArgFromArgsList(nodeArg)!.args; + const nestedType = extractFinalTypeFromArg(nodeArg.args[cleanedArgs.length - 1], references); + + if (isFnComplete.reason === 'fewArgs') { + const finalType = nestedType || nodeArgType || 'any'; + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + // this is a special case with AND/OR + // expression AND/OR + // technically another boolean value should be suggested, but it is a better experience + // to actually suggest a wider set of fields/functions + [ + finalType === 'boolean' && getFunctionDefinition(nodeArg.name)?.builtin + ? 'any' + : finalType, + ], + command.name, + getFieldsByType, + { + functions: true, + fields: true, + variables: references.variables, + } + )) + ); + } + if (isFnComplete.reason === 'wrongTypes') { + if (nestedType) { + // suggest something to complete the builtin function + if (nestedType !== argDef.type) { + suggestions.push( + ...getBuiltinCompatibleFunctionDefinition(command.name, nestedType, [argDef.type]) + ); + } + } + } + } + return suggestions; +} + +async function getFieldsOrFunctionsSuggestions( + types: string[], + commandName: string, + getFieldsByType: GetFieldsByTypeFn, + { + functions, + fields, + variables, + }: { + functions: boolean; + fields: boolean; + variables?: Map; + }, + { + ignoreFn = [], + ignoreFields = [], + }: { + ignoreFn?: string[]; + ignoreFields?: string[]; + } = {} +): Promise { + const filteredFieldsByType = (await (fields + ? getFieldsByType(types, ignoreFields) + : [])) as AutocompleteCommandDefinition[]; + + const filteredVariablesByType: string[] = []; + if (variables) { + for (const variable of variables.values()) { + if (types.includes('any') || types.includes(variable[0].type)) { + filteredVariablesByType.push(variable[0].name); + } + } + // due to a bug on the ES|QL table side, filter out fields list with underscored variable names (??) + // avg( numberField ) => avg_numberField_ + if ( + filteredVariablesByType.length && + filteredVariablesByType.some((v) => /[^a-zA-Z\d]/.test(v)) + ) { + for (const variable of filteredVariablesByType) { + const underscoredName = variable.replace(/[^a-zA-Z\d]/g, '_'); + const index = filteredFieldsByType.findIndex(({ label }) => underscoredName === label); + if (index >= 0) { + filteredFieldsByType.splice(index); + } + } + } + } + + const suggestions = filteredFieldsByType.concat( + functions ? getCompatibleFunctionDefinition(commandName, types, ignoreFn) : [], + variables ? buildVariablesDefinitions(filteredVariablesByType) : [], + getCompatibleLiterals(commandName, types) // literals are handled internally + ); + + // rewrite the sortText here to have literals first, then fields, last functions + return suggestions.map(({ sortText, kind, ...rest }) => ({ + ...rest, + kind, + sortText: String.fromCharCode(97 - kind), + command: TRIGGER_SUGGESTION_COMMAND, + })); +} + +async function getFunctionArgsSuggestions( + innerText: string, + commands: ESQLCommand[], + { + command, + node, + }: { + command: ESQLCommand; + node: ESQLFunction; + }, + getFieldsByType: GetFieldsByTypeFn, + getFieldsMap: GetFieldsMapFn, + getPolicyMetadata: GetPolicyMetadataFn +): Promise { + const fnDefinition = getFunctionDefinition(node.name); + if (fnDefinition) { + const fieldsMap: Map = await getFieldsMap(); + const variablesExcludingCurrentCommandOnes = excludeVariablesFromCurrentCommand( + commands, + command, + fieldsMap + ); + // pick the type of the next arg + const shouldGetNextArgument = node.text.includes(EDITOR_MARKER); + let argIndex = Math.max(node.args.length, 0); + if (!shouldGetNextArgument && argIndex) { + argIndex -= 1; + } + const types = fnDefinition.signatures.flatMap((signature) => { + if (signature.params.length > argIndex) { + return signature.params[argIndex].type; + } + if (signature.infiniteParams) { + return signature.params[0].type; + } + return []; + }); + + const arg = node.args[argIndex]; + + const hasMoreMandatoryArgs = + fnDefinition.signatures[0].params.filter( + ({ optional }, index) => !optional && index > argIndex + ).length > argIndex; + + const suggestions = []; + const noArgDefined = !arg; + const isUnknownColumn = + arg && + isColumnItem(arg) && + !columnExists(arg, { fields: fieldsMap, variables: variablesExcludingCurrentCommandOnes }) + .hit; + if (noArgDefined || isUnknownColumn) { + // ... | EVAL fn( ) + // ... | EVAL fn( field, ) + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + types, + command.name, + getFieldsByType, + { + functions: command.name !== 'stats', + fields: true, + variables: variablesExcludingCurrentCommandOnes, + }, + // do not repropose the same function as arg + // i.e. avoid cases like abs(abs(abs(...))) with suggestions + { ignoreFn: [node.name] } + )) + ); + } + + // for eval and row commands try also to complete numeric literals with time intervals where possible + if (arg) { + if (command.name !== 'stats') { + if (isLiteralItem(arg) && arg.literalType === 'number') { + // ... | EVAL fn(2 ) + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + ['time_literal_unit'], + command.name, + getFieldsByType, + { + functions: false, + fields: false, + variables: variablesExcludingCurrentCommandOnes, + } + )) + ); + } + } + if (hasMoreMandatoryArgs) { + // suggest a comma if there's another argument for the function + suggestions.push(commaCompleteItem); + } + // if there are other arguments in the function, inject automatically a comma after each suggestion + return suggestions.map((suggestion) => + suggestion !== commaCompleteItem + ? { + ...suggestion, + insertText: + hasMoreMandatoryArgs && !fnDefinition.builtin + ? `${suggestion.insertText},` + : suggestion.insertText, + } + : suggestion + ); + } + + return suggestions.map(({ insertText, ...rest }) => ({ + ...rest, + insertText: hasMoreMandatoryArgs && !fnDefinition.builtin ? `${insertText},` : insertText, + })); + } + return mathCommandDefinition; +} + +async function getOptionArgsSuggestions( + innerText: string, + commands: ESQLCommand[], + { + command, + option, + node, + }: { + command: ESQLCommand; + option: ESQLCommandOption; + node: ESQLSingleAstItem | undefined; + }, + getFieldsByType: GetFieldsByTypeFn, + getFieldsMaps: GetFieldsMapFn, + getPolicyMetadata: GetPolicyMetadataFn +) { + const optionDef = getCommandOption(option.name); + const suggestions = []; + const isNewExpression = isRestartingExpression(innerText) || option.args.length === 0; + if (command.name === 'enrich') { + if (option.name === 'on') { + // if it's a new expression, suggest fields to match on + if (isNewExpression || (option && isAssignment(option.args[0]) && !option.args[1])) { + const policyName = isSourceItem(command.args[0]) ? command.args[0].name : undefined; + if (policyName) { + const [policyMetadata, fieldsMap] = await Promise.all([ + getPolicyMetadata(policyName), + getFieldsMaps(), + ]); + if (policyMetadata) { + suggestions.push( + ...buildMatchingFieldsDefinition( + policyMetadata.matchField, + Array.from(fieldsMap.keys()) + ) + ); + } + } + } else { + // propose the with option + suggestions.push( + buildOptionDefinition(getCommandOption('with')!), + ...getFinalSuggestions({ + comma: true, + }) + ); + } + } + if (option.name === 'with') { + let argIndex = option.args.length; + let lastArg = option.args[Math.max(argIndex - 1, 0)]; + if (isIncompleteItem(lastArg)) { + argIndex = Math.max(argIndex - 1, 0); + lastArg = option.args[argIndex]; + } + const policyName = isSourceItem(command.args[0]) ? command.args[0].name : undefined; + if (policyName) { + const [policyMetadata, fieldsMap] = await Promise.all([ + getPolicyMetadata(policyName), + getFieldsMaps(), + ]); + const anyVariables = collectVariables( + commands, + appendEnrichFields(fieldsMap, policyMetadata) + ); + + if (isNewExpression) { + suggestions.push(buildNewVarDefinition(findNewVariable(anyVariables))); + } + + // make sure to remove the marker arg from the assign fn + const assignFn = isAssignment(lastArg) + ? (removeMarkerArgFromArgsList(lastArg) as ESQLFunction) + : undefined; + + if (policyMetadata) { + if (isNewExpression || (assignFn && !isAssignmentComplete(assignFn))) { + // ... | ENRICH ... WITH a = + suggestions.push(...buildFieldsDefinitions(policyMetadata.enrichFields)); + } + } + if ( + assignFn && + hasSameArgBothSides(assignFn) && + !isNewExpression && + !isIncompleteItem(assignFn) + ) { + // ... | ENRICH ... WITH a + // effectively only assign will apper + suggestions.push(...getBuiltinCompatibleFunctionDefinition(command.name, 'any')); + } + + if ( + assignFn && + (isAssignmentComplete(assignFn) || hasSameArgBothSides(assignFn)) && + !isNewExpression + ) { + suggestions.push( + ...getFinalSuggestions({ + comma: true, + }) + ); + } + } + } + } + if (command.name === 'rename') { + if (option.args.length < 2) { + const fieldsMap = await getFieldsMaps(); + const anyVariables = collectVariables(commands, fieldsMap); + suggestions.push(...buildVariablesDefinitions([findNewVariable(anyVariables)])); + } + } + + if (optionDef) { + if (!suggestions.length) { + const argIndex = Math.max(option.args.length - 1, 0); + const types = [optionDef.signature.params[argIndex].type].filter(nonNullable); + if (option.args.length && !isRestartingExpression(innerText)) { + suggestions.push( + ...getFinalSuggestions({ + comma: true, + }) + ); + } else if (!option.args.length || isRestartingExpression(innerText)) { + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + types[0] === 'column' ? ['any'] : types, + command.name, + getFieldsByType, + { + functions: false, + fields: true, + } + )) + ); + } + } + } + return suggestions; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/complete_items.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/complete_items.ts new file mode 100644 index 0000000000000..cfa0e9fa74b3f --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/complete_items.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { AutocompleteCommandDefinition } from './types'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import { builtinFunctions } from '../definitions/builtin'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { getAllCommands } from '../shared/helpers'; +import { + getAutocompleteFunctionDefinition, + getAutocompleteBuiltinDefinition, + getAutocompleteCommandDefinition, +} from './factories'; + +export const mathCommandDefinition: AutocompleteCommandDefinition[] = evalFunctionsDefinitions.map( + getAutocompleteFunctionDefinition +); + +export const aggregationFunctionsDefinitions: AutocompleteCommandDefinition[] = + statsAggregationFunctionDefinitions.map(getAutocompleteFunctionDefinition); + +export function getAssignmentDefinitionCompletitionItem() { + const assignFn = builtinFunctions.find(({ name }) => name === '=')!; + return getAutocompleteBuiltinDefinition(assignFn); +} + +export const getBuiltinCompatibleFunctionDefinition = ( + command: string, + argType: string, + returnTypes?: string[] +): AutocompleteCommandDefinition[] => { + const compatibleFunctions = builtinFunctions.filter( + ({ name, supportedCommands, signatures, ignoreAsSuggestion }) => + !ignoreAsSuggestion && + !/not_/.test(name) && + supportedCommands.includes(command) && + signatures.some(({ params }) => params.some((pArg) => pArg.type === argType)) + ); + + if (!returnTypes) { + return compatibleFunctions.map(getAutocompleteBuiltinDefinition); + } + return compatibleFunctions + .filter((mathDefinition) => + mathDefinition.signatures.some( + (signature) => returnTypes[0] === 'any' || returnTypes.includes(signature.returnType) + ) + ) + .map(getAutocompleteBuiltinDefinition); +}; + +export const commandAutocompleteDefinitions: AutocompleteCommandDefinition[] = getAllCommands().map( + getAutocompleteCommandDefinition +); + +export const pipeCompleteItem: AutocompleteCommandDefinition = { + label: '|', + insertText: '|', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.pipeDoc', { + defaultMessage: 'Pipe (|)', + }), + sortText: 'B', +}; + +export const commaCompleteItem: AutocompleteCommandDefinition = { + label: ',', + insertText: ',', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.commaDoc', { + defaultMessage: 'Comma (,)', + }), + sortText: 'C', +}; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/utils.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/documentation_util.ts similarity index 100% rename from packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/utils.ts rename to packages/kbn-monaco/src/esql/lib/ast/autocomplete/documentation_util.ts diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/factories.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/factories.ts new file mode 100644 index 0000000000000..fc136a87b23da --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/factories.ts @@ -0,0 +1,268 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { AutocompleteCommandDefinition } from './types'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { getFunctionSignatures, getCommandSignature } from '../definitions/helpers'; +import { chronoLiterals, timeLiterals } from '../definitions/literals'; +import { + FunctionDefinition, + CommandDefinition, + CommandOptionsDefinition, +} from '../definitions/types'; +import { getCommandDefinition } from '../shared/helpers'; +import { buildDocumentation, buildFunctionDocumentation } from './documentation_util'; + +const allFunctions = statsAggregationFunctionDefinitions.concat(evalFunctionsDefinitions); + +export const TRIGGER_SUGGESTION_COMMAND = { + title: 'Trigger Suggestion Dialog', + id: 'editor.action.triggerSuggest', +}; + +export function getAutocompleteFunctionDefinition(fn: FunctionDefinition) { + const fullSignatures = getFunctionSignatures(fn); + return { + label: fullSignatures[0].declaration, + insertText: `${fn.name}($0)`, + insertTextRules: 4, // monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + kind: 1, + detail: fn.description, + documentation: { + value: buildFunctionDocumentation(fullSignatures), + }, + sortText: 'C', + }; +} + +export function getAutocompleteBuiltinDefinition(fn: FunctionDefinition) { + return { + label: fn.name, + insertText: `${fn.name} $0`, + insertTextRules: 4, // monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + kind: 11, + detail: fn.description, + documentation: { + value: '', + }, + sortText: 'D', + command: TRIGGER_SUGGESTION_COMMAND, + }; +} + +export const isCompatibleFunctionName = (fnName: string, command: string) => { + const fnSupportedByCommand = allFunctions.filter(({ supportedCommands }) => + supportedCommands.includes(command) + ); + return fnSupportedByCommand.some(({ name }) => name === fnName); +}; + +export const getCompatibleFunctionDefinition = ( + command: string, + returnTypes?: string[], + ignored: string[] = [] +): AutocompleteCommandDefinition[] => { + const fnSupportedByCommand = allFunctions.filter( + ({ name, supportedCommands }) => supportedCommands.includes(command) && !ignored.includes(name) + ); + if (!returnTypes) { + return fnSupportedByCommand.map(getAutocompleteFunctionDefinition); + } + return fnSupportedByCommand + .filter((mathDefinition) => + mathDefinition.signatures.some( + (signature) => returnTypes[0] === 'any' || returnTypes.includes(signature.returnType) + ) + ) + .map(getAutocompleteFunctionDefinition); +}; + +export function getAutocompleteCommandDefinition( + command: CommandDefinition +): AutocompleteCommandDefinition { + const commandDefinition = getCommandDefinition(command.name); + const commandSignature = getCommandSignature(commandDefinition); + return { + label: commandDefinition.name, + insertText: commandDefinition.name, + kind: 0, + detail: commandDefinition.description, + documentation: { + value: buildDocumentation(commandSignature.declaration, commandSignature.examples), + }, + sortText: 'A', + }; +} + +export const buildFieldsDefinitions = (fields: string[]): AutocompleteCommandDefinition[] => + fields.map((label) => ({ + label, + insertText: label, + kind: 4, + detail: i18n.translate('monaco.esql.autocomplete.fieldDefinition', { + defaultMessage: `Field specified by the input table`, + }), + sortText: 'D', + })); + +export const buildVariablesDefinitions = (variables: string[]): AutocompleteCommandDefinition[] => + variables.map((label) => ({ + label, + insertText: /[^a-zA-Z\d]/.test(label) ? `\`${label}\`` : label, + kind: 4, + detail: i18n.translate('monaco.esql.autocomplete.variableDefinition', { + defaultMessage: `Variable specified by the user within the ES|QL query`, + }), + sortText: 'D', + })); + +export const buildSourcesDefinitions = (sources: string[]): AutocompleteCommandDefinition[] => + sources.map((label) => ({ + label, + insertText: label, + kind: 21, + detail: i18n.translate('monaco.esql.autocomplete.sourceDefinition', { + defaultMessage: `Input table`, + }), + sortText: 'A', + })); + +export const buildConstantsDefinitions = ( + userConstants: string[], + detail?: string +): AutocompleteCommandDefinition[] => + userConstants.map((label) => ({ + label, + insertText: label, + kind: 14, + detail: + detail ?? + i18n.translate('monaco.esql.autocomplete.constantDefinition', { + defaultMessage: `User defined variable`, + }), + sortText: 'A', + })); + +export const buildNewVarDefinition = (label: string): AutocompleteCommandDefinition => { + return { + label, + insertText: `${label} =`, + kind: 21, + detail: i18n.translate('monaco.esql.autocomplete.newVarDoc', { + defaultMessage: 'Define a new variable', + }), + sortText: '1', + }; +}; + +export const buildPoliciesDefinitions = ( + policies: Array<{ name: string; sourceIndices: string[] }> +): AutocompleteCommandDefinition[] => + policies.map(({ name: label, sourceIndices }) => ({ + label, + insertText: label, + kind: 5, + detail: i18n.translate('monaco.esql.autocomplete.policyDefinition', { + defaultMessage: `Policy defined on {count, plural, one {index} other {indices}}: {indices}`, + values: { + count: sourceIndices.length, + indices: sourceIndices.join(', '), + }, + }), + sortText: 'D', + })); + +export const buildMatchingFieldsDefinition = ( + matchingField: string, + fields: string[] +): AutocompleteCommandDefinition[] => + fields.map((label) => ({ + label, + insertText: label, + kind: 4, + detail: i18n.translate('monaco.esql.autocomplete.matchingFieldDefinition', { + defaultMessage: `Use to match on {matchingField} on the policy`, + values: { + matchingField, + }, + }), + sortText: 'D', + })); + +export const buildOptionDefinition = (option: CommandOptionsDefinition) => { + const completeItem: AutocompleteCommandDefinition = { + label: option.name, + insertText: option.name, + kind: 21, + detail: option.description, + sortText: 'D', + }; + if (option.wrapped) { + completeItem.insertText = `${option.wrapped[0]}${option.name} $0 ${option.wrapped[1]}`; + completeItem.insertTextRules = 4; // monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet; + } + return completeItem; +}; + +export const buildNoPoliciesAvailableDefinition = (): AutocompleteCommandDefinition => ({ + label: i18n.translate('monaco.esql.autocomplete.noPoliciesLabel', { + defaultMessage: 'No available policy', + }), + insertText: '', + kind: 26, + detail: i18n.translate('monaco.esql.autocomplete.noPoliciesLabelsFound', { + defaultMessage: 'Click to create', + }), + sortText: 'D', + command: { + id: 'esql.policies.create', + title: i18n.translate('monaco.esql.autocomplete.createNewPolicy', { + defaultMessage: 'Click to create', + }), + }, +}); + +function getUnitDuration(unit: number = 1) { + const filteredTimeLiteral = timeLiterals.filter(({ name }) => { + const result = /s$/.test(name); + return unit > 1 ? result : !result; + }); + return filteredTimeLiteral.map(({ name }) => `${unit} ${name}`); +} + +export function getCompatibleLiterals(commandName: string, types: string[], names?: string[]) { + const suggestions: AutocompleteCommandDefinition[] = []; + if (types.includes('number') && commandName === 'limit') { + // suggest 10/50/100 + suggestions.push(...buildConstantsDefinitions(['10', '100', '1000'], '')); + } + if (types.includes('time_literal')) { + // filter plural for now and suggest only unit + singular + suggestions.push(...buildConstantsDefinitions(getUnitDuration(1))); // i.e. 1 year + } + // this is a special type built from the suggestion system, not inherited from the AST + if (types.includes('time_literal_unit')) { + suggestions.push(...buildConstantsDefinitions(timeLiterals.map(({ name }) => name))); // i.e. year, month, ... + } + if (types.includes('chrono_literal')) { + suggestions.push(...buildConstantsDefinitions(chronoLiterals.map(({ name }) => name))); // i.e. EPOC_DAY, ... + } + if (types.includes('string')) { + if (names) { + const index = types.indexOf('string'); + if (/pattern/.test(names[index])) { + suggestions.push(...buildConstantsDefinitions(['"a-pattern"'], 'A pattern string')); + } else { + suggestions.push(...buildConstantsDefinitions(['string'], '')); + } + } + } + return suggestions; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/types.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/types.ts new file mode 100644 index 0000000000000..ad6428fcbc771 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/types.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { monaco } from '../../../../..'; + +/** @internal **/ +export interface UserDefinedVariables { + userDefined: string[]; + policies: string[]; +} + +/** @internal **/ +export type AutocompleteCommandDefinition = Pick< + monaco.languages.CompletionItem, + | 'label' + | 'insertText' + | 'kind' + | 'detail' + | 'documentation' + | 'sortText' + | 'insertTextRules' + | 'command' +>; diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/aggs.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/aggs.ts new file mode 100644 index 0000000000000..91011a87a26a1 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/aggs.ts @@ -0,0 +1,127 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { FunctionDefinition } from './types'; + +function createNumericAggDefinition({ + name, + description, + args = [], +}: { + name: string; + description: string; + args?: Array<{ name: string; type: string; value: string }>; +}): FunctionDefinition { + const extraParamsExample = args.length ? `, ${args.map(({ value }) => value).join(',')}` : ''; + return { + name, + description, + supportedCommands: ['stats'], + signatures: [ + { + params: [ + { name: 'column', type: 'number', noNestingFunctions: true }, + ...args.map(({ name: paramName, type }) => ({ + name: paramName, + type, + noNestingFunctions: true, + })), + ], + returnType: 'number', + examples: [ + `from index | stats result = ${name}(field${extraParamsExample})`, + `from index | stats ${name}(field${extraParamsExample})`, + ], + }, + ], + }; +} + +export const statsAggregationFunctionDefinitions: FunctionDefinition[] = [ + { + name: 'avg', + description: i18n.translate('monaco.esql.definitions.avgDoc', { + defaultMessage: 'Returns the average of the values in a field', + }), + }, + { + name: 'max', + description: i18n.translate('monaco.esql.definitions.maxDoc', { + defaultMessage: 'Returns the maximum value in a field.', + }), + }, + { + name: 'min', + description: i18n.translate('monaco.esql.definitions.minDoc', { + defaultMessage: 'Returns the minimum value in a field.', + }), + }, + { + name: 'sum', + description: i18n.translate('monaco.esql.definitions.sumDoc', { + defaultMessage: 'Returns the sum of the values in a field.', + }), + }, + { + name: 'median', + description: i18n.translate('monaco.esql.definitions.medianDoc', { + defaultMessage: 'Returns the 50% percentile.', + }), + }, + { + name: 'median_absolute_deviation', + description: i18n.translate('monaco.esql.definitions.medianDeviationDoc', { + defaultMessage: + 'Returns the median of each data point’s deviation from the median of the entire sample.', + }), + }, + { + name: 'percentile', + description: i18n.translate('monaco.esql.definitions.percentiletDoc', { + defaultMessage: 'Returns the n percentile of a field.', + }), + args: [{ name: 'percentile', type: 'number', value: '90' }], + }, +] + .map(createNumericAggDefinition) + .concat([ + { + name: 'count', + description: i18n.translate('monaco.esql.definitions.countDoc', { + defaultMessage: 'Returns the count of the values in a field.', + }), + supportedCommands: ['stats'], + signatures: [ + { + params: [ + { name: 'column', type: 'any', noNestingFunctions: true, supportsWildcard: true }, + ], + returnType: 'number', + examples: [`from index | stats result = count(field)`, `from index | stats count(field)`], + }, + ], + }, + { + name: 'count_distinct', + description: i18n.translate('monaco.esql.definitions.countDistinctDoc', { + defaultMessage: 'Returns the count of distinct values in a field.', + }), + supportedCommands: ['stats'], + signatures: [ + { + params: [{ name: 'column', type: 'any', noNestingFunctions: true }], + returnType: 'number', + examples: [ + `from index | stats result = count_distinct(field)`, + `from index | stats count_distinct(field)`, + ], + }, + ], + }, + ]); diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/builtin.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/builtin.ts new file mode 100644 index 0000000000000..eed2fcc5d65b4 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/builtin.ts @@ -0,0 +1,348 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { FunctionDefinition } from './types'; + +function createMathDefinition( + name: string, + types: Array, + description: string, + warning?: FunctionDefinition['warning'] +) { + return { + builtin: true, + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: types.map((type) => { + if (Array.isArray(type)) { + return { + params: [ + { name: 'left', type: type[0] }, + { name: 'right', type: type[1] }, + ], + returnType: /literal/.test(type[0]) ? type[1] : type[0], + }; + } + return { + params: [ + { name: 'left', type }, + { name: 'right', type }, + ], + returnType: type, + }; + }), + warning, + }; +} + +function createComparisonDefinition( + { + name, + description, + }: { + name: string; + description: string; + }, + warning?: FunctionDefinition['warning'] +) { + return { + builtin: true, + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [ + { name: 'left', type: 'number' }, + { name: 'right', type: 'number' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'string' }, + { name: 'right', type: 'string' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'date' }, + { name: 'right', type: 'date' }, + ], + returnType: 'boolean', + }, + ], + }; +} + +export const builtinFunctions: FunctionDefinition[] = [ + createMathDefinition( + '+', + ['number', 'date', ['date', 'time_literal'], ['time_literal', 'date']], + i18n.translate('monaco.esql.definition.addDoc', { + defaultMessage: 'Add (+)', + }) + ), + createMathDefinition( + '-', + ['number', 'date', ['date', 'time_literal'], ['time_literal', 'date']], + i18n.translate('monaco.esql.definition.subtractDoc', { + defaultMessage: 'Subtract (-)', + }) + ), + createMathDefinition( + '*', + ['number'], + i18n.translate('monaco.esql.definition.multiplyDoc', { + defaultMessage: 'Multiply (*)', + }) + ), + createMathDefinition( + '/', + ['number'], + i18n.translate('monaco.esql.definition.divideDoc', { + defaultMessage: 'Divide (/)', + }), + (left, right) => { + if (right.type === 'literal' && right.literalType === 'number') { + return right.value === 0 + ? i18n.translate('monaco.esql.divide.warning.divideByZero', { + defaultMessage: 'Cannot divide by zero: {left}/{right}', + values: { + left: left.text, + right: right.value, + }, + }) + : undefined; + } + } + ), + createMathDefinition( + '%', + ['number'], + i18n.translate('monaco.esql.definition.moduleDoc', { + defaultMessage: 'Module (%)', + }), + (left, right) => { + if (right.type === 'literal' && right.literalType === 'number') { + return right.value === 0 + ? i18n.translate('monaco.esql.divide.warning.zeroModule', { + defaultMessage: 'Module by zero can return null value: {left}/{right}', + values: { + left: left.text, + right: right.value, + }, + }) + : undefined; + } + } + ), + ...[ + { + name: '==', + description: i18n.translate('monaco.esql.definition.equalToDoc', { + defaultMessage: 'Equal to', + }), + }, + { + name: '!=', + description: i18n.translate('monaco.esql.definition.notEqualToDoc', { + defaultMessage: 'Not equal to', + }), + }, + { + name: '<', + description: i18n.translate('monaco.esql.definition.lessThanDoc', { + defaultMessage: 'Less than', + }), + }, + { + name: '>', + description: i18n.translate('monaco.esql.definition.greaterThanDoc', { + defaultMessage: 'Greater than', + }), + }, + { + name: '<=', + description: i18n.translate('monaco.esql.definition.lessThanOrEqualToDoc', { + defaultMessage: 'Less than or equal to', + }), + }, + { + name: '>=', + description: i18n.translate('monaco.esql.definition.greaterThanOrEqualToDoc', { + defaultMessage: 'Greater than or equal to', + }), + }, + ].map((op) => createComparisonDefinition(op)), + ...[ + { + name: 'like', + description: i18n.translate('monaco.esql.definition.likeDoc', { + defaultMessage: 'Filter data based on string patterns', + }), + }, + { name: 'not_like', description: '' }, + { + name: 'rlike', + description: i18n.translate('monaco.esql.definition.rlikeDoc', { + defaultMessage: 'Filter data based on string regular expressions', + }), + }, + { name: 'not_rlike', description: '' }, + ].map(({ name, description }) => ({ + builtin: true, + ignoreAsSuggestion: /not/.test(name), + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [ + { name: 'left', type: 'string' }, + { name: 'right', type: 'string' }, + ], + returnType: 'boolean', + }, + ], + })), + ...[ + { + name: 'in', + description: i18n.translate('monaco.esql.definition.inDoc', { + defaultMessage: + 'Tests if the value an expression takes is contained in a list of other expressions', + }), + }, + { name: 'not_in', description: '' }, + ].map(({ name, description }) => ({ + builtin: true, + ignoreAsSuggestion: /not/.test(name), + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [ + { name: 'left', type: 'number' }, + { name: 'right', type: 'number[]' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'string' }, + { name: 'right', type: 'string[]' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'boolean' }, + { name: 'right', type: 'boolean[]' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'date' }, + { name: 'right', type: 'date[]' }, + ], + returnType: 'boolean', + }, + ], + })), + ...[ + { + name: 'and', + description: i18n.translate('monaco.esql.definition.andDoc', { + defaultMessage: 'and', + }), + }, + { + name: 'or', + description: i18n.translate('monaco.esql.definition.orDoc', { + defaultMessage: 'or', + }), + }, + ].map(({ name, description }) => ({ + builtin: true, + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [ + { name: 'left', type: 'boolean' }, + { name: 'right', type: 'boolean' }, + ], + returnType: 'boolean', + }, + ], + })), + { + builtin: true, + name: 'not', + description: i18n.translate('monaco.esql.definition.notDoc', { + defaultMessage: 'Not', + }), + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [{ name: 'expression', type: 'boolean' }], + returnType: 'boolean', + }, + ], + }, + { + builtin: true, + name: '=', + description: i18n.translate('monaco.esql.definition.assignDoc', { + defaultMessage: 'Assign (=)', + }), + supportedCommands: ['eval', 'stats', 'row', 'dissect', 'where', 'enrich'], + signatures: [ + { + params: [ + { name: 'left', type: 'any' }, + { name: 'right', type: 'any' }, + ], + returnType: 'void', + }, + ], + }, + { + name: 'functions', + description: i18n.translate('monaco.esql.definition.functionsDoc', { + defaultMessage: 'Show ES|QL avaialble functions with signatures', + }), + supportedCommands: ['show'], + signatures: [ + { + params: [], + returnType: 'void', + }, + ], + }, + { + name: 'info', + description: i18n.translate('monaco.esql.definition.infoDoc', { + defaultMessage: 'Show information about the current ES node', + }), + supportedCommands: ['show'], + signatures: [ + { + params: [], + returnType: 'void', + }, + ], + }, +]; diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/commands.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/commands.ts new file mode 100644 index 0000000000000..4404bf00b5fad --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/commands.ts @@ -0,0 +1,280 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { isColumnItem } from '../shared/helpers'; +import { ESQLColumn, ESQLCommand, ESQLMessage } from '../types'; +import { + appendSeparatorOption, + asOption, + byOption, + metadataOption, + onOption, + withOption, +} from './options'; +import type { CommandDefinition } from './types'; + +export const commandDefinitions: CommandDefinition[] = [ + { + name: 'row', + description: i18n.translate('monaco.esql.definitions.rowDoc', { + defaultMessage: + 'Produces a row with one or more columns with values that you specify. This can be useful for testing.', + }), + examples: ['row a=1', 'row a=1, b=2'], + signature: { + multipleParams: true, + // syntax check already validates part of this + params: [{ name: 'assignment', type: 'any' }], + }, + options: [], + }, + { + name: 'from', + description: i18n.translate('monaco.esql.definitions.fromDoc', { + defaultMessage: + 'Retrieves data from one or more data streams, indices, or aliases. In a query or subquery, you must use the from command first and it does not need a leading pipe. For example, to retrieve data from an index:', + }), + examples: ['from logs', 'from logs-*', 'from logs_*, events-*'], + options: [metadataOption], + signature: { + multipleParams: true, + params: [{ name: 'index', type: 'source', wildcards: true }], + }, + }, + { + name: 'show', + description: i18n.translate('monaco.esql.definitions.showDoc', { + defaultMessage: 'Returns information about the deployment and its capabilities', + }), + examples: ['show functions', 'show info'], + options: [], + signature: { + multipleParams: false, + params: [{ name: 'functions', type: 'string', values: ['functions', 'info'] }], + }, + }, + { + name: 'stats', + description: i18n.translate('monaco.esql.definitions.statsDoc', { + defaultMessage: + 'Calculates aggregate statistics, such as average, count, and sum, over the incoming search results set. Similar to SQL aggregation, if the stats command is used without a BY clause, only one row is returned, which is the aggregation over the entire incoming search results set. When you use a BY clause, one row is returned for each distinct value in the field specified in the BY clause. The stats command returns only the fields in the aggregation, and you can use a wide range of statistical functions with the stats command. When you perform more than one aggregation, separate each aggregation with a comma.', + }), + examples: ['… | stats avg = avg(a)', '… | stats sum(b) by b'], + signature: { + multipleParams: true, + params: [{ name: 'expression', type: 'function' }], + }, + options: [byOption], + }, + { + name: 'eval', + description: i18n.translate('monaco.esql.definitions.evalDoc', { + defaultMessage: + 'Calculates an expression and puts the resulting value into a search results field.', + }), + examples: [ + '… | eval b * c', + '… | eval a = b * c', + '… | eval then = now() + 1 year + 2 weeks', + '… | eval a = b * c, d = e * f', + ], + signature: { + multipleParams: true, + params: [{ name: 'expression', type: 'any' }], + }, + options: [], + }, + { + name: 'rename', + description: i18n.translate('monaco.esql.definitions.renameDoc', { + defaultMessage: 'Renames an old column to a new one', + }), + examples: ['… | rename old as new', '… | rename old as new, a as b'], + signature: { + multipleParams: true, + params: [{ name: 'renameClause', type: 'column' }], + }, + options: [asOption], + }, + { + name: 'limit', + description: i18n.translate('monaco.esql.definitions.limitDoc', { + defaultMessage: + 'Returns the first search results, in search order, based on the "limit" specified.', + }), + examples: ['… | limit 100', '… | limit 0'], + signature: { + multipleParams: false, + params: [{ name: 'size', type: 'number', literalOnly: true }], + }, + options: [], + }, + { + name: 'keep', + description: i18n.translate('monaco.esql.definitions.keepDoc', { + defaultMessage: 'Rearranges fields in the input table by applying the keep clauses in fields', + }), + examples: ['… | keep a', '… | keep a,b'], + options: [], + signature: { + multipleParams: true, + params: [{ name: 'column', type: 'column', wildcards: true }], + }, + validate: (command: ESQLCommand) => { + // the command name is automatically converted into KEEP by the ast_walker + // so validate the actual text + const messages: ESQLMessage[] = []; + if (/^project/.test(command.text.toLowerCase())) { + messages.push({ + location: command.location, + text: i18n.translate('monaco.esql.validation.projectCommandDeprecated', { + defaultMessage: 'PROJECT command is no longer supported, please use KEEP instead', + }), + type: 'warning', + }); + } + return messages; + }, + }, + { + name: 'drop', + description: i18n.translate('monaco.esql.definitions.dropDoc', { + defaultMessage: 'Drops columns', + }), + examples: ['… | drop a', '… | drop a,b'], + options: [], + signature: { + multipleParams: true, + params: [{ name: 'column', type: 'column', wildcards: true }], + }, + validate: (command: ESQLCommand) => { + const messages: ESQLMessage[] = []; + const wildcardItems = command.args.filter((arg) => isColumnItem(arg) && arg.name === '*'); + if (wildcardItems.length) { + messages.push( + ...wildcardItems.map((column) => ({ + location: (column as ESQLColumn).location, + text: i18n.translate('monaco.esql.validation.dropAllColumnsError', { + defaultMessage: 'Removing all fields is not allowed [*]', + }), + type: 'error' as const, + })) + ); + } + const droppingTimestamp = command.args.find( + (arg) => isColumnItem(arg) && arg.name === '@timestamp' + ); + if (droppingTimestamp) { + messages.push({ + location: (droppingTimestamp as ESQLColumn).location, + text: i18n.translate('monaco.esql.validation.dropTimestampWarning', { + defaultMessage: 'Drop [@timestamp] will remove all time filters to the search results', + }), + type: 'warning', + }); + } + return messages; + }, + }, + { + name: 'sort', + description: i18n.translate('monaco.esql.definitions.sortDoc', { + defaultMessage: + 'Sorts all results by the specified fields. By default, null values are treated as being larger than any other value. With an ascending sort order, null values are sorted last, and with a descending sort order, null values are sorted first. You can change that by providing NULLS FIRST or NULLS LAST', + }), + examples: [ + '… | sort a desc, b nulls last, c asc nulls first', + '… | sort b nulls last', + '… | sort c asc nulls first', + ], + options: [], + signature: { + multipleParams: true, + params: [ + { name: 'column', type: 'column' }, + { name: 'direction', type: 'string', optional: true, values: ['asc', 'desc'] }, + { name: 'nulls', type: 'string', optional: true, values: ['nulls first', 'nulls last'] }, + ], + }, + }, + { + name: 'where', + description: i18n.translate('monaco.esql.definitions.whereDoc', { + defaultMessage: + 'Uses "predicate-expressions" to filter search results. A predicate expression, when evaluated, returns TRUE or FALSE. The where command only returns the results that evaluate to TRUE. For example, to filter results for a specific field value', + }), + examples: ['… | where status_code == 200'], + signature: { + multipleParams: false, + params: [{ name: 'expression', type: 'boolean' }], + }, + options: [], + }, + { + name: 'dissect', + description: i18n.translate('monaco.esql.definitions.dissectDoc', { + defaultMessage: + 'Extracts multiple string values from a single string input, based on a pattern', + }), + examples: ['… | dissect a "%{b} %{c}"'], + options: [appendSeparatorOption], + signature: { + multipleParams: false, + params: [ + { name: 'column', type: 'column', innerType: 'string' }, + { name: 'pattern', type: 'string', literalOnly: true }, + ], + }, + }, + { + name: 'grok', + description: i18n.translate('monaco.esql.definitions.grokDoc', { + defaultMessage: + 'Extracts multiple string values from a single string input, based on a pattern', + }), + examples: ['… | grok a "%{IP:b} %{NUMBER:c}"'], + options: [], + signature: { + multipleParams: false, + params: [ + { name: 'column', type: 'column', innerType: 'string' }, + { name: 'pattern', type: 'string', literalOnly: true }, + ], + }, + }, + { + name: 'mv_expand', + description: i18n.translate('monaco.esql.definitions.mvExpandDoc', { + defaultMessage: 'Expands multivalued fields into one row per value, duplicating other fields', + }), + examples: ['row a=[1,2,3] | mv_expand a'], + options: [], + signature: { + multipleParams: false, + params: [{ name: 'column', type: 'column', innerType: 'list' }], + }, + }, + { + name: 'enrich', + description: i18n.translate('monaco.esql.definitions.enrichDoc', { + defaultMessage: + 'Enrich table with another table. Before you can use enrich, you need to create and execute an enrich policy.', + }), + examples: [ + '… | enrich my-policy', + '… | enrich my-policy on pivotField', + '… | enrich my-policy on pivotField with a = enrichFieldA, b = enrichFieldB', + ], + options: [onOption, withOption], + signature: { + multipleParams: false, + params: [{ name: 'policyName', type: 'source', innerType: 'policy' }], + }, + }, +]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/functions.ts similarity index 52% rename from packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts rename to packages/kbn-monaco/src/esql/lib/ast/definitions/functions.ts index 12056ee784695..135987c4b30b6 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/functions.ts @@ -7,47 +7,12 @@ */ import { i18n } from '@kbn/i18n'; -import { buildDocumentation, buildFunctionDocumentation } from './utils'; +import { FunctionDefinition } from './types'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const whereCommandDefinition: AutocompleteCommandDefinition[] = [ - { - label: 'cidr_match', - insertText: 'cidr_match', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.cidrMatchDoc', { - defaultMessage: - 'The function takes a first parameter of type IP, followed by one or more parameters evaluated to a CIDR specificatione.', - }), - documentation: { - value: buildDocumentation('cidr_match(grouped[T]): aggregated[T]', [ - 'from index | eval cidr="10.0.0.0/8" | where cidr_match(ip_field, "127.0.0.1/30", cidr)', - ]), - }, - sortText: 'C', - }, -]; - -interface FunctionDefinition { - name: string; - description: string; - signatures: Array<{ - params: Array<{ - name: string; - type: string | string[]; - optional?: boolean; - }>; - infiniteParams?: boolean; - returnType: string; - examples?: string[]; - }>; -} - -const mathCommandFullDefinitions: FunctionDefinition[] = [ +export const evalFunctionsDefinitions: FunctionDefinition[] = [ { name: 'round', - description: i18n.translate('monaco.esql.autocomplete.roundDoc', { + description: i18n.translate('monaco.esql.definitions.roundDoc', { defaultMessage: 'Returns a number rounded to the decimal, specified by he closest integer value. The default is to round to an integer.', }), @@ -55,39 +20,39 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval round_value = round(field)`], + examples: [`from index | eval round_value = round(field)`], }, ], }, { name: 'abs', - description: i18n.translate('monaco.esql.autocomplete.absDoc', { + description: i18n.translate('monaco.esql.definitions.absDoc', { defaultMessage: 'Returns the absolute value.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval abs_value = abs(field)`], + examples: [`from index | eval abs_value = abs(field)`], }, ], }, { name: 'log10', - description: i18n.translate('monaco.esql.autocomplete.log10Doc', { + description: i18n.translate('monaco.esql.definitions.log10Doc', { defaultMessage: 'Returns the log base 10.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval log10_value = log10(field)`], + examples: [`from index | eval log10_value = log10(field)`], }, ], }, { name: 'pow', - description: i18n.translate('monaco.esql.autocomplete.powDoc', { + description: i18n.translate('monaco.esql.definitions.powDoc', { defaultMessage: 'Returns the the value of a base (first argument) raised to a power (second argument).', }), @@ -98,31 +63,48 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'exponent', type: 'number' }, ], returnType: 'number', - examples: ['from index where field="value" | eval s = POW(field, exponent)'], + examples: ['from index | eval s = POW(field, exponent)'], }, ], }, { name: 'concat', - description: i18n.translate('monaco.esql.autocomplete.concatDoc', { + description: i18n.translate('monaco.esql.definitions.concatDoc', { defaultMessage: 'Concatenates two or more strings.', }), signatures: [ { params: [{ name: 'field', type: 'string' }], infiniteParams: true, + minParams: 1, returnType: 'string', - examples: [ - 'from index where field="value" | eval concatenated = concat(field1, "-", field2)', + examples: ['from index | eval concatenated = concat(field1, "-", field2)'], + }, + ], + }, + { + name: 'replace', + description: i18n.translate('monaco.esql.definitions.replaceDoc', { + defaultMessage: + 'The function substitutes in the string (1st argument) any match of the regular expression (2nd argument) with the replacement string (3rd argument). If any of the arguments are NULL, the result is NULL.', + }), + signatures: [ + { + params: [ + { name: 'field', type: 'string' }, + { name: 'regexp', type: 'string' }, + { name: 'replacement', type: 'string' }, ], + returnType: 'string', + examples: ['from index | eval newStr = replace(field, "Hello", "World")'], }, ], }, { name: 'substring', - description: i18n.translate('monaco.esql.autocomplete.substringDoc', { + description: i18n.translate('monaco.esql.definitions.substringDoc', { defaultMessage: - 'Returns a substring of a string, specified by a start position and an optional length. This example returns the first three characters of every last name.', + 'Returns a substring of a string, specified by a start position and an optional length.', }), signatures: [ { @@ -132,26 +114,26 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'endIndex', type: 'number' }, ], returnType: 'string', - examples: ['from index where field="value" | eval new_string = substring(field, 1, 3)'], + examples: ['from index | eval new_string = substring(field, 1, 3)'], }, ], }, { name: 'trim', - description: i18n.translate('monaco.esql.autocomplete.trimDoc', { + description: i18n.translate('monaco.esql.definitions.trimDoc', { defaultMessage: 'Removes leading and trailing whitespaces from strings.', }), signatures: [ { params: [{ name: 'field', type: 'string' }], returnType: 'string', - examples: ['from index where field="value" | eval new_string = trim(field)'], + examples: ['from index | eval new_string = trim(field)'], }, ], }, { name: 'starts_with', - description: i18n.translate('monaco.esql.autocomplete.startsWithDoc', { + description: i18n.translate('monaco.esql.definitions.startsWithDoc', { defaultMessage: 'Returns a boolean that indicates whether a keyword string starts with another string.', }), @@ -162,13 +144,30 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'prefix', type: 'string' }, ], returnType: 'boolean', - examples: ['from index where field="value" | eval new_string = starts_with(field, "a")'], + examples: ['from index | eval starts_with_a = starts_with(field, "a")'], + }, + ], + }, + { + name: 'ends_with', + description: i18n.translate('monaco.esql.definitions.endsWithDoc', { + defaultMessage: + 'Returns a boolean that indicates whether a keyword string ends with another string:', + }), + signatures: [ + { + params: [ + { name: 'field', type: 'string' }, + { name: 'prefix', type: 'string' }, + ], + returnType: 'boolean', + examples: ['from index | eval ends_with_a = ends_with(field, "a")'], }, ], }, { name: 'split', - description: i18n.translate('monaco.esql.autocomplete.splitDoc', { + description: i18n.translate('monaco.esql.definitions.splitDoc', { defaultMessage: 'Splits a single valued string into multiple strings.', }), signatures: [ @@ -184,173 +183,183 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'to_string', - description: i18n.translate('monaco.esql.autocomplete.toStringDoc', { + alias: ['to_str'], + description: i18n.translate('monaco.esql.definitions.toStringDoc', { defaultMessage: 'Converts to string.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'string', - examples: [`from index where field="value"" | EVAL string = to_string(field)`], + examples: [`from index" | EVAL string = to_string(field)`], }, ], }, { name: 'to_boolean', - description: i18n.translate('monaco.esql.autocomplete.toBooleanDoc', { + alias: ['to_bool'], + description: i18n.translate('monaco.esql.definitions.toBooleanDoc', { defaultMessage: 'Converts to boolean.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'boolean', - examples: [`from index where field="value"" | EVAL bool = to_boolean(field)`], + examples: [`from index" | EVAL bool = to_boolean(field)`], }, ], }, { name: 'to_datetime', - description: i18n.translate('monaco.esql.autocomplete.toDateTimeDoc', { + alias: ['to_dt'], + description: i18n.translate('monaco.esql.definitions.toDateTimeDoc', { defaultMessage: 'Converts to date.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'date', - examples: [`from index where field="value"" | EVAL datetime = to_datetime(field)`], + examples: [`from index" | EVAL datetime = to_datetime(field)`], }, ], }, { name: 'to_degrees', - description: i18n.translate('monaco.esql.autocomplete.toDegreesDoc', { + description: i18n.translate('monaco.esql.definitions.toDegreesDoc', { defaultMessage: 'Coverts to degrees', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval degrees = to_degrees(field)`], + examples: [`from index | eval degrees = to_degrees(field)`], }, ], }, { name: 'to_double', - description: i18n.translate('monaco.esql.autocomplete.toDoubleDoc', { + alias: ['to_dbl'], + description: i18n.translate('monaco.esql.definitions.toDoubleDoc', { defaultMessage: 'Converts to double.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'number', - examples: [`from index where field="value"" | EVAL double = to_double(field)`], + examples: [`from index | EVAL double = to_double(field)`], }, ], }, { name: 'to_integer', - description: i18n.translate('monaco.esql.autocomplete.toIntegerDoc', { + alias: ['to_int'], + description: i18n.translate('monaco.esql.definitions.toIntegerDoc', { defaultMessage: 'Converts to integer.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'number', - examples: [`from index where field="value"" | EVAL integer = to_integer(field)`], + examples: [`from index | EVAL integer = to_integer(field)`], }, ], }, { name: 'to_long', - description: i18n.translate('monaco.esql.autocomplete.toLongDoc', { + description: i18n.translate('monaco.esql.definitions.toLongDoc', { defaultMessage: 'Converts to long.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'number', - examples: [`from index where field="value"" | EVAL long = to_long(field)`], + examples: [`from index | EVAL long = to_long(field)`], }, ], }, { name: 'to_radians', - description: i18n.translate('monaco.esql.autocomplete.toRadiansDoc', { + description: i18n.translate('monaco.esql.definitions.toRadiansDoc', { defaultMessage: 'Converts to radians', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval radians = to_radians(field)`], + examples: [`from index | eval radians = to_radians(field)`], }, ], }, { name: 'to_unsigned_long', - description: i18n.translate('monaco.esql.autocomplete.toUnsignedLongDoc', { + alias: ['to_ul', 'to_ulong'], + description: i18n.translate('monaco.esql.definitions.toUnsignedLongDoc', { defaultMessage: 'Converts to unsigned long.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'number', - examples: [ - `from index where field="value"" | EVAL unsigned_long = to_unsigned_long(field)`, - ], + examples: [`from index | EVAL unsigned_long = to_unsigned_long(field)`], }, ], }, { name: 'to_ip', - description: i18n.translate('monaco.esql.autocomplete.toIpDoc', { + description: i18n.translate('monaco.esql.definitions.toIpDoc', { defaultMessage: 'Converts to ip.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], - returnType: 'string[]', - examples: [`from index where field="value"" | EVAL ip = to_ip(field)`], + returnType: 'ip', + examples: [`from index | EVAL ip = to_ip(field)`], }, ], }, { name: 'to_version', - description: i18n.translate('monaco.esql.autocomplete.toVersionDoc', { + alias: ['to_ver'], + description: i18n.translate('monaco.esql.definitions.toVersionDoc', { defaultMessage: 'Converts to version.', }), signatures: [ { - params: [{ name: 'field', type: ['string', 'version'] }], + params: [{ name: 'field', type: 'string' }], returnType: 'version', - examples: [`from index where field="value"" | EVAL version = to_version(field)`], + examples: [`from index | EVAL version = to_version(stringField)`], + }, + { + params: [{ name: 'field', type: 'version' }], + returnType: 'version', + examples: [`from index | EVAL version = to_version(versionField)`], }, ], }, { name: 'date_extract', - description: i18n.translate('monaco.esql.autocomplete.dateExtractDoc', { + description: i18n.translate('monaco.esql.definitions.dateExtractDoc', { defaultMessage: `Extracts parts of a date, like year, month, day, hour. The supported field types are those provided by java.time.temporal.ChronoField`, }), signatures: [ { params: [ - { name: 'field', type: 'date' }, { name: 'date_part', - type: 'string', + type: 'chrono_literal', }, + { name: 'field', type: 'date' }, ], returnType: 'number', examples: [ - `ROW date = DATE_PARSE("2022-05-06", "yyyy-MM-dd") | EVAL year = DATE_EXTRACT(date, "year")`, + `ROW date = DATE_PARSE("yyyy-MM-dd", "2022-05-06") | EVAL year = DATE_EXTRACT("year", date)`, ], }, ], }, { name: 'date_format', - description: i18n.translate('monaco.esql.autocomplete.dateFormatDoc', { + description: i18n.translate('monaco.esql.definitions.dateFormatDoc', { defaultMessage: `Returns a string representation of a date in the provided format. If no format is specified, the "yyyy-MM-dd'T'HH:mm:ss.SSSZ" format is used.`, }), signatures: [ @@ -360,15 +369,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'format_string', type: 'string', optional: true }, ], returnType: 'string', - examples: [ - 'from index where field="value" | eval hired = date_format(hire_date, "YYYY-MM-dd")', - ], + examples: ['from index | eval hired = date_format("YYYY-MM-dd", hire_date)'], }, ], }, { name: 'date_trunc', - description: i18n.translate('monaco.esql.autocomplete.dateTruncDoc', { + description: i18n.translate('monaco.esql.definitions.dateTruncDoc', { defaultMessage: `Rounds down a date to the closest interval. Intervals can be expressed using the timespan literal syntax.`, }), signatures: [ @@ -378,15 +385,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'field', type: 'date' }, ], returnType: 'date', - examples: [ - `from index where field="value" | eval year_hired = DATE_TRUNC(1 year, hire_date)`, - ], + examples: [`from index | eval year_hired = DATE_TRUNC(1 year, hire_date)`], }, ], }, { name: 'date_parse', - description: i18n.translate('monaco.esql.autocomplete.dateParseDoc', { + description: i18n.translate('monaco.esql.definitions.dateParseDoc', { defaultMessage: `Parse dates from strings.`, }), signatures: [ @@ -397,14 +402,14 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ ], returnType: 'date', examples: [ - `from index where field="value" | eval year_hired = date_parse(hire_date, yyyy-MM-dd'T'HH:mm:ss.SSS'Z')`, + `from index | eval year_hired = date_parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", hire_date)`, ], }, ], }, { name: 'auto_bucket', - description: i18n.translate('monaco.esql.autocomplete.autoBucketDoc', { + description: i18n.translate('monaco.esql.definitions.autoBucketDoc', { defaultMessage: `Automatically bucket dates based on a given range and bucket target.`, }), signatures: [ @@ -417,7 +422,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ ], returnType: 'date', examples: [ - 'from index where field="value" | eval hd = auto_bucket(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")', + 'from index | eval hd = auto_bucket(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")', ], }, { @@ -428,113 +433,124 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'endValue', type: 'number' }, ], returnType: 'number', - examples: [ - 'from index where field="value" | eval bs = auto_bucket(salary, 20, 25324, 74999)', - ], + examples: ['from index | eval bs = auto_bucket(salary, 20, 25324, 74999)'], }, ], }, { name: 'is_finite', - description: i18n.translate('monaco.esql.autocomplete.isFiniteDoc', { + description: i18n.translate('monaco.esql.definitions.isFiniteDoc', { defaultMessage: 'Returns a boolean that indicates whether its input is a finite number.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'boolean', - examples: ['from index where field="value" | eval s = is_finite(field/0)'], + examples: ['from index | eval s = is_finite(field/0)'], }, ], }, { name: 'is_infinite', - description: i18n.translate('monaco.esql.autocomplete.isInfiniteDoc', { + description: i18n.translate('monaco.esql.definitions.isInfiniteDoc', { defaultMessage: 'Returns a boolean that indicates whether its input is infinite.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'boolean', - examples: ['from index where field="value" | eval s = is_infinite(field/0)'], + examples: ['from index | eval s = is_infinite(field/0)'], + }, + ], + }, + { + name: 'is_nan', + description: i18n.translate('monaco.esql.definitions.isNanDoc', { + defaultMessage: 'Returns a boolean that indicates whether its input is not a number.', + }), + signatures: [ + { + params: [{ name: 'field', type: 'number' }], + returnType: 'boolean', + examples: ['row a = 1 | eval is_nan(a)'], }, ], }, { name: 'case', - description: i18n.translate('monaco.esql.autocomplete.caseDoc', { + description: i18n.translate('monaco.esql.definitions.caseDoc', { defaultMessage: 'Accepts pairs of conditions and values. The function returns the value that belongs to the first condition that evaluates to `true`. If the number of arguments is odd, the last argument is the default value which is returned when no condition matches.', }), signatures: [ { params: [ - { name: 'condition', type: 'booleanExpression' }, + { name: 'condition', type: 'boolean' }, { name: 'value', type: 'any' }, ], - infiniteParams: true, + minParams: 3, returnType: 'any', examples: [ - `from index where field="value" | eval type = case(languages <= 1, "monolingual", languages <= 2, "bilingual", "polyglot")`, + `from index | eval type = case(languages <= 1, "monolingual", languages <= 2, "bilingual", "polyglot")`, ], }, ], }, { name: 'length', - description: i18n.translate('monaco.esql.autocomplete.lengthDoc', { + description: i18n.translate('monaco.esql.definitions.lengthDoc', { defaultMessage: 'Returns the character length of a string.', }), signatures: [ { params: [{ name: 'field', type: 'string' }], returnType: 'number', - examples: [`from index where field="value" | eval fn_length = length(field)`], + examples: [`from index | eval fn_length = length(field)`], }, ], }, { name: 'acos', - description: i18n.translate('monaco.esql.autocomplete.acosDoc', { + description: i18n.translate('monaco.esql.definitions.acosDoc', { defaultMessage: 'Inverse cosine trigonometric function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval acos = acos(field)`], + examples: [`from index | eval acos = acos(field)`], }, ], }, { name: 'asin', - description: i18n.translate('monaco.esql.autocomplete.asinDoc', { + description: i18n.translate('monaco.esql.definitions.asinDoc', { defaultMessage: 'Inverse sine trigonometric function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval asin = asin(field)`], + examples: [`from index | eval asin = asin(field)`], }, ], }, { name: 'atan', - description: i18n.translate('monaco.esql.autocomplete.atanDoc', { + description: i18n.translate('monaco.esql.definitions.atanDoc', { defaultMessage: 'Inverse tangent trigonometric function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval atan = atan(field)`], + examples: [`from index | eval atan = atan(field)`], }, ], }, { name: 'atan2', - description: i18n.translate('monaco.esql.autocomplete.atan2Doc', { + description: i18n.translate('monaco.esql.definitions.atan2Doc', { defaultMessage: 'The angle between the positive x-axis and the ray from the origin to the point (x , y) in the Cartesian plane', }), @@ -545,13 +561,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'y', type: 'number' }, ], returnType: 'number', - examples: [`from index where field="value" | eval atan2 = atan2(x, y)`], + examples: [`from index | eval atan2 = atan2(x, y)`], }, ], }, { name: 'coalesce', - description: i18n.translate('monaco.esql.autocomplete.coalesceDoc', { + description: i18n.translate('monaco.esql.definitions.coalesceDoc', { defaultMessage: 'Returns the first non-null value.', }), signatures: [ @@ -565,46 +581,46 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'cos', - description: i18n.translate('monaco.esql.autocomplete.cosDoc', { + description: i18n.translate('monaco.esql.definitions.cosDoc', { defaultMessage: 'Cosine trigonometric function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval cos = cos(field)`], + examples: [`from index | eval cos = cos(field)`], }, ], }, { name: 'cosh', - description: i18n.translate('monaco.esql.autocomplete.coshDoc', { + description: i18n.translate('monaco.esql.definitions.coshDoc', { defaultMessage: 'Cosine hyperbolic function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval cosh = cosh(field)`], + examples: [`from index | eval cosh = cosh(field)`], }, ], }, { name: 'floor', - description: i18n.translate('monaco.esql.autocomplete.floorDoc', { + description: i18n.translate('monaco.esql.definitions.floorDoc', { defaultMessage: 'Round a number down to the nearest integer.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval a = floor(field)`], + examples: [`from index | eval a = floor(field)`], }, ], }, { name: 'greatest', - description: i18n.translate('monaco.esql.autocomplete.greatestDoc', { + description: i18n.translate('monaco.esql.definitions.greatestDoc', { defaultMessage: 'Returns the maximum value from many columns.', }), signatures: [ @@ -618,7 +634,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'left', - description: i18n.translate('monaco.esql.autocomplete.leftDoc', { + description: i18n.translate('monaco.esql.definitions.leftDoc', { defaultMessage: 'Return the substring that extracts length chars from the string starting from the left.', }), @@ -629,13 +645,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'length', type: 'number' }, ], returnType: 'string', - examples: [`from index where field="value" | eval substr = left(field, 3)`], + examples: [`from index | eval substr = left(field, 3)`], }, ], }, { name: 'ltrim', - description: i18n.translate('monaco.esql.autocomplete.ltrimDoc', { + description: i18n.translate('monaco.esql.definitions.ltrimDoc', { defaultMessage: 'Removes leading whitespaces from strings.', }), signatures: [ @@ -648,7 +664,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'now', - description: i18n.translate('monaco.esql.autocomplete.nowDoc', { + description: i18n.translate('monaco.esql.definitions.nowDoc', { defaultMessage: 'Returns current date and time.', }), signatures: [ @@ -661,7 +677,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'right', - description: i18n.translate('monaco.esql.autocomplete.rightDoc', { + description: i18n.translate('monaco.esql.definitions.rightDoc', { defaultMessage: 'Return the substring that extracts length chars from the string starting from the right.', }), @@ -672,13 +688,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'length', type: 'number' }, ], returnType: 'string', - examples: [`from index where field="value" | eval string = right(field, 3)`], + examples: [`from index | eval string = right(field, 3)`], }, ], }, { name: 'rtrim', - description: i18n.translate('monaco.esql.autocomplete.rtrimDoc', { + description: i18n.translate('monaco.esql.definitions.rtrimDoc', { defaultMessage: 'Removes trailing whitespaces from strings.', }), signatures: [ @@ -691,7 +707,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'sin', - description: i18n.translate('monaco.esql.autocomplete.sinDoc', { + description: i18n.translate('monaco.esql.definitions.sinDoc', { defaultMessage: 'Sine trigonometric function.', }), signatures: [ @@ -704,7 +720,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'sinh', - description: i18n.translate('monaco.esql.autocomplete.sinhDoc', { + description: i18n.translate('monaco.esql.definitions.sinhDoc', { defaultMessage: 'Sine hyperbolic function.', }), signatures: [ @@ -717,7 +733,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'sqrt', - description: i18n.translate('monaco.esql.autocomplete.sqrtDoc', { + description: i18n.translate('monaco.esql.definitions.sqrtDoc', { defaultMessage: 'Returns the square root of a number. ', }), signatures: [ @@ -730,7 +746,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'tan', - description: i18n.translate('monaco.esql.autocomplete.tanDoc', { + description: i18n.translate('monaco.esql.definitions.tanDoc', { defaultMessage: 'Tangent trigonometric function.', }), signatures: [ @@ -743,7 +759,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'tanh', - description: i18n.translate('monaco.esql.autocomplete.tanhDoc', { + description: i18n.translate('monaco.esql.definitions.tanhDoc', { defaultMessage: 'Tangent hyperbolic function.', }), signatures: [ @@ -754,167 +770,180 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, ], }, -].sort(({ name: a }, { name: b }) => a.localeCompare(b)); - -function printArguments({ - name, - type, - optional, - reference, -}: { - name: string; - type: string | string[]; - optional?: boolean; - reference?: string; -}): string { - return `${name}${optional ? ':?' : ':'} ${Array.isArray(type) ? type.join(' | ') : type}`; -} - -export const mathCommandDefinition: AutocompleteCommandDefinition[] = - mathCommandFullDefinitions.map(({ name, description, signatures }) => ({ - label: name, - insertText: name, - kind: 1, - detail: description, - documentation: { - value: buildFunctionDocumentation( - signatures.map(({ params, returnType, infiniteParams, examples }) => ({ - declaration: `${name}(${params.map(printArguments).join(', ')}${ - infiniteParams ? ` ,[... ${params.map(printArguments)}]` : '' - }): ${returnType}`, - examples, - })) - ), - }, - sortText: 'C', - })); - -export const aggregationFunctionsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'avg', - insertText: 'avg', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.avgDoc', { - defaultMessage: 'Returns the average of the values in a field', - }), - documentation: { - value: buildDocumentation('avg(grouped[T]): aggregated[T]', [ - 'from index | stats average = avg(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'max', - insertText: 'max', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.maxDoc', { - defaultMessage: 'Returns the maximum value in a field.', - }), - documentation: { - value: buildDocumentation('max(grouped[T]): aggregated[T]', [ - 'from index | stats max = max(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'min', - insertText: 'min', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.minDoc', { - defaultMessage: 'Returns the minimum value in a field.', - }), - documentation: { - value: buildDocumentation('min(grouped[T]): aggregated[T]', [ - 'from index | stats min = min(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'sum', - insertText: 'sum', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.sumDoc', { - defaultMessage: 'Returns the sum of the values in a field.', - }), - documentation: { - value: buildDocumentation('sum(grouped[T]): aggregated[T]', [ - 'from index | stats sum = sum(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'count', - insertText: 'count', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.countDoc', { - defaultMessage: 'Returns the count of the values in a field.', - }), - documentation: { - value: buildDocumentation('count(grouped[T]): aggregated[T]', [ - 'from index | stats count = count(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'count_distinct', - insertText: 'count_distinct', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.countDistinctDoc', { - defaultMessage: 'Returns the count of distinct values in a field.', - }), - documentation: { - value: buildDocumentation('count(grouped[T]): aggregated[T]', [ - 'from index | stats count = count_distinct(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'median', - insertText: 'median', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.medianDoc', { - defaultMessage: 'Returns the 50% percentile.', - }), - documentation: { - value: buildDocumentation('count(grouped[T]): aggregated[T]', [ - 'from index | stats count = median(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'median_absolute_deviation', - insertText: 'median_absolute_deviation', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.medianDeviationDoc', { + { + name: 'cidr_match', + description: i18n.translate('monaco.esql.definitions.cidrMatchDoc', { defaultMessage: - 'Returns the median of each data point’s deviation from the median of the entire sample.', - }), - documentation: { - value: buildDocumentation('count(grouped[T]): aggregated[T]', [ - 'from index | stats count = median_absolute_deviation(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'percentile', - insertText: 'percentile', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.percentiletDoc', { - defaultMessage: 'Returns the n percentile of a field.', - }), - documentation: { - value: buildDocumentation('percentile(grouped[T]): aggregated[T]', [ - 'from index | stats pct = percentile(field, 90)', - ]), - }, - sortText: 'C', - }, -]; + 'The function takes a first parameter of type IP, followed by one or more parameters evaluated to a CIDR specificatione.', + }), + signatures: [ + { + minParams: 2, + params: [ + { name: 'ip', type: 'ip' }, + { name: 'cidr_block', type: 'string' }, + ], + returnType: 'boolean', + examples: [ + 'from index | where cidr_match(ip_field, "127.0.0.1/30")', + 'from index | eval cidr="10.0.0.0/8" | where cidr_match(ip_field, "127.0.0.1/30", cidr)', + ], + }, + ], + }, + { + name: 'mv_avg', + description: i18n.translate('monaco.esql.definitions.mvAvgDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the average of all of the values.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | mv_avg(a)'], + }, + ], + }, + { + name: 'mv_concat', + description: i18n.translate('monaco.esql.definitions.mvConcatDoc', { + defaultMessage: + 'Converts a multivalued string field into a single valued field containing the concatenation of all values separated by a delimiter', + }), + signatures: [ + { + params: [ + { name: 'multivalue', type: 'string[]' }, + { name: 'delimeter', type: 'string' }, + ], + returnType: 'string', + examples: ['row a = ["1", "2", "3"] | mv_concat(a, ", ")'], + }, + ], + }, + { + name: 'mv_count', + description: i18n.translate('monaco.esql.definitions.mvCountDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing a count of the number of values', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'any[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_count(a)'], + }, + ], + }, + { + name: 'mv_dedupe', + description: i18n.translate('monaco.esql.definitions.mvDedupeDoc', { + defaultMessage: 'Removes duplicates from a multivalued field', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'any[]' }], + returnType: 'any[]', + examples: ['row a = [2, 2, 3] | eval mv_dedupe(a)'], + }, + ], + }, + { + name: 'mv_max', + description: i18n.translate('monaco.esql.definitions.mvMaxDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the maximum value.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_max(a)'], + }, + ], + }, + { + name: 'mv_min', + description: i18n.translate('monaco.esql.definitions.mvMinDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the minimum value.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_min(a)'], + }, + ], + }, + { + name: 'mv_median', + description: i18n.translate('monaco.esql.definitions.mvMedianDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the median value.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_median(a)'], + }, + ], + }, + { + name: 'mv_sum', + description: i18n.translate('monaco.esql.definitions.mvSumDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the sum of all of the values.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_sum(a)'], + }, + ], + }, + { + name: 'pi', + description: i18n.translate('monaco.esql.definitions.piDoc', { + defaultMessage: 'The ratio of a circle’s circumference to its diameter.', + }), + signatures: [ + { + params: [], + returnType: 'number', + examples: ['row a = 1 | eval pi()'], + }, + ], + }, + { + name: 'e', + description: i18n.translate('monaco.esql.definitions.eDoc', { + defaultMessage: 'Euler’s number.', + }), + signatures: [ + { + params: [], + returnType: 'number', + examples: ['row a = 1 | eval e()'], + }, + ], + }, + { + name: 'tau', + description: i18n.translate('monaco.esql.definitions.tauDoc', { + defaultMessage: 'The ratio of a circle’s circumference to its radius.', + }), + signatures: [ + { + params: [], + returnType: 'number', + examples: ['row a = 1 | eval tau()'], + }, + ], + }, +] + .sort(({ name: a }, { name: b }) => a.localeCompare(b)) + .map((def) => ({ ...def, supportedCommands: ['eval', 'where', 'row'] })); diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/helpers.ts new file mode 100644 index 0000000000000..409aaf762475e --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/helpers.ts @@ -0,0 +1,101 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CommandDefinition, CommandOptionsDefinition, FunctionDefinition } from './types'; + +export function getCommandOrOptionsSignature({ + name, + signature, + ...rest +}: CommandDefinition | CommandOptionsDefinition): string { + const args = signature.params + .map(({ name: argName, type }) => { + return `<${argName}>`; + }) + .join(' '); + const optionArgs = + 'options' in rest ? rest.options.map(getCommandOrOptionsSignature).join(' ') : ''; + const signatureString = `${name.toUpperCase()} ${args}${ + signature.multipleParams ? `[, ${args}]` : '' + }${optionArgs ? ' ' + optionArgs : ''}`; + if ('wrapped' in rest && rest.wrapped) { + return `${rest.wrapped[0]}${signatureString}${rest.wrapped[1]}${rest.optional ? '?' : ''}`; + } + return signatureString; +} + +export function getFunctionSignatures( + { name, signatures }: FunctionDefinition, + { withTypes }: { withTypes: boolean } = { withTypes: true } +) { + return signatures.map(({ params, returnType, infiniteParams, examples }) => ({ + declaration: `${name}(${params.map((arg) => printArguments(arg, withTypes)).join(', ')}${ + infiniteParams ? ` ,[... ${params.map((arg) => printArguments(arg, withTypes))}]` : '' + })${withTypes ? `: ${returnType}` : ''}`, + examples, + })); +} + +export function getCommandSignature( + { name, signature, options, examples }: CommandDefinition, + { withTypes }: { withTypes: boolean } = { withTypes: true } +) { + return { + declaration: `${name} ${printCommandArguments(signature, withTypes)} ${options.map( + (option) => + `${option.wrapped ? option.wrapped[0] : ''}${option.name} ${printCommandArguments( + option.signature, + withTypes + )}${option.wrapped ? option.wrapped[1] : ''}` + )}`, + examples, + }; +} + +function printCommandArguments( + { multipleParams, params }: CommandDefinition['signature'], + withTypes: boolean +): string { + return `${params.map((arg) => printCommandArgument(arg, withTypes)).join(', `')}${ + multipleParams + ? ` ,[...${params.map((arg) => printCommandArgument(arg, withTypes)).join(', `')}]` + : '' + }`; +} + +function printCommandArgument( + param: CommandDefinition['signature']['params'][number], + withTypes: boolean +): string { + if (!withTypes) { + return param.name || ''; + } + return `${param.name}${param.optional ? ':?' : ':'} ${param.type}${ + param.innerType ? `{${param.innerType}}` : '' + }`; +} + +export function printArguments( + { + name, + type, + optional, + reference, + }: { + name: string; + type: string | string[]; + optional?: boolean; + reference?: string; + }, + withTypes: boolean +): string { + if (!withTypes) { + return name; + } + return `${name}${optional ? ':?' : ':'} ${Array.isArray(type) ? type.join(' | ') : type}`; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/literals.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/literals.ts new file mode 100644 index 0000000000000..3cc61683372a7 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/literals.ts @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { Literals } from './types'; + +export const timeLiterals: Literals[] = [ + { + name: 'year', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.year', { + defaultMessage: 'Year', + }), + }, + { + name: 'years', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.years', { + defaultMessage: 'Years (Plural)', + }), + }, + { + name: 'month', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.month', { + defaultMessage: 'Month', + }), + }, + { + name: 'months', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.months', { + defaultMessage: 'Months (Plural)', + }), + }, + { + name: 'week', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.week', { + defaultMessage: 'Week', + }), + }, + { + name: 'weeks', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.weeks', { + defaultMessage: 'Weeks (Plural)', + }), + }, + { + name: 'day', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.day', { + defaultMessage: 'Day', + }), + }, + { + name: 'days', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.days', { + defaultMessage: 'Days (Plural)', + }), + }, + { + name: 'hour', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.hour', { + defaultMessage: 'Hour', + }), + }, + { + name: 'hours', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.hours', { + defaultMessage: 'Hours (Plural)', + }), + }, + { + name: 'minute', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.minute', { + defaultMessage: 'Minute', + }), + }, + { + name: 'minutes', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.minutes', { + defaultMessage: 'Minutes (Plural)', + }), + }, + { + name: 'second', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.second', { + defaultMessage: 'Second', + }), + }, + { + name: 'seconds', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.seconds', { + defaultMessage: 'Seconds (Plural)', + }), + }, + { + name: 'millisecond', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.millisecond', { + defaultMessage: 'Millisecond', + }), + }, + { + name: 'milliseconds', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.milliseconds', { + defaultMessage: 'Milliseconds (Plural)', + }), + }, +]; + +export const chronoLiterals: Literals[] = [ + 'ALIGNED_DAY_OF_WEEK_IN_MONTH', + 'ALIGNED_DAY_OF_WEEK_IN_YEAR', + 'ALIGNED_WEEK_OF_MONTH', + 'ALIGNED_WEEK_OF_YEAR', + 'AMPM_OF_DAY', + 'CLOCK_HOUR_OF_AMPM', + 'CLOCK_HOUR_OF_DAY', + 'DAY_OF_MONTH', + 'DAY_OF_WEEK', + 'DAY_OF_YEAR', + 'EPOCH_DAY', + 'ERA', + 'HOUR_OF_AMPM', + 'HOUR_OF_DAY', + 'INSTANT_SECONDS', + 'MICRO_OF_DAY', + 'MICRO_OF_SECOND', + 'MILLI_OF_DAY', + 'MILLI_OF_SECOND', + 'MINUTE_OF_DAY', + 'MINUTE_OF_HOUR', + 'MONTH_OF_YEAR', + 'NANO_OF_DAY', + 'NANO_OF_SECOND', + 'OFFSET_SECONDS', + 'PROLEPTIC_MONTH', + 'SECOND_OF_DAY', + 'SECOND_OF_MINUTE', + 'YEAR', + 'YEAR_OF_ERA', +].map((name) => ({ name: `"${name}"`, description: '' })); diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/options.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/options.ts new file mode 100644 index 0000000000000..465d6d25dc32e --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/options.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { isLiteralItem } from '../shared/helpers'; +import { ESQLCommandOption, ESQLMessage } from '../types'; +import { CommandOptionsDefinition } from './types'; + +export const byOption: CommandOptionsDefinition = { + name: 'by', + description: i18n.translate('monaco.esql.definitions.byDoc', { + defaultMessage: 'By', + }), + signature: { + multipleParams: true, + params: [{ name: 'column', type: 'column' }], + }, + optional: true, +}; + +export const metadataOption: CommandOptionsDefinition = { + name: 'metadata', + description: i18n.translate('monaco.esql.definitions.metadataDoc', { + defaultMessage: 'Metadata', + }), + signature: { + multipleParams: true, + params: [{ name: 'column', type: 'column' }], + }, + optional: true, + wrapped: ['[', ']'], +}; + +export const asOption: CommandOptionsDefinition = { + name: 'as', + description: i18n.translate('monaco.esql.definitions.asDoc', { defaultMessage: 'As' }), + signature: { + multipleParams: false, + params: [ + { name: 'oldName', type: 'column' }, + { name: 'newName', type: 'column' }, + ], + }, + optional: false, +}; + +export const onOption: CommandOptionsDefinition = { + name: 'on', + description: i18n.translate('monaco.esql.definitions.onDoc', { defaultMessage: 'On' }), + signature: { + multipleParams: false, + params: [{ name: 'matchingColumn', type: 'column' }], + }, + optional: true, +}; + +export const withOption: CommandOptionsDefinition = { + name: 'with', + description: i18n.translate('monaco.esql.definitions.withDoc', { defaultMessage: 'With' }), + signature: { + multipleParams: true, + params: [{ name: 'assignment', type: 'any' }], + }, + optional: true, +}; + +export const appendSeparatorOption: CommandOptionsDefinition = { + name: 'append_separator', + description: i18n.translate('monaco.esql.definitions.appendSeparatorDoc', { + defaultMessage: + 'The character(s) that separate the appended fields. Default to empty string ("").', + }), + signature: { + multipleParams: false, + params: [{ name: 'separator', type: 'string' }], + }, + optional: true, + skipCommonValidation: true, // tell the validation engine to use only the validate function here + validate: (option: ESQLCommandOption) => { + const messages: ESQLMessage[] = []; + const [firstArg] = option.args; + if ( + !Array.isArray(firstArg) && + (!isLiteralItem(firstArg) || firstArg.literalType !== 'string') + ) { + const value = 'value' in firstArg ? firstArg.value : firstArg.name; + messages.push({ + location: firstArg.location, + text: i18n.translate('monaco.esql.validation.wrongDissectOptionArgumentType', { + defaultMessage: + 'Invalid value for dissect append_separator: expected a string, but was [{value}]', + values: { + value, + }, + }), + type: 'error', + }); + } + return messages; + }, +}; diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/types.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/types.ts new file mode 100644 index 0000000000000..c52f332f3f2eb --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/types.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ESQLCommand, ESQLCommandOption, ESQLMessage, ESQLSingleAstItem } from '../types'; + +export interface FunctionDefinition { + builtin?: boolean; + ignoreAsSuggestion?: boolean; + name: string; + alias?: string[]; + description: string; + supportedCommands: string[]; + signatures: Array<{ + params: Array<{ + name: string; + type: string; + optional?: boolean; + noNestingFunctions?: boolean; + supportsWildcard?: boolean; + }>; + infiniteParams?: boolean; + minParams?: number; + returnType: string; + examples?: string[]; + }>; + warning?: (...args: ESQLSingleAstItem[]) => string | undefined; +} + +export interface CommandBaseDefinition { + name: string; + alias?: string; + description: string; + signature: { + multipleParams: boolean; + // innerType here is useful to drill down the type in case of "column" + // i.e. column of type string + params: Array<{ + name: string; + type: string; + optional?: boolean; + innerType?: string; + values?: string[]; + literalOnly?: boolean; + wildcards?: boolean; + }>; + }; +} + +export interface CommandOptionsDefinition extends CommandBaseDefinition { + wrapped?: string[]; + optional: boolean; + skipCommonValidation?: boolean; + validate?: (option: ESQLCommandOption) => ESQLMessage[]; +} + +export interface CommandDefinition extends CommandBaseDefinition { + options: CommandOptionsDefinition[]; + examples: string[]; + validate?: (option: ESQLCommand) => ESQLMessage[]; +} + +export interface Literals { + name: string; + description: string; +} + +export type SignatureType = + | FunctionDefinition['signatures'][number] + | CommandOptionsDefinition['signature']; +export type SignatureArgType = SignatureType['params'][number]; diff --git a/packages/kbn-monaco/src/esql/lib/ast/hover/index.ts b/packages/kbn-monaco/src/esql/lib/ast/hover/index.ts new file mode 100644 index 0000000000000..b118a7dec5489 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/hover/index.ts @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { monaco } from '../../../../monaco_imports'; +import { getFunctionSignatures } from '../definitions/helpers'; +import { getAstContext } from '../shared/context'; +import { monacoPositionToOffset, getFunctionDefinition, isSourceItem } from '../shared/helpers'; +import { getPolicyHelper } from '../shared/resources_helpers'; +import { ESQLCallbacks } from '../shared/types'; +import type { AstProviderFn } from '../types'; + +export async function getHoverItem( + model: monaco.editor.ITextModel, + position: monaco.Position, + token: monaco.CancellationToken, + astProvider: AstProviderFn, + resourceRetriever?: ESQLCallbacks +) { + const innerText = model.getValue(); + const offset = monacoPositionToOffset(innerText, position); + + const { ast } = await astProvider(innerText); + const astContext = getAstContext(innerText, ast, offset); + const { getPolicyMetadata } = getPolicyHelper(resourceRetriever); + + if (['newCommand', 'list'].includes(astContext.type)) { + return { contents: [] }; + } + + if (astContext.type === 'function') { + const fnDefinition = getFunctionDefinition(astContext.node.name); + + if (fnDefinition) { + return { + contents: [ + { value: getFunctionSignatures(fnDefinition)[0].declaration }, + { value: fnDefinition.description }, + ], + }; + } + } + + if (astContext.type === 'expression') { + if ( + astContext.node && + isSourceItem(astContext.node) && + astContext.node.sourceType === 'policy' + ) { + const policyMetadata = await getPolicyMetadata(astContext.node.name); + if (policyMetadata) { + return { + contents: [ + { + value: `${i18n.translate('monaco.esql.hover.policyIndexes', { + defaultMessage: '**Indexes**', + })}: ${policyMetadata.sourceIndices}`, + }, + { + value: `${i18n.translate('monaco.esql.hover.policyMatchingField', { + defaultMessage: '**Matching field**', + })}: ${policyMetadata.matchField}`, + }, + { + value: `${i18n.translate('monaco.esql.hover.policyEnrichedFields', { + defaultMessage: '**Fields**', + })}: ${policyMetadata.enrichFields}`, + }, + ], + }; + } + } + } + + return { contents: [] }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/constants.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/constants.ts new file mode 100644 index 0000000000000..618928f36bcfb --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/constants.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const EDITOR_MARKER = 'marker_esql_editor'; diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/context.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/context.ts new file mode 100644 index 0000000000000..3a51038ec4e92 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/context.ts @@ -0,0 +1,158 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { + ESQLAstItem, + ESQLSingleAstItem, + ESQLAst, + ESQLFunction, + ESQLCommand, + ESQLCommandOption, +} from '../types'; +import { EDITOR_MARKER } from './constants'; +import { + isOptionItem, + isColumnItem, + getLastCharFromTrimmed, + getFunctionDefinition, +} from './helpers'; + +function findNode(nodes: ESQLAstItem[], offset: number): ESQLSingleAstItem | undefined { + for (const node of nodes) { + if (Array.isArray(node)) { + const ret = findNode(node, offset); + if (ret) { + return ret; + } + } else { + if (node.location.min <= offset && node.location.max >= offset) { + if ('args' in node) { + const ret = findNode(node.args, offset); + // if the found node is the marker, then return its parent + if (ret?.text === EDITOR_MARKER) { + return node; + } + if (ret) { + return ret; + } + } + return node; + } + } + } +} + +function findCommand(ast: ESQLAst, offset: number) { + const commandIndex = ast.findIndex( + ({ location }) => location.min <= offset && location.max >= offset + ); + return ast[commandIndex] || ast[ast.length - 1]; +} + +function findOption(nodes: ESQLAstItem[], offset: number): ESQLCommandOption | undefined { + // this is a similar logic to the findNode, but it check if the command is in root or option scope + for (const node of nodes) { + if (!Array.isArray(node) && isOptionItem(node)) { + if ( + (node.location.min <= offset && node.location.max >= offset) || + (nodes[nodes.length - 1] === node && node.location.max < offset) + ) { + return node; + } + } + } +} + +function isMarkerNode(node: ESQLSingleAstItem | undefined): boolean { + return Boolean(node && isColumnItem(node) && node.name === EDITOR_MARKER); +} + +function cleanMarkerNode(node: ESQLSingleAstItem | undefined): ESQLSingleAstItem | undefined { + return isMarkerNode(node) ? undefined : node; +} + +function isNotMarkerNodeOrArray(arg: ESQLAstItem) { + return Array.isArray(arg) || !isMarkerNode(arg); +} + +function mapToNonMarkerNode(arg: ESQLAstItem): ESQLAstItem { + return Array.isArray(arg) ? arg.filter(isNotMarkerNodeOrArray).map(mapToNonMarkerNode) : arg; +} + +export function removeMarkerArgFromArgsList( + node: T | undefined +) { + if (!node) { + return; + } + if (node.type === 'command' || node.type === 'option' || node.type === 'function') { + return { + ...node, + args: node.args.filter(isNotMarkerNodeOrArray).map(mapToNonMarkerNode), + }; + } + return node; +} + +function findAstPosition(ast: ESQLAst, offset: number) { + const command = findCommand(ast, offset); + if (!command) { + return { command: undefined, node: undefined, option: undefined }; + } + return { + command: removeMarkerArgFromArgsList(command)!, + option: removeMarkerArgFromArgsList(findOption(command.args, offset)), + node: removeMarkerArgFromArgsList(cleanMarkerNode(findNode(command.args, offset))), + }; +} + +function isNotEnrichClauseAssigment(node: ESQLFunction, command: ESQLCommand) { + return node.name !== '=' && command.name !== 'enrich'; +} +function isBuiltinFunction(node: ESQLFunction) { + return Boolean(getFunctionDefinition(node.name)?.builtin); +} + +export function getAstContext(innerText: string, ast: ESQLAst, offset: number) { + const { command, option, node } = findAstPosition(ast, offset); + if (node) { + if (node.type === 'function') { + if (['in', 'not_in'].includes(node.name)) { + // command ... a in ( ) + return { type: 'list' as const, command, node, option }; + } + if (isNotEnrichClauseAssigment(node, command) && !isBuiltinFunction(node)) { + // command ... fn( ) + return { type: 'function' as const, command, node, option }; + } + } + if (node.type === 'option' || option) { + // command ... by + return { type: 'option' as const, command, node, option }; + } + } + + if (!command || (innerText.length <= offset && getLastCharFromTrimmed(innerText) === '|')) { + // // ... | + return { type: 'newCommand' as const, command: undefined, node, option }; + } + + if (command && command.args.length) { + if (option) { + return { type: 'option' as const, command, node, option }; + } + } + + // command a ... OR command a = ... + return { + type: 'expression' as const, + command, + option, + node, + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/helpers.ts new file mode 100644 index 0000000000000..f54849b7e81cf --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/helpers.ts @@ -0,0 +1,451 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { monaco } from '../../../../monaco_imports'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import { builtinFunctions } from '../definitions/builtin'; +import { commandDefinitions } from '../definitions/commands'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { getFunctionSignatures } from '../definitions/helpers'; +import { chronoLiterals, timeLiterals } from '../definitions/literals'; +import { byOption, metadataOption, asOption, onOption, withOption } from '../definitions/options'; +import { + CommandDefinition, + CommandOptionsDefinition, + FunctionDefinition, + SignatureArgType, +} from '../definitions/types'; +import { + ESQLAstItem, + ESQLColumn, + ESQLCommandOption, + ESQLFunction, + ESQLLiteral, + ESQLSingleAstItem, + ESQLSource, + ESQLTimeInterval, +} from '../types'; +import { ESQLRealField, ESQLVariable, ReferenceMaps } from '../validation/types'; +import { removeMarkerArgFromArgsList } from './context'; + +export function isFunctionItem(arg: ESQLAstItem): arg is ESQLFunction { + return arg && !Array.isArray(arg) && arg.type === 'function'; +} + +export function isOptionItem(arg: ESQLAstItem): arg is ESQLCommandOption { + return !Array.isArray(arg) && arg.type === 'option'; +} + +export function isSourceItem(arg: ESQLAstItem): arg is ESQLSource { + return arg && !Array.isArray(arg) && arg.type === 'source'; +} + +export function isColumnItem(arg: ESQLAstItem): arg is ESQLColumn { + return arg && !Array.isArray(arg) && arg.type === 'column'; +} + +export function isLiteralItem(arg: ESQLAstItem): arg is ESQLLiteral { + return arg && !Array.isArray(arg) && arg.type === 'literal'; +} + +export function isTimeIntervalItem(arg: ESQLAstItem): arg is ESQLTimeInterval { + return arg && !Array.isArray(arg) && arg.type === 'timeInterval'; +} + +export function isAssignment(arg: ESQLAstItem): arg is ESQLFunction { + return isFunctionItem(arg) && arg.name === '='; +} + +export function isAssignmentComplete(node: ESQLFunction | undefined) { + const assignExpression = removeMarkerArgFromArgsList(node)?.args?.[1]; + return Boolean(assignExpression && Array.isArray(assignExpression) && assignExpression.length); +} + +export function isExpression(arg: ESQLAstItem): arg is ESQLFunction { + return isFunctionItem(arg) && arg.name !== '='; +} + +export function isIncompleteItem(arg: ESQLAstItem): boolean { + return !arg || (!Array.isArray(arg) && arg.incomplete); +} + +// From Monaco position to linear offset +export function monacoPositionToOffset(expression: string, position: monaco.Position): number { + const lines = expression.split(/\n/); + return lines + .slice(0, position.lineNumber) + .reduce( + (prev, current, index) => + prev + (index === position.lineNumber - 1 ? position.column - 1 : current.length + 1), + 0 + ); +} + +let fnLookups: Map | undefined; +let commandLookups: Map | undefined; + +function buildFunctionLookup() { + if (!fnLookups) { + fnLookups = builtinFunctions + .concat(evalFunctionsDefinitions, statsAggregationFunctionDefinitions) + .reduce((memo, def) => { + memo.set(def.name, def); + if (def.alias) { + for (const alias of def.alias) { + memo.set(alias, def); + } + } + return memo; + }, new Map()); + } + return fnLookups; +} + +type ReasonTypes = 'missingCommand' | 'unsupportedFunction' | 'unknownFunction'; + +export function isSupportedFunction( + name: string, + parentCommand?: string +): { supported: boolean; reason: ReasonTypes | undefined } { + if (!parentCommand) { + return { + supported: false, + reason: 'missingCommand', + }; + } + const fn = buildFunctionLookup().get(name); + const isSupported = Boolean(fn?.supportedCommands.includes(parentCommand)); + return { + supported: isSupported, + reason: isSupported ? undefined : fn ? 'unsupportedFunction' : 'unknownFunction', + }; +} + +export function getFunctionDefinition(name: string) { + return buildFunctionLookup().get(name.toLowerCase()); +} + +function buildCommandLookup() { + if (!commandLookups) { + commandLookups = commandDefinitions.reduce((memo, def) => { + memo.set(def.name, def); + if (def.alias) { + memo.set(def.alias, def); + } + return memo; + }, new Map()); + } + return commandLookups; +} + +export function getCommandDefinition(name: string): CommandDefinition { + return buildCommandLookup().get(name.toLowerCase())!; +} + +export function getAllCommands() { + return Array.from(buildCommandLookup().values()); +} + +export function getCommandOption(name: CommandOptionsDefinition['name']) { + switch (name) { + case 'by': + return byOption; + case 'metadata': + return metadataOption; + case 'as': + return asOption; + case 'on': + return onOption; + case 'with': + return withOption; + default: + return; + } +} + +function compareLiteralType(argTypes: string, item: ESQLLiteral) { + if (item.literalType !== 'string') { + return argTypes === item.literalType; + } + if (argTypes === 'chrono_literal') { + return chronoLiterals.some(({ name }) => name === item.text); + } + return argTypes === item.literalType; +} + +export function getColumnHit( + columnName: string, + { fields, variables }: Pick, + position?: number +): ESQLRealField | ESQLVariable | undefined { + return fields.get(columnName) || variables.get(columnName)?.[0]; +} + +const ARRAY_REGEXP = /\[\]$/; + +export function isArrayType(type: string) { + return ARRAY_REGEXP.test(type); +} + +export function extractSingleType(type: string) { + return type.replace(ARRAY_REGEXP, ''); +} + +export function createMapFromList(arr: T[]): Map { + const arrMap = new Map(); + for (const item of arr) { + arrMap.set(item.name, item); + } + return arrMap; +} + +export function areFieldAndVariableTypesCompatible( + fieldType: string | string[] | undefined, + variableType: string | string[] +) { + if (fieldType == null) { + return false; + } + return fieldType === variableType; +} + +export function printFunctionSignature(arg: ESQLFunction): string { + const fnDef = getFunctionDefinition(arg.name); + if (fnDef) { + const signature = getFunctionSignatures( + { + ...fnDef, + signatures: [ + { + ...fnDef?.signatures[0], + params: arg.args.map((innerArg) => + Array.isArray(innerArg) + ? { name: `InnerArgument[]`, type: '' } + : { name: innerArg.text, type: innerArg.type } + ), + returnType: '', + }, + ], + }, + { withTypes: false } + ); + return signature[0].declaration; + } + return ''; +} + +export function getAllArrayValues(arg: ESQLAstItem) { + const values: string[] = []; + if (Array.isArray(arg)) { + for (const subArg of arg) { + if (Array.isArray(subArg)) { + break; + } + if (subArg.type === 'literal') { + values.push(String(subArg.value)); + } + if (subArg.type === 'column') { + values.push(subArg.name); + } + if (subArg.type === 'timeInterval') { + values.push(subArg.name); + } + if (subArg.type === 'function') { + const signature = printFunctionSignature(subArg); + if (signature) { + values.push(signature); + } + } + } + } + return values; +} + +export function getAllArrayTypes( + arg: ESQLAstItem, + parentCommand: string, + references: ReferenceMaps +) { + const types = []; + if (Array.isArray(arg)) { + for (const subArg of arg) { + if (Array.isArray(subArg)) { + break; + } + if (subArg.type === 'literal') { + types.push(subArg.literalType); + } + if (subArg.type === 'column') { + const hit = getColumnHit(subArg.name, references); + types.push(hit?.type || 'unsupported'); + } + if (subArg.type === 'timeInterval') { + types.push('time_literal'); + } + if (subArg.type === 'function') { + if (isSupportedFunction(subArg.name, parentCommand).supported) { + const fnDef = buildFunctionLookup().get(subArg.name)!; + types.push(fnDef.signatures[0].returnType); + } + } + } + } + return types; +} + +export function inKnownTimeInterval(item: ESQLTimeInterval): boolean { + return timeLiterals.some(({ name }) => name === item.unit.toLowerCase()); +} + +export function isEqualType( + item: ESQLSingleAstItem, + argDef: SignatureArgType, + references: ReferenceMaps, + parentCommand?: string +) { + const argType = 'innerType' in argDef && argDef.innerType ? argDef.innerType : argDef.type; + if (argType === 'any') { + return true; + } + if (item.type === 'literal') { + return compareLiteralType(argType, item); + } + if (item.type === 'list') { + const listType = `${item.values[0].literalType}[]`; + // argType = 'list' means any list value is ok + return argType === item.type || argType === listType; + } + if (item.type === 'function') { + if (isSupportedFunction(item.name, parentCommand).supported) { + const fnDef = buildFunctionLookup().get(item.name)!; + return fnDef.signatures.some((signature) => argType === signature.returnType); + } + } + if (item.type === 'timeInterval') { + return argType === 'time_literal' && inKnownTimeInterval(item); + } + if (item.type === 'column') { + if (argType === 'column') { + // anything goes, so avoid any effort here + return true; + } + const hit = getColumnHit(item.name, references); + if (!hit) { + return false; + } + const wrappedTypes = Array.isArray(hit.type) ? hit.type : [hit.type]; + return wrappedTypes.some((ct) => argType === ct); + } + if (item.type === 'source') { + return item.sourceType === argType; + } +} + +export function endsWithOpenBracket(text: string) { + return /\($/.test(text); +} + +export function isDateFunction(fnName: string) { + // TODO: improve this and rely in signature in the future + return ['to_datetime', 'date_trunc', 'date_parse'].includes(fnName.toLowerCase()); +} + +export function getDateMathOperation() { + return builtinFunctions.filter(({ name }) => ['+', '-'].includes(name)); +} + +export function getDurationItemsWithQuantifier(quantifier: number = 1) { + return timeLiterals + .filter(({ name }) => !/s$/.test(name)) + .map(({ name, ...rest }) => ({ + label: `${quantifier} ${name}`, + insertText: `${quantifier} ${name}`, + ...rest, + })); +} + +function fuzzySearch(fuzzyName: string, resources: IterableIterator) { + const wildCardPosition = getWildcardPosition(fuzzyName); + if (wildCardPosition !== 'none') { + const matcher = getMatcher(fuzzyName, wildCardPosition); + for (const resourceName of resources) { + if (matcher(resourceName)) { + return true; + } + } + } +} + +function getMatcher(name: string, position: 'start' | 'end' | 'middle') { + if (position === 'start') { + const prefix = name.substring(1); + return (resource: string) => resource.endsWith(prefix); + } + if (position === 'end') { + const prefix = name.substring(0, name.length - 1); + return (resource: string) => resource.startsWith(prefix); + } + const [prefix, postFix] = name.split('*'); + return (resource: string) => resource.startsWith(prefix) && resource.endsWith(postFix); +} + +function getWildcardPosition(name: string) { + if (!hasWildcard(name)) { + return 'none'; + } + if (name.startsWith('*')) { + return 'start'; + } + if (name.endsWith('*')) { + return 'end'; + } + return 'middle'; +} + +export function hasWildcard(name: string) { + return name.includes('*'); +} +export function hasCCSSource(name: string) { + return name.includes(':'); +} + +export function columnExists( + column: ESQLColumn, + { fields, variables }: Pick +) { + if (fields.has(column.name) || variables.has(column.name)) { + return { hit: true, nameHit: column.name }; + } + if (column.quoted) { + const trimmedName = column.name.replace(/\s/g, ''); + if (variables.has(trimmedName)) { + return { hit: true, nameHit: trimmedName }; + } + } + if ( + Boolean(fuzzySearch(column.name, fields.keys()) || fuzzySearch(column.name, variables.keys())) + ) { + return { hit: true, nameHit: column.name }; + } + return { hit: false }; +} + +export function sourceExists(index: string, sources: Set) { + if (sources.has(index)) { + return true; + } + return Boolean(fuzzySearch(index, sources.keys())); +} + +export function getLastCharFromTrimmed(text: string) { + return text[text.trimEnd().length - 1]; +} + +export function isRestartingExpression(text: string) { + return getLastCharFromTrimmed(text) === ','; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/resources_helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/resources_helpers.ts new file mode 100644 index 0000000000000..fcd4cbb0737ff --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/resources_helpers.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ESQLCallbacks } from './types'; +import type { ESQLRealField } from '../validation/types'; + +export function getFieldsByTypeHelper(queryText: string, resourceRetriever?: ESQLCallbacks) { + const cacheFields = new Map(); + const getFields = async () => { + if (!cacheFields.size) { + const fieldsOfType = await resourceRetriever?.getFieldsFor?.({ query: queryText }); + for (const field of fieldsOfType || []) { + cacheFields.set(field.name, field); + } + } + }; + return { + getFieldsByType: async (expectedType: string | string[] = 'any', ignored: string[] = []) => { + const types = Array.isArray(expectedType) ? expectedType : [expectedType]; + await getFields(); + return ( + Array.from(cacheFields.values()) + ?.filter(({ name, type }) => { + const ts = Array.isArray(type) ? type : [type]; + return ( + !ignored.includes(name) && ts.some((t) => types[0] === 'any' || types.includes(t)) + ); + }) + .map(({ name }) => name) || [] + ); + }, + getFieldsMap: async () => { + await getFields(); + const cacheCopy = new Map(); + cacheFields.forEach((value, key) => cacheCopy.set(key, value)); + return cacheCopy; + }, + }; +} + +export function getPolicyHelper(resourceRetriever?: ESQLCallbacks) { + const getPolicies = async () => { + return (await resourceRetriever?.getPolicies?.()) || []; + }; + return { + getPolicies: async () => { + const policies = await getPolicies(); + return policies; + }, + getPolicyMetadata: async (policyName: string) => { + const policies = await getPolicies(); + return policies.find(({ name }) => name === policyName); + }, + }; +} + +export function getSourcesHelper(resourceRetriever?: ESQLCallbacks) { + return async () => { + return (await resourceRetriever?.getSources?.()) || []; + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/types.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/types.ts new file mode 100644 index 0000000000000..ceb507f59784a --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/types.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** @internal **/ +type CallbackFn = (ctx?: Options) => Result[] | Promise; + +/** @public **/ +export interface ESQLCallbacks { + getSources?: CallbackFn<{}, { name: string; hidden: boolean }>; + getFieldsFor?: CallbackFn<{ query: string }, { name: string; type: string }>; + getPolicies?: CallbackFn< + {}, + { name: string; sourceIndices: string[]; matchField: string; enrichFields: string[] } + >; + getPolicyFields?: CallbackFn; + getPolicyMatchingField?: CallbackFn; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/variables.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/variables.ts new file mode 100644 index 0000000000000..3f93ce50b71c3 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/variables.ts @@ -0,0 +1,172 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ESQLColumn, ESQLAstItem, ESQLCommand, ESQLCommandOption } from '../types'; +import type { ESQLVariable, ESQLRealField } from '../validation/types'; +import { EDITOR_MARKER } from './constants'; +import { + isColumnItem, + isAssignment, + isExpression, + isOptionItem, + isFunctionItem, + getFunctionDefinition, +} from './helpers'; + +function addToVariableOccurrencies(variables: Map, instance: ESQLVariable) { + if (!variables.has(instance.name)) { + variables.set(instance.name, []); + } + const variablesOccurrencies = variables.get(instance.name)!; + variablesOccurrencies.push(instance); +} + +function replaceTrimmedVariable( + variables: Map, + newRef: ESQLColumn, + oldRef: ESQLVariable[] +) { + // now replace the existing trimmed version with this original one + addToVariableOccurrencies(variables, { + name: newRef.name, + type: oldRef[0].type, + location: newRef.location, + }); + // remove the trimmed one + variables.delete(oldRef[0].name); +} + +function addToVariables( + oldArg: ESQLAstItem, + newArg: ESQLAstItem, + fields: Map, + variables: Map +) { + if (isColumnItem(oldArg) && isColumnItem(newArg)) { + const newVariable: ESQLVariable = { + name: newArg.name, + type: 'number' /* fallback to number */, + location: newArg.location, + }; + // Now workout the exact type + // it can be a rename of another variable as well + let oldRef = fields.get(oldArg.name) || variables.get(oldArg.name); + if (oldRef) { + addToVariableOccurrencies(variables, newVariable); + newVariable.type = Array.isArray(oldRef) ? oldRef[0].type : oldRef.type; + } else if (oldArg.quoted) { + // a last attempt in case the user tried to rename an expression: + // trim every space and try a new hit + const expressionTrimmedRef = oldArg.name.replace(/\s/g, ''); + oldRef = variables.get(expressionTrimmedRef); + if (oldRef) { + addToVariableOccurrencies(variables, newVariable); + newVariable.type = oldRef[0].type; + replaceTrimmedVariable(variables, oldArg, oldRef); + } + } + } +} + +function getAssignRightHandSideType(item: ESQLAstItem, fields: Map) { + if (Array.isArray(item)) { + const firstArg = item[0]; + if (Array.isArray(firstArg) || !firstArg) { + return; + } + if (firstArg.type === 'literal') { + return firstArg.literalType; + } + if (isColumnItem(firstArg)) { + const field = fields.get(firstArg.name); + if (field) { + return field.type; + } + } + if (isFunctionItem(firstArg)) { + const fnDefinition = getFunctionDefinition(firstArg.name); + return fnDefinition?.signatures[0].returnType; + } + return firstArg.type; + } +} + +export function excludeVariablesFromCurrentCommand( + commands: ESQLCommand[], + currentCommand: ESQLCommand, + fieldsMap: Map +) { + const anyVariables = collectVariables(commands, fieldsMap); + const currentCommandVariables = collectVariables([currentCommand], fieldsMap); + const resultVariables = new Map(); + anyVariables.forEach((value, key) => { + if (!currentCommandVariables.has(key)) { + resultVariables.set(key, value); + } + }); + return resultVariables; +} + +export function collectVariables( + commands: ESQLCommand[], + fields: Map +): Map { + const variables = new Map(); + for (const command of commands) { + if (['row', 'eval', 'stats'].includes(command.name)) { + const assignOperations = command.args.filter(isAssignment); + for (const assignOperation of assignOperations) { + if (isColumnItem(assignOperation.args[0])) { + const rightHandSideArgType = getAssignRightHandSideType(assignOperation.args[1], fields); + addToVariableOccurrencies(variables, { + name: assignOperation.args[0].name, + type: rightHandSideArgType || 'number' /* fallback to number */, + location: assignOperation.args[0].location, + }); + } + } + const expressionOperations = command.args.filter(isExpression); + for (const expressionOperation of expressionOperations) { + if (!expressionOperation.text.includes(EDITOR_MARKER)) { + // just save the entire expression as variable string + const expressionType = 'number'; + addToVariableOccurrencies(variables, { + name: expressionOperation.text, + type: expressionType, + location: expressionOperation.location, + }); + } + } + } + if (command.name === 'enrich') { + const commandOptionsWithAssignment = command.args.filter( + (arg) => isOptionItem(arg) && arg.name === 'with' + ) as ESQLCommandOption[]; + for (const commandOption of commandOptionsWithAssignment) { + for (const assignFn of commandOption.args) { + if (isFunctionItem(assignFn)) { + const [newArg, oldArg] = assignFn?.args || []; + if (Array.isArray(oldArg)) { + addToVariables(oldArg[0], newArg, fields, variables); + } + } + } + } + } + if (command.name === 'rename') { + const commandOptionsWithAssignment = command.args.filter( + (arg) => isOptionItem(arg) && arg.name === 'as' + ) as ESQLCommandOption[]; + for (const commandOption of commandOptionsWithAssignment) { + const [oldArg, newArg] = commandOption.args; + addToVariables(oldArg, newArg, fields, variables); + } + } + } + return variables; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/signature/index.ts b/packages/kbn-monaco/src/esql/lib/ast/signature/index.ts new file mode 100644 index 0000000000000..a3202591a9c7a --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/signature/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { monaco } from '../../../../monaco_imports'; +import type { AstProviderFn } from '../types'; + +export function getSignatureHelp( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.SignatureHelpContext, + astProvider: AstProviderFn +): monaco.languages.SignatureHelpResult { + return { + value: { signatures: [], activeParameter: 0, activeSignature: 0 }, + dispose: () => {}, + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/types.ts b/packages/kbn-monaco/src/esql/lib/ast/types.ts new file mode 100644 index 0000000000000..6c241270de457 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/types.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EditorError } from '../../../types'; + +export type ESQLAst = ESQLCommand[]; + +export type ESQLSingleAstItem = + | ESQLFunction + | ESQLCommandOption + | ESQLSource + | ESQLColumn + | ESQLTimeInterval + | ESQLList + | ESQLLiteral; + +export type ESQLAstItem = ESQLSingleAstItem | ESQLAstItem[]; + +export interface ESQLLocation { + min: number; + max: number; +} + +interface ESQLAstBaseItem { + name: string; + text: string; + location: ESQLLocation; + incomplete: boolean; +} + +export interface ESQLCommand extends ESQLAstBaseItem { + type: 'command'; + args: ESQLAstItem[]; +} + +export interface ESQLCommandOption extends ESQLAstBaseItem { + type: 'option'; + args: ESQLAstItem[]; +} + +export interface ESQLFunction extends ESQLAstBaseItem { + type: 'function'; + args: ESQLAstItem[]; +} + +export interface ESQLTimeInterval extends ESQLAstBaseItem { + type: 'timeInterval'; + unit: string; + quantity: number; +} + +export interface ESQLSource extends ESQLAstBaseItem { + type: 'source'; + sourceType: 'index' | 'policy'; +} + +export interface ESQLColumn extends ESQLAstBaseItem { + type: 'column'; + quoted: boolean; +} + +export interface ESQLList extends ESQLAstBaseItem { + type: 'list'; + values: ESQLLiteral[]; +} + +export interface ESQLLiteral extends ESQLAstBaseItem { + type: 'literal'; + literalType: 'string' | 'number' | 'boolean' | 'null'; + value: string | number; +} + +export interface ESQLMessage { + type: 'error' | 'warning'; + text: string; + location: ESQLLocation; +} + +export type AstProviderFn = ( + text: string | undefined +) => Promise<{ ast: ESQLAst; errors: EditorError[] }>; diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/errors.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/errors.ts new file mode 100644 index 0000000000000..16913677c4890 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/errors.ts @@ -0,0 +1,217 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { ESQLLocation, ESQLMessage } from '../types'; +import type { ErrorTypes, ErrorValues } from './types'; + +function getMessageAndTypeFromId({ + messageId, + values, +}: { + messageId: K; + values: ErrorValues; +}): { message: string; type?: 'error' | 'warning' } { + // Use a less strict type instead of doing a typecast on each message type + const out = values as unknown as Record; + // i18n validation wants to the values prop to be declared inline, so need to unpack and redeclare again all props + switch (messageId) { + case 'wrongArgumentType': + return { + message: i18n.translate('monaco.esql.validation.wrongArgumentType', { + defaultMessage: + 'Argument of [{name}] must be [{argType}], found value [{value}] type [{givenType}]', + values: { + name: out.name, + argType: out.argType, + value: out.value, + givenType: out.givenType, + }, + }), + }; + case 'unknownColumn': + return { + message: i18n.translate('monaco.esql.validation.unknownColumn', { + defaultMessage: 'Unknown column [{name}]', + values: { name: out.name }, + }), + }; + case 'unknownIndex': + return { + message: i18n.translate('monaco.esql.validation.unknownIndex', { + defaultMessage: 'Unknown index [{name}]', + values: { name: out.name }, + }), + }; + case 'unknownFunction': + return { + message: i18n.translate('monaco.esql.validation.missingFunction', { + defaultMessage: 'Unknown function [{name}]', + values: { name: out.name }, + }), + }; + case 'wrongArgumentNumber': + return { + message: i18n.translate('monaco.esql.validation.wrongArgumentNumber', { + defaultMessage: + 'Error building [{fn}]: expects exactly {numArgs, plural, one {one argument} other {{numArgs} arguments}}, passed {passedArgs} instead.', + values: { fn: out.fn, numArgs: out.numArgs, passedArgs: out.passedArgs }, + }), + }; + case 'noNestedArgumentSupport': + return { + message: i18n.translate('monaco.esql.validation.noNestedArgumentSupport', { + defaultMessage: + "Aggregate function's parameters must be an attribute or literal; found [{name}] of type [{argType}]", + values: { name: out.name, argType: out.argType }, + }), + }; + case 'shadowFieldType': + return { + message: i18n.translate('monaco.esql.validation.typeOverwrite', { + defaultMessage: + 'Column [{field}] of type {fieldType} has been overwritten as new type: {newType}', + values: { field: out.field, fieldType: out.fieldType, newType: out.newType }, + }), + type: 'warning', + }; + case 'unsupportedColumnTypeForCommand': + return { + message: i18n.translate('monaco.esql.validation.unsupportedColumnTypeForCommand', { + defaultMessage: + '{command} only supports {type} {typeCount, plural, one {type} other {types}} values, found [{column}] of type {givenType}', + values: { + command: out.command, + type: out.type, + typeCount: out.typeCount, + column: out.column, + givenType: out.givenType, + }, + }), + }; + case 'unknownOption': + return { + message: i18n.translate('monaco.esql.validation.unknownOption', { + defaultMessage: 'Invalid option for {command}: [{option}]', + values: { + command: out.command, + option: out.option, + }, + }), + }; + case 'unsupportedFunction': + return { + message: i18n.translate('monaco.esql.validation.unsupportedFunction', { + defaultMessage: '{command} does not support function {name}', + values: { + command: out.command, + name: out.name, + }, + }), + }; + case 'unknownInterval': + return { + message: i18n.translate('monaco.esql.validation.unknownInterval', { + defaultMessage: `Unexpected time interval qualifier: '{value}'`, + values: { + value: out.value, + }, + }), + }; + case 'unsupportedTypeForCommand': + return { + message: i18n.translate('monaco.esql.validation.unsupportedTypeForCommand', { + defaultMessage: '{command} does not support [{type}] in expression [{value}]', + values: { + command: out.command, + type: out.type, + value: out.value, + }, + }), + }; + case 'unknownPolicy': + return { + message: i18n.translate('monaco.esql.validation.unknownPolicy', { + defaultMessage: 'Unknown policy [{name}]', + values: { + name: out.name, + }, + }), + }; + case 'unknownAggregateFunction': + return { + message: i18n.translate('monaco.esql.validation.unknowAggregateFunction', { + defaultMessage: '{command} expects an aggregate function, found [{value}]', + values: { + command: out.command, + value: out.value, + }, + }), + }; + case 'wildcardNotSupportedForCommand': + return { + message: i18n.translate('monaco.esql.validation.wildcardNotSupportedForCommand', { + defaultMessage: 'Using wildcards (*) in {command} is not allowed [{value}]', + values: { + command: out.command, + value: out.value, + }, + }), + }; + case 'noWildcardSupportAsArg': + return { + message: i18n.translate('monaco.esql.validation.wildcardNotSupportedForFunction', { + defaultMessage: 'Using wildcards (*) in {name} is not allowed', + values: { + name: out.name, + }, + }), + }; + case 'ccsNotSupportedForCommand': + return { + message: i18n.translate('monaco.esql.validation.ccsNotSupportedForCommand', { + defaultMessage: 'ES|QL does not yet support querying remote indices [{value}]', + values: { + value: out.value, + }, + }), + }; + case 'unsupportedFieldType': + return { + message: i18n.translate('monaco.esql.validation.unsupportedFieldType', { + defaultMessage: + 'Field [{field}] cannot be retrieved, it is unsupported or not indexed; returning null', + values: { + field: out.field, + }, + }), + type: 'warning', + }; + } + return { message: '' }; +} + +export function getMessageFromId({ + locations, + ...payload +}: { + messageId: K; + values: ErrorValues; + locations: ESQLLocation; +}): ESQLMessage { + const { message, type = 'error' } = getMessageAndTypeFromId(payload); + return createMessage(type, message, locations); +} + +export function createMessage(type: 'error' | 'warning', message: string, location: ESQLLocation) { + return { + type, + text: message, + location, + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/helpers.ts new file mode 100644 index 0000000000000..51015e0d8d09d --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/helpers.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ESQLAst } from '../types'; +import type { ESQLPolicy } from './types'; + +export function buildQueryForFieldsFromSource(queryString: string, ast: ESQLAst) { + const firstCommand = ast[0]; + return queryString.substring(0, firstCommand.location.max + 1); +} + +export function buildQueryForFieldsInPolicies(policies: ESQLPolicy[]) { + return `from ${policies + .flatMap(({ sourceIndices }) => sourceIndices) + .join(', ')} | keep ${policies.flatMap(({ enrichFields }) => enrichFields).join(', ')}`; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/resources.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/resources.ts new file mode 100644 index 0000000000000..24c6de0f7db6f --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/resources.ts @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { nonNullable } from '../ast_helpers'; +import { createMapFromList, isSourceItem } from '../shared/helpers'; +import { + getFieldsByTypeHelper, + getPolicyHelper, + getSourcesHelper, +} from '../shared/resources_helpers'; +import type { ESQLCallbacks } from '../shared/types'; +import type { ESQLCommand } from '../types'; +import { buildQueryForFieldsFromSource, buildQueryForFieldsInPolicies } from './helpers'; +import type { ESQLRealField, ESQLPolicy } from './types'; + +export async function retrieveFields( + queryString: string, + commands: ESQLCommand[], + callbacks?: ESQLCallbacks +): Promise> { + if (!callbacks || commands.length < 1) { + return new Map(); + } + if (commands[0].name === 'row') { + return new Map(); + } + const customQuery = buildQueryForFieldsFromSource(queryString, commands); + return await getFieldsByTypeHelper(customQuery, callbacks).getFieldsMap(); +} + +export async function retrievePolicies( + commands: ESQLCommand[], + callbacks?: ESQLCallbacks +): Promise> { + if (!callbacks || commands.every(({ name }) => name !== 'enrich')) { + return new Map(); + } + + const policies = await getPolicyHelper(callbacks).getPolicies(); + return createMapFromList(policies); +} + +export async function retrieveSources( + commands: ESQLCommand[], + callbacks?: ESQLCallbacks +): Promise> { + if (!callbacks || commands.length < 1) { + return new Set(); + } + if (['row', 'show'].includes(commands[0].name)) { + return new Set(); + } + const sources = await getSourcesHelper(callbacks)(); + return new Set(sources.map(({ name }) => name)); +} + +export async function retrievePoliciesFields( + commands: ESQLCommand[], + policies: Map, + callbacks?: ESQLCallbacks +): Promise> { + if (!callbacks) { + return new Map(); + } + const enrichCommands = commands.filter(({ name }) => name === 'enrich'); + if (!enrichCommands.length) { + return new Map(); + } + const policyNames = enrichCommands + .map(({ args }) => (isSourceItem(args[0]) ? args[0].name : undefined)) + .filter(nonNullable); + if (!policyNames.every((name) => policies.has(name))) { + return new Map(); + } + + const customQuery = buildQueryForFieldsInPolicies( + policyNames.map((name) => policies.get(name)) as ESQLPolicy[] + ); + return await getFieldsByTypeHelper(customQuery, callbacks).getFieldsMap(); +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/types.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/types.ts new file mode 100644 index 0000000000000..07b7e504ab1be --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/types.ts @@ -0,0 +1,127 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EditorError } from '../../../../types'; +import { ESQLMessage, ESQLLocation } from '../types'; + +export interface ESQLVariable { + name: string; + type: string; + location: ESQLLocation; +} + +export interface ESQLRealField { + name: string; + type: string; +} + +export interface ESQLPolicy { + name: string; + sourceIndices: string[]; + matchField: string; + enrichFields: string[]; +} + +export interface ReferenceMaps { + sources: Set; + variables: Map; + fields: Map; + policies: Map; +} + +export interface ValidationErrors { + wrongArgumentType: { + message: string; + type: { + name: string; + argType: string; + value: string | number | Date; + givenType: string; + }; + }; + wrongArgumentNumber: { + message: string; + type: { fn: string; numArgs: number; passedArgs: number }; + }; + unknownColumn: { + message: string; + type: { name: string | number }; + }; + unknownFunction: { + message: string; + type: { name: string }; + }; + unknownIndex: { + message: string; + type: { name: string }; + }; + noNestedArgumentSupport: { + message: string; + type: { name: string; argType: string }; + }; + unsupportedFunction: { + message: string; + type: { name: string; command: string }; + }; + shadowFieldType: { + message: string; + type: { field: string; fieldType: string; newType: string }; + }; + unsupportedColumnTypeForCommand: { + message: string; + type: { command: string; type: string; typeCount: number; givenType: string; column: string }; + }; + unknownOption: { + message: string; + type: { command: string; option: string }; + }; + wrongOptionArgumentType: { + message: string; + type: { command: string; option: string; type: string; givenValue: string }; + }; + unknownInterval: { + message: string; + type: { value: string }; + }; + unsupportedTypeForCommand: { + message: string; + type: { command: string; value: string; type: string }; + }; + unknownPolicy: { + message: string; + type: { name: string }; + }; + unknownAggregateFunction: { + message: string; + type: { command: string; value: string }; + }; + wildcardNotSupportedForCommand: { + message: string; + type: { command: string; value: string }; + }; + noWildcardSupportAsArg: { + message: string; + type: { name: string }; + }; + ccsNotSupportedForCommand: { + message: string; + type: { value: string }; + }; + unsupportedFieldType: { + message: string; + type: { field: string }; + }; +} + +export type ErrorTypes = keyof ValidationErrors; +export type ErrorValues = ValidationErrors[K]['type']; + +export interface ValidationResult { + errors: Array; + warnings: ESQLMessage[]; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/validation.test.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/validation.test.ts new file mode 100644 index 0000000000000..8da25c2b46b8a --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/validation.test.ts @@ -0,0 +1,1440 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CharStreams } from 'antlr4ts'; +import { getParser, ROOT_STATEMENT } from '../../antlr_facade'; +// import { mathCommandDefinition } from '../../autocomplete/autocomplete_definitions'; +// import { getDurationItemsWithQuantifier } from '../../autocomplete/helpers'; +import { AstListener } from '../ast_factory'; +import { validateAst } from './validation'; +import { ESQLAst } from '../types'; +import { ESQLErrorListener } from '../../monaco/esql_error_listener'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { getFunctionSignatures } from '../definitions/helpers'; +import { FunctionDefinition } from '../definitions/types'; +import { chronoLiterals, timeLiterals } from '../definitions/literals'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import capitalize from 'lodash/capitalize'; +import { EditorError } from '../../../../types'; + +function getCallbackMocks() { + return { + getFieldsFor: jest.fn(async ({ query }) => + /enrich/.test(query) + ? [ + { name: 'otherField', type: 'string' }, + { name: 'yetAnotherField', type: 'number' }, + ] + : /unsupported_index/.test(query) + ? [{ name: 'unsupported_field', type: 'unsupported' }] + : [ + ...['string', 'number', 'date', 'boolean', 'ip'].map((type) => ({ + name: `${type}Field`, + type, + })), + { name: 'any#Char$ field', type: 'number' }, + { name: 'kubernetes.something.something', type: 'number' }, + { + name: `listField`, + type: `list`, + }, + { name: '@timestamp', type: 'date' }, + ] + ), + getSources: jest.fn(async () => + ['a', 'index', 'otherIndex', '.secretIndex', 'my-index', 'unsupported_index'].map((name) => ({ + name, + hidden: name.startsWith('.'), + })) + ), + getPolicies: jest.fn(async () => [ + { + name: 'policy', + sourceIndices: ['enrichIndex1'], + matchField: 'otherStringField', + enrichFields: ['otherField', 'yetAnotherField'], + }, + ]), + }; +} + +const toDoubleSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_double')!; +const toStringSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_string')!; +const toDateSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_datetime')!; +const toBooleanSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_boolean')!; +const toIpSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_ip')!; + +const toAvgSignature = statsAggregationFunctionDefinitions.find(({ name }) => name === 'avg')!; + +const nestedFunctions = { + number: prepareNestedFunction(toDoubleSignature), + string: prepareNestedFunction(toStringSignature), + date: prepareNestedFunction(toDateSignature), + boolean: prepareNestedFunction(toBooleanSignature), + ip: prepareNestedFunction(toIpSignature), +}; + +const literals = { + chrono_literal: chronoLiterals[0].name, + time_literal: timeLiterals[0].name, +}; +function getLiteralType(typeString: 'chrono_literal' | 'time_literal') { + if (typeString === 'chrono_literal') { + return literals[typeString]; + } + return `1 ${literals[typeString]}`; +} +function getFieldName( + typeString: 'string' | 'number' | 'date' | 'boolean' | 'ip', + { useNestedFunction, isStats }: { useNestedFunction: boolean; isStats: boolean } +) { + if (useNestedFunction && isStats) { + return prepareNestedFunction(toAvgSignature); + } + return useNestedFunction ? nestedFunctions[typeString] : `${typeString}Field`; +} + +function getMultiValue(type: 'string[]' | 'number[]' | 'boolean[]' | 'any[]') { + if (/string|any/.test(type)) { + return `["a", "b", "c"]`; + } + if (/number/.test(type)) { + return `[1, 2, 3]`; + } + return `[true, false]`; +} + +function prepareNestedFunction(fnSignature: FunctionDefinition): string { + return getFunctionSignatures( + { + ...fnSignature, + signatures: [ + { + ...fnSignature?.signatures[0]!, + params: getFieldMapping(fnSignature?.signatures[0]!.params), + }, + ], + }, + { withTypes: false } + )[0].declaration; +} +function getFieldMapping( + params: FunctionDefinition['signatures'][number]['params'], + { useNestedFunction, useLiterals }: { useNestedFunction: boolean; useLiterals: boolean } = { + useNestedFunction: false, + useLiterals: true, + } +) { + return params.map(({ name: _name, type, ...rest }) => { + const typeString: string = type; + if (['string', 'number', 'date', 'boolean', 'ip'].includes(typeString)) { + return { + name: getFieldName(typeString as 'string' | 'number' | 'date' | 'boolean' | 'ip', { + useNestedFunction, + isStats: !useLiterals, + }), + type, + ...rest, + }; + } + if (/literal$/.test(typeString) && useLiterals) { + return { + name: getLiteralType(typeString as 'chrono_literal' | 'time_literal'), + type, + ...rest, + }; + } + if (['string[]', 'number[]', 'boolean[]', 'any[]'].includes(typeString)) { + return { + name: getMultiValue(typeString as 'string[]' | 'number[]' | 'boolean[]' | 'any[]'), + type, + ...rest, + }; + } + return { name: 'stringField', type, ...rest }; + }); +} + +describe('validation logic', () => { + const getAstAndErrors = async ( + text: string | undefined + ): Promise<{ + errors: EditorError[]; + ast: ESQLAst; + }> => { + if (text == null) { + return { ast: [], errors: [] }; + } + const errorListener = new ESQLErrorListener(); + const parseListener = new AstListener(); + const parser = getParser(CharStreams.fromString(text), errorListener, parseListener); + + parser[ROOT_STATEMENT](); + + return { ...parseListener.getAst(), errors: errorListener.getErrors() }; + }; + + function testErrorsAndWarningsFn( + statement: string, + expectedErrors: string[] = [], + expectedWarnings: string[] = [], + { only, skip }: { only?: boolean; skip?: boolean } = {} + ) { + const testFn = only ? it.only : skip ? it.skip : it; + testFn( + `${statement} => ${expectedErrors.length} errors, ${expectedWarnings.length} warnings`, + async () => { + const callbackMocks = getCallbackMocks(); + const { warnings, errors } = await validateAst(statement, getAstAndErrors, callbackMocks); + expect(errors.map((e) => ('message' in e ? e.message : e.text))).toEqual(expectedErrors); + expect(warnings.map((w) => w.text)).toEqual(expectedWarnings); + } + ); + } + + type TestArgs = [string, string[], string[]?]; + + // Make only and skip work with our custom wrapper + const testErrorsAndWarnings = Object.assign(testErrorsAndWarningsFn, { + skip: (...args: TestArgs) => { + const warningArgs = [[]].slice(args.length - 2); + return testErrorsAndWarningsFn( + ...((args.length > 1 ? [...args, ...warningArgs] : args) as TestArgs), + { + skip: true, + } + ); + }, + only: (...args: TestArgs) => { + const warningArgs = [[]].slice(args.length - 2); + return testErrorsAndWarningsFn( + ...((args.length > 1 ? [...args, ...warningArgs] : args) as TestArgs), + { + only: true, + } + ); + }, + }); + + describe('ESQL query should start with a source command', () => { + ['eval', 'stats', 'rename', 'limit', 'keep', 'drop', 'mv_expand', 'dissect', 'grok'].map( + (command) => + testErrorsAndWarnings(command, [ + `SyntaxError: expected {FROM, ROW, SHOW} but found "${command}"`, + ]) + ); + }); + + describe('from', () => { + testErrorsAndWarnings('f', ['SyntaxError: expected {FROM, ROW, SHOW} but found "f"']); + testErrorsAndWarnings(`from `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings(`from index,`, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings(`from assignment = 1`, [ + 'SyntaxError: expected {, PIPE, COMMA, OPENING_BRACKET} but found "="', + 'Unknown index [assignment]', + ]); + testErrorsAndWarnings(`from index`, []); + testErrorsAndWarnings(`FROM index`, []); + testErrorsAndWarnings(`FrOm index`, []); + testErrorsAndWarnings('from `index`', []); + + testErrorsAndWarnings(`from index, otherIndex`, []); + testErrorsAndWarnings(`from index, missingIndex`, ['Unknown index [missingIndex]']); + testErrorsAndWarnings(`from fn()`, ['Unknown index [fn()]']); + testErrorsAndWarnings(`from average()`, ['Unknown index [average()]']); + testErrorsAndWarnings(`from index [METADATA _id]`, []); + testErrorsAndWarnings(`from index [metadata _id]`, []); + + testErrorsAndWarnings(`from index [METADATA _id, _source]`, []); + testErrorsAndWarnings(`from index [metadata _id, _source] [METADATA _id2]`, [ + 'SyntaxError: expected {, PIPE} but found "["', + ]); + testErrorsAndWarnings(`from index metadata _id`, [ + 'SyntaxError: expected {, PIPE, COMMA, OPENING_BRACKET} but found "metadata"', + ]); + testErrorsAndWarnings(`from index (metadata _id)`, [ + 'SyntaxError: expected {, PIPE, COMMA, OPENING_BRACKET} but found "(metadata"', + ]); + testErrorsAndWarnings(`from ind*, other*`, []); + testErrorsAndWarnings(`from index*`, []); + testErrorsAndWarnings(`from *ex`, []); + testErrorsAndWarnings(`from in*ex`, []); + testErrorsAndWarnings(`from ind*ex`, []); + testErrorsAndWarnings(`from indexes*`, ['Unknown index [indexes*]']); + + testErrorsAndWarnings(`from remote-*:indexes*`, [ + 'ES|QL does not yet support querying remote indices [remote-*:indexes*]', + ]); + testErrorsAndWarnings(`from remote-*:indexes`, [ + 'ES|QL does not yet support querying remote indices [remote-*:indexes]', + ]); + testErrorsAndWarnings(`from remote-ccs:indexes`, [ + 'ES|QL does not yet support querying remote indices [remote-ccs:indexes]', + ]); + testErrorsAndWarnings(`from a, remote-ccs:indexes`, [ + 'ES|QL does not yet support querying remote indices [remote-ccs:indexes]', + ]); + testErrorsAndWarnings(`from remote-ccs:indexes [METADATA _id]`, [ + 'ES|QL does not yet support querying remote indices [remote-ccs:indexes]', + ]); + testErrorsAndWarnings(`from *:indexes [METADATA _id]`, [ + 'ES|QL does not yet support querying remote indices [*:indexes]', + ]); + testErrorsAndWarnings('from .secretIndex', []); + testErrorsAndWarnings('from my-index', []); + }); + + describe('row', () => { + testErrorsAndWarnings('row', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('row missing_column', ['Unknown column [missing_column]']); + testErrorsAndWarnings('row fn()', ['Unknown function [fn]']); + testErrorsAndWarnings('row missing_column, missing_column2', [ + 'Unknown column [missing_column]', + 'Unknown column [missing_column2]', + ]); + testErrorsAndWarnings('row a=1', []); + testErrorsAndWarnings('row a=1, missing_column', ['Unknown column [missing_column]']); + testErrorsAndWarnings('row a=1, b = average()', ['Unknown function [average]']); + testErrorsAndWarnings('row a = [1, 2, 3]', []); + testErrorsAndWarnings('row a = (1)', []); + testErrorsAndWarnings('row a = (1, 2, 3)', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ","', + "SyntaxError: extraneous input ')' expecting ", + ]); + + testErrorsAndWarnings('row var = 1 in (1, 2, 3)', []); + testErrorsAndWarnings('row var = 5 in (1, 2, 3)', []); + testErrorsAndWarnings('row var = 5 not in (1, 2, 3)', []); + testErrorsAndWarnings('row var = 1 in (1, 2, 3, round(5))', []); + testErrorsAndWarnings('row var = "a" in ("a", "b", "c")', []); + testErrorsAndWarnings('row var = "a" in ("a", "b", "c")', []); + testErrorsAndWarnings('row var = "a" not in ("a", "b", "c")', []); + testErrorsAndWarnings('row var = 1 in ("a", "b", "c")', [ + 'Argument of [in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('row var = 5 in ("a", "b", "c")', [ + 'Argument of [in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('row var = 5 not in ("a", "b", "c")', [ + 'Argument of [not_in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('row var = 5 not in (1, 2, 3, "a")', [ + 'Argument of [not_in] must be [number[]], found value [(1, 2, 3, "a")] type [(number, number, number, string)]', + ]); + + function tweakSignatureForRowCommand(signature: string) { + /** + * row has no access to any field, so replace it with literal + * or functions (for dates) + */ + return signature + .replace(/numberField/g, '5') + .replace(/stringField/g, '"a"') + .replace(/dateField/g, 'now()') + .replace(/booleanField/g, 'true') + .replace(/ipField/g, 'to_ip("127.0.0.1")'); + } + + for (const { name, alias, signatures, ...defRest } of evalFunctionsDefinitions) { + for (const { params, returnType } of signatures) { + const fieldMapping = getFieldMapping(params); + const signatureStringCorrect = tweakSignatureForRowCommand( + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + ); + + testErrorsAndWarnings(`row var = ${signatureStringCorrect}`, []); + testErrorsAndWarnings(`row ${signatureStringCorrect}`); + + if (alias) { + for (const otherName of alias) { + const signatureStringWithAlias = tweakSignatureForRowCommand( + getFunctionSignatures( + { name: otherName, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + ); + + testErrorsAndWarnings(`row var = ${signatureStringWithAlias}`, []); + } + } + + // Skip functions that have only arguments of type "any", as it is not possible to pass "the wrong type". + // auto_bucket and to_version functions are a bit harder to test exactly a combination of argument and predict the + // the right error message + if ( + params.every(({ type }) => type !== 'any') && + !['auto_bucket', 'to_version'].includes(name) + ) { + // now test nested functions + const fieldMappingWithNestedFunctions = getFieldMapping(params, { + useNestedFunction: true, + useLiterals: true, + }); + const signatureString = tweakSignatureForRowCommand( + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithNestedFunctions, returnType }], + }, + { withTypes: false } + )[0].declaration + ); + + testErrorsAndWarnings(`row var = ${signatureString}`); + + const wrongFieldMapping = params.map(({ name: _name, type, ...rest }) => { + const typeString = type; + const canBeFieldButNotString = ['number', 'date', 'boolean', 'ip'].includes(typeString); + const isLiteralType = /literal$/.test(typeString); + // pick a field name purposely wrong + const nameValue = canBeFieldButNotString || isLiteralType ? '"a"' : '5'; + return { name: nameValue, type, ...rest }; + }); + const expectedErrors = params.map( + ({ type }, i) => + `Argument of [${name}] must be [${type}], found value [${ + wrongFieldMapping[i].name + }] type [${wrongFieldMapping[i].name === '5' ? 'number' : 'string'}]` + ); + const wrongSignatureString = tweakSignatureForRowCommand( + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: wrongFieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + ); + testErrorsAndWarnings(`row var = ${wrongSignatureString}`, expectedErrors); + } + } + } + for (const op of ['>', '>=', '<', '<=', '==']) { + testErrorsAndWarnings(`row var = 5 ${op} 0`, []); + testErrorsAndWarnings(`row var = NOT 5 ${op} 0`, []); + testErrorsAndWarnings(`row var = (numberField ${op} 0)`, []); + testErrorsAndWarnings(`row var = (NOT (5 ${op} 0))`, []); + testErrorsAndWarnings(`row var = "a" ${op} 0`, [ + `Argument of [${op}] must be [number], found value ["a"] type [string]`, + ]); + } + for (const op of ['+', '-', '*', '/', '%']) { + testErrorsAndWarnings(`row var = 1 ${op} 1`, []); + testErrorsAndWarnings(`row var = (5 ${op} 1)`, []); + } + + for (const op of ['like', 'rlike']) { + testErrorsAndWarnings(`row var = "a" ${op} "?a"`, []); + testErrorsAndWarnings(`row var = "a" NOT ${op} "?a"`, []); + testErrorsAndWarnings(`row var = NOT "a" ${op} "?a"`, []); + testErrorsAndWarnings(`row var = NOT "a" NOT ${op} "?a"`, []); + testErrorsAndWarnings(`row var = 5 ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [5] type [number]`, + ]); + testErrorsAndWarnings(`row var = 5 NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [5] type [number]`, + ]); + testErrorsAndWarnings(`row var = NOT 5 ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [5] type [number]`, + ]); + testErrorsAndWarnings(`row var = NOT 5 NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [5] type [number]`, + ]); + } + + describe('date math', () => { + testErrorsAndWarnings('row 1 anno', [ + 'Row does not support [date_period] in expression [1 anno]', + ]); + testErrorsAndWarnings('row var = 1 anno', ["Unexpected time interval qualifier: 'anno'"]); + testErrorsAndWarnings('row now() + 1 anno', ["Unexpected time interval qualifier: 'anno'"]); + for (const timeLiteral of timeLiterals) { + testErrorsAndWarnings(`row 1 ${timeLiteral.name}`, [ + `Row does not support [date_period] in expression [1 ${timeLiteral.name}]`, + ]); + testErrorsAndWarnings(`row 1 ${timeLiteral.name}`, [ + `Row does not support [date_period] in expression [1 ${timeLiteral.name}]`, + ]); + + // this is not possible for now + // testErrorsAndWarnings(`row var = 1 ${timeLiteral.name}`, [ + // `Row does not support [date_period] in expression [1 ${timeLiteral.name}]`, + // ]); + testErrorsAndWarnings(`row var = now() - 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings(`row var = now() - 1 ${timeLiteral.name.toUpperCase()}`, []); + testErrorsAndWarnings(`row var = now() - 1 ${capitalize(timeLiteral.name)}`, []); + testErrorsAndWarnings(`row var = now() + 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings(`row 1 ${timeLiteral.name} + 1 year`, [ + `Argument of [+] must be [date], found value [1 ${timeLiteral.name}] type [duration]`, + ]); + for (const op of ['*', '/', '%']) { + testErrorsAndWarnings(`row var = now() ${op} 1 ${timeLiteral.name}`, [ + `Argument of [${op}] must be [number], found value [now()] type [date]`, + `Argument of [${op}] must be [number], found value [1 ${timeLiteral.name}] type [duration]`, + ]); + } + } + }); + }); + + describe('show', () => { + testErrorsAndWarnings('show', ['SyntaxError: expected {SHOW} but found ""']); + testErrorsAndWarnings('show functions', []); + testErrorsAndWarnings('show info', []); + testErrorsAndWarnings('show functions blah', [ + "SyntaxError: extraneous input 'blah' expecting ", + ]); + }); + + describe('limit', () => { + testErrorsAndWarnings('from index | limit ', [ + `SyntaxError: missing INTEGER_LITERAL at ''`, + ]); + testErrorsAndWarnings('from index | limit 4 ', []); + testErrorsAndWarnings('from index | limit 4.5', [ + 'SyntaxError: expected {INTEGER_LITERAL} but found "4.5"', + ]); + testErrorsAndWarnings('from index | limit a', [ + 'SyntaxError: expected {INTEGER_LITERAL} but found "a"', + ]); + testErrorsAndWarnings('from index | limit numberField', [ + 'SyntaxError: expected {INTEGER_LITERAL} but found "numberField"', + ]); + testErrorsAndWarnings('from index | limit stringField', [ + 'SyntaxError: expected {INTEGER_LITERAL} but found "stringField"', + ]); + testErrorsAndWarnings('from index | limit 4', []); + }); + + describe('keep', () => { + testErrorsAndWarnings('from index | keep ', [ + `SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''`, + ]); + testErrorsAndWarnings('from index | keep stringField, numberField, dateField', []); + testErrorsAndWarnings('from index | keep `stringField`, `numberField`, `dateField`', []); + testErrorsAndWarnings('from index | keep 4.5', ['Unknown column [4.5]']); + testErrorsAndWarnings('from index | keep missingField, numberField, dateField', [ + 'Unknown column [missingField]', + ]); + testErrorsAndWarnings('from index | keep `any#Char$ field`', []); + testErrorsAndWarnings( + 'from index | project ', + [`SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''`], + ['PROJECT command is no longer supported, please use KEEP instead'] + ); + testErrorsAndWarnings( + 'from index | project stringField, numberField, dateField', + [], + ['PROJECT command is no longer supported, please use KEEP instead'] + ); + testErrorsAndWarnings( + 'from index | PROJECT stringField, numberField, dateField', + [], + ['PROJECT command is no longer supported, please use KEEP instead'] + ); + testErrorsAndWarnings( + 'from index | project missingField, numberField, dateField', + ['Unknown column [missingField]'], + ['PROJECT command is no longer supported, please use KEEP instead'] + ); + testErrorsAndWarnings('from index | keep s*', []); + testErrorsAndWarnings('from index | keep *Field', []); + testErrorsAndWarnings('from index | keep s*Field', []); + testErrorsAndWarnings('from index | keep string*Field', []); + testErrorsAndWarnings('from index | keep s*, n*', []); + testErrorsAndWarnings('from index | keep m*', ['Unknown column [m*]']); + testErrorsAndWarnings('from index | keep *m', ['Unknown column [*m]']); + testErrorsAndWarnings('from index | keep d*m', ['Unknown column [d*m]']); + testErrorsAndWarnings( + 'from unsupported_index | keep unsupported_field', + [], + [ + 'Field [unsupported_field] cannot be retrieved, it is unsupported or not indexed; returning null', + ] + ); + }); + + describe('drop', () => { + testErrorsAndWarnings('from index | drop ', [ + `SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''`, + ]); + testErrorsAndWarnings('from index | drop stringField, numberField, dateField', []); + testErrorsAndWarnings('from index | drop 4.5', ['Unknown column [4.5]']); + testErrorsAndWarnings('from index | drop missingField, numberField, dateField', [ + 'Unknown column [missingField]', + ]); + testErrorsAndWarnings('from index | drop `any#Char$ field`', []); + testErrorsAndWarnings('from index | drop s*', []); + testErrorsAndWarnings('from index | drop *Field', []); + testErrorsAndWarnings('from index | drop s*Field', []); + testErrorsAndWarnings('from index | drop string*Field', []); + testErrorsAndWarnings('from index | drop s*, n*', []); + testErrorsAndWarnings('from index | drop m*', ['Unknown column [m*]']); + testErrorsAndWarnings('from index | drop *m', ['Unknown column [*m]']); + testErrorsAndWarnings('from index | drop d*m', ['Unknown column [d*m]']); + testErrorsAndWarnings('from index | drop *', ['Removing all fields is not allowed [*]']); + testErrorsAndWarnings('from index | drop stringField, *', [ + 'Removing all fields is not allowed [*]', + ]); + testErrorsAndWarnings( + 'from index | drop @timestamp', + [], + ['Drop [@timestamp] will remove all time filters to the search results'] + ); + testErrorsAndWarnings( + 'from index | drop stringField, @timestamp', + [], + ['Drop [@timestamp] will remove all time filters to the search results'] + ); + }); + + describe('mv_expand', () => { + testErrorsAndWarnings('from a | mv_expand ', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | mv_expand stringField', [ + 'Mv_expand only supports list type values, found [stringField] of type string', + ]); + + testErrorsAndWarnings(`from a | mv_expand listField`, []); + + testErrorsAndWarnings('from a | mv_expand listField, b', [ + 'SyntaxError: expected {, PIPE} but found ","', + ]); + + testErrorsAndWarnings('row a = "a" | mv_expand a', [ + 'Mv_expand only supports list type values, found [a] of type string', + ]); + testErrorsAndWarnings('row a = [1, 2, 3] | mv_expand a', []); + }); + + describe('rename', () => { + testErrorsAndWarnings('from a | rename', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | rename stringField', [ + 'SyntaxError: expected {AS} but found ""', + ]); + testErrorsAndWarnings('from a | rename a', [ + 'SyntaxError: expected {AS} but found ""', + 'Unknown column [a]', + ]); + testErrorsAndWarnings('from a | rename stringField as', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | rename missingField as', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + 'Unknown column [missingField]', + ]); + testErrorsAndWarnings('from a | rename stringField as b', []); + testErrorsAndWarnings('from a | rename stringField AS b', []); + testErrorsAndWarnings('from a | rename stringField As b', []); + testErrorsAndWarnings('from a | rename stringField As b, b AS c', []); + testErrorsAndWarnings('from a | rename fn() as a', [ + 'Unknown column [fn()]', + 'Unknown column [a]', + ]); + testErrorsAndWarnings('from a | eval numberField + 1 | rename `numberField + 1` as a', []); + testErrorsAndWarnings( + 'from a | stats avg(numberField) | rename `avg(numberField)` as avg0', + [] + ); + testErrorsAndWarnings('from a | eval numberField + 1 | rename `numberField + 1` as ', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | rename s* as strings', [ + 'Using wildcards (*) in rename is not allowed [s*]', + 'Unknown column [strings]', + ]); + }); + + describe('dissect', () => { + testErrorsAndWarnings('from a | dissect', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | dissect stringField', [ + "SyntaxError: missing STRING at ''", + ]); + testErrorsAndWarnings('from a | dissect stringField 2', [ + 'SyntaxError: expected {STRING, DOT} but found "2"', + ]); + testErrorsAndWarnings('from a | dissect stringField .', [ + "SyntaxError: missing {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} at ''", + 'Unknown column [stringField.]', + ]); + testErrorsAndWarnings('from a | dissect stringField %a', [ + "SyntaxError: missing STRING at '%'", + ]); + // Do not try to validate the dissect pattern string + testErrorsAndWarnings('from a | dissect stringField "%{a}"', []); + testErrorsAndWarnings('from a | dissect numberField "%{a}"', [ + 'Dissect only supports string type values, found [numberField] of type number', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" option ', [ + 'SyntaxError: expected {ASSIGN} but found ""', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" option = ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET} but found ""', + 'Invalid option for dissect: [option]', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" option = 1', [ + 'Invalid option for dissect: [option]', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" append_separator = "-"', []); + testErrorsAndWarnings('from a | dissect stringField "%{a}" ignore_missing = true', [ + 'Invalid option for dissect: [ignore_missing]', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" append_separator = true', [ + 'Invalid value for dissect append_separator: expected a string, but was [true]', + ]); + // testErrorsAndWarnings('from a | dissect s* "%{a}"', [ + // 'Using wildcards (*) in dissect is not allowed [s*]', + // ]); + }); + + describe('grok', () => { + testErrorsAndWarnings('from a | grok', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | grok stringField', ["SyntaxError: missing STRING at ''"]); + testErrorsAndWarnings('from a | grok stringField 2', [ + 'SyntaxError: expected {STRING, DOT} but found "2"', + ]); + testErrorsAndWarnings('from a | grok stringField .', [ + "SyntaxError: missing {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} at ''", + 'Unknown column [stringField.]', + ]); + testErrorsAndWarnings('from a | grok stringField %a', ["SyntaxError: missing STRING at '%'"]); + // Do not try to validate the grok pattern string + testErrorsAndWarnings('from a | grok stringField "%{a}"', []); + testErrorsAndWarnings('from a | grok numberField "%{a}"', [ + 'Grok only supports string type values, found [numberField] of type number', + ]); + // testErrorsAndWarnings('from a | grok s* "%{a}"', [ + // 'Using wildcards (*) in grok is not allowed [s*]', + // ]); + }); + + describe('where', () => { + testErrorsAndWarnings('from a | where b', ['Unknown column [b]']); + for (const cond of ['true', 'false']) { + testErrorsAndWarnings(`from a | where ${cond}`, []); + testErrorsAndWarnings(`from a | where NOT ${cond}`, []); + } + for (const nValue of ['1', '+1', '1 * 1', '-1', '1 / 1']) { + testErrorsAndWarnings(`from a | where ${nValue} > 0`, []); + testErrorsAndWarnings(`from a | where NOT ${nValue} > 0`, []); + } + for (const op of ['>', '>=', '<', '<=', '==']) { + testErrorsAndWarnings(`from a | where numberField ${op} 0`, []); + testErrorsAndWarnings(`from a | where NOT numberField ${op} 0`, []); + testErrorsAndWarnings(`from a | where (numberField ${op} 0)`, []); + testErrorsAndWarnings(`from a | where (NOT (numberField ${op} 0))`, []); + testErrorsAndWarnings(`from a | where 1 ${op} 0`, []); + testErrorsAndWarnings(`from a | eval stringField ${op} 0`, [ + `Argument of [${op}] must be [number], found value [stringField] type [string]`, + ]); + } + for (const op of ['like', 'rlike']) { + testErrorsAndWarnings(`from a | where stringField ${op} "?a"`, []); + testErrorsAndWarnings(`from a | where stringField NOT ${op} "?a"`, []); + testErrorsAndWarnings(`from a | where NOT stringField ${op} "?a"`, []); + testErrorsAndWarnings(`from a | where NOT stringField NOT ${op} "?a"`, []); + testErrorsAndWarnings(`from a | where numberField ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | where numberField NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | where NOT numberField ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | where NOT numberField NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [numberField] type [number]`, + ]); + } + + testErrorsAndWarnings(`from a | where cidr_match(ipField)`, [ + `Error building [cidr_match]: expects exactly 2 arguments, passed 1 instead.`, + ]); + testErrorsAndWarnings( + `from a | eval cidr = "172.0.0.1/30" | where cidr_match(ipField, "172.0.0.1/30", cidr)`, + [] + ); + + // Test that all functions work in where + const numericOrStringFunctions = evalFunctionsDefinitions.filter(({ name, signatures }) => { + return signatures.some( + ({ returnType, params }) => + ['number', 'string'].includes(returnType) && + params.every(({ type }) => ['number', 'string'].includes(type)) + ); + }); + for (const { name, signatures, ...rest } of numericOrStringFunctions) { + const supportedSignatures = signatures.filter(({ returnType }) => + ['number', 'string'].includes(returnType) + ); + for (const { params, returnType } of supportedSignatures) { + const correctMapping = params + .filter(({ optional }) => !optional) + .map(({ type }) => + ['number', 'string'].includes(Array.isArray(type) ? type.join(', ') : type) + ? { name: `${type}Field`, type } + : { name: `numberField`, type } + ); + testErrorsAndWarnings( + `from a | where ${returnType !== 'number' ? 'length(' : ''}${ + // hijacking a bit this function to produce a function call + getFunctionSignatures( + { name, ...rest, signatures: [{ params: correctMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }${returnType !== 'number' ? ')' : ''} > 0`, + [] + ); + + // now test that validation is working also inside each function + // put a number field where a string is expected and viceversa + // then test an error is returned + const incorrectMapping = params + .filter(({ optional }) => !optional) + .map(({ type }) => + type === 'string' ? { name: `numberField`, type } : { name: 'stringField', type } + ); + + const expectedErrors = params + .filter(({ optional }) => !optional) + .map(({ name: argName, type }) => { + const actualValue = + type === 'string' + ? { name: `numberField`, type: 'number' } + : { name: 'stringField', type: 'string' }; + return `Argument of [${name}] must be [${type}], found value [${actualValue.name}] type [${actualValue.type}]`; + }); + testErrorsAndWarnings( + `from a | where ${returnType !== 'number' ? 'length(' : ''}${ + // hijacking a bit this function to produce a function call + getFunctionSignatures( + { name, ...rest, signatures: [{ params: incorrectMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }${returnType !== 'number' ? ')' : ''} > 0`, + expectedErrors + ); + } + } + }); + + describe('eval', () => { + testErrorsAndWarnings('from a | eval ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | eval stringField ', []); + testErrorsAndWarnings('from a | eval b = stringField', []); + testErrorsAndWarnings('from a | eval numberField + 1', []); + testErrorsAndWarnings('from a | eval numberField + ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | eval stringField + 1', [ + 'Argument of [+] must be [number], found value [stringField] type [string]', + ]); + testErrorsAndWarnings('from a | eval a=b', ['Unknown column [b]']); + testErrorsAndWarnings('from a | eval a=b, ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + 'Unknown column [b]', + ]); + testErrorsAndWarnings('from a | eval a=round', ['Unknown column [round]']); + testErrorsAndWarnings('from a | eval a=round(', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | eval a=round(numberField) ', []); + testErrorsAndWarnings('from a | eval a=round(numberField), ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | eval a=round(numberField) + round(numberField) ', []); + testErrorsAndWarnings('from a | eval a=round(numberField) + round(stringField) ', [ + 'Argument of [round] must be [number], found value [stringField] type [string]', + ]); + testErrorsAndWarnings( + 'from a | eval a=round(numberField) + round(stringField), numberField ', + ['Argument of [round] must be [number], found value [stringField] type [string]'] + ); + testErrorsAndWarnings( + 'from a | eval a=round(numberField) + round(numberField), numberField ', + [] + ); + testErrorsAndWarnings( + 'from a | eval a=round(numberField) + round(numberField), b = numberField ', + [] + ); + + for (const { name, alias, signatures, ...defRest } of evalFunctionsDefinitions) { + for (const { params, returnType } of signatures) { + const fieldMapping = getFieldMapping(params); + testErrorsAndWarnings( + `from a | eval var = ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }` + ); + testErrorsAndWarnings( + `from a | eval ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }` + ); + + if (alias) { + for (const otherName of alias) { + const signatureStringWithAlias = getFunctionSignatures( + { name: otherName, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration; + + testErrorsAndWarnings(`from a | eval var = ${signatureStringWithAlias}`, []); + } + } + + // Skip functions that have only arguments of type "any", as it is not possible to pass "the wrong type". + // auto_bucket and to_version functions are a bit harder to test exactly a combination of argument and predict the + // the right error message + if ( + params.every(({ type }) => type !== 'any') && + !['auto_bucket', 'to_version'].includes(name) + ) { + // now test nested functions + const fieldMappingWithNestedFunctions = getFieldMapping(params, { + useNestedFunction: true, + useLiterals: true, + }); + testErrorsAndWarnings( + `from a | eval var = ${ + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithNestedFunctions, returnType }], + }, + { withTypes: false } + )[0].declaration + }` + ); + + const wrongFieldMapping = params.map(({ name: _name, type, ...rest }) => { + const typeString = type; + const canBeFieldButNotString = ['number', 'date', 'boolean', 'ip'].includes(typeString); + const isLiteralType = /literal$/.test(typeString); + // pick a field name purposely wrong + const nameValue = + canBeFieldButNotString || isLiteralType ? 'stringField' : 'numberField'; + return { name: nameValue, type, ...rest }; + }); + const expectedErrors = params.map( + ({ type }, i) => + `Argument of [${name}] must be [${type}], found value [${ + wrongFieldMapping[i].name + }] type [${wrongFieldMapping[i].name.replace('Field', '')}]` + ); + testErrorsAndWarnings( + `from a | eval ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: wrongFieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }`, + expectedErrors + ); + } + + // test that wildcard won't work as arg + if (fieldMapping.length === 1) { + const fieldMappingWithWildcard = [...fieldMapping]; + fieldMappingWithWildcard[0].name = '*'; + + testErrorsAndWarnings( + `from a | eval var = ${ + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithWildcard, returnType }], + }, + { withTypes: false } + )[0].declaration + }`, + [`Using wildcards (*) in ${name} is not allowed`] + ); + } + } + } + for (const op of ['>', '>=', '<', '<=', '==']) { + testErrorsAndWarnings(`from a | eval numberField ${op} 0`, []); + testErrorsAndWarnings(`from a | eval NOT numberField ${op} 0`, []); + testErrorsAndWarnings(`from a | eval (numberField ${op} 0)`, []); + testErrorsAndWarnings(`from a | eval (NOT (numberField ${op} 0))`, []); + testErrorsAndWarnings(`from a | eval 1 ${op} 0`, []); + testErrorsAndWarnings(`from a | eval stringField ${op} 0`, [ + `Argument of [${op}] must be [number], found value [stringField] type [string]`, + ]); + } + for (const op of ['+', '-', '*', '/', '%']) { + testErrorsAndWarnings(`from a | eval numberField ${op} 1`, []); + testErrorsAndWarnings(`from a | eval (numberField ${op} 1)`, []); + testErrorsAndWarnings(`from a | eval 1 ${op} 1`, []); + } + for (const divideByZeroExpr of ['1/0', 'var = 1/0', '1 + 1/0']) { + testErrorsAndWarnings( + `from a | eval ${divideByZeroExpr}`, + [], + ['Cannot divide by zero: 1/0'] + ); + } + for (const divideByZeroExpr of ['1%0', 'var = 1%0', '1 + 1%0']) { + testErrorsAndWarnings( + `from a | eval ${divideByZeroExpr}`, + [], + ['Module by zero can return null value: 1/0'] + ); + } + for (const op of ['like', 'rlike']) { + testErrorsAndWarnings(`from a | eval stringField ${op} "?a"`, []); + testErrorsAndWarnings(`from a | eval stringField NOT ${op} "?a"`, []); + testErrorsAndWarnings(`from a | eval NOT stringField ${op} "?a"`, []); + testErrorsAndWarnings(`from a | eval NOT stringField NOT ${op} "?a"`, []); + testErrorsAndWarnings(`from a | eval numberField ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | eval numberField NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | eval NOT numberField ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | eval NOT numberField NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [numberField] type [number]`, + ]); + } + // test lists + testErrorsAndWarnings('from a | eval 1 in (1, 2, 3)', []); + testErrorsAndWarnings('from a | eval numberField in (1, 2, 3)', []); + testErrorsAndWarnings('from a | eval numberField not in (1, 2, 3)', []); + testErrorsAndWarnings('from a | eval numberField not in (1, 2, 3, numberField)', []); + testErrorsAndWarnings('from a | eval 1 in (1, 2, 3, round(numberField))', []); + testErrorsAndWarnings('from a | eval "a" in ("a", "b", "c")', []); + testErrorsAndWarnings('from a | eval stringField in ("a", "b", "c")', []); + testErrorsAndWarnings('from a | eval stringField not in ("a", "b", "c")', []); + testErrorsAndWarnings('from a | eval stringField not in ("a", "b", "c", stringField)', []); + testErrorsAndWarnings('from a | eval 1 in ("a", "b", "c")', [ + 'Argument of [in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('from a | eval numberField in ("a", "b", "c")', [ + 'Argument of [in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('from a | eval numberField not in ("a", "b", "c")', [ + 'Argument of [not_in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('from a | eval numberField not in (1, 2, 3, stringField)', [ + 'Argument of [not_in] must be [number[]], found value [(1, 2, 3, stringField)] type [(number, number, number, string)]', + ]); + + testErrorsAndWarnings('from a | eval avg(numberField)', ['Eval does not support function avg']); + testErrorsAndWarnings('from a | stats avg(numberField) | eval `avg(numberField)` + 1', []); + + describe('date math', () => { + testErrorsAndWarnings('from a | eval 1 anno', [ + 'Eval does not support [date_period] in expression [1 anno]', + ]); + testErrorsAndWarnings('from a | eval var = 1 anno', [ + "Unexpected time interval qualifier: 'anno'", + ]); + testErrorsAndWarnings('from a | eval now() + 1 anno', [ + "Unexpected time interval qualifier: 'anno'", + ]); + for (const timeLiteral of timeLiterals) { + testErrorsAndWarnings(`from a | eval 1 ${timeLiteral.name}`, [ + `Eval does not support [date_period] in expression [1 ${timeLiteral.name}]`, + ]); + testErrorsAndWarnings(`from a | eval 1 ${timeLiteral.name}`, [ + `Eval does not support [date_period] in expression [1 ${timeLiteral.name}]`, + ]); + + // this is not possible for now + // testErrorsAndWarnings(`from a | eval var = 1 ${timeLiteral.name}`, [ + // `Eval does not support [date_period] in expression [1 ${timeLiteral.name}]`, + // ]); + testErrorsAndWarnings(`from a | eval var = now() - 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings(`from a | eval var = dateField - 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings( + `from a | eval var = dateField - 1 ${timeLiteral.name.toUpperCase()}`, + [] + ); + testErrorsAndWarnings( + `from a | eval var = dateField - 1 ${capitalize(timeLiteral.name)}`, + [] + ); + testErrorsAndWarnings(`from a | eval var = dateField + 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings(`from a | eval 1 ${timeLiteral.name} + 1 year`, [ + `Argument of [+] must be [date], found value [1 ${timeLiteral.name}] type [duration]`, + ]); + for (const op of ['*', '/', '%']) { + testErrorsAndWarnings(`from a | eval var = now() ${op} 1 ${timeLiteral.name}`, [ + `Argument of [${op}] must be [number], found value [now()] type [date]`, + `Argument of [${op}] must be [number], found value [1 ${timeLiteral.name}] type [duration]`, + ]); + } + } + }); + }); + + describe('stats', () => { + testErrorsAndWarnings('from a | stats ', []); + testErrorsAndWarnings('from a | stats numberField ', [ + 'Stats expects an aggregate function, found [numberField]', + ]); + testErrorsAndWarnings('from a | stats numberField=', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | stats numberField=5 by ', [ + "SyntaxError: missing {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | stats numberField=5 by ', [ + "SyntaxError: missing {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} at ''", + ]); + + testErrorsAndWarnings('from a | stats avg(numberField) by wrongField', [ + 'Unknown column [wrongField]', + ]); + testErrorsAndWarnings('from a | stats avg(numberField) by 1', [ + 'SyntaxError: expected {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found "1"', + 'Unknown column [1]', + ]); + testErrorsAndWarnings('from a | stats avg(numberField) by percentile(numberField)', [ + 'SyntaxError: expected {, PIPE, COMMA, DOT} but found "("', + 'Unknown column [percentile]', + ]); + + testErrorsAndWarnings( + 'from a | stats avg(numberField) by stringField, percentile(numberField) by ipField', + [ + 'SyntaxError: expected {, PIPE, COMMA, DOT} but found "("', + 'Unknown column [percentile]', + ] + ); + + testErrorsAndWarnings( + 'from a | stats avg(numberField), percentile(numberField, 50) by ipField', + [] + ); + + testErrorsAndWarnings( + 'from a | stats avg(numberField), percentile(numberField, 50) BY ipField', + [] + ); + + testErrorsAndWarnings('from a | stats numberField + 1', ['Stats does not support function +']); + + testErrorsAndWarnings('from a | stats numberField + 1 by ipField', [ + 'Stats does not support function +', + ]); + + testErrorsAndWarnings( + 'from a | stats avg(numberField), percentile(numberField, 50) + 1 by ipField', + ['Stats does not support function +'] + ); + + testErrorsAndWarnings('from a | stats avg(numberField) by avg(numberField)', [ + 'SyntaxError: expected {, PIPE, COMMA, DOT} but found "("', + 'Unknown column [avg]', + ]); + + testErrorsAndWarnings('from a | stats count(*)', []); + testErrorsAndWarnings('from a | stats var0 = count(*)', []); + testErrorsAndWarnings('from a | stats var0 = avg(numberField), count(*)', []); + + for (const { name, alias, signatures, ...defRest } of statsAggregationFunctionDefinitions) { + for (const { params, returnType } of signatures) { + const fieldMapping = getFieldMapping(params); + testErrorsAndWarnings( + `from a | stats var = ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }` + ); + testErrorsAndWarnings( + `from a | stats ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }` + ); + + if (alias) { + for (const otherName of alias) { + const signatureStringWithAlias = getFunctionSignatures( + { name: otherName, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration; + + testErrorsAndWarnings(`from a | stats var = ${signatureStringWithAlias}`, []); + } + } + + // Skip functions that have only arguments of type "any", as it is not possible to pass "the wrong type". + // auto_bucket and to_version functions are a bit harder to test exactly a combination of argument and predict the + // the right error message + if ( + params.every(({ type }) => type !== 'any') && + !['auto_bucket', 'to_version'].includes(name) + ) { + // now test nested functions + const fieldMappingWithNestedFunctions = getFieldMapping(params, { + useNestedFunction: true, + useLiterals: false, + }); + testErrorsAndWarnings( + `from a | stats var = ${ + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithNestedFunctions, returnType }], + }, + { withTypes: false } + )[0].declaration + }`, + params.map( + (_) => + `Aggregate function's parameters must be an attribute or literal; found [avg(numberField)] of type [number]` + ) + ); + // and the message is case of wrong argument type is passed + const wrongFieldMapping = params.map(({ name: _name, type, ...rest }) => { + const typeString = type; + const canBeFieldButNotString = ['number', 'date', 'boolean', 'ip'].includes(typeString); + const isLiteralType = /literal$/.test(typeString); + // pick a field name purposely wrong + const nameValue = + canBeFieldButNotString || isLiteralType ? 'stringField' : 'numberField'; + return { name: nameValue, type, ...rest }; + }); + + const expectedErrors = params.map( + ({ type }, i) => + `Argument of [${name}] must be [${type}], found value [${ + wrongFieldMapping[i].name + }] type [${wrongFieldMapping[i].name.replace('Field', '')}]` + ); + testErrorsAndWarnings( + `from a | stats ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: wrongFieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }`, + expectedErrors + ); + + // test that only count() accepts wildcard as arg + // just check that the function accepts only 1 arg as the parser cannot handle multiple args with * as start arg + if (fieldMapping.length === 1) { + const fieldMappingWithWildcard = [...fieldMapping]; + fieldMappingWithWildcard[0].name = '*'; + + testErrorsAndWarnings( + `from a | stats var = ${ + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithWildcard, returnType }], + }, + { withTypes: false } + )[0].declaration + }`, + name === 'count' ? [] : [`Using wildcards (*) in ${name} is not allowed`] + ); + } + } + } + } + }); + + describe('sort', () => { + testErrorsAndWarnings('from a | sort ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | sort "field" ', []); + testErrorsAndWarnings('from a | sort wrongField ', ['Unknown column [wrongField]']); + testErrorsAndWarnings('from a | sort numberField, ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | sort numberField, stringField', []); + for (const dir of ['desc', 'asc']) { + testErrorsAndWarnings(`from a | sort "field" ${dir} `, []); + testErrorsAndWarnings(`from a | sort numberField ${dir} `, []); + testErrorsAndWarnings(`from a | sort numberField ${dir} nulls `, [ + "SyntaxError: missing {FIRST, LAST} at ''", + ]); + for (const nullDir of ['first', 'last']) { + testErrorsAndWarnings(`from a | sort numberField ${dir} nulls ${nullDir}`, []); + testErrorsAndWarnings(`from a | sort numberField ${dir} ${nullDir}`, [ + `SyntaxError: extraneous input '${nullDir}' expecting `, + ]); + } + } + for (const nullDir of ['first', 'last']) { + testErrorsAndWarnings(`from a | sort numberField nulls ${nullDir}`, []); + testErrorsAndWarnings(`from a | sort numberField ${nullDir}`, [ + `SyntaxError: extraneous input '${nullDir}' expecting `, + ]); + } + }); + + describe('enrich', () => { + testErrorsAndWarnings(`from a | enrich`, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings(`from a | enrich policy `, []); + testErrorsAndWarnings(`from a | enrich missing-policy `, ['Unknown policy [missing-policy]']); + testErrorsAndWarnings(`from a | enrich policy on `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings(`from a | enrich policy on b `, ['Unknown column [b]']); + testErrorsAndWarnings(`from a | enrich policy on numberField with `, [ + 'SyntaxError: expected {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 `, [ + 'Unknown column [var0]', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + 'Unknown column [var0]', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = c `, [ + 'Unknown column [var0]', + `Unknown column [c]`, + ]); + // need to re-enable once the fields/variables become location aware + // testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = stringField `, [ + // `Unknown column [stringField]`, + // ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = , `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ','", + 'SyntaxError: expected {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} but found ""', + 'Unknown column [var0]', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = otherField, var1 `, [ + 'Unknown column [var1]', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = otherField `, []); + testErrorsAndWarnings( + `from a | enrich policy on numberField with var0 = otherField, yetAnotherField `, + [] + ); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = otherField, var1 = `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + 'Unknown column [var1]', + ]); + + testErrorsAndWarnings( + `from a | enrich policy on numberField with var0 = otherField, var1 = yetAnotherField`, + [] + ); + testErrorsAndWarnings(`from a | enrich policy with `, [ + 'SyntaxError: expected {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings(`from a | enrich policy with otherField`, []); + testErrorsAndWarnings(`from a | enrich policy | eval otherField`, []); + testErrorsAndWarnings(`from a | enrich policy with var0 = otherField | eval var0`, []); + testErrorsAndWarnings('from a | enrich my-pol*', [ + 'Using wildcards (*) in enrich is not allowed [my-pol*]', + ]); + }); + + describe('shadowing', () => { + testErrorsAndWarnings( + 'from a | eval stringField = 5', + [], + ['Column [stringField] of type string has been overwritten as new type: number'] + ); + testErrorsAndWarnings( + 'from a | eval numberField = "5"', + [], + ['Column [numberField] of type number has been overwritten as new type: string'] + ); + }); + + describe('callbacks', () => { + it(`should not fetch source and fields list when a row command is set`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`row a = 1 | eval a`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getFieldsFor).not.toHaveBeenCalled(); + expect(callbackMocks.getSources).not.toHaveBeenCalled(); + }); + + it(`should fetch policies if no enrich command is found`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`row a = 1 | eval a`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getPolicies).not.toHaveBeenCalled(); + }); + + it(`should not fetch source and fields for empty command`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(` `, getAstAndErrors, callbackMocks); + expect(callbackMocks.getFieldsFor).not.toHaveBeenCalled(); + expect(callbackMocks.getSources).not.toHaveBeenCalled(); + }); + + it(`should skip initial source and fields call but still call fields for enriched policy`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`row a = 1 | eval b = a | enrich policy`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getSources).not.toHaveBeenCalled(); + expect(callbackMocks.getPolicies).toHaveBeenCalled(); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledTimes(1); + expect(callbackMocks.getFieldsFor).toHaveBeenLastCalledWith({ + query: `from enrichIndex1 | keep otherField, yetAnotherField`, + }); + }); + + it('should call fields callbacks also for show command', async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`show functions | keep name`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getSources).not.toHaveBeenCalled(); + expect(callbackMocks.getPolicies).not.toHaveBeenCalled(); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledTimes(1); + expect(callbackMocks.getFieldsFor).toHaveBeenLastCalledWith({ + query: 'show functions', + }); + }); + + it(`should fetch additional fields if an enrich command is found`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`from a | eval b = a | enrich policy`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getSources).toHaveBeenCalled(); + expect(callbackMocks.getPolicies).toHaveBeenCalled(); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledTimes(2); + expect(callbackMocks.getFieldsFor).toHaveBeenLastCalledWith({ + query: `from enrichIndex1 | keep otherField, yetAnotherField`, + }); + }); + }); +}); diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/validation.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/validation.ts new file mode 100644 index 0000000000000..b1a2a53be7acf --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/validation.ts @@ -0,0 +1,780 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import uniqBy from 'lodash/uniqBy'; +import capitalize from 'lodash/capitalize'; +import { CommandOptionsDefinition, SignatureArgType } from '../definitions/types'; +import { + areFieldAndVariableTypesCompatible, + extractSingleType, + getAllArrayTypes, + getAllArrayValues, + getColumnHit, + getCommandDefinition, + getFunctionDefinition, + isArrayType, + isAssignment, + isColumnItem, + isEqualType, + isFunctionItem, + isLiteralItem, + isOptionItem, + isSourceItem, + isSupportedFunction, + isTimeIntervalItem, + inKnownTimeInterval, + printFunctionSignature, + sourceExists, + columnExists, + hasWildcard, + hasCCSSource, +} from '../shared/helpers'; +import { collectVariables } from '../shared/variables'; +import type { + AstProviderFn, + ESQLAstItem, + ESQLColumn, + ESQLCommand, + ESQLCommandOption, + ESQLFunction, + ESQLMessage, + ESQLSingleAstItem, + ESQLSource, +} from '../types'; +import { getMessageFromId, createMessage } from './errors'; +import type { ESQLRealField, ESQLVariable, ReferenceMaps, ValidationResult } from './types'; +import type { ESQLCallbacks } from '../shared/types'; +import { + retrieveSources, + retrieveFields, + retrievePolicies, + retrievePoliciesFields, +} from './resources'; + +function validateFunctionLiteralArg( + astFunction: ESQLFunction, + actualArg: ESQLAstItem, + argDef: SignatureArgType, + references: ReferenceMaps, + parentCommand: string +) { + const messages: ESQLMessage[] = []; + if (isLiteralItem(actualArg)) { + if (!isEqualType(actualArg, argDef, references, parentCommand)) { + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: actualArg.value, + givenType: actualArg.literalType, + }, + locations: actualArg.location, + }) + ); + } + } + if (isTimeIntervalItem(actualArg)) { + // check first if it's a valid interval string + if (!inKnownTimeInterval(actualArg)) { + messages.push( + getMessageFromId({ + messageId: 'unknownInterval', + values: { + value: actualArg.unit, + }, + locations: actualArg.location, + }) + ); + } else { + if (!isEqualType(actualArg, argDef, references, parentCommand)) { + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: actualArg.name, + givenType: 'duration', + }, + locations: actualArg.location, + }) + ); + } + } + } + return messages; +} + +function validateNestedFunctionArg( + astFunction: ESQLFunction, + actualArg: ESQLAstItem, + argDef: SignatureArgType, + references: ReferenceMaps, + parentCommand: string +) { + const messages: ESQLMessage[] = []; + if ( + isFunctionItem(actualArg) && + // no need to check the reason here, it is checked already above + isSupportedFunction(actualArg.name, parentCommand).supported + ) { + const argFn = getFunctionDefinition(actualArg.name)!; + if (!isEqualType(actualArg, argDef, references, parentCommand)) { + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: printFunctionSignature(actualArg) || actualArg.name, + givenType: argFn.signatures[0].returnType, + }, + locations: actualArg.location, + }) + ); + } else { + if ('noNestingFunctions' in argDef && argDef.noNestingFunctions) { + messages.push( + getMessageFromId({ + messageId: 'noNestedArgumentSupport', + values: { name: actualArg.text, argType: argFn.signatures[0].returnType }, + locations: actualArg.location, + }) + ); + } + } + } + return messages; +} + +function validateFunctionColumnArg( + astFunction: ESQLFunction, + actualArg: ESQLAstItem, + argDef: SignatureArgType, + references: ReferenceMaps, + parentCommand: string +) { + const messages: ESQLMessage[] = []; + if (isColumnItem(actualArg) && actualArg.name) { + const { hit: columnCheck, nameHit } = columnExists(actualArg, references); + if (!columnCheck) { + messages.push( + getMessageFromId({ + messageId: 'unknownColumn', + values: { + name: actualArg.name, + }, + locations: actualArg.location, + }) + ); + } else { + if (actualArg.name === '*') { + // if function does not support wildcards return a specific error + if (!('supportsWildcard' in argDef) || !argDef.supportsWildcard) { + messages.push( + getMessageFromId({ + messageId: 'noWildcardSupportAsArg', + values: { + name: astFunction.name, + }, + locations: actualArg.location, + }) + ); + } + // do not validate any further for now, only count() accepts wildcard as args... + } else { + // guaranteed by the check above + const columnHit = getColumnHit(nameHit!, references); + // check the type of the column hit + const typeHit = columnHit!.type; + if (!isEqualType(actualArg, argDef, references, parentCommand)) { + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: actualArg.name, + givenType: typeHit, + }, + locations: actualArg.location, + }) + ); + } + } + } + } + return messages; +} + +function validateFunction( + astFunction: ESQLFunction, + parentCommand: string, + references: ReferenceMaps +): ESQLMessage[] { + const messages: ESQLMessage[] = []; + + if (astFunction.incomplete) { + return messages; + } + + const isFnSupported = isSupportedFunction(astFunction.name, parentCommand); + + if (!isFnSupported.supported) { + if (isFnSupported.reason === 'unknownFunction') { + messages.push( + getMessageFromId({ + messageId: 'unknownFunction', + values: { + name: astFunction.name, + }, + locations: astFunction.location, + }) + ); + } + if (isFnSupported.reason === 'unsupportedFunction') { + messages.push( + getMessageFromId({ + messageId: 'unsupportedFunction', + values: { name: astFunction.name, command: capitalize(parentCommand) }, + locations: astFunction.location, + }) + ); + } + return messages; + } + const fnDefinition = getFunctionDefinition(astFunction.name)!; + const matchingSignatures = fnDefinition.signatures.filter((def) => { + if (def.infiniteParams && astFunction.args.length > 0) { + return true; + } + if (def.minParams && astFunction.args.length >= def.minParams) { + return true; + } + if (astFunction.args.length === def.params.length) { + return true; + } + return astFunction.args.length >= def.params.filter(({ optional }) => !optional).length; + }); + if (!matchingSignatures.length) { + const numArgs = fnDefinition.signatures[0].params.filter(({ optional }) => !optional).length; + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentNumber', + values: { + fn: astFunction.name, + numArgs, + passedArgs: astFunction.args.length, + }, + locations: astFunction.location, + }) + ); + } + // now perform the same check on all functions args + for (const arg of astFunction.args) { + const wrappedArray = Array.isArray(arg) ? arg : [arg]; + for (const subArg of wrappedArray) { + if (isFunctionItem(subArg)) { + messages.push(...validateFunction(subArg, parentCommand, references)); + } + } + } + // check if the definition has some warning to show: + if (fnDefinition.warning) { + const message = fnDefinition.warning( + ...(astFunction.args.filter((arg) => !Array.isArray(arg)) as ESQLSingleAstItem[]) + ); + if (message) { + messages.push(createMessage('warning', message, astFunction.location)); + } + } + // at this point we're sure that at least one signature is matching + const failingSignatures: ESQLMessage[][] = []; + for (const signature of matchingSignatures) { + const failingSignature: ESQLMessage[] = []; + signature.params.forEach((argDef, index) => { + const outerArg = astFunction.args[index]!; + if (!outerArg && argDef.optional) { + // that's ok, just skip it + // the else case is already catched with the argument counts check + // few lines above + return; + } + if (Array.isArray(outerArg) && isArrayType(argDef.type)) { + const extractedType = extractSingleType(argDef.type); + const everyArgInListMessages = outerArg + .map((arg) => { + return [ + validateFunctionLiteralArg, + validateNestedFunctionArg, + validateFunctionColumnArg, + ].flatMap((validateFn) => { + return validateFn( + astFunction, + arg, + { ...argDef, type: extractedType }, + references, + parentCommand + ); + }); + }) + .filter((ms) => ms.length); + if (everyArgInListMessages.length) { + failingSignature.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: `(${getAllArrayValues(outerArg).join(', ')})`, + givenType: `(${getAllArrayTypes(outerArg, parentCommand, references).join(', ')})`, + }, + locations: { + min: (outerArg[0] as ESQLSingleAstItem).location.min, + max: (outerArg[outerArg.length - 1] as ESQLSingleAstItem).location.max, + }, + }) + ); + } + return; + } + const wrappedArg = Array.isArray(outerArg) ? outerArg : [outerArg]; + for (const actualArg of wrappedArg) { + const argValidationMessages = [ + validateFunctionLiteralArg, + validateNestedFunctionArg, + validateFunctionColumnArg, + ].flatMap((validateFn) => { + return validateFn(astFunction, actualArg, argDef, references, parentCommand); + }); + failingSignature.push(...argValidationMessages); + + if (isSourceItem(actualArg)) { + // something went wrong with the AST translation + throw new Error('Source should not allowed as function argument'); + } + } + }); + if (failingSignature.length) { + failingSignatures.push(failingSignature); + } + } + if (failingSignatures.length && failingSignatures.length === matchingSignatures.length) { + const failingSignatureOrderedByErrorCount = failingSignatures + .map((arr, index) => ({ index, count: arr.length })) + .sort((a, b) => a.count - b.count); + const indexForShortestFailingsignature = failingSignatureOrderedByErrorCount[0].index; + messages.push(...failingSignatures[indexForShortestFailingsignature]); + } + // This is due to a special case in enrich where an implicit assignment is possible + // so the AST needs to store an explicit "columnX = columnX" which duplicates the message + return uniqBy(messages, ({ location }) => `${location.min}-${location.max}`); +} + +function validateOption( + option: ESQLCommandOption, + optionDef: CommandOptionsDefinition | undefined, + command: ESQLCommand, + referenceMaps: ReferenceMaps +): ESQLMessage[] { + // check if the arguments of the option are of the correct type + const messages: ESQLMessage[] = []; + if (option.incomplete || command.incomplete) { + return messages; + } + if (!optionDef) { + messages.push( + getMessageFromId({ + messageId: 'unknownOption', + values: { command: command.name, option: option.name }, + locations: option.location, + }) + ); + return messages; + } + // use dedicate validate fn if provided + if (optionDef.validate) { + messages.push(...optionDef.validate(option)); + } + if (!optionDef.skipCommonValidation) { + option.args.forEach((arg, index) => { + if (!Array.isArray(arg)) { + if (!optionDef.signature.multipleParams) { + const argDef = optionDef.signature.params[index]; + if (!isEqualType(arg, argDef, referenceMaps, command.name)) { + const value = 'value' in arg ? arg.value : arg.name; + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: option.name, + argType: argDef.type, + value, + givenType: arg.type, + }, + locations: arg.location, + }) + ); + } + if (isColumnItem(arg)) { + messages.push(...validateColumnForCommand(arg, command.name, referenceMaps)); + } + } else { + const argDef = optionDef.signature.params[0]; + if (!isEqualType(arg, argDef, referenceMaps, command.name)) { + const value = 'value' in arg ? arg.value : arg.name; + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: argDef.name, + argType: argDef.type, + value, + givenType: arg.type, + }, + locations: arg.location, + }) + ); + } + if (isColumnItem(arg)) { + messages.push(...validateColumnForCommand(arg, command.name, referenceMaps)); + } + if (isFunctionItem(arg) && isAssignment(arg)) { + messages.push(...validateFunction(arg, command.name, referenceMaps)); + } + } + } + }); + } + + return messages; +} + +function validateSource( + source: ESQLSource, + commandName: string, + { sources, policies }: ReferenceMaps +) { + const messages: ESQLMessage[] = []; + if (source.incomplete) { + return messages; + } + const commandDef = getCommandDefinition(commandName); + if (commandDef.signature.params.every(({ type }) => type !== source.type)) { + const firstArg = commandDef.signature.params[0]; + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: firstArg.name, + argType: firstArg.type, + value: source.name, + givenType: source.type, + }, + locations: source.location, + }) + ); + } else { + const hasCCS = hasCCSSource(source.name); + if (hasCCS) { + messages.push( + getMessageFromId({ + messageId: 'ccsNotSupportedForCommand', + values: { value: source.name }, + locations: source.location, + }) + ); + } else { + const isWildcardAndNotSupported = + hasWildcard(source.name) && !commandDef.signature.params.some(({ wildcards }) => wildcards); + if (isWildcardAndNotSupported) { + messages.push( + getMessageFromId({ + messageId: 'wildcardNotSupportedForCommand', + values: { command: commandName, value: source.name }, + locations: source.location, + }) + ); + } else { + if (source.sourceType === 'index' && !sourceExists(source.name, sources)) { + messages.push( + getMessageFromId({ + messageId: 'unknownIndex', + values: { name: source.name }, + locations: source.location, + }) + ); + } else if (source.sourceType === 'policy' && !policies.has(source.name)) { + messages.push( + getMessageFromId({ + messageId: 'unknownPolicy', + values: { name: source.name }, + locations: source.location, + }) + ); + } + } + } + } + return messages; +} + +function validateColumnForCommand( + column: ESQLColumn, + commandName: string, + references: ReferenceMaps +): ESQLMessage[] { + const messages: ESQLMessage[] = []; + + if (['from', 'show', 'limit'].includes(commandName)) { + return messages; + } + if (commandName === 'row') { + if (!references.variables.has(column.name)) { + messages.push( + getMessageFromId({ + messageId: 'unknownColumn', + values: { + name: column.name, + }, + locations: column.location, + }) + ); + } + } else { + const { hit: columnCheck, nameHit } = columnExists(column, references); + if (columnCheck && nameHit) { + const commandDef = getCommandDefinition(commandName); + const columnParamsWithInnerTypes = commandDef.signature.params.filter( + ({ type, innerType }) => type === 'column' && innerType + ); + + if (columnParamsWithInnerTypes.length) { + // this should be guaranteed by the columnCheck above + const columnRef = getColumnHit(nameHit, references)!; + if ( + columnParamsWithInnerTypes.every(({ innerType }) => { + return innerType !== columnRef.type; + }) + ) { + const supportedTypes = columnParamsWithInnerTypes.map(({ innerType }) => innerType); + + messages.push( + getMessageFromId({ + messageId: 'unsupportedColumnTypeForCommand', + values: { + command: capitalize(commandName), + type: supportedTypes.join(', '), + typeCount: supportedTypes.length, + givenType: columnRef.type, + column: nameHit, + }, + locations: column.location, + }) + ); + } + } + if ( + hasWildcard(nameHit) && + !commandDef.signature.params.some(({ type, wildcards }) => type === 'column' && wildcards) + ) { + messages.push( + getMessageFromId({ + messageId: 'wildcardNotSupportedForCommand', + values: { + command: commandName, + value: nameHit, + }, + locations: column.location, + }) + ); + } + } else { + if (column.name) { + messages.push( + getMessageFromId({ + messageId: 'unknownColumn', + values: { + name: column.name, + }, + locations: column.location, + }) + ); + } + } + } + return messages; +} + +function validateCommand(command: ESQLCommand, references: ReferenceMaps): ESQLMessage[] { + const messages: ESQLMessage[] = []; + if (command.incomplete) { + return messages; + } + // do not check the command exists, the grammar is already picking that up + const commandDef = getCommandDefinition(command.name); + + if (commandDef.validate) { + messages.push(...commandDef.validate(command)); + } + + // Now validate arguments + for (const commandArg of command.args) { + const wrappedArg = Array.isArray(commandArg) ? commandArg : [commandArg]; + for (const arg of wrappedArg) { + if (isFunctionItem(arg)) { + messages.push(...validateFunction(arg, command.name, references)); + } + + if (isOptionItem(arg)) { + messages.push( + ...validateOption( + arg, + commandDef.options.find(({ name }) => name === arg.name), + command, + references + ) + ); + } + if (isColumnItem(arg)) { + if (command.name === 'stats') { + messages.push( + getMessageFromId({ + messageId: 'unknownAggregateFunction', + values: { + command: capitalize(command.name), + value: (arg as ESQLSingleAstItem).name, + }, + locations: (arg as ESQLSingleAstItem).location, + }) + ); + } else { + messages.push(...validateColumnForCommand(arg, command.name, references)); + } + } + if (isTimeIntervalItem(arg)) { + messages.push( + getMessageFromId({ + messageId: 'unsupportedTypeForCommand', + values: { + command: capitalize(command.name), + type: 'date_period', + value: arg.name, + }, + locations: arg.location, + }) + ); + } + if (isSourceItem(arg)) { + messages.push(...validateSource(arg, command.name, references)); + } + } + } + // no need to check for mandatory options passed + // as they are already validated at syntax level + return messages; +} + +function validateFieldsShadowing( + fields: Map, + variables: Map +) { + const messages: ESQLMessage[] = []; + for (const variable of variables.keys()) { + if (fields.has(variable)) { + const variableHits = variables.get(variable)!; + if (!areFieldAndVariableTypesCompatible(fields.get(variable)?.type, variableHits[0].type)) { + const fieldType = fields.get(variable)!.type; + const variableType = variableHits[0].type; + const flatFieldType = fieldType; + const flatVariableType = variableType; + messages.push( + getMessageFromId({ + messageId: 'shadowFieldType', + values: { + field: variable, + fieldType: flatFieldType, + newType: flatVariableType, + }, + locations: variableHits[0].location, + }) + ); + } + } + } + return messages; +} + +function validateUnsupportedTypeFields(fields: Map) { + const messages: ESQLMessage[] = []; + for (const field of fields.values()) { + if (field.type === 'unsupported') { + messages.push( + getMessageFromId({ + messageId: 'unsupportedFieldType', + values: { + field: field.name, + }, + locations: { min: 1, max: 1 }, + }) + ); + } + } + return messages; +} + +/** + * This function will perform an high level validation of the + * query AST. An initial syntax validation is already performed by the parser + * while here it can detect things like function names, types correctness and potential warnings + * @param ast A valid AST data structure + */ +export async function validateAst( + queryString: string, + astProvider: AstProviderFn, + callbacks?: ESQLCallbacks +): Promise { + const messages: ESQLMessage[] = []; + + const { ast, errors } = await astProvider(queryString); + + const [sources, availableFields, availablePolicies] = await Promise.all([ + // retrieve the list of available sources + retrieveSources(ast, callbacks), + // retrieve available fields (if a source command has been defined) + retrieveFields(queryString, ast, callbacks), + // retrieve available policies (if an enrich command has been defined) + retrievePolicies(ast, callbacks), + ]); + + if (availablePolicies.size && ast.filter(({ name }) => name === 'enrich')) { + const fieldsFromPoliciesMap = await retrievePoliciesFields(ast, availablePolicies, callbacks); + fieldsFromPoliciesMap.forEach((value, key) => availableFields.set(key, value)); + } + + const variables = collectVariables(ast, availableFields); + // notify if the user is rewriting a column as variable with another type + messages.push(...validateFieldsShadowing(availableFields, variables)); + messages.push(...validateUnsupportedTypeFields(availableFields)); + + for (const command of ast) { + const commandMessages = validateCommand(command, { + sources, + fields: availableFields, + policies: availablePolicies, + variables, + }); + messages.push(...commandMessages); + } + return { + errors: [...errors, ...messages.filter(({ type }) => type === 'error')], + warnings: messages.filter(({ type }) => type === 'warning'), + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts deleted file mode 100644 index 92b2e8f7c31d1..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const comparisonOperatorsCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'or', - insertText: 'or', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.orDoc', { - defaultMessage: 'or', - }), - sortText: 'D', - }, - { - label: 'and', - insertText: 'and', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.andDoc', { - defaultMessage: 'and', - }), - sortText: 'D', - }, -]; - -export const comparisonCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: '==', - insertText: '==', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.equalToDoc', { - defaultMessage: 'Equal to', - }), - sortText: 'D', - }, - { - label: '!=', - insertText: '!=', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.notEqualToDoc', { - defaultMessage: 'Not equal to', - }), - sortText: 'D', - }, - { - label: '<', - insertText: '<', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.lessThanDoc', { - defaultMessage: 'Less than', - }), - sortText: 'D', - }, - { - label: '>', - insertText: '>', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.greaterThanDoc', { - defaultMessage: 'Greater than', - }), - sortText: 'D', - }, - { - label: '<=', - insertText: '<=', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.lessThanOrEqualToDoc', { - defaultMessage: 'Less than or equal to', - }), - sortText: 'D', - }, - { - label: '>=', - insertText: '>=', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.greaterThanOrEqualToDoc', { - defaultMessage: 'Greater than or equal to', - }), - sortText: 'D', - }, - { - label: 'like', - insertText: 'like', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.likeDoc', { - defaultMessage: 'Filter data based on string patterns', - }), - sortText: 'D', - }, - { - label: 'rlike', - insertText: 'rlike', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.rlikeDoc', { - defaultMessage: 'Filter data based on string regular expressions', - }), - sortText: 'D', - }, - { - label: 'in', - insertText: 'in', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.inDoc', { - defaultMessage: - 'Tests if the value an expression takes is contained in a list of other expressions', - }), - sortText: 'D', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/date_math_expressions.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/date_math_expressions.ts deleted file mode 100644 index 2eb0226914ee9..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/date_math_expressions.ts +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const dateExpressionDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'year', - insertText: 'year', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.year', { - defaultMessage: 'Year', - }), - sortText: 'D', - }, - { - label: 'years', - insertText: 'years', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.years', { - defaultMessage: 'Years (Plural)', - }), - sortText: 'D', - }, - { - label: 'month', - insertText: 'month', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.month', { - defaultMessage: 'Month', - }), - sortText: 'D', - }, - { - label: 'months', - insertText: 'months', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.months', { - defaultMessage: 'Months (Plural)', - }), - sortText: 'D', - }, - { - label: 'week', - insertText: 'week', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.week', { - defaultMessage: 'Week', - }), - sortText: 'D', - }, - { - label: 'weeks', - insertText: 'weeks', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.weeks', { - defaultMessage: 'Weeks (Plural)', - }), - sortText: 'D', - }, - { - label: 'day', - insertText: 'day', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.day', { - defaultMessage: 'Day', - }), - sortText: 'D', - }, - { - label: 'days', - insertText: 'days', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.days', { - defaultMessage: 'Days (Plural)', - }), - sortText: 'D', - }, - { - label: 'hour', - insertText: 'hour', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.hour', { - defaultMessage: 'Hour', - }), - sortText: 'D', - }, - { - label: 'hours', - insertText: 'hours', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.hours', { - defaultMessage: 'Hours (Plural)', - }), - sortText: 'D', - }, - { - label: 'minute', - insertText: 'minute', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.minute', { - defaultMessage: 'Minute', - }), - sortText: 'D', - }, - { - label: 'minutes', - insertText: 'minutes', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.minutes', { - defaultMessage: 'Minutes (Plural)', - }), - sortText: 'D', - }, - { - label: 'second', - insertText: 'second', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.second', { - defaultMessage: 'Second', - }), - sortText: 'D', - }, - { - label: 'seconds', - insertText: 'seconds', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.seconds', { - defaultMessage: 'Seconds (Plural)', - }), - sortText: 'D', - }, - { - label: 'millisecond', - insertText: 'millisecond', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.millisecond', { - defaultMessage: 'Millisecond', - }), - sortText: 'D', - }, - { - label: 'milliseconds', - insertText: 'milliseconds', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.milliseconds', { - defaultMessage: 'Milliseconds (Plural)', - }), - sortText: 'D', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts deleted file mode 100644 index f6348fe2c11e2..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const buildPoliciesDefinitions = ( - policies: Array<{ name: string; indices: string[] }> -): AutocompleteCommandDefinition[] => - policies.map(({ name: label, indices }) => ({ - label, - insertText: label, - kind: 5, - detail: i18n.translate('monaco.esql.autocomplete.policyDefinition', { - defaultMessage: `Policy defined on {count, plural, one {index} other {indices}}: {indices}`, - values: { - count: indices.length, - indices: indices.join(', '), - }, - }), - sortText: 'D', - })); - -export const buildFieldsDefinitions = (fields: string[]): AutocompleteCommandDefinition[] => - fields.map((label) => ({ - label, - insertText: label, - kind: 4, - detail: i18n.translate('monaco.esql.autocomplete.fieldDefinition', { - defaultMessage: `Field specified by the input table`, - }), - sortText: 'D', - })); - -export const buildNoPoliciesAvailableDefinition = (): AutocompleteCommandDefinition[] => [ - { - label: i18n.translate('monaco.esql.autocomplete.noPoliciesLabel', { - defaultMessage: 'No available policy', - }), - insertText: '', - kind: 26, - detail: i18n.translate('monaco.esql.autocomplete.noPoliciesLabelsFound', { - defaultMessage: 'Click to create', - }), - sortText: 'D', - command: { - id: 'esql.policies.create', - title: i18n.translate('monaco.esql.autocomplete.createNewPolicy', { - defaultMessage: 'Click to create', - }), - }, - }, -]; - -export const buildMatchingFieldsDefinition = ( - matchingField: string, - fields: string[] -): AutocompleteCommandDefinition[] => - fields.map((label) => ({ - label, - insertText: label, - kind: 4, - detail: i18n.translate('monaco.esql.autocomplete.matchingFieldDefinition', { - defaultMessage: `Use to match on {matchingField} on the policy`, - values: { - matchingField, - }, - }), - sortText: 'D', - })); - -export const buildNewVarDefinition = (label: string): AutocompleteCommandDefinition => { - return { - label, - insertText: label, - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.newVarDoc', { - defaultMessage: 'Define a new variable', - }), - sortText: 'D', - }; -}; - -export const buildSourcesDefinitions = (sources: string[]): AutocompleteCommandDefinition[] => - sources.map((label) => ({ - label, - insertText: label, - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.sourceDefinition', { - defaultMessage: `Input table`, - }), - sortText: 'A', - })); - -export const buildConstantsDefinitions = ( - userConstants: string[], - detail?: string -): AutocompleteCommandDefinition[] => - userConstants.map((label) => ({ - label, - insertText: label, - kind: 14, - detail: - detail ?? - i18n.translate('monaco.esql.autocomplete.constantDefinition', { - defaultMessage: `User defined variable`, - }), - sortText: 'A', - })); diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts deleted file mode 100644 index e1fb514cfa4de..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { - aggregationFunctionsDefinitions, - mathCommandDefinition, - whereCommandDefinition, -} from './functions_commands'; -export { sourceCommandsDefinitions } from './source_commands'; -export { processingCommandsDefinitions, pipeDefinition } from './processing_commands'; - -export { - comparisonCommandsDefinitions, - comparisonOperatorsCommandsDefinitions, -} from './comparison_commands'; -export { - mathOperatorsCommandsDefinitions, - assignOperatorDefinition, - asOperatorDefinition, - byOperatorDefinition, - openBracketDefinition, - closeBracketDefinition, -} from './operators_commands'; - -export { - orderingCommandsDefinitions, - nullsCommandsDefinition, - nullsOrderingCommandsDefinitions, -} from './ordering_commands'; - -export { - buildNewVarDefinition, - buildSourcesDefinitions, - buildFieldsDefinitions, - buildConstantsDefinitions, -} from './dynamic_commands'; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts deleted file mode 100644 index 91ccb74cb9501..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const byOperatorDefinition: AutocompleteCommandDefinition = { - label: 'by', - insertText: 'by', - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.byDoc', { - defaultMessage: 'By', - }), - sortText: 'D', -}; - -export const onOperatorDefinition: AutocompleteCommandDefinition = { - label: 'on', - insertText: 'on', - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.onDoc', { - defaultMessage: 'On', - }), - sortText: 'D', -}; - -export const withOperatorDefinition: AutocompleteCommandDefinition = { - label: 'with', - insertText: 'with', - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.withDoc', { - defaultMessage: 'With', - }), - sortText: 'D', -}; - -export const asOperatorDefinition: AutocompleteCommandDefinition = { - label: 'as', - insertText: 'as', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.asDoc', { - defaultMessage: 'As', - }), - sortText: 'D', -}; - -export const assignOperatorDefinition: AutocompleteCommandDefinition = { - label: '=', - insertText: '=', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.assignDoc', { - defaultMessage: 'Assign (=)', - }), - sortText: 'D', -}; - -export const openBracketDefinition: AutocompleteCommandDefinition = { - label: '(', - insertText: '(', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.openBracketDoc', { - defaultMessage: 'Open Bracket (', - }), - sortText: 'A', -}; - -export const closeBracketDefinition: AutocompleteCommandDefinition = { - label: ')', - insertText: ')', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.closeBracketDoc', { - defaultMessage: 'Close Bracket )', - }), - sortText: 'A', -}; - -export const mathOperatorsCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: '+', - insertText: '+', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.addDoc', { - defaultMessage: 'Add (+)', - }), - sortText: 'D', - }, - { - label: '-', - insertText: '-', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.subtractDoc', { - defaultMessage: 'Subtract (-)', - }), - sortText: 'D', - }, - { - label: '/', - insertText: '/', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.divideDoc', { - defaultMessage: 'Divide (/)', - }), - sortText: 'D', - }, - { - label: '*', - insertText: '*', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.multiplyDoc', { - defaultMessage: 'Multiply (*)', - }), - sortText: 'D', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/ordering_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/ordering_commands.ts deleted file mode 100644 index 6e932e742a69b..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/ordering_commands.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; - -import type { AutocompleteCommandDefinition } from '../types'; - -export const orderingCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'asc', - insertText: 'asc', - kind: 17, - detail: i18n.translate('monaco.esql.autocomplete.ascDoc', { - defaultMessage: 'Ascending Order', - }), - sortText: 'D', - }, - { - label: 'desc', - insertText: 'desc', - kind: 17, - detail: i18n.translate('monaco.esql.autocomplete.descDoc', { - defaultMessage: 'Descending Order', - }), - sortText: 'D', - }, -]; - -export const nullsCommandsDefinition: AutocompleteCommandDefinition = { - label: 'nulls', - insertText: 'nulls', - kind: 13, - sortText: 'D', -}; - -export const nullsOrderingCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'first', - insertText: 'first', - kind: 13, - sortText: 'D', - }, - { - label: 'last', - insertText: 'last', - kind: 13, - sortText: 'D', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts deleted file mode 100644 index 5fe6969f3eddb..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { buildDocumentation } from './utils'; - -import type { AutocompleteCommandDefinition } from '../types'; - -export const pipeDefinition: AutocompleteCommandDefinition = { - label: '|', - insertText: '|', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.pipeDoc', { - defaultMessage: 'Pipe (|)', - }), - sortText: 'B', -}; - -export const processingCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'stats', - insertText: 'stats', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.statsDoc', { - defaultMessage: - 'Calculates aggregate statistics, such as average, count, and sum, over the incoming search results set. Similar to SQL aggregation, if the stats command is used without a BY clause, only one row is returned, which is the aggregation over the entire incoming search results set. When you use a BY clause, one row is returned for each distinct value in the field specified in the BY clause. The stats command returns only the fields in the aggregation, and you can use a wide range of statistical functions with the stats command. When you perform more than one aggregation, separate each aggregation with a comma.', - }), - documentation: { - value: buildDocumentation( - 'stats aggs = fieldSpecification ( `,` fieldSpecification )* ( `by` groups = identifier ( `,` identifier )* )?', - ['… | stats sum(b) by b)', '… | stats avg = avg(a)'] - ), - }, - sortText: 'B', - }, - { - label: 'limit', - insertText: 'limit', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.limitDoc', { - defaultMessage: - 'Returns the first search results, in search order, based on the "limit" specified.', - }), - documentation: { - value: buildDocumentation('limit size = integerLiteral', ['… | limit 100', '… | limit 0']), - }, - sortText: 'B', - }, - { - label: 'eval', - insertText: 'eval', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.evalDoc', { - defaultMessage: - 'Calculates an expression and puts the resulting value into a search results field.', - }), - documentation: { - value: buildDocumentation('eval columns = fieldSpecification ( `,` fieldSpecification )*', [ - '… | eval a = b * c', - '… | eval then = 1 year + 2 weeks', - ]), - }, - sortText: 'B', - }, - { - label: 'keep', - insertText: 'keep', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.keepDoc', { - defaultMessage: 'Rearranges fields in the input table by applying the keep clauses in fields', - }), - documentation: { - value: buildDocumentation('keep fieldSpecification `,` fieldSpecification *', [ - '… | keep a,b', - ]), - }, - sortText: 'B', - }, - { - label: 'rename', - insertText: 'rename', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.renameDoc', { - defaultMessage: 'Renames an old column to a new one', - }), - documentation: { - value: buildDocumentation('rename new as old', ['… | rename a as b']), - }, - sortText: 'B', - }, - { - label: 'drop', - insertText: 'drop', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.dropDoc', { - defaultMessage: 'Drops columns', - }), - documentation: { - value: buildDocumentation('drop fieldSpecification `,` fieldSpecification *', [ - '… | drop a,b', - ]), - }, - sortText: 'B', - }, - { - label: 'sort', - insertText: 'sort', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.sortDoc', { - defaultMessage: - 'Sorts all results by the specified fields. When in descending order, the results missing a field are considered the smallest possible value of the field, or the largest possible value of the field when in ascending order.', - }), - documentation: { - value: buildDocumentation('sort orders = orderExpression ( `,` orderExpression )*', [ - '… | sort a desc, b nulls last, c asc nulls first', - '… | sort b nulls last`', - '… | sort c asc nulls first`', - ]), - }, - sortText: 'B', - }, - { - label: 'where', - insertText: 'where', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.whereDoc', { - defaultMessage: - 'Uses "predicate-expressions" to filter search results. A predicate expression, when evaluated, returns TRUE or FALSE. The where command only returns the results that evaluate to TRUE. For example, to filter results for a specific field value', - }), - documentation: { - value: buildDocumentation('where condition = expression', ['… | where status_code == 200']), - }, - sortText: 'B', - }, - { - label: 'dissect', - insertText: 'dissect', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.dissectDoc', { - defaultMessage: - 'Extracts multiple string values from a single string input, based on a pattern', - }), - documentation: { - value: buildDocumentation( - 'dissect (append_separator=)?', - ['… | dissect a "%{b} %{c}";'] - ), - }, - sortText: 'B', - }, - { - label: 'grok', - insertText: 'grok', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.grokDoc', { - defaultMessage: - 'Extracts multiple string values from a single string input, based on a pattern', - }), - documentation: { - value: buildDocumentation('grok ', [ - '… | grok a "%{b} %{c}";', - ]), - }, - sortText: 'B', - }, - { - label: 'mv_expand', - insertText: 'mv_expand', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.mvExpandDoc', { - defaultMessage: 'Expands multivalued fields into one row per value, duplicating other fields', - }), - documentation: { - value: buildDocumentation('mv_expand field', [ - 'ROW a=[1,2,3], b="b", j=["a","b"] | MV_EXPAND a', - ]), - }, - sortText: 'B', - }, - { - label: 'enrich', - insertText: 'enrich', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.enrichDoc', { - defaultMessage: 'Enrich table with another table', - }), - documentation: { - value: buildDocumentation('enrich policy', ['... | ENRICH a']), - }, - sortText: 'B', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/source_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/source_commands.ts deleted file mode 100644 index a14f776de1bbf..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/source_commands.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { buildDocumentation } from './utils'; - -import type { AutocompleteCommandDefinition } from '../types'; - -export const sourceCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'from', - insertText: 'from', - kind: 0, - detail: i18n.translate('monaco.esql.autocomplete.fromDoc', { - defaultMessage: - 'Retrieves data from one or more datasets. A dataset is a collection of data that you want to search. The only supported dataset is an index. In a query or subquery, you must use the from command first and it does not need a leading pipe. For example, to retrieve data from an index:', - }), - documentation: { - value: buildDocumentation( - 'from` indexPatterns = wildcardIdentifier (`,` wildcardIdentifier)*', - ['from logs', 'from logs-*', 'from logs_*, events-*', 'from from remote*:logs*'] - ), - }, - sortText: 'A', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts deleted file mode 100644 index a33c9f99f6f9e..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { CharStreams } from 'antlr4ts'; -import { AutocompleteListener } from './autocomplete_listener'; -import { ANTLREErrorListener } from '../../../common/error_listener'; - -import { getParser, ROOT_STATEMENT } from '../antlr_facade'; - -import { isDynamicAutocompleteItem } from './dymanic_item'; -import { getDurationItemsWithQuantifier } from './helpers'; -import { mathCommandDefinition } from './autocomplete_definitions/functions_commands'; - -describe('autocomplete_listener', () => { - const getAutocompleteSuggestions = (text: string) => { - const errorListener = new ANTLREErrorListener(); - const parseListener = new AutocompleteListener(); - const parser = getParser(CharStreams.fromString(text), errorListener, parseListener); - - parser[ROOT_STATEMENT](); - - return parseListener.getAutocompleteSuggestions(); - }; - - const testSuggestions = (text: string, expected: string[]) => { - test(`${text} => [${expected.join(',')}]`, () => { - const { suggestions } = getAutocompleteSuggestions(text); - expect(suggestions.map((i) => (isDynamicAutocompleteItem(i) ? i : i.label))).toEqual( - expected - ); - }); - }; - - describe('from', () => { - testSuggestions('f', ['from']); - testSuggestions('from ', ['SourceIdentifier']); - testSuggestions('from a,', ['SourceIdentifier']); - testSuggestions('from a, b ', ['SourceIdentifier']); - }); - - describe('where', () => { - testSuggestions('from a | where ', ['cidr_match', 'FieldIdentifier']); - testSuggestions('from a | where "field" ', [ - '==', - '!=', - '<', - '>', - '<=', - '>=', - 'like', - 'rlike', - 'in', - ]); - testSuggestions('from a | where "field" >= ', ['FieldIdentifier']); - testSuggestions('from a | where "field" >= "field1" ', ['or', 'and', '|']); - testSuggestions('from a | where "field" >= "field1" and ', ['FieldIdentifier']); - testSuggestions('from a | where "field" >= "field1" and "field2" ', [ - '==', - '!=', - '<', - '>', - '<=', - '>=', - 'like', - 'rlike', - 'in', - ]); - testSuggestions('from a | stats a=avg("field") | where a ', [ - '==', - '!=', - '<', - '>', - '<=', - '>=', - 'like', - 'rlike', - 'in', - ]); - testSuggestions('from a | stats a=avg("b") | where "c" ', [ - '==', - '!=', - '<', - '>', - '<=', - '>=', - 'like', - 'rlike', - 'in', - ]); - testSuggestions('from a | where "field" >= "field1" and "field2 == ', ['FieldIdentifier']); - }); - - describe('sort', () => { - testSuggestions('from a | sort ', ['FieldIdentifier']); - testSuggestions('from a | sort "field" ', ['asc', 'desc']); - testSuggestions('from a | sort "field" desc ', ['nulls']); - testSuggestions('from a | sort "field" desc nulls ', ['first', 'last']); - }); - - describe('limit', () => { - testSuggestions('from a | limit ', ['1000']); - testSuggestions('from a | limit 4 ', ['|']); - }); - - describe('mv_expand', () => { - testSuggestions('from a | mv_expand ', ['FieldIdentifier']); - testSuggestions('from a | mv_expand a ', ['|']); - }); - - describe('stats', () => { - testSuggestions('from a | stats ', ['var0']); - testSuggestions('from a | stats a ', ['=']); - testSuggestions('from a | stats a=', [ - 'avg', - 'max', - 'min', - 'sum', - 'count', - 'count_distinct', - 'median', - 'median_absolute_deviation', - 'percentile', - ]); - testSuggestions('from a | stats a=b by ', ['FieldIdentifier']); - testSuggestions('from a | stats a=c by d', ['|']); - testSuggestions('from a | stats a=b, ', ['var0']); - testSuggestions('from a | stats a=max', ['(']); - testSuggestions('from a | stats a=min(', ['FieldIdentifier']); - testSuggestions('from a | stats a=min(b', [')', 'FieldIdentifier']); - testSuggestions('from a | stats a=min(b) ', ['|', 'by']); - testSuggestions('from a | stats a=min(b) by ', ['FieldIdentifier']); - testSuggestions('from a | stats a=min(b),', ['var0']); - testSuggestions('from a | stats var0=min(b),var1=c,', ['var2']); - testSuggestions('from a | stats a=min(b), b=max(', ['FieldIdentifier']); - }); - - describe('enrich', () => { - for (const prevCommand of [ - '', - '| enrich other-policy ', - '| enrich other-policy on b ', - '| enrich other-policy with c ', - ]) { - testSuggestions(`from a ${prevCommand}| enrich`, ['PolicyIdentifier']); - testSuggestions(`from a ${prevCommand}| enrich policy `, ['|', 'on', 'with']); - testSuggestions(`from a ${prevCommand}| enrich policy on `, [ - 'PolicyMatchingFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy on b `, ['|', 'with']); - testSuggestions(`from a ${prevCommand}| enrich policy on b with `, [ - 'var0', - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 `, ['=', '|']); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = `, [ - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c `, ['|']); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, `, [ - 'var1', - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, var1 `, ['=', '|']); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, var1 = `, [ - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy with `, [ - 'var0', - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy with c`, ['=', '|']); - } - }); - - describe('eval', () => { - const functionSuggestions = mathCommandDefinition.map(({ label }) => String(label)); - - testSuggestions('from a | eval ', ['var0']); - testSuggestions('from a | eval a ', ['=']); - testSuggestions('from a | eval a=', functionSuggestions); - testSuggestions('from a | eval a=b, ', ['var0']); - testSuggestions('from a | eval a=round', ['(']); - testSuggestions('from a | eval a=round(', ['FieldIdentifier']); - testSuggestions('from a | eval a=round(b) ', ['|', '+', '-', '/', '*']); - testSuggestions('from a | eval a=round(b),', ['var0']); - testSuggestions('from a | eval a=round(b) + ', ['FieldIdentifier', ...functionSuggestions]); - // NOTE: this is handled also partially in the suggestion wrapper with auto-injection of closing brackets - testSuggestions('from a | eval a=round(b', [')', 'FieldIdentifier']); - testSuggestions('from a | eval a=round(b), b=round(', ['FieldIdentifier']); - testSuggestions('from a | stats a=round(b), b=round(', ['FieldIdentifier']); - testSuggestions('from a | eval var0=round(b), var1=round(c) | stats ', ['var2']); - - describe('date math', () => { - const dateSuggestions = [ - 'year', - 'month', - 'week', - 'day', - 'hour', - 'minute', - 'second', - 'millisecond', - ].flatMap((v) => [v, `${v}s`]); - const dateMathSymbols = ['+', '-']; - testSuggestions('from a | eval a = 1 ', dateMathSymbols.concat(dateSuggestions, ['|'])); - testSuggestions('from a | eval a = 1 year ', dateMathSymbols.concat(dateSuggestions, ['|'])); - testSuggestions( - 'from a | eval a = 1 day + 2 ', - dateMathSymbols.concat(dateSuggestions, ['|']) - ); - testSuggestions( - 'from a | eval var0=date_trunc(', - ['FieldIdentifier'].concat(...getDurationItemsWithQuantifier().map(({ label }) => label)) - ); - testSuggestions( - 'from a | eval var0=date_trunc(2 ', - [')', 'FieldIdentifier'].concat(dateSuggestions) - ); - }); - }); -}); diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts deleted file mode 100644 index 35c75e6ce6021..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import type { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import type { AutocompleteCommandDefinition, UserDefinedVariables } from './types'; -import { DynamicAutocompleteItem } from './dymanic_item'; - -import { esql_parserListener as ESQLParserListener } from '../../antlr/esql_parser_listener'; -import { - esql_parser, - esql_parser as ESQLParser, - EnrichCommandContext, - EnrichWithClauseContext, - OperatorExpressionContext, -} from '../../antlr/esql_parser'; - -import { - processingCommandsDefinitions, - sourceCommandsDefinitions, - orderingCommandsDefinitions, - nullsCommandsDefinition, - nullsOrderingCommandsDefinitions, - comparisonCommandsDefinitions, - comparisonOperatorsCommandsDefinitions, - byOperatorDefinition, - pipeDefinition, - openBracketDefinition, - closeBracketDefinition, - mathOperatorsCommandsDefinitions, - aggregationFunctionsDefinitions, - mathCommandDefinition, - whereCommandDefinition, - assignOperatorDefinition, - buildConstantsDefinitions, - buildNewVarDefinition, - asOperatorDefinition, -} from './autocomplete_definitions'; - -import { - EvalCommandContext, - StatsCommandContext, - ComparisonContext, - WhereCommandContext, - SourceCommandContext, - OrderExpressionContext, - FieldContext, - QualifiedNameContext, - ProcessingCommandContext, - SourceIdentifierContext, - UserVariableContext, - BooleanExpressionContext, - RegexBooleanExpressionContext, - WhereBooleanExpressionContext, - LimitCommandContext, - ValueExpressionContext, - KeepCommandContext, - DropCommandContext, - RenameCommandContext, - DissectCommandContext, - GrokCommandContext, - MvExpandCommandContext, -} from '../../antlr/esql_parser'; -import { - onOperatorDefinition, - withOperatorDefinition, -} from './autocomplete_definitions/operators_commands'; -import { dateExpressionDefinitions } from './autocomplete_definitions/date_math_expressions'; -import { - endsWithOpenBracket, - getDateMathOperation, - getDurationItemsWithQuantifier, - isDateFunction, -} from './helpers'; - -export function nonNullable(v: T): v is NonNullable { - return v != null; -} - -export class AutocompleteListener implements ESQLParserListener { - private suggestions: Array = []; - private readonly userDefinedVariables: UserDefinedVariables = { - sourceIdentifiers: [], - policyIdentifiers: [], - }; - private readonly tables: string[][] = []; - private parentContext: number | undefined; - - private get fields(): [DynamicAutocompleteItem] { - return [DynamicAutocompleteItem.FieldIdentifier]; - } - - private get policies(): [DynamicAutocompleteItem] { - return [DynamicAutocompleteItem.PolicyIdentifier]; - } - - private get policyFields(): [DynamicAutocompleteItem] { - return [DynamicAutocompleteItem.PolicyFieldIdentifier]; - } - - private get policyMatchingField(): [DynamicAutocompleteItem] { - return [DynamicAutocompleteItem.PolicyMatchingFieldIdentifier]; - } - - private get hasSuggestions() { - return Boolean(this.suggestions.length); - } - - private isTerminalNodeExists(node: TerminalNode | undefined) { - return node && node.payload?.startIndex >= 0; - } - - private inspectOperatorExpressionContext( - context: OperatorExpressionContext | OperatorExpressionContext[] | undefined, - innerScope: 'constant' | 'dateExpression' | 'booleanExpression' - ): boolean { - if (!context) { - return false; - } - if (Array.isArray(context)) { - return context.some((c) => this.inspectOperatorExpressionContext(c, innerScope)); - } - if (context.operatorExpression()?.length) { - return this.inspectOperatorExpressionContext(context.operatorExpression(), innerScope); - } - if (context.primaryExpression()) { - return Boolean(context.primaryExpression()?.[innerScope]()); - } - return false; - } - - private hasDateExpressionTerminalNode( - context: OperatorExpressionContext | OperatorExpressionContext[] | undefined - ): boolean { - return this.inspectOperatorExpressionContext(context, 'dateExpression'); - } - - private hasOnlyConstantDefined( - context: OperatorExpressionContext | OperatorExpressionContext[] | undefined - ): boolean { - return this.inspectOperatorExpressionContext(context, 'constant'); - } - - private applyConditionalSuggestion( - skipDefinitions: AutocompleteCommandDefinition[], - targetDefinition: AutocompleteCommandDefinition, - context: number - ) { - if (!skipDefinitions.find((i) => i === targetDefinition) && this.parentContext === context) { - return targetDefinition; - } - } - - private getEndCommandSuggestions(skipDefinitions: AutocompleteCommandDefinition[] = []) { - return [ - pipeDefinition, - this.applyConditionalSuggestion(skipDefinitions, byOperatorDefinition, ESQLParser.STATS), - this.applyConditionalSuggestion(skipDefinitions, onOperatorDefinition, ESQLParser.ENRICH), - this.applyConditionalSuggestion(skipDefinitions, withOperatorDefinition, ESQLParser.ENRICH), - ].filter(nonNullable); - } - - private getNewVarName() { - const vars = this.tables.flat(); - let index = 0; - - while (true) { - const value = `var${index}`; - if (!vars.includes(value)) { - return value; - } - index++; - } - } - - getAutocompleteSuggestions() { - return { - suggestions: this.suggestions, - userDefinedVariables: this.userDefinedVariables, - }; - } - - /** ESQLParserListener fields **/ - - enterSourceCommand(ctx: SourceCommandContext) { - this.suggestions = []; - } - - exitSourceCommand(ctx: SourceCommandContext) { - if (ctx.exception) { - this.suggestions = sourceCommandsDefinitions; - } - } - - enterSourceIdentifier(ctx: SourceIdentifierContext) { - this.suggestions = [DynamicAutocompleteItem.SourceIdentifier]; - } - - exitSourceIdentifier(ctx: SourceIdentifierContext) { - if (!ctx.childCount) { - this.suggestions = [DynamicAutocompleteItem.SourceIdentifier]; - } else if (!ctx.exception && ctx.text) { - this.userDefinedVariables.sourceIdentifiers.push(ctx.text); - } - } - - enterProcessingCommand(ctx: ProcessingCommandContext) { - this.tables.push([]); - this.suggestions = []; - this.parentContext = undefined; - } - - exitProcessingCommand(ctx: ProcessingCommandContext) { - if (ctx.exception) { - this.suggestions = processingCommandsDefinitions; - } - this.parentContext = undefined; - } - - enterStatsCommand(ctx: StatsCommandContext) { - this.suggestions = []; - this.parentContext = ESQLParser.STATS; - const fn = ctx.fields(); - if (!fn) { - this.suggestions = [buildNewVarDefinition(this.getNewVarName())]; - return; - } - } - - enterEvalCommand(ctx: EvalCommandContext) { - this.suggestions = []; - this.parentContext = ESQLParser.EVAL; - } - - exitStatsCommand(ctx: StatsCommandContext) { - const qn = ctx.qualifiedNames(); - if (qn && qn.text) { - this.suggestions = this.getEndCommandSuggestions([byOperatorDefinition]); - } - } - - exitKeepCommand?(ctx: KeepCommandContext) { - const qn = ctx.qualifiedNames(); - if (qn && qn.text) { - if (qn.text.slice(-1) !== ',') { - this.suggestions = this.getEndCommandSuggestions(); - } - } - } - - exitDropCommand?(ctx: DropCommandContext) { - const qn = ctx.qualifiedNames(); - if (qn && qn.text) { - if (qn.text.slice(-1) !== ',') { - this.suggestions = this.getEndCommandSuggestions(); - } - } - } - - enterRenameCommand(ctx: RenameCommandContext) { - this.parentContext = ESQLParser.RENAME; - } - - exitRenameCommand?(ctx: RenameCommandContext) { - const rc = ctx.renameClause(); - const commaExists = ctx.COMMA(); - if (!rc[0].exception) { - const qn = rc[0].renameVariable(); - const asExists = this.isTerminalNodeExists(rc[0].AS()); - if (asExists && qn && !qn.text) { - this.suggestions = []; - } - if (qn && qn.text) { - if (!commaExists.length) { - this.suggestions = this.getEndCommandSuggestions(); - } - } - } - } - - exitDissectCommand?(ctx: DissectCommandContext) { - const qn = ctx.qualifiedNames(); - const pattern = ctx.string(); - if (qn && qn.text && pattern && pattern.text && pattern.text !== '') { - this.suggestions = this.getEndCommandSuggestions(); - } - } - - exitGrokCommand?(ctx: GrokCommandContext) { - const qn = ctx.qualifiedNames(); - const pattern = ctx.string(); - if (qn && qn.text && pattern && pattern.text && pattern.text !== '') { - this.suggestions = this.getEndCommandSuggestions(); - } - } - - exitMvExpandCommand?(ctx: MvExpandCommandContext) { - const qn = ctx.qualifiedNames(); - if (qn && qn.text) { - this.suggestions = this.getEndCommandSuggestions(); - } - } - - exitQualifiedName(ctx: QualifiedNameContext) { - const isInEval = this.parentContext === ESQLParser.EVAL; - const isInStats = this.parentContext === ESQLParser.STATS; - const isInRename = this.parentContext === ESQLParser.RENAME; - if (this.parentContext && isInRename) { - if (!ctx.exception && ctx.text) { - this.suggestions = [asOperatorDefinition]; - } - } - if (this.parentContext && (isInStats || isInEval)) { - this.suggestions = [ - ...this.getEndCommandSuggestions(), - ...(isInEval ? mathOperatorsCommandsDefinitions : []), - ]; - } - - if ( - ctx - .identifier() - .some( - (i) => - !( - this.isTerminalNodeExists(i.QUOTED_IDENTIFIER()) || - this.isTerminalNodeExists(i.UNQUOTED_IDENTIFIER()) - ) - ) - ) { - this.suggestions = this.fields; - } - } - - enterField(ctx: FieldContext) { - this.suggestions = []; - } - - exitField(ctx: FieldContext) { - const hasAssign = this.isTerminalNodeExists(ctx.ASSIGN()); - - if (ctx.exception) { - if (!hasAssign) { - this.suggestions = [buildNewVarDefinition(this.getNewVarName())]; - return; - } - } else { - if (!hasAssign) { - this.suggestions = [assignOperatorDefinition]; - } - } - } - - exitUserVariable(ctx: UserVariableContext) { - if (!ctx.exception && ctx.text) { - this.tables.at(-1)?.push(ctx.text); - } - } - - enterBooleanExpression(ctx: BooleanExpressionContext) { - this.suggestions = []; - } - - exitBooleanExpression(ctx: BooleanExpressionContext) { - if (ctx.exception) { - const ve = ctx.valueExpression(); - if (!ve) { - if (this.parentContext === ESQLParser.STATS) { - this.suggestions = [...aggregationFunctionsDefinitions]; - return; - } - - if (this.parentContext === ESQLParser.EVAL) { - this.suggestions = [...mathCommandDefinition]; - return; - } - } - } - } - - exitValueExpression(ctx: ValueExpressionContext) { - const isInStats = this.parentContext === ESQLParser.STATS; - const isInEval = this.parentContext === ESQLParser.EVAL; - - if (isInStats || isInEval) { - const hasFN = - ctx.tryGetToken(esql_parser.UNARY_FUNCTION, 0) || - ctx.tryGetToken(esql_parser.MATH_FUNCTION, 0); - const hasLP = ctx.tryGetToken(esql_parser.LP, 0); - const hasRP = ctx.tryGetToken(esql_parser.RP, 0); - // TODO: handle also other math signs later on - const hasPlusOrMinus = - ctx.tryGetToken(esql_parser.PLUS, 0) || ctx.tryGetToken(esql_parser.MINUS, 0); - - const hasDateLiteral = ctx.tryGetToken(esql_parser.DATE_LITERAL, 0); - - const isInDurationMode = hasDateLiteral || (hasFN && isDateFunction(hasFN.text)); - if (hasPlusOrMinus && this.isTerminalNodeExists(hasPlusOrMinus)) { - if (isInEval) { - this.suggestions = isInDurationMode - ? // eval a = 1 year + || eval a = date_trunc(1 year, date) - - [ - ...mathCommandDefinition.filter(({ label }) => isDateFunction(String(label))), - ...getDurationItemsWithQuantifier(), - ] - : // eval a = 1 + || eval a = abs(b) - - [...this.fields, ...mathCommandDefinition]; - } else { - this.suggestions = [...this.fields, ...aggregationFunctionsDefinitions]; - } - return; - } - - // Monaco will auto close the brackets but the language listener will not pick up yet this auto-change. - // We try to inject it outside but it won't cover all scenarios - if (hasFN) { - if (!hasLP) { - this.suggestions = [openBracketDefinition]; - return; - } - - this.suggestions = []; - - if (!hasRP) { - if (ctx.childCount === 3) { - // TODO: improve here to suggest comma if signature has multiple args - this.suggestions.push(closeBracketDefinition); - } - } - this.suggestions.push(...this.fields); - // Need to get the function name from the previous node (current is "(" ) - const fnName = hasFN.text; - const fnsToCheck = isInEval ? mathCommandDefinition : aggregationFunctionsDefinitions; - if (fnName && fnsToCheck.some(({ label }) => label === fnName)) { - // push date suggestions only for date functions - // TODO: improve this checks - if (isInEval && isDateFunction(fnName)) { - if (!ctx.tryGetToken(esql_parser.DATE_LITERAL, 0)) { - this.suggestions.push( - // if it's just after the open bracket, suggest also a number together with a date period, - // otherwise just the date period unit - ...(endsWithOpenBracket(ctx.text) - ? getDurationItemsWithQuantifier() - : dateExpressionDefinitions) - ); - } - } - } - - return; - } else { - if (ctx.childCount === 1) { - if (ctx.text && ctx.text.indexOf('(') === -1) { - this.suggestions = [...mathOperatorsCommandsDefinitions]; - if (isInEval) { - // eval a = 1 || eval a = 1 year + 1 - if ( - this.hasDateExpressionTerminalNode(ctx.operatorExpression()) || - this.hasOnlyConstantDefined(ctx.operatorExpression()) - ) { - this.suggestions = [...getDateMathOperation(), ...dateExpressionDefinitions]; - } - } - - if (isInStats) { - this.suggestions.push(...aggregationFunctionsDefinitions); - } - - this.suggestions.push(...this.getEndCommandSuggestions()); - } - return; - } - } - this.suggestions = [...this.fields]; - if (ctx.exception && isInEval) { - // case: eval a = x * or / - this.suggestions.push(...mathCommandDefinition); - } - this.suggestions.push(...this.getEndCommandSuggestions()); - } - } - - enterWhereBooleanExpression(ctx: WhereBooleanExpressionContext) { - this.suggestions = []; - } - - enterWhereCommand(ctx: WhereCommandContext) { - this.suggestions = []; - this.parentContext = ESQLParser.WHERE; - } - - enterEnrichCommand(ctx: EnrichCommandContext) { - this.suggestions = []; - this.parentContext = ESQLParser.ENRICH; - } - - exitEnrichCommand(ctx: EnrichCommandContext) { - const policyName = ctx.enrichIdentifier().text; - if (policyName && !this.userDefinedVariables.policyIdentifiers.includes(policyName)) { - this.userDefinedVariables.policyIdentifiers.push(policyName); - } - - if (this.parentContext === ESQLParser.WITH) { - return; - } - if (!policyName) { - this.suggestions = this.policies; - } - - if (policyName) - if (this.parentContext === ESQLParser.ENRICH) { - const hasOn = this.isTerminalNodeExists(ctx.ON()); - if (hasOn && !ctx._matchField.text) { - this.suggestions = this.policyMatchingField; - } else { - this.suggestions = this.getEndCommandSuggestions( - hasOn ? [onOperatorDefinition] : undefined - ); - } - } - } - - enterEnrichWithClause(ctx: EnrichWithClauseContext) { - this.suggestions = []; - this.parentContext = ESQLParser.WITH; - } - - exitEnrichWithClause(ctx: EnrichWithClauseContext) { - const hasAssign = this.isTerminalNodeExists(ctx.ASSIGN()); - // Note: this gets filled only after the assign operation :( - if (ctx._newName?.text) { - this.tables.at(-1)?.push(ctx._newName.text); - } - - if (!ctx.exception && ctx.enrichFieldIdentifier().length === 1) { - // if it's after the assign operator, then suggest the fields from the policy - // TODO: need to check if the enrichFieldIdentifier given is a policyField or not and decide whether append the assignOperator - this.suggestions = !hasAssign - ? [assignOperatorDefinition, ...this.getEndCommandSuggestions()] - : this.policyFields; - } else { - this.suggestions = []; - if (!hasAssign) { - this.suggestions.push(buildNewVarDefinition(this.getNewVarName())); - } - if (!ctx._enrichField?.text) { - this.suggestions.push(...this.policyFields); - } - if (this.suggestions.length === 0) { - this.suggestions = this.getEndCommandSuggestions([ - onOperatorDefinition, - withOperatorDefinition, - ]); - } - } - } - - exitWhereCommand(ctx: WhereCommandContext) { - const booleanExpression = ctx.whereBooleanExpression(); - - if (booleanExpression.exception) { - if (!booleanExpression.text) { - this.suggestions = [...whereCommandDefinition, ...this.fields]; - return; - } - this.suggestions = this.fields; - return; - } else { - const innerBooleanExpressions = booleanExpression.getRuleContexts( - WhereBooleanExpressionContext - ); - const regexBooleanExpression = booleanExpression.getRuleContexts( - RegexBooleanExpressionContext - ); - - if (booleanExpression.WHERE_FUNCTIONS()) { - if (booleanExpression.COMMA().length) { - this.suggestions = []; - return; - } - } - - if (regexBooleanExpression.length) { - this.suggestions = []; - return; - } - - if (innerBooleanExpressions.some((be) => be.exception)) { - this.suggestions = this.fields; - return; - } - } - if (!this.hasSuggestions && !booleanExpression.WHERE_FUNCTIONS()) { - this.suggestions = comparisonCommandsDefinitions; - } - } - - exitComparison(ctx: ComparisonContext) { - const operatorExpression = ctx.operatorExpression(); - if (operatorExpression.some((o) => o.exception)) { - this.suggestions = this.fields; - return; - } - this.suggestions = [ - ...comparisonOperatorsCommandsDefinitions, - ...this.getEndCommandSuggestions(), - ]; - } - - exitOrderExpression(ctx: OrderExpressionContext) { - if (ctx.booleanExpression().exception) { - this.suggestions = this.fields; - return; - } - if (!this.isTerminalNodeExists(ctx.ORDERING())) { - this.suggestions = orderingCommandsDefinitions; - return; - } - if (!this.isTerminalNodeExists(ctx.NULLS_ORDERING())) { - this.suggestions = [nullsCommandsDefinition]; - return; - } - if (!this.isTerminalNodeExists(ctx.NULLS_ORDERING_DIRECTION())) { - this.suggestions = nullsOrderingCommandsDefinitions; - return; - } - } - - exitLimitCommand(ctx: LimitCommandContext) { - const DEFAULT_LIMIT_SIZE = 1000; - - if (!this.isTerminalNodeExists(ctx.INTEGER_LITERAL())) { - this.suggestions = buildConstantsDefinitions([DEFAULT_LIMIT_SIZE.toString()], ''); - } else { - this.suggestions = this.getEndCommandSuggestions(); - } - } -} diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts deleted file mode 100644 index 621c8900447a0..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export enum DynamicAutocompleteItem { - SourceIdentifier = 'SourceIdentifier', - FieldIdentifier = 'FieldIdentifier', - PolicyIdentifier = 'PolicyIdentifier', - PolicyFieldIdentifier = 'PolicyFieldIdentifier', - PolicyMatchingFieldIdentifier = 'PolicyMatchingFieldIdentifier', -} - -const DynamicAutocompleteItems = Object.values(DynamicAutocompleteItem); - -export function isDynamicAutocompleteItem(v: unknown): v is DynamicAutocompleteItem { - return DynamicAutocompleteItems.some((dai) => dai === v); -} diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/helpers.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/helpers.ts deleted file mode 100644 index be1392cb11e72..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/helpers.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { mathOperatorsCommandsDefinitions } from './autocomplete_definitions'; -import { dateExpressionDefinitions } from './autocomplete_definitions/date_math_expressions'; - -export function endsWithOpenBracket(text: string) { - return /\($/.test(text); -} - -export function isDateFunction(fnName: string) { - // TODO: improve this and rely in signature in the future - return ['to_datetime', 'date_trunc', 'date_parse'].includes(fnName.toLowerCase()); -} - -export function getDateMathOperation() { - return mathOperatorsCommandsDefinitions.filter(({ label }) => ['+', '-'].includes(String(label))); -} - -export function getDurationItemsWithQuantifier(quantifier: number = 1) { - return dateExpressionDefinitions - .filter(({ label }) => !/s$/.test(label.toString())) - .map(({ label, insertText, ...rest }) => ({ - label: `${quantifier} ${label}`, - insertText: `${quantifier} ${insertText}`, - ...rest, - })); -} diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts deleted file mode 100644 index fc22bae7bbdb9..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { monaco } from '../../../..'; - -/** @public **/ -export interface ESQLCustomAutocompleteCallbacks { - getSourceIdentifiers?: CallbackFn; - getFieldsIdentifiers?: CallbackFn; - getPoliciesIdentifiers?: CallbackFn<{ name: string; indices: string[] }>; - getPolicyFieldsIdentifiers?: CallbackFn; - getPolicyMatchingFieldIdentifiers?: CallbackFn; -} - -/** @internal **/ -type CallbackFn = (ctx: { - word: string; - userDefinedVariables: UserDefinedVariables; -}) => T[] | Promise; - -/** @internal **/ -export interface UserDefinedVariables { - sourceIdentifiers: string[]; - policyIdentifiers: string[]; -} - -/** @internal **/ -export type AutocompleteCommandDefinition = Pick< - monaco.languages.CompletionItem, - 'label' | 'insertText' | 'kind' | 'detail' | 'documentation' | 'sortText' | 'command' ->; diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_ast_provider.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_ast_provider.ts new file mode 100644 index 0000000000000..39bd193d5611c --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_ast_provider.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { EditorError } from '../../../types'; +import type { ESQLCallbacks } from '../ast/shared/types'; +import { monaco } from '../../../monaco_imports'; +import type { ESQLWorker } from '../../worker/esql_worker'; +import { suggest } from '../ast/autocomplete/autocomplete'; +import { getHoverItem } from '../ast/hover'; +import { getSignatureHelp } from '../ast/signature'; +import type { ESQLMessage } from '../ast/types'; +import { validateAst } from '../ast/validation/validation'; + +// from linear offset to Monaco position +export function offsetToRowColumn(expression: string, offset: number): monaco.Position { + const lines = expression.split(/\n/); + let remainingChars = offset; + let lineNumber = 1; + for (const line of lines) { + if (line.length >= remainingChars) { + return new monaco.Position(lineNumber, remainingChars + 1); + } + remainingChars -= line.length + 1; + lineNumber++; + } + + throw new Error('Algorithm failure'); +} + +function wrapAsMonacoMessage( + type: 'error' | 'warning', + code: string, + messages: Array +): EditorError[] { + const fallbackPosition = { column: 0, lineNumber: 0 }; + return messages.map((e) => { + if ('severity' in e) { + return e; + } + const startPosition = e.location ? offsetToRowColumn(code, e.location.min) : fallbackPosition; + const endPosition = e.location + ? offsetToRowColumn(code, e.location.max || 0) + : fallbackPosition; + return { + message: e.text, + startColumn: startPosition.column, + startLineNumber: startPosition.lineNumber, + endColumn: endPosition.column + 1, + endLineNumber: endPosition.lineNumber, + severity: type === 'error' ? monaco.MarkerSeverity.Error : monaco.MarkerSeverity.Warning, + _source: 'client' as const, + }; + }); +} + +export class ESQLAstAdapter { + constructor( + private worker: (...uris: monaco.Uri[]) => Promise, + private callbacks?: ESQLCallbacks + ) {} + + private async getAstWorker(model: monaco.editor.ITextModel) { + const worker = await this.worker(model.uri); + return worker.getAst; + } + + async getAst(model: monaco.editor.ITextModel, code?: string) { + const getAstFn = await this.getAstWorker(model); + return getAstFn(code ?? model.getValue()); + } + + async validate(model: monaco.editor.ITextModel, code: string) { + const getAstFn = await this.getAstWorker(model); + const { errors, warnings } = await validateAst( + code ?? model.getValue(), + getAstFn, + this.callbacks + ); + const monacoErrors = wrapAsMonacoMessage('error', code, errors); + const monacoWarnings = wrapAsMonacoMessage('warning', code, warnings); + return { errors: monacoErrors, warnings: monacoWarnings }; + } + + async suggestSignature( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.SignatureHelpContext + ) { + const getAstFn = await this.getAstWorker(model); + return getSignatureHelp(model, position, context, getAstFn); + } + + async getHover( + model: monaco.editor.ITextModel, + position: monaco.Position, + token: monaco.CancellationToken + ) { + const getAstFn = await this.getAstWorker(model); + return getHoverItem(model, position, token, getAstFn, this.callbacks); + } + + async autocomplete( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.CompletionContext + ) { + const getAstFn = await this.getAstWorker(model); + const suggestionEntries = await suggest(model, position, context, getAstFn, this.callbacks); + return { + suggestions: suggestionEntries.map((suggestion) => ({ + ...suggestion, + range: undefined as unknown as monaco.IRange, + })), + }; + } +} diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts deleted file mode 100644 index 4a407c3519769..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { monaco } from '../../../monaco_imports'; -import { DynamicAutocompleteItem, isDynamicAutocompleteItem } from '../autocomplete/dymanic_item'; -import { - buildFieldsDefinitions, - buildSourcesDefinitions, - buildPoliciesDefinitions, - buildNoPoliciesAvailableDefinition, - buildMatchingFieldsDefinition, -} from '../autocomplete/autocomplete_definitions/dynamic_commands'; -import { pipeDefinition } from '../autocomplete/autocomplete_definitions'; - -import type { - AutocompleteCommandDefinition, - ESQLCustomAutocompleteCallbacks, - UserDefinedVariables, -} from '../autocomplete/types'; -import type { ESQLWorker } from '../../worker/esql_worker'; - -export class ESQLCompletionAdapter implements monaco.languages.CompletionItemProvider { - constructor( - private worker: (...uris: monaco.Uri[]) => Promise, - private callbacks?: ESQLCustomAutocompleteCallbacks - ) {} - - public triggerCharacters = ['(', ' ', '']; - - private async injectDynamicAutocompleteItems( - suggestions: Array, - ctx: { - word: string; - userDefinedVariables: UserDefinedVariables; - } - ): Promise { - const allSuggestions: AutocompleteCommandDefinition[][] = await Promise.all( - suggestions.map(async (suggestion) => { - if (!isDynamicAutocompleteItem(suggestion)) { - return [suggestion]; - } - let dynamicItems: AutocompleteCommandDefinition[] = []; - - if (suggestion === DynamicAutocompleteItem.SourceIdentifier) { - dynamicItems = buildSourcesDefinitions( - (await this.callbacks?.getSourceIdentifiers?.(ctx)) ?? [] - ); - if (!ctx.word && ctx.userDefinedVariables.sourceIdentifiers.length) { - dynamicItems = [pipeDefinition]; - } - } - - if (suggestion === DynamicAutocompleteItem.FieldIdentifier) { - dynamicItems = buildFieldsDefinitions( - (await this.callbacks?.getFieldsIdentifiers?.(ctx)) ?? [] - ); - } - - if (suggestion === DynamicAutocompleteItem.PolicyIdentifier) { - const results = await this.callbacks?.getPoliciesIdentifiers?.(ctx); - dynamicItems = results?.length - ? buildPoliciesDefinitions(results) - : buildNoPoliciesAvailableDefinition(); - } - - if (suggestion === DynamicAutocompleteItem.PolicyFieldIdentifier) { - dynamicItems = buildFieldsDefinitions( - (await this.callbacks?.getPolicyFieldsIdentifiers?.(ctx)) || [] - ); - } - - if (suggestion === DynamicAutocompleteItem.PolicyMatchingFieldIdentifier) { - const [fields = [], matchingField] = await Promise.all([ - this.callbacks?.getFieldsIdentifiers?.(ctx), - this.callbacks?.getPolicyMatchingFieldIdentifiers?.(ctx), - ]); - dynamicItems = matchingField?.length - ? buildMatchingFieldsDefinition(matchingField[0], fields) - : buildFieldsDefinitions(fields); - } - return dynamicItems; - }) - ); - - return allSuggestions.flat(); - } - - async provideCompletionItems( - model: monaco.editor.IReadOnlyModel, - position: monaco.Position - ): Promise { - const lines = model.getLineCount(); - - const currentLineChars = model.getValueInRange({ - startLineNumber: 0, - startColumn: 0, - endLineNumber: position.lineNumber, - endColumn: position.column, - }); - const wordInfo = model.getWordUntilPosition(position); - const worker = await this.worker(model.uri); - const providedSuggestions = - lines !== position.lineNumber || - model.getLineContent(position.lineNumber).trimEnd().length >= position.column - ? await worker.provideAutocompleteSuggestionsFromString(currentLineChars) - : await worker.provideAutocompleteSuggestions(model.uri.toString(), { - word: wordInfo.word, - line: position.lineNumber, - index: position.column, - }); - - const withDynamicItems = providedSuggestions - ? await this.injectDynamicAutocompleteItems(providedSuggestions.suggestions, { - word: wordInfo.word, - userDefinedVariables: providedSuggestions.userDefinedVariables, - }) - : []; - - return { - suggestions: withDynamicItems.map((i) => ({ - ...i, - range: { - startLineNumber: position.lineNumber, - endLineNumber: position.lineNumber, - startColumn: wordInfo.startColumn, - endColumn: wordInfo.endColumn, - }, - })), - }; - } -} diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_error_listener.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_error_listener.ts new file mode 100644 index 0000000000000..8881c9b458cc0 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_error_listener.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ANTLRErrorListener, Recognizer, RecognitionException } from 'antlr4ts'; +import type { EditorError } from '../../../types'; +import { createError } from '../ast/ast_errors'; + +export class ESQLErrorListener implements ANTLRErrorListener { + private errors: EditorError[] = []; + + syntaxError( + recognizer: Recognizer, + offendingSymbol: any, + line: number, + column: number, + message: string, + error: RecognitionException | undefined + ): void { + const higherLevelError = error ? createError(error) : undefined; + const textMessage = + higherLevelError?.text && higherLevelError.text !== error?.message + ? higherLevelError.text + : `SyntaxError: ${message}`; + + let endColumn = column + 1; + let startColumn = column; + + if (higherLevelError) { + startColumn = higherLevelError.location.min + 1; + endColumn = higherLevelError.location.max + 1; + } else if (offendingSymbol?._text) { + endColumn = column + offendingSymbol._text.length; + } + + this.errors.push({ + startLineNumber: line, + endLineNumber: line, + startColumn, + endColumn, + message: textMessage, + severity: 8, // monaco.MarkerSeverity.Error, + }); + } + + getErrors(): EditorError[] { + return this.errors; + } +} diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_line_tokens.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_line_tokens.ts index c4817aac586d4..0148884f9bf8b 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_line_tokens.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_line_tokens.ts @@ -11,11 +11,12 @@ import { ESQLState } from './esql_state'; /** @internal **/ export class ESQLLineTokens implements monaco.languages.ILineTokens { - endState: monaco.languages.IState; + endState: ESQLState; tokens: monaco.languages.IToken[]; - constructor(tokens: monaco.languages.IToken[]) { + constructor(tokens: monaco.languages.IToken[], line: number) { this.endState = new ESQLState(); + this.endState.setLineNumber(line); this.tokens = tokens; } } diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_state.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_state.ts index a7cfd10f79276..d69702ff926f4 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_state.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_state.ts @@ -10,8 +10,20 @@ import { monaco } from '../../../monaco_imports'; /** @internal **/ export class ESQLState implements monaco.languages.IState { + private lastLine: number = 0; + + setLineNumber(n: number) { + this.lastLine = n; + } + + getLineNumber() { + return this.lastLine; + } + clone(): monaco.languages.IState { - return new ESQLState(); + const newState = new ESQLState(); + newState.setLineNumber(this.lastLine); + return newState; } equals(other: monaco.languages.IState): boolean { diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts index 6fc6caee2886f..1647b954ada7d 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts @@ -77,12 +77,9 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ 'row', 'show', 'limit', - 'cidr_match', 'nulls_ordering_direction', 'nulls_ordering', 'null', - 'boolean_value', - 'comparison_operator', 'enrich', 'on', 'with', @@ -90,12 +87,8 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ euiThemeVars.euiColorPrimaryText ), - // aggregation functions - ...buildRuleGroup(['unary_function'], euiThemeVars.euiColorPrimaryText), - // is null functions - ...buildRuleGroup(['where_functions'], euiThemeVars.euiColorPrimaryText), - // math functions - ...buildRuleGroup(['math_function'], euiThemeVars.euiColorPrimaryText), + // functions + ...buildRuleGroup(['functions'], euiThemeVars.euiColorPrimaryText), // operators ...buildRuleGroup( diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_token_helpers.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_token_helpers.ts new file mode 100644 index 0000000000000..497344dd606c4 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_token_helpers.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { monaco } from '../../../monaco_imports'; +import { nonNullable } from '../ast/ast_helpers'; +import { ESQL_TOKEN_POSTFIX } from '../constants'; + +export function enrichTokensWithFunctionsMetadata( + tokens: monaco.languages.IToken[] +): monaco.languages.IToken[] { + // need to trim spaces as "abs (arg)" is still valid as function + const myTokensWithoutSpaces = tokens.filter( + ({ scopes }) => scopes !== 'expr_ws' + ESQL_TOKEN_POSTFIX + ); + // find out all unquoted_identifiers index + const possiblyFunctions = myTokensWithoutSpaces + .map((t, i) => (t.scopes === 'unquoted_identifier' + ESQL_TOKEN_POSTFIX ? i : undefined)) + .filter(nonNullable); + + // then check if the token next is an opening bracket + for (const index of possiblyFunctions) { + if (myTokensWithoutSpaces[index + 1]?.scopes === 'lp' + ESQL_TOKEN_POSTFIX) { + // set the custom "functions" token (only used in theming) + myTokensWithoutSpaces[index].scopes = 'functions' + ESQL_TOKEN_POSTFIX; + } + } + return [...tokens]; +} diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_tokens_provider.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_tokens_provider.ts index 2166a5e6f68ea..aa0234c155c33 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_tokens_provider.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_tokens_provider.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { CharStreams, Token } from 'antlr4ts'; +import { CharStreams, type Token } from 'antlr4ts'; import { monaco } from '../../../monaco_imports'; import { ANTLREErrorListener } from '../../../common/error_listener'; @@ -16,6 +16,7 @@ import { ESQLState } from './esql_state'; import { getLexer } from '../antlr_facade'; import { ESQL_TOKEN_POSTFIX } from '../constants'; +import { enrichTokensWithFunctionsMetadata } from './esql_token_helpers'; const EOF = -1; @@ -24,10 +25,16 @@ export class ESQLTokensProvider implements monaco.languages.TokensProvider { return new ESQLState(); } - tokenize(line: string, state: monaco.languages.IState): monaco.languages.ILineTokens { + tokenize(line: string, prevState: ESQLState): monaco.languages.ILineTokens { const errorStartingPoints: number[] = []; const errorListener = new ANTLREErrorListener(); - const inputStream = CharStreams.fromString(line); + // This has the drawback of not styling any ESQL wrong query as + // | from ... + const cleanedLine = + prevState.getLineNumber() && line.trimStart()[0] === '|' + ? line.trimStart().substring(1) + : line; + const inputStream = CharStreams.fromString(cleanedLine); const lexer = getLexer(inputStream, errorListener); let done = false; @@ -63,6 +70,11 @@ export class ESQLTokensProvider implements monaco.languages.TokensProvider { myTokens.sort((a, b) => a.startIndex - b.startIndex); - return new ESQLLineTokens(myTokens); + // special tratement for functions + // the previous custom Kibana grammar baked functions directly as tokens, so highlight was easier + // The ES grammar doesn't have the token concept of "function" + const tokensWithFunctions = enrichTokensWithFunctionsMetadata(myTokens); + + return new ESQLLineTokens(tokensWithFunctions, prevState.getLineNumber() + 1); } } diff --git a/packages/kbn-monaco/src/esql/worker/esql_worker.ts b/packages/kbn-monaco/src/esql/worker/esql_worker.ts index 4656ac9e9db7c..db3e01ae220e5 100644 --- a/packages/kbn-monaco/src/esql/worker/esql_worker.ts +++ b/packages/kbn-monaco/src/esql/worker/esql_worker.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import { CharStreams, type CodePointCharStream } from 'antlr4ts'; -import { monaco } from '../../monaco_imports'; -import { AutocompleteListener } from '../lib/autocomplete/autocomplete_listener'; +import { CharStreams } from 'antlr4ts'; +import type { monaco } from '../../monaco_imports'; import type { BaseWorkerDefinition } from '../../types'; import { getParser, ROOT_STATEMENT } from '../lib/antlr_facade'; -import { ANTLREErrorListener } from '../../common/error_listener'; +import { AstListener } from '../lib/ast/ast_factory'; +import { ESQLErrorListener } from '../lib/monaco/esql_error_listener'; export class ESQLWorker implements BaseWorkerDefinition { private readonly _ctx: monaco.worker.IWorkerContext; @@ -33,7 +33,7 @@ export class ESQLWorker implements BaseWorkerDefinition { const inputStream = this.getModelCharStream(modelUri); if (inputStream) { - const errorListener = new ANTLREErrorListener(); + const errorListener = new ESQLErrorListener(); const parser = getParser(inputStream, errorListener); parser[ROOT_STATEMENT](); @@ -43,32 +43,21 @@ export class ESQLWorker implements BaseWorkerDefinition { return []; } - private async provideAutocompleteSuggestionFromRawString( - inputStream: CodePointCharStream | undefined - ) { - if (inputStream) { - const errorListener = new ANTLREErrorListener(); - const parseListener = new AutocompleteListener(); - const parser = getParser(inputStream, errorListener, parseListener); - - parser[ROOT_STATEMENT](); - - return parseListener.getAutocompleteSuggestions(); + async getAst(text: string | undefined) { + if (!text) { + return { ast: [], errors: [] }; } - } - - public async provideAutocompleteSuggestions( - modelUri: string, - meta: { - word: string; - line: number; - index: number; - } - ) { - return this.provideAutocompleteSuggestionFromRawString(this.getModelCharStream(modelUri)); - } - - public async provideAutocompleteSuggestionsFromString(text: string) { - return this.provideAutocompleteSuggestionFromRawString(CharStreams.fromString(text)); + const inputStream = CharStreams.fromString(text); + const errorListener = new ESQLErrorListener(); + const parserListener = new AstListener(); + const parser = getParser(inputStream, errorListener, parserListener); + + parser[ROOT_STATEMENT](); + + const { ast } = parserListener.getAst(); + return { + ast, + errors: errorListener.getErrors(), + }; } } diff --git a/packages/kbn-monaco/src/types.ts b/packages/kbn-monaco/src/types.ts index 0e5952db8344c..b2559fd919d16 100644 --- a/packages/kbn-monaco/src/types.ts +++ b/packages/kbn-monaco/src/types.ts @@ -23,11 +23,25 @@ export interface CompleteLangModuleType extends LangModuleType { validation$: () => Observable; } -export interface CustomLangModuleType extends LangModuleType { +export interface LanguageProvidersModule { + validate: ( + model: monaco.editor.ITextModel, + code: string, + callbacks?: Deps + ) => Promise<{ errors: monaco.editor.IMarkerData[]; warnings: monaco.editor.IMarkerData[] }>; + getSuggestionProvider: (callbacks?: Deps) => monaco.languages.CompletionItemProvider; + getSignatureProvider?: (callbacks?: Deps) => monaco.languages.SignatureHelpProvider; + getHoverProvider?: (callbacks?: Deps) => monaco.languages.HoverProvider; +} + +export interface CustomLangModuleType + extends Omit, + LanguageProvidersModule { onLanguage: () => void; } export interface EditorError { + severity: monaco.MarkerSeverity; startLineNumber: number; startColumn: number; endLineNumber: number; diff --git a/packages/kbn-text-based-editor/src/editor_footer.tsx b/packages/kbn-text-based-editor/src/editor_footer.tsx index 6bc663713a8d0..0841058aca9e1 100644 --- a/packages/kbn-text-based-editor/src/editor_footer.tsx +++ b/packages/kbn-text-based-editor/src/editor_footer.tsx @@ -26,7 +26,7 @@ import { import { Interpolation, Theme, css } from '@emotion/react'; import { css as classNameCss } from '@emotion/css'; -import type { MonacoError } from './helpers'; +import type { MonacoMessage } from './helpers'; const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0; const COMMAND_KEY = isMac ? '⌘' : '^'; @@ -98,10 +98,10 @@ export function ErrorsWarningsPopover({ isSpaceReduced, }: { isPopoverOpen: boolean; - items: MonacoError[]; + items: MonacoMessage[]; type: 'error' | 'warning'; setIsPopoverOpen: (flag: boolean) => void; - onErrorClick: (error: MonacoError) => void; + onErrorClick: (error: MonacoMessage) => void; isSpaceReduced?: boolean; }) { const strings = getConstsByType(type, items.length); @@ -184,10 +184,10 @@ export function ErrorsWarningsPopover({ interface EditorFooterProps { lines: number; containerCSS: Interpolation; - errors?: MonacoError[]; - warning?: MonacoError[]; + errors?: MonacoMessage[]; + warnings?: MonacoMessage[]; detectTimestamp: boolean; - onErrorClick: (error: MonacoError) => void; + onErrorClick: (error: MonacoMessage) => void; runQuery: () => void; hideRunQueryText?: boolean; disableSubmitAction?: boolean; @@ -199,7 +199,7 @@ export const EditorFooter = memo(function EditorFooter({ lines, containerCSS, errors, - warning, + warnings, detectTimestamp, onErrorClick, runQuery, @@ -209,8 +209,8 @@ export const EditorFooter = memo(function EditorFooter({ isSpaceReduced, }: EditorFooterProps) { const { euiTheme } = useEuiTheme(); - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - + const [isErrorPopoverOpen, setIsErrorPopoverOpen] = useState(false); + const [isWarningPopoverOpen, setIsWarningPopoverOpen] = useState(false); return ( 0 && ( { + if (isOpen) { + setIsWarningPopoverOpen(false); + } + setIsErrorPopoverOpen(isOpen); + }} onErrorClick={onErrorClick} - isSpaceReduced={isSpaceReduced} /> )} - {warning && warning.length > 0 && ( + {warnings && warnings.length > 0 && ( { + if (isOpen) { + setIsErrorPopoverOpen(false); + } + setIsWarningPopoverOpen(isOpen); + }} onErrorClick={onErrorClick} - isSpaceReduced={isSpaceReduced} /> )} diff --git a/packages/kbn-text-based-editor/src/helpers.test.ts b/packages/kbn-text-based-editor/src/helpers.test.ts index f0a4268f857bc..8ba691bb4e3ee 100644 --- a/packages/kbn-text-based-editor/src/helpers.test.ts +++ b/packages/kbn-text-based-editor/src/helpers.test.ts @@ -11,7 +11,7 @@ import { parseWarning, getInlineEditorText, getWrappedInPipesCode, - getIndicesForAutocomplete, + getIndicesList, } from './helpers'; describe('helpers', function () { @@ -23,7 +23,7 @@ describe('helpers', function () { const errors = [error]; expect(parseErrors(errors, 'SELECT miaou from test')).toEqual([ { - endColumn: 13, + endColumn: 14, endLineNumber: 1, message: ' Unknown column [miaou]', severity: 8, @@ -47,7 +47,7 @@ describe('helpers', function () { ) ).toEqual([ { - endColumn: 11, + endColumn: 12, endLineNumber: 3, message: ' Condition expression needs to be boolean, found [TEXT]', severity: 8, @@ -83,7 +83,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', - severity: 8, + severity: 4, startColumn: 52, startLineNumber: 1, }, @@ -99,7 +99,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', - severity: 8, + severity: 4, startColumn: 52, startLineNumber: 1, }, @@ -108,7 +108,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'evaluation of [date_parse(geo.src)] failed, treating result as null. Only first 20 failures recorded.', - severity: 8, + severity: 4, startColumn: 84, startLineNumber: 1, }, @@ -124,7 +124,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -133,7 +133,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -142,7 +142,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [timestamp_range] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -157,7 +157,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -166,7 +166,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -175,7 +175,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', - severity: 8, + severity: 4, startColumn: 52, startLineNumber: 1, }, @@ -233,8 +233,8 @@ describe('helpers', function () { }); }); - describe('getIndicesForAutocomplete', function () { - it('should not return system indices', async function () { + describe('getIndicesList', function () { + it('should return also system indices with hidden flag on', async function () { const dataViewsMock = dataViewPluginMocks.createStartContract(); const updatedDataViewsMock = { ...dataViewsMock, @@ -249,8 +249,11 @@ describe('helpers', function () { }, ]), }; - const indices = await getIndicesForAutocomplete(updatedDataViewsMock); - expect(indices).toStrictEqual(['logs']); + const indices = await getIndicesList(updatedDataViewsMock); + expect(indices).toStrictEqual([ + { name: '.system1', hidden: true }, + { name: 'logs', hidden: false }, + ]); }); }); }); diff --git a/packages/kbn-text-based-editor/src/helpers.ts b/packages/kbn-text-based-editor/src/helpers.ts index 234a5ae0089ab..88df8ef6a75e4 100644 --- a/packages/kbn-text-based-editor/src/helpers.ts +++ b/packages/kbn-text-based-editor/src/helpers.ts @@ -11,15 +11,9 @@ import useDebounce from 'react-use/lib/useDebounce'; import { monaco } from '@kbn/monaco'; import { i18n } from '@kbn/i18n'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { MapCache } from 'lodash'; -export interface MonacoError { - message: string; - startColumn: number; - startLineNumber: number; - endColumn: number; - endLineNumber: number; - severity: monaco.MarkerSeverity; -} +export type MonacoMessage = monaco.editor.IMarkerData; export const useDebounceWithOptions = ( fn: Function, @@ -45,7 +39,7 @@ export const useDebounceWithOptions = ( const quotedWarningMessageRegexp = /"(.*?)"/g; -export const parseWarning = (warning: string): MonacoError[] => { +export const parseWarning = (warning: string): MonacoMessage[] => { if (quotedWarningMessageRegexp.test(warning)) { const matches = warning.match(quotedWarningMessageRegexp); if (matches) { @@ -81,7 +75,7 @@ export const parseWarning = (warning: string): MonacoError[] => { startLineNumber, endColumn: startColumn + errorLength - 1, endLineNumber: startLineNumber, - severity: monaco.MarkerSeverity.Error, + severity: monaco.MarkerSeverity.Warning, }; }); } @@ -94,14 +88,18 @@ export const parseWarning = (warning: string): MonacoError[] => { startLineNumber: 1, endColumn: 10, endLineNumber: 1, - severity: monaco.MarkerSeverity.Error, + severity: monaco.MarkerSeverity.Warning, }, ]; }; -export const parseErrors = (errors: Error[], code: string): MonacoError[] => { +export const parseErrors = (errors: Error[], code: string): MonacoMessage[] => { return errors.map((error) => { - if (error.message.includes('line')) { + if ( + // Found while testing random commands (as inlinestats) + !error.message.includes('esql_illegal_argument_exception') && + error.message.includes('line') + ) { const text = error.message.split('line')[1]; const [lineNumber, startPosition, errorMessage] = text.split(':'); // initialize the length to 10 in case no error word found @@ -114,7 +112,7 @@ export const parseErrors = (errors: Error[], code: string): MonacoError[] => { message: errorMessage, startColumn: Number(startPosition), startLineNumber: Number(lineNumber), - endColumn: Number(startPosition) + errorLength, + endColumn: Number(startPosition) + errorLength + 1, endLineNumber: Number(lineNumber), severity: monaco.MarkerSeverity.Error, }; @@ -193,11 +191,23 @@ export const getWrappedInPipesCode = (code: string, isWrapped: boolean): string return codeNoLines.join(isWrapped ? ' | ' : '\n| '); }; -export const getIndicesForAutocomplete = async (dataViews: DataViewsPublicPluginStart) => { +export const getIndicesList = async (dataViews: DataViewsPublicPluginStart) => { const indices = await dataViews.getIndices({ showAllIndices: false, pattern: '*', isRollupIndex: () => false, }); - return indices.filter((index) => !index.name.startsWith('.')).map((i) => i.name); + return indices.map((index) => ({ name: index.name, hidden: index.name.startsWith('.') })); +}; + +// refresh the esql cache entry after 10 minutes +const CACHE_INVALIDATE_DELAY = 10 * 60 * 1000; + +export const clearCacheWhenOld = (cache: MapCache, esqlQuery: string) => { + if (cache.has(esqlQuery)) { + const cacheEntry = cache.get(esqlQuery); + if (Date.now() - cacheEntry.timestamp > CACHE_INVALIDATE_DELAY) { + cache.delete(esqlQuery); + } + } }; diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index 9d175ef86ecf0..356b4722c0f87 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -6,22 +6,22 @@ * Side Public License, v 1. */ -import React, { useRef, memo, useEffect, useState, useCallback } from 'react'; +import React, { useRef, memo, useEffect, useState, useCallback, useMemo } from 'react'; import classNames from 'classnames'; +import memoize from 'lodash/memoize'; import { SQLLang, monaco, ESQL_LANG_ID, ESQL_THEME_ID, ESQLLang, - ESQLCustomAutocompleteCallbacks, + type ESQLCallbacks, } from '@kbn/monaco'; import type { AggregateQuery } from '@kbn/es-query'; import { getAggregateQueryMode, getLanguageDisplayName } from '@kbn/es-query'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; import type { IndexManagementPluginSetup } from '@kbn/index-management-plugin/public'; -import type { SerializedEnrichPolicy } from '@kbn/index-management-plugin/common'; import { type LanguageDocumentationSections, LanguageDocumentationPopover, @@ -50,13 +50,14 @@ import { } from './text_based_languages_editor.styles'; import { useDebounceWithOptions, - parseErrors, parseWarning, getInlineEditorText, getDocumentationSections, - MonacoError, + type MonacoMessage, getWrappedInPipesCode, - getIndicesForAutocomplete, + parseErrors, + getIndicesList, + clearCacheWhenOld, } from './helpers'; import { EditorFooter } from './editor_footer'; import { ResizableButton } from './resizable_button'; @@ -136,7 +137,6 @@ const languageId = (language: string) => { let clickedOutside = false; let initialRender = true; let updateLinesFromModel = false; -let currentCursorContent = ''; let lines = 1; export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ @@ -146,8 +146,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ expandCodeEditor, isCodeEditorExpanded, detectTimestamp = false, - errors, - warning, + errors: serverErrors, + warning: serverWarning, isDisabled, isDarkMode, hideMinimizeButton, @@ -163,6 +163,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const { dataViews, expressions, indexManagementApiService, application } = kibana.services; const [code, setCode] = useState(queryString ?? ''); const [codeOneLiner, setCodeOneLiner] = useState(''); + // To make server side errors less "sticky", register the state of the code when submitting + const [codeWhenSubmitted, setCodeStateOnSubmission] = useState(code); const [editorHeight, setEditorHeight] = useState( isCodeEditorExpanded ? EDITOR_INITIAL_HEIGHT_EXPANDED : EDITOR_INITIAL_HEIGHT ); @@ -171,13 +173,27 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const [isCompactFocused, setIsCompactFocused] = useState(isCodeEditorExpanded); const [isCodeEditorExpandedFocused, setIsCodeEditorExpandedFocused] = useState(false); const [isWordWrapped, setIsWordWrapped] = useState(false); - const [editorErrors, setEditorErrors] = useState([]); - const [editorWarning, setEditorWarning] = useState([]); + + const [editorMessages, setEditorMessages] = useState<{ + errors: MonacoMessage[]; + warnings: MonacoMessage[]; + }>({ + errors: serverErrors ? parseErrors(serverErrors, code) : [], + warnings: serverWarning ? parseWarning(serverWarning) : [], + }); + + const onQuerySubmit = useCallback(() => { + const currentValue = editor1.current?.getValue(); + if (currentValue != null) { + setCodeStateOnSubmission(currentValue); + } + onTextLangQuerySubmit({ [language]: currentValue } as AggregateQuery); + }, [language, onTextLangQuerySubmit]); const [documentationSections, setDocumentationSections] = useState(); - const policiesRef = useRef([]); + const codeRef = useRef(code); // Registers a command to redirect users to the index management page // to create a new policy. The command is called by the buildNoPoliciesAvailableDefinition @@ -193,8 +209,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ isCompactFocused, editorHeight, isCodeEditorExpanded, - Boolean(errors?.length), - Boolean(warning), + Boolean(editorMessages.errors.length), + Boolean(editorMessages.warnings.length), isCodeEditorExpandedFocused, Boolean(documentationSections), Boolean(editorIsInline) @@ -247,11 +263,6 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ [editorHeight] ); - const onQuerySubmit = useCallback(() => { - const currentValue = editor1.current?.getValue(); - onTextLangQuerySubmit({ [language]: currentValue } as AggregateQuery); - }, [language, onTextLangQuerySubmit]); - const restoreInitialMode = () => { setIsCodeEditorExpandedFocused(false); if (isCodeEditorExpanded) return; @@ -294,30 +305,117 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ updateLinesFromModel = true; }, []); + const { cache: esqlFieldsCache, memoizedFieldsFromESQL } = useMemo(() => { + // need to store the timing of the first request so we can atomically clear the cache per query + const fn = memoize( + (...args: [{ esql: string }, ExpressionsStart]) => ({ + timestamp: Date.now(), + result: fetchFieldsFromESQL(...args), + }), + ({ esql }) => esql + ); + return { cache: fn.cache, memoizedFieldsFromESQL: fn }; + }, []); + + const esqlCallbacks: ESQLCallbacks = useMemo( + () => ({ + getSources: async () => { + return await getIndicesList(dataViews); + }, + getFieldsFor: async ({ query: queryToExecute }: { query?: string } | undefined = {}) => { + if (queryToExecute) { + // ES|QL with limit 0 returns only the columns and is more performant + const esqlQuery = { + esql: `${queryToExecute} | limit 0`, + }; + // Check if there's a stale entry and clear it + clearCacheWhenOld(esqlFieldsCache, esqlQuery.esql); + try { + const table = await memoizedFieldsFromESQL(esqlQuery, expressions).result; + return table?.columns.map((c) => ({ name: c.name, type: c.meta.type })) || []; + } catch (e) { + // no action yet + } + } + return []; + }, + getPolicies: async () => { + const { data: policies, error } = + (await indexManagementApiService?.getAllEnrichPolicies()) || {}; + if (error || !policies) { + return []; + } + return policies.map(({ type, query: policyQuery, ...rest }) => rest); + }, + }), + [dataViews, expressions, indexManagementApiService, esqlFieldsCache, memoizedFieldsFromESQL] + ); + + const queryValidation = useCallback( + async ({ active }: { active: boolean }) => { + if (!editorModel.current || language !== 'esql' || editorModel.current.isDisposed()) return; + monaco.editor.setModelMarkers(editorModel.current, 'Unified search', []); + const { warnings: parserWarnings, errors: parserErrors } = await ESQLLang.validate( + editorModel.current, + code, + esqlCallbacks + ); + const markers = []; + + if (parserErrors.length) { + markers.push(...parserErrors); + } + if (active) { + setEditorMessages({ errors: parserErrors, warnings: parserWarnings }); + monaco.editor.setModelMarkers(editorModel.current, 'Unified search', markers); + return; + } + }, + [esqlCallbacks, language, code] + ); + useDebounceWithOptions( () => { if (!editorModel.current) return; - if (warning && (!errors || !errors.length)) { - const parsedWarning = parseWarning(warning); - setEditorWarning(parsedWarning); - } else { - setEditorWarning([]); - } - if (errors && errors.length) { - const parsedErrors = parseErrors(errors, code); - setEditorErrors(parsedErrors); - monaco.editor.setModelMarkers(editorModel.current, 'Unified search', parsedErrors); + const subscription = { active: true }; + if (code === codeWhenSubmitted) { + if (serverErrors || serverWarning) { + const parsedErrors = parseErrors(serverErrors || [], code); + const parsedWarning = serverWarning ? parseWarning(serverWarning) : []; + setEditorMessages({ + errors: parsedErrors, + warnings: parsedErrors.length ? [] : parsedWarning, + }); + monaco.editor.setModelMarkers( + editorModel.current, + 'Unified search', + parsedErrors.length ? parsedErrors : [] + ); + return; + } } else { - monaco.editor.setModelMarkers(editorModel.current, 'Unified search', []); - setEditorErrors([]); + queryValidation(subscription).catch((error) => { + // console.log({ error }); + }); } + return () => (subscription.active = false); }, { skipFirstRender: false }, 256, - [errors, warning] + [serverErrors, serverWarning, code] ); - const onErrorClick = useCallback(({ startLineNumber, startColumn }: MonacoError) => { + const suggestionProvider = useMemo( + () => (language === 'esql' ? ESQLLang.getSuggestionProvider?.(esqlCallbacks) : undefined), + [language, esqlCallbacks] + ); + + const hoverProvider = useMemo( + () => (language === 'esql' ? ESQLLang.getHoverProvider?.(esqlCallbacks) : undefined), + [language, esqlCallbacks] + ); + + const onErrorClick = useCallback(({ startLineNumber, startColumn }: MonacoMessage) => { if (!editor1.current) { return; } @@ -351,7 +449,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const text = getInlineEditorText(queryString, Boolean(hasLines)); const queryLength = text.length; const unusedSpace = - (errors && errors.length) || warning + editorMessages.errors.length || editorMessages.warnings.length ? EDITOR_ONE_LINER_UNUSED_SPACE_WITH_ERRORS : EDITOR_ONE_LINER_UNUSED_SPACE; const charactersAlowed = Math.floor((width - unusedSpace) / FONT_WIDTH); @@ -364,7 +462,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ } } }, - [isCompactFocused, queryString, errors, warning] + [isCompactFocused, queryString, editorMessages] ); useEffect(() => { @@ -417,73 +515,6 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ } }, [language, documentationSections]); - const getSourceIdentifiers: ESQLCustomAutocompleteCallbacks['getSourceIdentifiers'] = - useCallback(async () => { - return await getIndicesForAutocomplete(dataViews); - }, [dataViews]); - - const getFieldsIdentifiers: ESQLCustomAutocompleteCallbacks['getFieldsIdentifiers'] = useCallback( - async (ctx) => { - const pipes = currentCursorContent?.split('|'); - pipes?.pop(); - const validContent = pipes?.join('|'); - if (validContent) { - // ES|QL with limit 0 returns only the columns and is more performant - const esqlQuery = { - esql: `${validContent} | limit 0`, - }; - try { - const table = await fetchFieldsFromESQL(esqlQuery, expressions); - return table?.columns.map((c) => c.name) || []; - } catch (e) { - // no action yet - } - } - return []; - }, - [expressions] - ); - - const getPoliciesIdentifiers: ESQLCustomAutocompleteCallbacks['getPoliciesIdentifiers'] = - useCallback( - async (ctx) => { - const { data: policies, error } = - (await indexManagementApiService?.getAllEnrichPolicies()) || {}; - policiesRef.current = policies || []; - if (error || !policies) { - return []; - } - return policies.map(({ name, sourceIndices }) => ({ name, indices: sourceIndices })); - }, - [indexManagementApiService] - ); - - const getPolicyFieldsIdentifiers: ESQLCustomAutocompleteCallbacks['getPolicyFieldsIdentifiers'] = - useCallback( - async (ctx) => - policiesRef.current - .filter(({ name }) => ctx.userDefinedVariables.policyIdentifiers.includes(name)) - .flatMap(({ enrichFields }) => enrichFields), - [] - ); - - const getPolicyMatchingFieldIdentifiers: ESQLCustomAutocompleteCallbacks['getPolicyMatchingFieldIdentifiers'] = - useCallback( - async (ctx) => { - // try to load the list if none is present yet but - // at least one policy is declared in the userDefinedVariables - // (this happens if the user pastes an ESQL statement with the policy name in it) - if (!policiesRef.current.length && ctx.userDefinedVariables.policyIdentifiers.length) { - await getPoliciesIdentifiers(ctx); - } - const matchingField = policiesRef.current.find(({ name }) => - ctx.userDefinedVariables.policyIdentifiers.includes(name) - )?.matchField; - return matchingField ? [matchingField] : []; - }, - [getPoliciesIdentifiers] - ); - const codeEditorOptions: CodeEditorProps['options'] = { automaticLayout: false, accessibilitySupport: 'off', @@ -675,7 +706,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ )} )} - {!isCompactFocused && errors && errors.length > 0 && ( + {!isCompactFocused && editorMessages.errors.length > 0 && ( - {errors.length} - - )} - {!isCompactFocused && warning && (!errors || errors.length === 0) && ( - - {editorWarning.length} + {editorMessages.errors.length} )} + {!isCompactFocused && + editorMessages.warnings.length > 0 && + editorMessages.errors.length === 0 && ( + + {editorMessages.warnings.length} + + )} { + if (isCompactFocused || !hoverProvider?.provideHover) { + return { contents: [] }; + } + return hoverProvider?.provideHover(model, position, token); + }, + }} onChange={onQueryUpdate} editorDidMount={(editor) => { editor1.current = editor; @@ -736,7 +767,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ endColumn: currentPosition?.column ?? 1, }); if (content) { - currentCursorContent = content || editor.getValue(); + codeRef.current = content || editor.getValue(); } }); @@ -752,9 +783,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ editor.addCommand( // eslint-disable-next-line no-bitwise monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, - function () { - onQuerySubmit(); - } + onQuerySubmit ); if (!isCodeEditorExpanded) { editor.onDidContentSizeChange((e) => { @@ -767,10 +796,13 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ { + if (editorMessages.errors.some((e) => e.source !== 'client')) { + onQuerySubmit(); + } + }} detectTimestamp={detectTimestamp} editorIsInline={editorIsInline} disableSubmitAction={disableSubmitAction} @@ -858,8 +890,6 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ )} {isCodeEditorExpanded && ( diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 330edcd2e2776..3be5d1d968720 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -4951,129 +4951,6 @@ "management.settings.offLabel": "Désactivé", "management.settings.onLabel": "Activé", "management.settings.resetToDefaultLinkText": "Réinitialiser à la valeur par défaut", - "monaco.esql.autocomplete.matchingFieldDefinition": "Utiliser pour correspondance avec {matchingField} de la politique", - "monaco.esql.autocomplete.policyDefinition": "Politique définie selon {count, plural, one {index} many {index système non migrés} other {des index}} : {indices}", - "monaco.esql.autocomplete.absDoc": "Renvoie la valeur absolue.", - "monaco.esql.autocomplete.acosDoc": "Fonction trigonométrique cosinus inverse", - "monaco.esql.autocomplete.addDoc": "Ajouter (+)", - "monaco.esql.autocomplete.andDoc": "et", - "monaco.esql.autocomplete.ascDoc": "Ordre croissant", - "monaco.esql.autocomplete.asDoc": "En tant que", - "monaco.esql.autocomplete.asinDoc": "Fonction trigonométrique sinus inverse", - "monaco.esql.autocomplete.assignDoc": "Affecter (=)", - "monaco.esql.autocomplete.atan2Doc": "L'angle entre l'axe positif des x et le rayon allant de l'origine au point (x , y) dans le plan cartésien", - "monaco.esql.autocomplete.atanDoc": "Fonction trigonométrique tangente inverse", - "monaco.esql.autocomplete.autoBucketDoc": "Groupement automatique des dates en fonction d'une plage et d'un compartiment cible donnés.", - "monaco.esql.autocomplete.avgDoc": "Renvoie la moyenne des valeurs dans un champ", - "monaco.esql.autocomplete.byDoc": "Par", - "monaco.esql.autocomplete.caseDoc": "Accepte les paires de conditions et de valeurs. La fonction renvoie la valeur correspondant à la première condition évaluée à \"True\" (Vraie). Si le nombre d'arguments est impair, le dernier argument est la valeur par défaut qui est renvoyée si aucune condition ne correspond.", - "monaco.esql.autocomplete.cidrMatchDoc": "La fonction utilise un premier paramètre de type adresse IP, puis un ou plusieurs paramètres évalués en fonction d'une spécification CIDR.", - "monaco.esql.autocomplete.closeBracketDoc": "Parenthèse fermante )", - "monaco.esql.autocomplete.coalesceDoc": "Renvoie la première valeur non nulle.", - "monaco.esql.autocomplete.concatDoc": "Concatène deux ou plusieurs chaînes.", - "monaco.esql.autocomplete.constantDefinition": "Variable définie par l'utilisateur", - "monaco.esql.autocomplete.cosDoc": "Fonction trigonométrique cosinus", - "monaco.esql.autocomplete.coshDoc": "Fonction hyperbolique cosinus", - "monaco.esql.autocomplete.countDistinctDoc": "Renvoie le décompte des valeurs distinctes dans un champ.", - "monaco.esql.autocomplete.countDoc": "Renvoie le décompte des valeurs dans un champ.", - "monaco.esql.autocomplete.createNewPolicy": "Cliquez pour créer", - "monaco.esql.autocomplete.dateDurationDefinition.day": "Jour", - "monaco.esql.autocomplete.dateDurationDefinition.days": "Jours (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.hour": "Heure", - "monaco.esql.autocomplete.dateDurationDefinition.hours": "Heures (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.millisecond": "Milliseconde", - "monaco.esql.autocomplete.dateDurationDefinition.milliseconds": "Millisecondes (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.minute": "Minute", - "monaco.esql.autocomplete.dateDurationDefinition.minutes": "Minutes (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.month": "Mois", - "monaco.esql.autocomplete.dateDurationDefinition.months": "Mois (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.second": "Seconde", - "monaco.esql.autocomplete.dateDurationDefinition.seconds": "Secondes (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.week": "Semaine", - "monaco.esql.autocomplete.dateDurationDefinition.weeks": "Semaines (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.year": "An", - "monaco.esql.autocomplete.dateDurationDefinition.years": "Ans (pluriel)", - "monaco.esql.autocomplete.dateExtractDoc": "Extrait des parties d'une date, telles que l'année, le mois, le jour, l'heure. Les types de champs pris en charge sont ceux fournis par la fonction \"java.time.temporal.ChronoField\"", - "monaco.esql.autocomplete.dateFormatDoc": "Renvoie une représentation sous forme de chaîne d'une date dans le format fourni. Si aucun format n'est indiqué, le format \"yyyy-MM-dd'T'HH:mm:ss.SSSZ\" est utilisé.", - "monaco.esql.autocomplete.dateParseDoc": "Analyser les dates à partir de chaînes.", - "monaco.esql.autocomplete.dateTruncDoc": "Arrondit une date à l'intervalle le plus proche. Les intervalles peuvent être exprimés à l'aide de la syntaxe littérale timespan.", - "monaco.esql.autocomplete.declarationLabel": "Déclaration :", - "monaco.esql.autocomplete.descDoc": "Ordre décroissant", - "monaco.esql.autocomplete.dissectDoc": "Extrait de multiples valeurs de chaîne à partir d'une entrée de chaîne unique, suivant un modèle", - "monaco.esql.autocomplete.divideDoc": "Diviser (/)", - "monaco.esql.autocomplete.dropDoc": "Supprime les colonnes", - "monaco.esql.autocomplete.enrichDoc": "Enrichir le tableau à l'aide d'un autre tableau", - "monaco.esql.autocomplete.equalToDoc": "Égal à", - "monaco.esql.autocomplete.evalDoc": "Calcule une expression et place la valeur résultante dans un champ de résultats de recherche.", - "monaco.esql.autocomplete.examplesLabel": "Exemples :", - "monaco.esql.autocomplete.fieldDefinition": "Champ spécifié par le tableau d'entrée", - "monaco.esql.autocomplete.floorDoc": "Arrondir un nombre à l'entier inférieur.", - "monaco.esql.autocomplete.fromDoc": "Récupère les données d'un ou de plusieurs ensembles de données. Un ensemble de données est une collection de données dans laquelle vous souhaitez effectuer une recherche. Le seul ensemble de données pris en charge est un index. Dans une requête ou une sous-requête, vous devez utiliser d'abord la commande from, et cette dernière ne nécessite pas de barre verticale au début. Par exemple, pour récupérer des données d'un index :", - "monaco.esql.autocomplete.greaterThanDoc": "Supérieur à", - "monaco.esql.autocomplete.greaterThanOrEqualToDoc": "Supérieur ou égal à", - "monaco.esql.autocomplete.greatestDoc": "Renvoie la valeur maximale de plusieurs colonnes.", - "monaco.esql.autocomplete.grokDoc": "Extrait de multiples valeurs de chaîne à partir d'une entrée de chaîne unique, suivant un modèle", - "monaco.esql.autocomplete.inDoc": "Teste si la valeur d'une expression est contenue dans une liste d'autres expressions", - "monaco.esql.autocomplete.isFiniteDoc": "Renvoie un booléen qui indique si son entrée est un nombre fini.", - "monaco.esql.autocomplete.isInfiniteDoc": "Renvoie un booléen qui indique si son entrée est infinie.", - "monaco.esql.autocomplete.keepDoc": "Réarrange les champs dans le tableau d'entrée en appliquant les clauses \"KEEP\" dans les champs", - "monaco.esql.autocomplete.leftDoc": "Renvoyer la sous-chaîne qui extrait la longueur des caractères de la chaîne en partant de la gauche.", - "monaco.esql.autocomplete.lengthDoc": "Renvoie la longueur des caractères d'une chaîne.", - "monaco.esql.autocomplete.lessThanDoc": "Inférieur à", - "monaco.esql.autocomplete.lessThanOrEqualToDoc": "Inférieur ou égal à", - "monaco.esql.autocomplete.likeDoc": "Filtrer les données en fonction des modèles de chaînes", - "monaco.esql.autocomplete.limitDoc": "Renvoie les premiers résultats de recherche, dans l'ordre de recherche, en fonction de la \"limite\" spécifiée.", - "monaco.esql.autocomplete.log10Doc": "Renvoie le log de base 10.", - "monaco.esql.autocomplete.ltrimDoc": "Supprime les espaces blancs au début des chaînes.", - "monaco.esql.autocomplete.maxDoc": "Renvoie la valeur maximale dans un champ.", - "monaco.esql.autocomplete.medianDeviationDoc": "Renvoie la médiane de chaque écart de point de données par rapport à la médiane de l'ensemble de l'échantillon.", - "monaco.esql.autocomplete.medianDoc": "Renvoie le 50centile.", - "monaco.esql.autocomplete.minDoc": "Renvoie la valeur minimale dans un champ.", - "monaco.esql.autocomplete.multiplyDoc": "Multiplier (*)", - "monaco.esql.autocomplete.mvExpandDoc": "Développe des champs comportant des valeurs multiples en indiquant une valeur par ligne et en dupliquant les autres champs", - "monaco.esql.autocomplete.newVarDoc": "Définir une nouvelle variable", - "monaco.esql.autocomplete.noPoliciesLabel": "Pas de stratégie disponible", - "monaco.esql.autocomplete.noPoliciesLabelsFound": "Cliquez pour créer", - "monaco.esql.autocomplete.notEqualToDoc": "Différent de", - "monaco.esql.autocomplete.nowDoc": "Renvoie la date et l'heure actuelles.", - "monaco.esql.autocomplete.onDoc": "Activé", - "monaco.esql.autocomplete.openBracketDoc": "Parenthèse ouvrante (", - "monaco.esql.autocomplete.orDoc": "ou", - "monaco.esql.autocomplete.percentiletDoc": "Renvoie le n-ième centile d'un champ.", - "monaco.esql.autocomplete.pipeDoc": "Barre verticale (|)", - "monaco.esql.autocomplete.powDoc": "Renvoie la valeur d'une base (premier argument) élevée à une puissance (deuxième argument).", - "monaco.esql.autocomplete.renameDoc": "Attribue un nouveau nom à une ancienne colonne", - "monaco.esql.autocomplete.rightDoc": "Renvoyer la sous-chaîne qui extrait la longueur des caractères de la chaîne en partant de la droite.", - "monaco.esql.autocomplete.rlikeDoc": "Filtrer les données en fonction des expressions régulières des chaînes", - "monaco.esql.autocomplete.roundDoc": "Renvoie un nombre arrondi à la décimale, spécifié par la valeur entière la plus proche. La valeur par défaut est arrondie à un entier.", - "monaco.esql.autocomplete.rtrimDoc": "Supprime les espaces blancs à la fin des chaînes.", - "monaco.esql.autocomplete.sinDoc": "Fonction trigonométrique sinus.", - "monaco.esql.autocomplete.sinhDoc": "Fonction hyperbolique sinus.", - "monaco.esql.autocomplete.sortDoc": "Trie tous les résultats en fonction des champs spécifiés. Lorsqu'ils sont en ordre décroissant, les résultats pour lesquels un champ est manquant sont considérés comme la plus petite valeur possible du champ, ou la plus grande valeur possible du champ lorsqu'ils sont en ordre croissant.", - "monaco.esql.autocomplete.sourceDefinition": "Tableau d'entrée", - "monaco.esql.autocomplete.splitDoc": "Divise une chaîne de valeur unique en plusieurs chaînes.", - "monaco.esql.autocomplete.sqrtDoc": "Renvoie la racine carrée d'un nombre. ", - "monaco.esql.autocomplete.startsWithDoc": "Renvoie un booléen qui indique si une chaîne de mot-clés débute par une autre chaîne.", - "monaco.esql.autocomplete.statsDoc": "Calcule les statistiques agrégées, telles que la moyenne, le décompte et la somme, sur l'ensemble des résultats de recherche entrants. Comme pour l'agrégation SQL, si la commande stats est utilisée sans clause BY, une seule ligne est renvoyée, qui est l'agrégation de tout l'ensemble des résultats de recherche entrants. Lorsque vous utilisez une clause BY, une ligne est renvoyée pour chaque valeur distincte dans le champ spécifié dans la clause BY. La commande stats renvoie uniquement les champs dans l'agrégation, et vous pouvez utiliser un large éventail de fonctions statistiques avec la commande stats. Lorsque vous effectuez plusieurs agrégations, séparez chacune d'entre elle par une virgule.", - "monaco.esql.autocomplete.substringDoc": "Renvoie la sous-chaîne d'une chaîne, délimitée en fonction d'une position de départ et d'une longueur optionnelle. Cet exemple renvoie les trois premières lettres de chaque nom de famille.", - "monaco.esql.autocomplete.subtractDoc": "Subtract (-)", - "monaco.esql.autocomplete.sumDoc": "Renvoie la somme des valeurs dans un champ.", - "monaco.esql.autocomplete.tanDoc": "Fonction trigonométrique tangente.", - "monaco.esql.autocomplete.tanhDoc": "Fonction hyperbolique tangente.", - "monaco.esql.autocomplete.toBooleanDoc": "Convertit en booléen.", - "monaco.esql.autocomplete.toDateTimeDoc": "Convertit en date.", - "monaco.esql.autocomplete.toDegreesDoc": "Convertit en degrés", - "monaco.esql.autocomplete.toDoubleDoc": "Convertit en double.", - "monaco.esql.autocomplete.toIntegerDoc": "Convertit en nombre entier.", - "monaco.esql.autocomplete.toIpDoc": "Convertit en ip.", - "monaco.esql.autocomplete.toLongDoc": "Convertit en long.", - "monaco.esql.autocomplete.toRadiansDoc": "Convertit en radians", - "monaco.esql.autocomplete.toStringDoc": "Convertit en chaîne.", - "monaco.esql.autocomplete.toUnsignedLongDoc": "Convertit en long non signé.", - "monaco.esql.autocomplete.toVersionDoc": "Convertit en version.", - "monaco.esql.autocomplete.trimDoc": "Supprime les espaces de début et de fin d'une chaîne.", - "monaco.esql.autocomplete.whereDoc": "Utilise \"predicate-expressions\" pour filtrer les résultats de recherche. Une expression predicate, lorsqu'elle est évaluée, renvoie TRUE ou FALSE. La commande where renvoie uniquement les résultats qui donnent la valeur TRUE. Par exemple, pour filtrer les résultats pour une valeur de champ spécifique", - "monaco.esql.autocomplete.withDoc": "Avec", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "Accéder à une valeur de champ dans un script au moyen de la syntaxe doc['field_name']", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "Émettre une valeur sans rien renvoyer", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "Récupérer la valeur du champ \"{fieldName}\"", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 364c17cad6690..d9350d64732a0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4966,129 +4966,6 @@ "management.settings.offLabel": "オフ", "management.settings.onLabel": "オン", "management.settings.resetToDefaultLinkText": "デフォルトにリセット", - "monaco.esql.autocomplete.matchingFieldDefinition": "ポリシーで{matchingField}で照合するために使用", - "monaco.esql.autocomplete.policyDefinition": "{count, plural, other {インデックス}}で定義されたポリシー:{indices}", - "monaco.esql.autocomplete.absDoc": "絶対値を返します。", - "monaco.esql.autocomplete.acosDoc": "逆余弦三角関数", - "monaco.esql.autocomplete.addDoc": "加算(+)", - "monaco.esql.autocomplete.andDoc": "AND", - "monaco.esql.autocomplete.ascDoc": "昇順", - "monaco.esql.autocomplete.asDoc": "として", - "monaco.esql.autocomplete.asinDoc": "逆正弦三角関数", - "monaco.esql.autocomplete.assignDoc": "割り当て(=)", - "monaco.esql.autocomplete.atan2Doc": "直交平面上の原点から点(x , y)に向かう光線と正のx軸のなす角", - "monaco.esql.autocomplete.atanDoc": "逆正接三角関数", - "monaco.esql.autocomplete.autoBucketDoc": "指定された範囲とバケット目標に基づいて、日付を自動的にバケット化します。", - "monaco.esql.autocomplete.avgDoc": "フィールドの値の平均を返します", - "monaco.esql.autocomplete.byDoc": "グループ基準", - "monaco.esql.autocomplete.caseDoc": "条件と値のペアを指定できます。この関数は、最初にtrueと評価された条件に属する値を返します。引数の数が奇数の場合、最後の引数は条件に一致しない場合に返されるデフォルト値になります。", - "monaco.esql.autocomplete.cidrMatchDoc": "この関数は、IP型の最初のパラメーターを取り、その後にCIDR指定に対して評価された1つ以上のパラメーターを取ります。", - "monaco.esql.autocomplete.closeBracketDoc": "閉じ括弧 )", - "monaco.esql.autocomplete.coalesceDoc": "最初のNULL以外の値を返します。", - "monaco.esql.autocomplete.concatDoc": "2つ以上の文字列を連結します。", - "monaco.esql.autocomplete.constantDefinition": "ユーザー定義変数", - "monaco.esql.autocomplete.cosDoc": "余弦三角関数", - "monaco.esql.autocomplete.coshDoc": "余弦双曲線関数", - "monaco.esql.autocomplete.countDistinctDoc": "フィールド内の異なる値の数を返します。", - "monaco.esql.autocomplete.countDoc": "フィールドの値の数を返します。", - "monaco.esql.autocomplete.createNewPolicy": "クリックして作成", - "monaco.esql.autocomplete.dateDurationDefinition.day": "日", - "monaco.esql.autocomplete.dateDurationDefinition.days": "日(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.hour": "時間", - "monaco.esql.autocomplete.dateDurationDefinition.hours": "時間(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.millisecond": "ミリ秒", - "monaco.esql.autocomplete.dateDurationDefinition.milliseconds": "ミリ秒(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.minute": "分", - "monaco.esql.autocomplete.dateDurationDefinition.minutes": "分(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.month": "月", - "monaco.esql.autocomplete.dateDurationDefinition.months": "月(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.second": "秒", - "monaco.esql.autocomplete.dateDurationDefinition.seconds": "秒(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.week": "週", - "monaco.esql.autocomplete.dateDurationDefinition.weeks": "週(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.year": "年", - "monaco.esql.autocomplete.dateDurationDefinition.years": "年(複数)", - "monaco.esql.autocomplete.dateExtractDoc": "年、月、日、時間など、日付の一部を抽出します。サポートされているフィールド型はjava.time.temporal.ChronoFieldで提供されている型です。", - "monaco.esql.autocomplete.dateFormatDoc": "指定した書式の日付の文字列表現を返します。書式が指定されていない場合は、yyyy-MM-dd'T'HH:mm:ss.SSSZの書式が使用されます。", - "monaco.esql.autocomplete.dateParseDoc": "文字列から日付を解析します。", - "monaco.esql.autocomplete.dateTruncDoc": "最も近い区間まで日付を切り捨てます。区間はtimespanリテラル構文を使って表現できます。", - "monaco.esql.autocomplete.declarationLabel": "宣言:", - "monaco.esql.autocomplete.descDoc": "降順", - "monaco.esql.autocomplete.dissectDoc": "単一の文字列入力から、パターンに基づいて複数の文字列値を抽出", - "monaco.esql.autocomplete.divideDoc": "除算(/)", - "monaco.esql.autocomplete.dropDoc": "列を削除", - "monaco.esql.autocomplete.enrichDoc": "別のテーブルでテーブルをエンリッチ", - "monaco.esql.autocomplete.equalToDoc": "等しい", - "monaco.esql.autocomplete.evalDoc": "式を計算し、結果の値を検索結果フィールドに入力します。", - "monaco.esql.autocomplete.examplesLabel": "例:", - "monaco.esql.autocomplete.fieldDefinition": "入力テーブルで指定されたフィールド", - "monaco.esql.autocomplete.floorDoc": "最も近い整数に数値を切り捨てます。", - "monaco.esql.autocomplete.fromDoc": "1つ以上のデータセットからデータを取得します。データセットは検索するデータの集合です。唯一のサポートされているデータセットはインデックスです。クエリまたはサブクエリでは、最初にコマンドから使用する必要があります。先頭のパイプは不要です。たとえば、インデックスからデータを取得します。", - "monaco.esql.autocomplete.greaterThanDoc": "より大きい", - "monaco.esql.autocomplete.greaterThanOrEqualToDoc": "よりも大きいまたは等しい", - "monaco.esql.autocomplete.greatestDoc": "多数の列から最大値を返します。", - "monaco.esql.autocomplete.grokDoc": "単一の文字列入力から、パターンに基づいて複数の文字列値を抽出", - "monaco.esql.autocomplete.inDoc": "ある式が取る値が、他の式のリストに含まれているかどうかをテストします", - "monaco.esql.autocomplete.isFiniteDoc": "入力が有限数であるかどうかを示すブール値を返します。", - "monaco.esql.autocomplete.isInfiniteDoc": "入力が無限数であるかどうかを示すブール値を返します。", - "monaco.esql.autocomplete.keepDoc": "フィールドでkeep句を適用して、入力テーブルのフィールドを並べ替えます", - "monaco.esql.autocomplete.leftDoc": "stringから左から順にlength文字を抜き出したサブ文字列を返します。", - "monaco.esql.autocomplete.lengthDoc": "文字列の文字数を返します。", - "monaco.esql.autocomplete.lessThanDoc": "より小さい", - "monaco.esql.autocomplete.lessThanOrEqualToDoc": "以下", - "monaco.esql.autocomplete.likeDoc": "文字列パターンに基づいてデータをフィルター", - "monaco.esql.autocomplete.limitDoc": "指定された「制限」に基づき、検索順序で、最初の検索結果を返します。", - "monaco.esql.autocomplete.log10Doc": "底が10の対数を返します。", - "monaco.esql.autocomplete.ltrimDoc": "文字列から先頭の空白を取り除きます。", - "monaco.esql.autocomplete.maxDoc": "フィールドの最大値を返します。", - "monaco.esql.autocomplete.medianDeviationDoc": "サンプル全体の中央値からの各データポイントの偏差の中央値を返します。", - "monaco.esql.autocomplete.medianDoc": "50%パーセンタイルを返します。", - "monaco.esql.autocomplete.minDoc": "フィールドの最小値を返します。", - "monaco.esql.autocomplete.multiplyDoc": "乗算(*)", - "monaco.esql.autocomplete.mvExpandDoc": "複数値フィールドを値ごとに1行に展開し、他のフィールドを複製します", - "monaco.esql.autocomplete.newVarDoc": "新しい変数を定義", - "monaco.esql.autocomplete.noPoliciesLabel": "ポリシーがありません", - "monaco.esql.autocomplete.noPoliciesLabelsFound": "クリックして作成", - "monaco.esql.autocomplete.notEqualToDoc": "Not equal to", - "monaco.esql.autocomplete.nowDoc": "現在の日付と時刻を返します。", - "monaco.esql.autocomplete.onDoc": "オン", - "monaco.esql.autocomplete.openBracketDoc": "開き括弧 (", - "monaco.esql.autocomplete.orDoc": "または", - "monaco.esql.autocomplete.percentiletDoc": "フィールドのnパーセンタイルを返します。", - "monaco.esql.autocomplete.pipeDoc": "パイプ(|)", - "monaco.esql.autocomplete.powDoc": "底(第1引数)を累乗(第2引数)した値を返します。", - "monaco.esql.autocomplete.renameDoc": "古い列の名前を新しい列に変更", - "monaco.esql.autocomplete.rightDoc": "stringのうち右から数えてlength文字までのサブ文字列を返します。", - "monaco.esql.autocomplete.rlikeDoc": "文字列の正規表現に基づいてデータをフィルター", - "monaco.esql.autocomplete.roundDoc": "最も近い整数値で指定された数字まで端数処理された数値を返します。デフォルトは整数になるように四捨五入されます。", - "monaco.esql.autocomplete.rtrimDoc": "文字列から末尾の空白を取り除きます。", - "monaco.esql.autocomplete.sinDoc": "正弦三角関数。", - "monaco.esql.autocomplete.sinhDoc": "正弦双曲線関数。", - "monaco.esql.autocomplete.sortDoc": "すべての結果を指定されたフィールドで並べ替えます。降順では、フィールドが見つからない結果は、フィールドの最も小さい可能な値と見なされます。昇順では、フィールドの最も大きい可能な値と見なされます。", - "monaco.esql.autocomplete.sourceDefinition": "入力テーブル", - "monaco.esql.autocomplete.splitDoc": "単一の値の文字列を複数の文字列に分割します。", - "monaco.esql.autocomplete.sqrtDoc": "数値の平方根を返します。", - "monaco.esql.autocomplete.startsWithDoc": "キーワード文字列が他の文字列で始まるかどうかを示すブール値を返します。", - "monaco.esql.autocomplete.statsDoc": "受信検索結果セットで、平均、カウント、合計などの集約統計情報を計算します。SQL集約と同様に、statsコマンドをBY句なしで使用した場合は、1行のみが返されます。これは、受信検索結果セット全体に対する集約です。BY句を使用すると、BY句で指定したフィールドの1つの値ごとに1行が返されます。statsコマンドは集約のフィールドのみを返します。statsコマンドではさまざまな統計関数を使用できます。複数の集約を実行するときには、各集約をカンマで区切ります。", - "monaco.esql.autocomplete.substringDoc": "文字列のサブ文字列を、開始位置とオプションの長さで指定して返します。この例では、それぞれの姓の最初の3文字を返します。", - "monaco.esql.autocomplete.subtractDoc": "減算(-)", - "monaco.esql.autocomplete.sumDoc": "フィールドの値の合計を返します。", - "monaco.esql.autocomplete.tanDoc": "正接三角関数。", - "monaco.esql.autocomplete.tanhDoc": "正接双曲線関数。", - "monaco.esql.autocomplete.toBooleanDoc": "ブール値に変換します。", - "monaco.esql.autocomplete.toDateTimeDoc": "日付に変換します。", - "monaco.esql.autocomplete.toDegreesDoc": "度に変換します", - "monaco.esql.autocomplete.toDoubleDoc": "doubleに変換します。", - "monaco.esql.autocomplete.toIntegerDoc": "整数に変換します。", - "monaco.esql.autocomplete.toIpDoc": "IPに変換します。", - "monaco.esql.autocomplete.toLongDoc": "longに変換します。", - "monaco.esql.autocomplete.toRadiansDoc": "ラジアンに変換します", - "monaco.esql.autocomplete.toStringDoc": "文字列に変換します。", - "monaco.esql.autocomplete.toUnsignedLongDoc": "符号なしlongに変換します。", - "monaco.esql.autocomplete.toVersionDoc": "バージョンに変換します。", - "monaco.esql.autocomplete.trimDoc": "文字列から先頭と末尾の空白を削除します。", - "monaco.esql.autocomplete.whereDoc": "「predicate-expressions」を使用して、検索結果をフィルターします。予測式は評価時にTRUEまたはFALSEを返します。whereコマンドはTRUEに評価される結果のみを返します。たとえば、特定のフィールド値の結果をフィルターします", - "monaco.esql.autocomplete.withDoc": "を使用して", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "doc['field_name'] 構文を使用して、スクリプトからフィールド値にアクセスします", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "戻らずに値を発行します。", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "フィールド「{fieldName}」の値を取得します", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 70c282560d63e..5eaafecf3e9d5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4965,129 +4965,6 @@ "management.settings.offLabel": "关闭", "management.settings.onLabel": "开启", "management.settings.resetToDefaultLinkText": "重置为默认值", - "monaco.esql.autocomplete.matchingFieldDefinition": "用于匹配策略上的{matchingField}", - "monaco.esql.autocomplete.policyDefinition": "策略在{count, plural, other {索引}}上定义:{indices}", - "monaco.esql.autocomplete.absDoc": "返回绝对值。", - "monaco.esql.autocomplete.acosDoc": "反余弦三角函数", - "monaco.esql.autocomplete.addDoc": "添加 (+)", - "monaco.esql.autocomplete.andDoc": "且", - "monaco.esql.autocomplete.ascDoc": "升序", - "monaco.esql.autocomplete.asDoc": "作为", - "monaco.esql.autocomplete.asinDoc": "反正弦三角函数", - "monaco.esql.autocomplete.assignDoc": "分配 (=)", - "monaco.esql.autocomplete.atan2Doc": "笛卡儿平面中正 x 轴与从原点到点 (x , y) 构成的射线之间的角度", - "monaco.esql.autocomplete.atanDoc": "反正切三角函数", - "monaco.esql.autocomplete.autoBucketDoc": "根据给定范围和存储桶目标自动收集存储桶日期。", - "monaco.esql.autocomplete.avgDoc": "返回字段中的值的平均值", - "monaco.esql.autocomplete.byDoc": "依据", - "monaco.esql.autocomplete.caseDoc": "接受成对的条件和值。此函数返回属于第一个评估为 `true` 的条件的值。如果参数数量为奇数,则最后一个参数为在无条件匹配时返回的默认值。", - "monaco.esql.autocomplete.cidrMatchDoc": "此函数接受的第一个参数应为 IP 类型,后接一个或多个评估为 CIDR 规范的参数。", - "monaco.esql.autocomplete.closeBracketDoc": "右括号 )", - "monaco.esql.autocomplete.coalesceDoc": "返回第一个非 null 值。", - "monaco.esql.autocomplete.concatDoc": "串联两个或多个字符串。", - "monaco.esql.autocomplete.constantDefinition": "用户定义的变量", - "monaco.esql.autocomplete.cosDoc": "余弦三角函数", - "monaco.esql.autocomplete.coshDoc": "余弦双曲函数", - "monaco.esql.autocomplete.countDistinctDoc": "返回字段中不同值的计数。", - "monaco.esql.autocomplete.countDoc": "返回字段中的值的计数。", - "monaco.esql.autocomplete.createNewPolicy": "单击以创建", - "monaco.esql.autocomplete.dateDurationDefinition.day": "天", - "monaco.esql.autocomplete.dateDurationDefinition.days": "天(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.hour": "小时", - "monaco.esql.autocomplete.dateDurationDefinition.hours": "小时(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.millisecond": "毫秒", - "monaco.esql.autocomplete.dateDurationDefinition.milliseconds": "毫秒(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.minute": "分钟", - "monaco.esql.autocomplete.dateDurationDefinition.minutes": "分钟(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.month": "月", - "monaco.esql.autocomplete.dateDurationDefinition.months": "月(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.second": "秒", - "monaco.esql.autocomplete.dateDurationDefinition.seconds": "秒(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.week": "周", - "monaco.esql.autocomplete.dateDurationDefinition.weeks": "周(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.year": "年", - "monaco.esql.autocomplete.dateDurationDefinition.years": "年(复数)", - "monaco.esql.autocomplete.dateExtractDoc": "提取日期的某些部分,如年、月、日、小时。支持的字段类型为 java.time.temporal.ChronoField 提供的那些类型", - "monaco.esql.autocomplete.dateFormatDoc": "以提供的格式返回日期的字符串表示形式。如果未指定格式,则使用“yyyy-MM-dd'T'HH:mm:ss.SSSZ”格式。", - "monaco.esql.autocomplete.dateParseDoc": "解析字符串中的日期。", - "monaco.esql.autocomplete.dateTruncDoc": "将日期向下舍入到最近的时间间隔。时间间隔可以用时间跨度文本语法表示。", - "monaco.esql.autocomplete.declarationLabel": "声明:", - "monaco.esql.autocomplete.descDoc": "降序", - "monaco.esql.autocomplete.dissectDoc": "根据模式从单个字符串输入中提取多个字符串值", - "monaco.esql.autocomplete.divideDoc": "除 (/)", - "monaco.esql.autocomplete.dropDoc": "丢弃列", - "monaco.esql.autocomplete.enrichDoc": "用其他表来扩充表", - "monaco.esql.autocomplete.equalToDoc": "等于", - "monaco.esql.autocomplete.evalDoc": "计算表达式并将生成的值置入搜索结果字段。", - "monaco.esql.autocomplete.examplesLabel": "示例:", - "monaco.esql.autocomplete.fieldDefinition": "由输入表指定的字段", - "monaco.esql.autocomplete.floorDoc": "将数字向下舍入到最近的整数。", - "monaco.esql.autocomplete.fromDoc": "从一个或多个数据集中检索数据。数据集是您希望搜索的数据的集合。索引是唯一受支持的数据集。在查询或子查询中,必须先使用 from 命令,并且它不需要前导管道符。例如,要从索引中检索数据:", - "monaco.esql.autocomplete.greaterThanDoc": "大于", - "monaco.esql.autocomplete.greaterThanOrEqualToDoc": "大于或等于", - "monaco.esql.autocomplete.greatestDoc": "返回许多列中的最大值。", - "monaco.esql.autocomplete.grokDoc": "根据模式从单个字符串输入中提取多个字符串值", - "monaco.esql.autocomplete.inDoc": "测试某表达式接受的值是否包含在其他表达式列表中", - "monaco.esql.autocomplete.isFiniteDoc": "返回指示其输入是否为有限数字的布尔值。", - "monaco.esql.autocomplete.isInfiniteDoc": "返回指示其输入是否无限的布尔值。", - "monaco.esql.autocomplete.keepDoc": "通过在字段中应用 keep 子句重新安排输入表中的字段", - "monaco.esql.autocomplete.leftDoc": "返回从字符串中提取长度字符的子字符串,从左侧开始。", - "monaco.esql.autocomplete.lengthDoc": "返回字符串的字符长度。", - "monaco.esql.autocomplete.lessThanDoc": "小于", - "monaco.esql.autocomplete.lessThanOrEqualToDoc": "小于或等于", - "monaco.esql.autocomplete.likeDoc": "根据字符串模式筛选数据", - "monaco.esql.autocomplete.limitDoc": "根据指定的“限制”按搜索顺序返回第一个搜索结果。", - "monaco.esql.autocomplete.log10Doc": "返回对数底数 10。", - "monaco.esql.autocomplete.ltrimDoc": "从字符串中移除前导空格。", - "monaco.esql.autocomplete.maxDoc": "返回字段中的最大值。", - "monaco.esql.autocomplete.medianDeviationDoc": "返回每个数据点的中位数与整个样例的中位数的偏差。", - "monaco.esql.autocomplete.medianDoc": "返回 50% 百分位数。", - "monaco.esql.autocomplete.minDoc": "返回字段中的最小值。", - "monaco.esql.autocomplete.multiplyDoc": "乘 (*)", - "monaco.esql.autocomplete.mvExpandDoc": "将多值字段扩展成每个值一行,从而复制其他字段", - "monaco.esql.autocomplete.newVarDoc": "定义新变量", - "monaco.esql.autocomplete.noPoliciesLabel": "没有可用策略", - "monaco.esql.autocomplete.noPoliciesLabelsFound": "单击以创建", - "monaco.esql.autocomplete.notEqualToDoc": "不等于", - "monaco.esql.autocomplete.nowDoc": "返回当前日期和时间。", - "monaco.esql.autocomplete.onDoc": "开启", - "monaco.esql.autocomplete.openBracketDoc": "左括号 (", - "monaco.esql.autocomplete.orDoc": "或", - "monaco.esql.autocomplete.percentiletDoc": "返回字段的第 n 个百分位。", - "monaco.esql.autocomplete.pipeDoc": "管道符 (|)", - "monaco.esql.autocomplete.powDoc": "返回提升为幂(第二个参数)的底数(第一个参数)的值。", - "monaco.esql.autocomplete.renameDoc": "将旧列重命名为新列", - "monaco.esql.autocomplete.rightDoc": "返回从字符串中提取长度字符的子字符串,从右侧开始。", - "monaco.esql.autocomplete.rlikeDoc": "根据字符串正则表达式筛选数据", - "monaco.esql.autocomplete.roundDoc": "返回四舍五入到小数(由最近的整数值指定)的数字。默认做法是四舍五入到整数。", - "monaco.esql.autocomplete.rtrimDoc": "从字符串中移除尾随空格。", - "monaco.esql.autocomplete.sinDoc": "正弦三角函数。", - "monaco.esql.autocomplete.sinhDoc": "正弦双曲函数。", - "monaco.esql.autocomplete.sortDoc": "按指定字段对所有结果排序。采用降序时,会将缺少字段的结果视为字段的最小可能值,或者,在采用升序时,会将其视为字段的最大可能值。", - "monaco.esql.autocomplete.sourceDefinition": "输入表", - "monaco.esql.autocomplete.splitDoc": "将单值字符串拆分成多个字符串。", - "monaco.esql.autocomplete.sqrtDoc": "返回数字的平方根。", - "monaco.esql.autocomplete.startsWithDoc": "返回指示关键字字符串是否以另一个字符串开头的布尔值。", - "monaco.esql.autocomplete.statsDoc": "对传入的搜索结果集计算汇总统计信息,如平均值、计数和总和。与 SQL 聚合类似,如果使用不含 BY 子句的 stats 命令,则只返回一行内容,即聚合传入的整个搜索结果集。使用 BY 子句时,将为在 BY 子句中指定的字段中的每个不同值返回一行内容。stats 命令仅返回聚合中的字段,并且您可以将一系列统计函数与 stats 命令搭配在一起使用。执行多个聚合时,请用逗号分隔每个聚合。", - "monaco.esql.autocomplete.substringDoc": "返回字符串的子字符串,用起始位置和可选长度指定。此示例返回每个姓氏的前三个字符。", - "monaco.esql.autocomplete.subtractDoc": "减 (-)", - "monaco.esql.autocomplete.sumDoc": "返回字段中的值的总和。", - "monaco.esql.autocomplete.tanDoc": "正切三角函数。", - "monaco.esql.autocomplete.tanhDoc": "正切双曲函数。", - "monaco.esql.autocomplete.toBooleanDoc": "转换为布尔值。", - "monaco.esql.autocomplete.toDateTimeDoc": "转换为日期。", - "monaco.esql.autocomplete.toDegreesDoc": "转换为度", - "monaco.esql.autocomplete.toDoubleDoc": "转换为双精度值。", - "monaco.esql.autocomplete.toIntegerDoc": "转换为整数。", - "monaco.esql.autocomplete.toIpDoc": "转换为 IP。", - "monaco.esql.autocomplete.toLongDoc": "转换为长整型。", - "monaco.esql.autocomplete.toRadiansDoc": "转换为弧度", - "monaco.esql.autocomplete.toStringDoc": "转换为字符串。", - "monaco.esql.autocomplete.toUnsignedLongDoc": "转换为无符号长整型。", - "monaco.esql.autocomplete.toVersionDoc": "转换为版本。", - "monaco.esql.autocomplete.trimDoc": "从字符串中移除前导和尾随空格。", - "monaco.esql.autocomplete.whereDoc": "使用“predicate-expressions”可筛选搜索结果。进行计算时,谓词表达式将返回 TRUE 或 FALSE。where 命令仅返回计算结果为 TRUE 的结果。例如,筛选特定字段值的结果", - "monaco.esql.autocomplete.withDoc": "具有", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "使用 doc['field_name'] 语法,从脚本中访问字段值", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "发出值,而不返回值。", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "检索字段“{fieldName}”的值",