|
| 1 | +/* |
| 2 | + * Copyright 2013-2026 consulo.io |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | + |
| 17 | +{ |
| 18 | + parserClass = "consulo.spring.spel.language.impl.parser.SpELParser" |
| 19 | + extends = "consulo.spring.spel.language.impl.psi.SpELElementImpl" |
| 20 | + version = "3" |
| 21 | + |
| 22 | + psiClassPrefix = "SpEL" |
| 23 | + psiImplClassSuffix = "Impl" |
| 24 | + psiPackage = "consulo.spring.spel.language.psi" |
| 25 | + psiImplPackage = "consulo.spring.spel.language.impl.psi" |
| 26 | + psiVisitorName = "SpELElementVisitor" |
| 27 | + |
| 28 | + elementTypeHolderClass = "consulo.spring.spel.language.psi.SpELTypes" |
| 29 | + elementTypeClass = "consulo.spring.spel.language.SpELElementType" |
| 30 | + tokenTypeClass = "consulo.spring.spel.language.SpELTokenType" |
| 31 | + |
| 32 | + implements(".*expression") = "consulo.spring.spel.language.psi.SpELElement" |
| 33 | + |
| 34 | + tokens = [ |
| 35 | + // literals |
| 36 | + INTEGER_LITERAL |
| 37 | + REAL_LITERAL |
| 38 | + STRING_LITERAL |
| 39 | + |
| 40 | + // keywords (remapped from IDENTIFIER by SpELLexer) |
| 41 | + TRUE = 'true' |
| 42 | + FALSE = 'false' |
| 43 | + NULL = 'null' |
| 44 | + NEW = 'new' |
| 45 | + INSTANCEOF = 'instanceof' |
| 46 | + MATCHES = 'matches' |
| 47 | + AND = 'and' |
| 48 | + OR = 'or' |
| 49 | + NOT = 'not' |
| 50 | + T_KEYWORD = 'T' |
| 51 | + |
| 52 | + // operators |
| 53 | + PLUS = '+' |
| 54 | + MINUS = '-' |
| 55 | + STAR = '*' |
| 56 | + DIV = '/' |
| 57 | + MOD = '%' |
| 58 | + POWER = '^' |
| 59 | + EQ = '==' |
| 60 | + NE = '!=' |
| 61 | + LT = '<' |
| 62 | + GT = '>' |
| 63 | + LE = '<=' |
| 64 | + GE = '>=' |
| 65 | + ASSIGN = '=' |
| 66 | + QMARK = '?' |
| 67 | + COLON = ':' |
| 68 | + ELVIS = '?:' |
| 69 | + SAFE_NAV = '?.' |
| 70 | + BANG = '!' |
| 71 | + AND_AND = '&&' |
| 72 | + OR_OR = '||' |
| 73 | + |
| 74 | + // delimiters |
| 75 | + LPAREN = '(' |
| 76 | + RPAREN = ')' |
| 77 | + LBRACKET = '[' |
| 78 | + RBRACKET = ']' |
| 79 | + LBRACE = '{' |
| 80 | + RBRACE = '}' |
| 81 | + DOT = '.' |
| 82 | + COMMA = ',' |
| 83 | + HASH = '#' |
| 84 | + AT = '@' |
| 85 | + |
| 86 | + // special composite tokens |
| 87 | + PROJECTION = '.![' |
| 88 | + SELECTION = '.?[' |
| 89 | + SELECT_LAST = '.$[' |
| 90 | + SELECT_FIRST = '.^[' |
| 91 | + |
| 92 | + IDENTIFIER |
| 93 | + ] |
| 94 | +} |
| 95 | + |
| 96 | +// root rule |
| 97 | +spelExpression ::= expression |
| 98 | + |
| 99 | +// expression precedence (low to high) |
| 100 | +expression ::= assignmentExpression |
| 101 | + |
| 102 | +assignmentExpression ::= ternaryExpression ('=' ternaryExpression)* { |
| 103 | + pin(".*")=1 |
| 104 | +} |
| 105 | + |
| 106 | +ternaryExpression ::= elvisExpression ('?' expression ':' expression)* { |
| 107 | + pin(".*")=1 |
| 108 | +} |
| 109 | + |
| 110 | +elvisExpression ::= logicalOrExpression ('?:' logicalOrExpression)* { |
| 111 | + pin(".*")=1 |
| 112 | +} |
| 113 | + |
| 114 | +logicalOrExpression ::= logicalAndExpression (('||' | 'or') logicalAndExpression)* { |
| 115 | + pin(".*")=1 |
| 116 | +} |
| 117 | + |
| 118 | +logicalAndExpression ::= equalityExpression (('&&' | 'and') equalityExpression)* { |
| 119 | + pin(".*")=1 |
| 120 | +} |
| 121 | + |
| 122 | +equalityExpression ::= relationalExpression (('==' | '!=') relationalExpression)* { |
| 123 | + pin(".*")=1 |
| 124 | +} |
| 125 | + |
| 126 | +relationalExpression ::= additiveExpression (relationalOperator additiveExpression)* { |
| 127 | + pin(".*")=1 |
| 128 | +} |
| 129 | + |
| 130 | +private relationalOperator ::= '<=' | '>=' | '<' | '>' | 'instanceof' | 'matches' |
| 131 | + |
| 132 | +additiveExpression ::= multiplicativeExpression (('+' | '-') multiplicativeExpression)* { |
| 133 | + pin(".*")=1 |
| 134 | +} |
| 135 | + |
| 136 | +multiplicativeExpression ::= powerExpression (('*' | '/' | '%') powerExpression)* { |
| 137 | + pin(".*")=1 |
| 138 | +} |
| 139 | + |
| 140 | +powerExpression ::= unaryExpression ('^' unaryExpression)* { |
| 141 | + pin(".*")=1 |
| 142 | +} |
| 143 | + |
| 144 | +unaryExpression ::= ('-' | '!' | 'not') unaryExpression | postfixExpression |
| 145 | + |
| 146 | +postfixExpression ::= primaryExpression postfixOp* |
| 147 | + |
| 148 | +private postfixOp ::= dotAccess |
| 149 | + | safeNavAccess |
| 150 | + | indexAccess |
| 151 | + | projectionAccess |
| 152 | + | selectionAccess |
| 153 | + | selectLastAccess |
| 154 | + | selectFirstAccess |
| 155 | + |
| 156 | +dotAccess ::= '.' (methodCall | IDENTIFIER) |
| 157 | + |
| 158 | +safeNavAccess ::= '?.' (methodCall | IDENTIFIER) |
| 159 | + |
| 160 | +indexAccess ::= '[' expression ']' |
| 161 | + |
| 162 | +projectionAccess ::= '.![' expression ']' |
| 163 | + |
| 164 | +selectionAccess ::= '.?[' expression ']' |
| 165 | + |
| 166 | +selectLastAccess ::= '.$[' expression ']' |
| 167 | + |
| 168 | +selectFirstAccess ::= '.^[' expression ']' |
| 169 | + |
| 170 | +// primary expressions |
| 171 | +private primaryExpression ::= literalExpression |
| 172 | + | parenthesizedExpression |
| 173 | + | typeReference |
| 174 | + | constructorCall |
| 175 | + | beanReference |
| 176 | + | variableReference |
| 177 | + | inlineList |
| 178 | + | inlineMap |
| 179 | + | methodCall |
| 180 | + | IDENTIFIER |
| 181 | + |
| 182 | +literalExpression ::= INTEGER_LITERAL |
| 183 | + | REAL_LITERAL |
| 184 | + | STRING_LITERAL |
| 185 | + | 'true' |
| 186 | + | 'false' |
| 187 | + | 'null' |
| 188 | + |
| 189 | +parenthesizedExpression ::= '(' expression ')' |
| 190 | + |
| 191 | +typeReference ::= 'T' '(' qualifiedName ')' |
| 192 | + |
| 193 | +qualifiedName ::= IDENTIFIER ('.' IDENTIFIER)* |
| 194 | + |
| 195 | +constructorCall ::= 'new' qualifiedName '(' argumentList? ')' |
| 196 | + |
| 197 | +argumentList ::= expression (',' expression)* |
| 198 | + |
| 199 | +beanReference ::= '@' IDENTIFIER |
| 200 | + |
| 201 | +variableReference ::= '#' IDENTIFIER |
| 202 | + |
| 203 | +inlineList ::= '{' [expression (',' expression)*] '}' |
| 204 | + |
| 205 | +inlineMap ::= '{' mapEntry (',' mapEntry)* '}' |
| 206 | + |
| 207 | +mapEntry ::= expression ':' expression |
| 208 | + |
| 209 | +methodCall ::= IDENTIFIER '(' argumentList? ')' |
0 commit comments