Files
2024-09-11 22:33:24 -04:00

192 lines
3.8 KiB
ANTLR

/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
lexer grammar SpelLexer;
@header {
/*******************************************************************************
* Copyright (c) 2024 Broadcom, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Broadcom, Inc. - initial API and implementation
*******************************************************************************/
}
@members {
int nesting = 0;
}
SEMICOLON: ';';
fragment NEWLINE
: '\r\n'
| [\r\n\u2028\u2029]
;
WS
: [ \t\r\n]+ -> channel(HIDDEN)
;
// ========================== S P E L ====================================================
INC: '++';
PLUS: '+';
DEC: '--';
MINUS: '-';
COLON: ':';
DOT: '.';
COMMA: ',';
STAR: '*';
DIV: '/';
MOD: '%';
LPAREN: '(';
RPAREN: ')';
LSQUARE: '[';
RSQUARE: ']';
HASH: '#';
BEAN_REF: '@';
SELECT_FIRST: '^[';
POWER: '^';
NE: '!=';
PROJECT: '![';
NOT: '!';
EQ: '==';
ASSIGN: '=';
SYMBOLIC_AND: '&&';
FACTORY_BEAN_REF: '&';
SYMBOLIC_OR: '||';
SELECT: '?[';
ELVIS: '?:';
SAFE_NAVI: '?.';
QMARK: '?';
SELECT_LAST: '$[';
GE: '>=';
GT: '>';
LE: '<=';
LT: '<';
// Special treatment to support template literals
LCURLY: '{' { nesting++; } -> pushMode(DEFAULT_MODE);
RCURLY: '}' {
if (nesting > 0) {
nesting--;
}
} -> popMode;
BACKTICK
: '`' -> pushMode(IN_TEMPLATE_STRING)
;
OR: 'or';
AND: 'and';
TRUE: 'true';
FALSE: 'false';
NEW: 'new';
NULL: 'null';
T: 'T';
MATCHES: 'matches';
GT_KEYWORD: 'gt';
GE_KEYWORD: 'ge';
LE_KEYWORD: 'le';
LT_KEYWORD: 'lt';
EQ_KEYWORD: 'eq';
NE_KEYWORD: 'ne';
// IDENTIFIER appearing AFTER tokens like OR and AND make those lex as special tokens,
// like SpEL's lexIdentifier() does
IDENTIFIER
: (ALPHABETIC | '_') (ALPHABETIC | DIGIT | '_' | '$')*
;
REAL_LITERAL
: '.' DECIMAL_DIGIT+ EXPONENT_PART? REAL_TYPE_SUFFIX?
| DECIMAL_DIGIT+ '.' DECIMAL_DIGIT+ EXPONENT_PART? REAL_TYPE_SUFFIX?
| DECIMAL_DIGIT+ EXPONENT_PART REAL_TYPE_SUFFIX?
| DECIMAL_DIGIT+ REAL_TYPE_SUFFIX
;
INTEGER_LITERAL
: DECIMAL_DIGIT+ INTEGER_TYPE_SUFFIX?
;
STRING_LITERAL
: SINGLE_QUOTED_STRING
| DOUBLE_QUOTED_STRING
;
SINGLE_QUOTED_STRING
: '\'' ( '\'\'' | ~['\n] )* '\''
;
DOUBLE_QUOTED_STRING
: '"' ( '""' | ~["\n] )* '"'
;
PROPERTY_PLACE_HOLDER
: '${' (.)*? '}'
;
fragment INTEGER_TYPE_SUFFIX : ( 'L' | 'l' );
fragment HEX_DIGIT : [0-9A-Fa-f];
fragment DECIMAL_DIGIT: [0-9];
fragment EXPONENT_PART
: 'e' (SIGN)* (DECIMAL_DIGIT)+
| 'E' (SIGN)* (DECIMAL_DIGIT)+
;
fragment SIGN : '+' | '-' ;
fragment REAL_TYPE_SUFFIX : 'F' | 'f' | 'D' | 'd';
fragment ALPHABETIC
// See Character.isLetter()
// and https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md#lexer-rule-elements
// and https://github.com/spring-projects/spring-framework/commit/c8c8f5722bc58452894742534954c0935653771f
: [\p{Lu}] // UPPERCASE_LETTER
| [\p{Ll}] // LOWERCASE_LETTER
| [\p{Lt}] // TITLECASE_LETTER
| [\p{Lm}] // MODIFIER_LETTER
| [\p{Lo}] // OTHER_LETTER
;
fragment DIGIT
: [0-9]
;
mode IN_TEMPLATE_STRING;
ESCAPED_BACKTICK
: '``'
;
SPEL_IN_TEMPLATE_STRING_OPEN: '#{' { nesting++; } -> pushMode(DEFAULT_MODE);
TEMPLATE_TEXT
: ~[`\n]
;
BACKTICK_IN_TEMPLATE
: '`' -> type(BACKTICK), popMode
;