blob: b329faa5727d4fe6991cc4476f9f9b5351f2a146 [file] [log] [blame]
George Mountc09acd42015-01-07 16:34:06 -08001/*
2 * This grammar is a tweaked subset of that in Java.g4, which has a
3 * BSD license and is redistributed along with this.
4 */
5grammar BindingExpression;
6
7bindingSyntax
8// : '{' expression defaults? '}'
9 : expression defaults?
10 ;
11
12defaults
13 : ',' 'default' '=' constantValue
14 ;
15constantValue
16 : literal
17 | ResourceReference
18 | constantExpression
19 ;
20
21constantExpression
22 : constantExpression '.' Identifier
23 | identifier
24 ;
25
26expression
27 : '(' expression ')' # Grouping
28// this isn't allowed yet.
29// | THIS # Primary
30 | literal # Primary
31 | identifier # Primary
32 | classExtraction # Primary
33 | ResourceReference # Resource
34 | typeArguments (explicitGenericInvocationSuffix | 'this' arguments) # GenericCall
35 | expression '.' Identifier # DotOp
36// | expression '.' 'this' # ThisReference
37 | expression '.' explicitGenericInvocation # ExplicitGenericInvocationOp
38 | expression '[' expression ']' # BracketOp
39 | expression '.' Identifier '(' expressionList? ')' # MethodInvocation
40 | '(' type ')' expression # CastOp
41 | ('+'|'-') expression # UnaryOp
42 | ('~'|'!') expression # UnaryOp
Yigit Boyar35e303e2015-01-09 10:43:24 -080043 | left=expression op=('*'|'/'|'%') right=expression # MathOp
44 | left=expression op=('+'|'-') right=expression # MathOp
45 | left=expression op=('<<' | '>>>' | '>>') right=expression # BitShiftOp
46 | left=expression op=('<=' | '>=' | '>' | '<') right=expression # ComparisonOp
George Mountc09acd42015-01-07 16:34:06 -080047 | expression 'instanceof' type # InstanceOfOp
Yigit Boyar35e303e2015-01-09 10:43:24 -080048 | left=expression op=('==' | '!=') right=expression # ComparisonOp
49 | left=expression op='&' right=expression # BinaryOp
50 | left=expression op='^' right=expression # BinaryOp
51 | left=expression op='|' right=expression # BinaryOp
52 | left=expression op='&&' right=expression # AndOrOp
53 | left=expression op='||' right=expression # AndOrOp
54 | left=expression op='?' iftrue=expression ':' iffalse=expression # TernaryOp
55 | left=expression op='??' right=expression # QuestionQuestionOp
George Mountc09acd42015-01-07 16:34:06 -080056 ;
57
58THIS
59 : 'this'
60 ;
61
62classExtraction
63 : type '.' 'class'
64 | 'void' '.' 'class'
65 ;
66
67expressionList
68 : expression (',' expression)*
69 ;
70
71literal
72 : javaLiteral
73 | stringLiteral
74 ;
75
76identifier
77 : Identifier
78 ;
79
80javaLiteral
81 : IntegerLiteral
82 | FloatingPointLiteral
83 | BooleanLiteral
84 | NullLiteral
85 | CharacterLiteral
86 ;
87
88stringLiteral
89 : SingleQuoteString
90 | DoubleQuoteString
91 ;
92
93explicitGenericInvocation
94 : typeArguments explicitGenericInvocationSuffix
95 ;
96
97typeArguments
98 : '<' type (',' type)* '>'
99 ;
100
101type
102 : classOrInterfaceType ('[' ']')*
103 | primitiveType ('[' ']')*
104 ;
105
106explicitGenericInvocationSuffix
107 : Identifier arguments
108 ;
109
110arguments
111 : '(' expressionList? ')'
112 ;
113
114classOrInterfaceType
115 : identifier typeArguments? ('.' Identifier typeArguments? )*
116 ;
117
118primitiveType
119 : 'boolean'
120 | 'char'
121 | 'byte'
122 | 'short'
123 | 'int'
124 | 'long'
125 | 'float'
126 | 'double'
127 ;
128
129// LEXER
130
131// §3.10.1 Integer Literals
132
133IntegerLiteral
134 : DecimalIntegerLiteral
135 | HexIntegerLiteral
136 | OctalIntegerLiteral
137 | BinaryIntegerLiteral
138 ;
139
140fragment
141DecimalIntegerLiteral
142 : DecimalNumeral IntegerTypeSuffix?
143 ;
144
145fragment
146HexIntegerLiteral
147 : HexNumeral IntegerTypeSuffix?
148 ;
149
150fragment
151OctalIntegerLiteral
152 : OctalNumeral IntegerTypeSuffix?
153 ;
154
155fragment
156BinaryIntegerLiteral
157 : BinaryNumeral IntegerTypeSuffix?
158 ;
159
160fragment
161IntegerTypeSuffix
162 : [lL]
163 ;
164
165fragment
166DecimalNumeral
167 : '0'
168 | NonZeroDigit (Digits? | Underscores Digits)
169 ;
170
171fragment
172Digits
173 : Digit (DigitOrUnderscore* Digit)?
174 ;
175
176fragment
177Digit
178 : '0'
179 | NonZeroDigit
180 ;
181
182fragment
183NonZeroDigit
184 : [1-9]
185 ;
186
187fragment
188DigitOrUnderscore
189 : Digit
190 | '_'
191 ;
192
193fragment
194Underscores
195 : '_'+
196 ;
197
198fragment
199HexNumeral
200 : '0' [xX] HexDigits
201 ;
202
203fragment
204HexDigits
205 : HexDigit (HexDigitOrUnderscore* HexDigit)?
206 ;
207
208fragment
209HexDigit
210 : [0-9a-fA-F]
211 ;
212
213fragment
214HexDigitOrUnderscore
215 : HexDigit
216 | '_'
217 ;
218
219fragment
220OctalNumeral
221 : '0' Underscores? OctalDigits
222 ;
223
224fragment
225OctalDigits
226 : OctalDigit (OctalDigitOrUnderscore* OctalDigit)?
227 ;
228
229fragment
230OctalDigit
231 : [0-7]
232 ;
233
234fragment
235OctalDigitOrUnderscore
236 : OctalDigit
237 | '_'
238 ;
239
240fragment
241BinaryNumeral
242 : '0' [bB] BinaryDigits
243 ;
244
245fragment
246BinaryDigits
247 : BinaryDigit (BinaryDigitOrUnderscore* BinaryDigit)?
248 ;
249
250fragment
251BinaryDigit
252 : [01]
253 ;
254
255fragment
256BinaryDigitOrUnderscore
257 : BinaryDigit
258 | '_'
259 ;
260
261// §3.10.2 Floating-Point Literals
262
263FloatingPointLiteral
264 : DecimalFloatingPointLiteral
265 | HexadecimalFloatingPointLiteral
266 ;
267
268fragment
269DecimalFloatingPointLiteral
270 : Digits '.' Digits? ExponentPart? FloatTypeSuffix?
271 | '.' Digits ExponentPart? FloatTypeSuffix?
272 | Digits ExponentPart FloatTypeSuffix?
273 | Digits FloatTypeSuffix
274 ;
275
276fragment
277ExponentPart
278 : ExponentIndicator SignedInteger
279 ;
280
281fragment
282ExponentIndicator
283 : [eE]
284 ;
285
286fragment
287SignedInteger
288 : Sign? Digits
289 ;
290
291fragment
292Sign
293 : [+-]
294 ;
295
296fragment
297FloatTypeSuffix
298 : [fFdD]
299 ;
300
301fragment
302HexadecimalFloatingPointLiteral
303 : HexSignificand BinaryExponent FloatTypeSuffix?
304 ;
305
306fragment
307HexSignificand
308 : HexNumeral '.'?
309 | '0' [xX] HexDigits? '.' HexDigits
310 ;
311
312fragment
313BinaryExponent
314 : BinaryExponentIndicator SignedInteger
315 ;
316
317fragment
318BinaryExponentIndicator
319 : [pP]
320 ;
321
322// §3.10.3 Boolean Literals
323
324BooleanLiteral
325 : 'true'
326 | 'false'
327 ;
328
329// §3.10.4 Character Literals
330
331CharacterLiteral
332 : '\'' SingleCharacter '\''
333 | '\'' EscapeSequence '\''
334 ;
335
336fragment
337SingleCharacter
338 : ~['\\]
339 ;
340// §3.10.5 String Literals
341SingleQuoteString
342 : '`' SingleQuoteStringCharacter SingleQuoteStringCharacter+ '`'
343 ;
344
345DoubleQuoteString
346 : '"' StringCharacters? '"'
347 ;
348
349fragment
350StringCharacters
351 : StringCharacter+
352 ;
353fragment
354StringCharacter
355 : ~["\\]
356 | EscapeSequence
357 ;
358fragment
359SingleQuoteStringCharacter
360 : ~[`\\]
361 | EscapeSequence
362 ;
363
364// §3.10.6 Escape Sequences for Character and String Literals
365fragment
366EscapeSequence
367 : '\\' [btnfr"'`\\]
368 | OctalEscape
369 | UnicodeEscape
370 ;
371
372fragment
373OctalEscape
374 : '\\' OctalDigit
375 | '\\' OctalDigit OctalDigit
376 | '\\' ZeroToThree OctalDigit OctalDigit
377 ;
378
379fragment
380UnicodeEscape
381 : '\\' 'u' HexDigit HexDigit HexDigit HexDigit
382 ;
383
384fragment
385ZeroToThree
386 : [0-3]
387 ;
388
389// §3.10.7 The Null Literal
390
391NullLiteral
392 : 'null'
393 ;
394
395// §3.8 Identifiers (must appear after all keywords in the grammar)
396
397Identifier
398 : JavaLetter JavaLetterOrDigit*
399 ;
400
401fragment
402JavaLetter
403 : [a-zA-Z$_] // these are the "java letters" below 0xFF
404 | // covers all characters above 0xFF which are not a surrogate
405 ~[\u0000-\u00FF\uD800-\uDBFF]
406 {Character.isJavaIdentifierStart(_input.LA(-1))}?
407 | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
408 [\uD800-\uDBFF] [\uDC00-\uDFFF]
409 {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
410 ;
411
412fragment
413JavaLetterOrDigit
414 : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0xFF
415 | // covers all characters above 0xFF which are not a surrogate
416 ~[\u0000-\u00FF\uD800-\uDBFF]
417 {Character.isJavaIdentifierPart(_input.LA(-1))}?
418 | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
419 [\uD800-\uDBFF] [\uDC00-\uDFFF]
420 {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
421 ;
422
423//
424// Whitespace and comments
425//
426
427WS : [ \t\r\n\u000C]+ -> skip
428 ;
429
430//
431// Resource references
432//
433
434ResourceReference
435 : '@' (PackageName ':')? ResourceType '/' ResourceName
436 ;
437
438fragment
439PackageName
440 : 'android'
441 | Identifier
442 ;
443
444fragment
445ResourceType
446 : 'anim'
447 | 'animator'
448 | 'array'
449 | 'attr'
450 | 'bool'
451 | 'color'
452 | 'dimen'
453 | 'drawable'
454 | 'fraction'
455 | 'id'
456 | 'integer'
457 | 'interpolator'
458 | 'layout'
459 | 'menu'
460 | 'mipmap'
461 | 'plurals'
462 | 'raw'
463 | 'string'
464 | 'style'
465 | 'transition'
466 | 'xml'
467 ;
468
469ResourceName
470 : ResourceLetter ResourceLetterOrDigit*
471 ;
472
473fragment
474ResourceLetter
475 : [a-z$_] // these are the "lower-case java letters" below 0xFF
476 | // covers all characters above 0xFF which are not a surrogate
477 ~[\u0000-\u00FF\uD800-\uDBFF]
478 {Character.isJavaIdentifierStart(_input.LA(-1)) && !Character.isUpperCase(_input.LA(-1))}?
479 | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
480 [\uD800-\uDBFF] [\uDC00-\uDFFF]
481 {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1))) && !Character.isUpperCase(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
482 ;
483
484fragment
485ResourceLetterOrDigit
486 : [a-z0-9$_] // these are the "java letters or digits" below 0xFF
487 | // covers all characters above 0xFF which are not a surrogate
488 ~[\u0000-\u00FF\uD800-\uDBFF]
489 {Character.isJavaIdentifierPart(_input.LA(-1)) && !Character.isUpperCase(_input.LA(-1))}?
490 | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
491 [\uD800-\uDBFF] [\uDC00-\uDFFF]
492 {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1))) && !Character.isUpperCase(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
493 ;