Statistics
| Revision:

root / branches / modelio4.0.x / src / main / java / org / modelio / module / javadesigner / reverse / antlr / Java.g @ 451

History | View | Annotate | Download (41.7 KB)

1
/** Java 1.7 Recognizer
2
 * Contributing authors:
3
 *    John Mitchell     johnm@non.net
4
 *    Terence Parr      parrt@magelang.com
5
 *    John Lilley       jlilley@empathy.com
6
 *    Scott Stanchfield thetick@magelang.com
7
 *    Markus Mohnen     mohnen@informatik.rwth-aachen.de
8
 *    Peter Williams    pete.williams@sun.com
9
 *    Allan Jacobs      Allan.Jacobs@eng.sun.com
10
 *    Steve Messick     messick@redhills.com
11
 *    John Pybus        john@pybus.org
12
 *    Modelio development team
13
 * This grammar is in the PUBLIC DOMAIN
14
 */
15
grammar Java;
16

    
17
options {
18
  output       = AST;
19
  backtrack    = true;
20
  memoize      = true;
21
  ASTLabelType = ASTTree; // type of AST nodes id ASTTree
22
}
23

    
24
tokens {
25
  COMPILATION_UNIT;
26
  MODIFIERS;
27
  OBJBLOCK;
28
  SLIST;
29
  METHOD_DEF;
30
  VARIABLE_DEF;
31
  INSTANCE_INIT;
32
  STATIC_INIT;
33
  TYPE;
34
  CLASS_DEF;
35
  INTERFACE_DEF;
36
  PACKAGE_DEF;
37
  ARRAY_DECLARATOR;
38
  EXTENDS_CLAUSE;
39
  IMPLEMENTS_CLAUSE;
40
  PARAMETERS;
41
  PARAMETER_DEF;
42
  LABELED_STAT;
43
  TYPECAST;
44
  METHOD_CALL;
45
  EXPR;
46
  ARRAY_INIT;
47
  IMPORT;
48
  UNARY_MINUS;
49
  UNARY_PLUS;
50
  CASE_GROUP;
51
  ELIST;
52
  FOR_INIT;
53
  FOR_CONDITION;
54
  FOR_ITERATOR;
55
  EMPTY_STAT;
56
  SUPER_CTOR_CALL;
57
  CTOR_CALL;
58
  COMMENTS;
59
  JAVADOC;
60
  TRAILING_COMMENT;
61
  TYPE_ARGS;
62
  TYPE_PARAMS;
63
  WILDCARD;
64
  FORMAL_TYPE_PARAMS;
65
  TYPE_PARAM;
66
  ENUM_DEF;
67
  ENUM_CONST;
68
  ANNOTATION_DEF;
69
  ANNOTATION_MEMBER_DEF;
70
  ANNOTATION;
71
  ANNOTATION_DEFAULT;
72
  ANNOTATION_INIT_VALUE;
73
  ANNOTATION_INIT_LIST;
74
  ANNOTATION_INIT_MEMBER;
75
  ANNOTATION_ARRAY_INIT;
76
  SR_ASSIGN;
77
  BSR_ASSIGN;
78
  GE;
79
  SL_ASSIGN;
80
  LE;
81
  SL;
82
  SR;
83
  BSR;
84
  GENERIC_EXTENDS;
85
  STATIC;
86
  BUILT_IN;
87
  THROWS;
88
  RETURN = 'return';
89
  VOID;
90
}
91

    
92
@header {
93
package com.modeliosoft.modelio.javadesigner.reverse.antlr;
94
   import com.modeliosoft.modelio.javadesigner.reverse.antlr.ASTTree;
95
}
96

    
97
@members {
98
/**
99
 *  Look for comments tokens above 'start' token and attach them to 'node'
100
 *  Existing comments tokens attached to 'node' are kept.
101
 */
102
private void attachAboveComments(final ASTTree node, final Token start) {
103
  if (node == null) return;
104
	ASTTree commentsNode = new ASTTree(createToken(COMMENTS));
105
	List<? extends Token> tokens = ((CommonTokenStream) input).getTokens();
106
	int tokenPos = start.getTokenIndex() - 1;
107
	// step back the token stream, searching for javadocs 
108
	while (tokenPos >= 0) {
109
		Token curToken = tokens.get(tokenPos);
110
		if (curToken.getType() == JAVADOC || curToken.getType() == COMMENT) {
111
			// Comment found
112
			commentsNode.insertInFront(new ASTTree(curToken));
113
		} else if (curToken.getChannel() == Token.DEFAULT_CHANNEL) {
114
			// we have stepped back through a non hidden token : exit the loop
115
			// (the previous test is required because hidden tokens other than javadoc should be ignored.)
116
			break;
117
		}
118
		tokenPos--;
119
	}
120
	if (commentsNode.getChildCount() != 0) {
121
		attachToNodeBefore(node, commentsNode);
122
	}
123
}
124

    
125
/**
126
 *  Look for comment tokens after 'start' token but on the same line and attach them to 'node'
127
 *  Existing comment tokens attached to 'node' are kept.
128
 */
129
private void attachTrailingComments(final ASTTree node, final Token start) {
130
  if (node == null) return;
131
	ASTTree commentsNode = new ASTTree(); // nil temporary node
132
	List<? extends Token> tokens = ((CommonTokenStream) input).getTokens();
133
	int tokenPos = start.getTokenIndex() + 1;
134
	// Step forward on the same line, searching for comments
135
	while (tokenPos < tokens.size()) {
136
		Token curToken = tokens.get(tokenPos);
137
		if ((curToken.getType() == COMMENT || curToken.getType() == JAVADOC)
138
				&& curToken.getLine() == start.getLine()) {
139
			// comment found : change its type and store it
140
			// Note : it's because the token type is changed that it will not be
141
			// found by 'attachAboveComments' for the next element (attribute, etc)
142
			curToken.setType(TRAILING_COMMENT);
143
			commentsNode.addChild(new ASTTree(curToken));
144
		} else if (curToken.getChannel() == Token.DEFAULT_CHANNEL
145
				|| curToken.getLine() > start.getLine()) {
146
			// non hidden token or change of line : exit the loop
147
			break;
148
		}
149
		tokenPos++;
150
	}
151
	if (commentsNode.getChildCount() != 0) {
152
		attachToNode(node, commentsNode);
153
	}
154

    
155
}
156

    
157
/**
158
 *  Look for comment tokens underneath 'start' token and attach them to 'node'
159
 *  Existing comment tokens attached to 'node' are kept.
160
 */
161
private void attachUnderneathComments(final ASTTree node, final Token start) {
162
  if (node == null) return;
163
	ASTTree commentsNode = new ASTTree(createToken(COMMENTS));
164
	List<? extends Token> tokens = ((CommonTokenStream) input).getTokens();
165
	int tokenPos = start.getTokenIndex() + 1;
166
	// step back the token stream, searching for javadocs 
167
	while (tokenPos < tokens.size()) {
168
		Token curToken = tokens.get(tokenPos);
169
		if (curToken.getType() == JAVADOC || curToken.getType() == COMMENT) {
170
			// comment found
171
			commentsNode.addChild(new ASTTree(curToken));
172
		} else if (curToken.getChannel() == Token.DEFAULT_CHANNEL) {
173
			// we have stepped forward through a non hidden token : exit the loop
174
			// (the previous test is required because hidden tokens other than javadoc or comment should be ignored.)
175
			break;
176
		}
177
		tokenPos++;
178
	}
179
	if (commentsNode.getChildCount() != 0) {
180
		attachToNode(node, commentsNode);
181
	}
182
}
183

    
184
private void attachToNode(final ASTTree node, final ASTTree commentsNode) {
185
	ASTTree anchor = node;
186
	while (anchor.isNil()) {
187
		// flat list : attach to the first non nil child
188
		anchor = (ASTTree) anchor.getChild(0);
189
		if (anchor == null)
190
			return;
191
	}
192
	anchor.addChild(commentsNode);
193
}
194

    
195
private void attachToNodeBefore(final ASTTree node, final ASTTree commentsNode) {
196
	ASTTree anchor = node;
197
	while (anchor.isNil()) {
198
		// flat list : attach to the first non nil child
199
		anchor = (ASTTree) anchor.getChild(0);
200
		if (anchor == null)
201
			return;
202
	}
203
	try {
204
		if (anchor.getChildren() != null) {
205
		  anchor.insertInFront(commentsNode);
206
		} else {
207
			// anchor has no child, add its first
208
			anchor.addChild(commentsNode);
209
		}
210
		// should be: anchor.insertChild(0, commentsNode);
211
	} catch (Throwable e) {
212
		e.printStackTrace();
213
	}
214
}
215

    
216
/**
217
 *  Create a token with an identifiable text for debug purpose
218
 *  (Note : prefer not use the constructor CommonToken(type, text) because
219
 *   it set the channel to the default one)
220
 */
221
private Token createToken(int type) {
222
	Token com = new CommonToken(type);
223
	com.setText(tokenNames[type]);
224
	return com;
225
}
226

    
227
/**
228
 * Adjust the start token in order to include all comments on top of the given 'start' as well as
229
 * the white space on the same line than the given 'start'
230
 */
231
private Token adjustStartToken(final Token start) {
232
	List<? extends Token> tokens = ((CommonTokenStream) input).getTokens();
233
	int tokenpos = start.getTokenIndex() - 1;
234
	// step back to the first meaningful token (or begining of token stream)
235
	// Trailing_comments are stoppers because they are somehow meaningful
236
	while (tokenpos >= 0
237
			&& tokens.get(tokenpos).getChannel() != Token.DEFAULT_CHANNEL && tokens.get(tokenpos).getType() != TRAILING_COMMENT) {
238
		tokenpos--;
239
	}
240
	tokenpos++;
241
	// skip white space on the first line
242
	int stoppos = start.getTokenIndex();
243
	int adjstartpos = tokenpos;
244
	while (tokenpos < stoppos) {
245
		Token curtoken = tokens.get(tokenpos);
246

    
247
		int curtype = curtoken.getType();
248
		if (curtype == NL) {
249
			// 1st new line after 'from' the adjusted token is what follows NL  
250
			adjstartpos = tokenpos + 1;
251
			break;
252
		} else if (curtype != WS) {
253
			// 1st token which is not a NL or a WS. This is the adjusted token.
254
			adjstartpos = tokenpos;
255
			break;
256
		}
257
		tokenpos++;
258
	}
259
	return tokens.get(adjstartpos);
260
}
261

    
262
/**
263
 * Adjust the stop token in order to catch comments 
264
 * The goal is to catch all comments between 'from' and 'to'
265
 */
266
private Token adjustStopToken(final Token stop) {
267
	List<? extends Token> tokens = ((CommonTokenStream) input).getTokens();
268
	int tokenpos = stop.getTokenIndex() + 1;
269
	int adjstartpos = tokenpos - 1;
270
	while (tokenpos < tokens.size()
271
			&& tokens.get(tokenpos).getChannel() != Token.DEFAULT_CHANNEL) {
272
		Token curtoken = tokens.get(tokenpos);
273
		int curtype = curtoken.getType();
274
		if (curtype != NL && curtype != WS) {
275
			// We are at a useful hidden token (not to say a comment), this is the new adjusted token so far 
276
			adjstartpos = tokenpos;
277
		}
278
		tokenpos++;
279
	}
280
	return tokens.get(adjstartpos);
281
}
282

    
283
private String getSource(final Token start, final Token stop) {
284
	return this.input.toString(start, stop);
285
}
286
}
287
/* @rulecatch { }  // previously  options { defaultErrorHandler = false} */
288

    
289
/* Declarations for the lexer */
290

    
291
@lexer::header {
292
package com.modeliosoft.modelio.javadesigner.reverse.antlr;
293
}
294

    
295
@lexer::members {
296
//  @Override
297
//  public String getErrorMessage(RecognitionException e, String[] tokenNames) {
298
//     return super.getErrorMessage(e, tokenNames);
299
//  }
300
}
301

    
302
/* End of lexer declarations */
303

    
304
// Compilation Unit: In Java, this is a single file.  This is the start
305
//   rule for this parser
306

    
307
compilationUnit
308
@after {
309
// JavaTop
310
attachAboveComments($compilationUnit.tree, $compilationUnit.start);
311
// JavaBottom
312
attachUnderneathComments($compilationUnit.tree, $compilationUnit.stop);
313
}
314
  :
315
  pd=packageDefinition? impd+=importDefinition* td+=typeDefinition*
316
    -> ^(COMPILATION_UNIT $pd? $impd* $td* )
317
  ;
318

    
319
// Definition of an annotation type (JSR 175)
320

    
321
annotationTypeDefinition[Object ama]
322
  :
323
  AT 'interface' IDENT ab=annotationBlock
324
    -> ^(ANNOTATION_DEF IDENT {$ama} $ab )
325
  ;
326

    
327
// This is the body of an annotation type. Only inner type definitions and
328
// members (which use a notation similar to methods) are allowed.
329

    
330
annotationBlock
331
@after {
332
attachAboveComments($annotationBlock.tree, $rc);
333
}
334
  :
335
  LCURLY
336
  (
337
    annotationField
338
    | SEMI
339
  )*
340
  rc=RCURLY
341
    -> ^(OBJBLOCK annotationField* )
342
  ;
343

    
344
// Field in an annotation definition
345
// (Note : the syntaxic predicate above is to work around
346
// an antlr3.4.1 generation error that produces non compilable code)
347

    
348
annotationField
349
@after {
350
// attach comments & javadoc above the annotation.
351
// note eventhough there is no annotation in source, ann is still valid.
352
attachAboveComments($annotationField.tree, $annotationField.start);
353
}
354
  :
355
  (
356
    ama=annotmodannot
357
    (
358
      def=enumDefinition[$ama.tree] // inner enum
359
      | def=classDefinition[$ama.tree] // inner class
360
      | def=interfaceDefinition[$ama.tree] // inner interface
361
      | def=annotationTypeDefinition[$ama.tree] // inner annotation type
362
      | (annotationMethod[null]) => def=annotationMethod[$ama.tree] // annotation method
363
      | def=attributeDefinitions[$ama.tree] // attribute
364
    )
365
  )
366
    -> $def
367
  ;
368

    
369
annotationMethod[Object ama]
370
@after {
371
attachTrailingComments($annotationMethod.tree, $sm);
372
}
373
  :
374
  ts=typeSpec id=IDENT LPAREN RPAREN rt=declaratorBrackets[$ts.tree] dv=defaultValue? sm=SEMI
375
    -> ^(ANNOTATION_MEMBER_DEF {$ama} $rt $id $dv? )
376
  ;
377

    
378
// Annotation method may have optional default values.
379

    
380
defaultValue
381
  :
382
  dflt='default' anv=annotationMemberValue 
383
                                          {
384
                                           $anv.tree.setSourceCode(this.getSource(this.adjustStartToken($anv.start),
385
                                           		$anv.stop));
386
                                          }
387
    -> ^(ANNOTATION_DEFAULT annotationMemberValue )
388
  ;
389

    
390
// annotations can appear before or after modifiers
391
annotmodannot
392
   :
393
   annotation* modifiers? annotation*
394
   ;
395
   
396
annotation
397
@after {
398
$annotation.tree.setSourceCode($text);
399
}
400
  :
401
  at=AT identifier ani=annotationInit
402
    -> ^(ANNOTATION[$at] identifier $ani? )
403
  ;
404

    
405
// The initialization (list of assignments, single value, or nothing).
406

    
407
annotationInit
408
  :
409
  (
410
    lp=LPAREN
411
    (
412
      annotationMemberInit (COMMA annotationMemberInit)*
413
        -> ^(ANNOTATION_INIT_LIST[$lp] annotationMemberInit* )
414
      | annotationMemberValue
415
        -> ^(ANNOTATION_INIT_VALUE[$lp] annotationMemberValue )
416
      |
417
    /* empty */
418
    )
419
    RPAREN
420
  )
421
  |
422
  /* empty */
423
  ;
424

    
425
annotationMemberInit
426
  :
427
  IDENT ASSIGN annotationMemberValue
428
    -> ^(ANNOTATION_INIT_MEMBER IDENT annotationMemberValue )
429
  ;
430

    
431
annotationMemberValue
432
@after {
433
$annotationMemberValue.tree.setSourceCode($text);
434
}
435
  :
436
    annotation
437
  | conditionalExpression[true] -> ^(EXPR conditionalExpression )
438
  | annotationMemberArrayInitializer
439
  ;
440

    
441
// This is an initializer used to set up an array as an annotation member
442
// value.
443

    
444
annotationMemberArrayInitializer
445
  :
446
  lc=LCURLY (annotationMemberValue (COMMA annotationMemberValue)*)? COMMA? RCURLY
447
    -> ^(ANNOTATION_ARRAY_INIT[$lc] annotationMemberValue* )
448
  ;
449

    
450
enumDefinition[Object ama]
451
  :
452
  'enum' id=IDENT
453
    // it might implement some interfaces...
454
  ic=implementsClause?
455
    // now parse the body of the enum
456
  eb=enumBlock
457
    -> ^(ENUM_DEF $id $ic? {$ama} $eb)
458
  ;
459

    
460
// This is the body of an enumeration.  It can contain a list of comma
461
// separated identifiers (the enum values), and optionally, seperated by a
462
// semicolon, some declarations like in a class at the end.
463
// The values of the enumeration may be annotated.
464
// Note : weird enum block are accepted (checked with eclipse) like {;} or {,;}
465

    
466
enumBlock
467
@after {
468
attachAboveComments($enumBlock.tree, $rc);
469
}
470
  :
471
  LCURLY (ec=enumConst (c=COMMA 
472
                               {
473
                                attachTrailingComments($ec.tree, $c);
474
                               }
475
      ec=enumConst)*)? (c2=COMMA 
476
                                {
477
                                 attachTrailingComments($ec.tree, $c2);
478
                                })? // optional comma at end of value list
479
  (
480
    sem=SEMI {attachTrailingComments($ec.tree, $sem);}
481
    (
482
      field[true]
483
      | SEMI
484
    )*
485
  )?
486
  rc=RCURLY
487
    -> ^(OBJBLOCK enumConst* field* )
488
  ;
489

    
490
// Each enum value is in fact a class instance, and can be followed by the
491
// usual class declarations.
492

    
493
enumConst
494
@after {
495
attachAboveComments($enumConst.tree, $enumConst.start);
496
attachTrailingComments($enumConst.tree, $enumConst.stop);
497
}
498
  :
499
  ann=annotation* IDENT enumConstInit? classBlock?
500
    -> ^(ENUM_CONST $ann* IDENT enumConstInit? classBlock? )
501
  ;
502

    
503
// This is really a constructor invocation.
504

    
505
enumConstInit
506
@after {
507
$enumConstInit.tree.setSourceCode(this.getSource(
508
		this.adjustStartToken($al.start), this.adjustStopToken($al.stop)));
509
}
510
  :
511
  lp=LPAREN al=argList rp=RPAREN
512
    -> $al
513
  ;
514

    
515
// Package statement: 'package' followed by an identifier.
516

    
517
packageDefinition
518
  :
519
  an=annotation* p='package' identifier SEMI
520
    -> ^(PACKAGE_DEF[$p] identifier $an*)
521
  ;
522

    
523
// Import statement: import followed by a package or class name
524

    
525
importDefinition
526
  :
527
  i='import' (st='static' 
528
                         {
529
                          st.setType(STATIC);
530
                         })? identifierStar SEMI
531
    -> ^(IMPORT[$i] $st? identifierStar )
532
  ;
533

    
534
// A type definition in a file is either a class, an interface and annotation or an enum definition.
535

    
536
typeDefinition
537
@after {
538
attachAboveComments($typeDefinition.tree, $typeDefinition.start);
539
}
540
  :
541
  ama=annotmodannot
542
  (
543
    def=classDefinition[$ama.tree]
544
    | def=interfaceDefinition[$ama.tree]
545
    | def=annotationTypeDefinition[$ama.tree]
546
    | def=enumDefinition[$ama.tree]
547
  ) SEMI*
548
    -> $def
549
  ;
550

    
551
/** A declaration is the creation of a reference or primitive-type variable
552
 *  Create a separate Type/Var tree for each var in the var list.
553
 */
554
declaration
555
  :
556
  ama=annotmodannot t=typeSpec v=variableDefinitions[$ama.tree, $t.tree]
557
    -> $v
558
  ;
559

    
560
// A type specification is a type name with possible brackets afterwards
561
// (which would make it an array type).
562

    
563
typeSpec
564
  :
565
  classTypeSpec
566
  | builtInTypeSpec
567
  ;
568

    
569
// A class type specification is a class type with possible brackets afterwards
570

    
571
classTypeSpec
572
@init {
573
boolean arraySeen = false;
574
}
575
  :
576
  (coi=classOrInterfaceType -> $coi) 
577
  (lb=LBRACK RBRACK {arraySeen = true;} -> ^(ARRAY_DECLARATOR[$lb] $classTypeSpec ))*
578
  -> {arraySeen}? ^(TYPE $classTypeSpec)
579
  -> $classTypeSpec
580
  ;
581

    
582
// A builtin type specification is a builtin type with possible brackets
583
builtInTypeSpec
584
@init {
585
boolean arraySeen = false;
586
}
587
  :
588
  (bit=builtInType -> {$bit.tree.getType() != VOID}? ^(TYPE $bit)
589
                   -> $bit
590
  ) 
591
  (lb=LBRACK RBRACK {arraySeen = true;}  -> ^(ARRAY_DECLARATOR[$lb] $builtInTypeSpec))*
592
  -> {arraySeen}? ^(TYPE $builtInTypeSpec)
593
  -> $builtInTypeSpec
594
  ;
595

    
596
// Something simple as Klazz or complicated as Klazz<?>.SubKlazz<?>
597
classOrInterfaceType
598
@init {
599
// add TYPE node if a DOT has been seen to be sure to return a TYPE node but not a (TYPE (TYPE ident))
600
boolean dotSeen = false;
601
}
602
@after {
603
$classOrInterfaceType.tree.setSourceCode($text);
604
}
605
  :
606
  (simpleClassOrInterfaceType -> simpleClassOrInterfaceType) 
607
  (options {greedy=true;}: 
608
    d=DOT { dotSeen = true; }
609
    scoi=simpleClassOrInterfaceType -> ^(DOT[$d] $classOrInterfaceType $scoi ))*
610
    -> {dotSeen}? ^(TYPE $classOrInterfaceType)
611
    -> $classOrInterfaceType
612
  ;
613

    
614
simpleClassOrInterfaceType
615
  :
616
  IDENT typeArguments?
617
    -> ^(TYPE IDENT typeArguments? )
618
  ;
619

    
620
// The primitive types.
621
builtInType
622
  :
623
  (
624
    t='boolean'
625
    | t='byte'
626
    | t='char'
627
    | t='short'
628
    | t='int'
629
    | t='float'
630
    | t='long'
631
    | t='double'
632
  ) -> ^(BUILT_IN[$t])
633
  | v='void' -> ^(VOID[$v])
634
  ;
635

    
636
// a (possibly-qualified) java identifier possibly terminated by '.*'
637

    
638
identifierStar
639
  :
640
  identifier (DOT^ STAR)?
641
  ;
642

    
643
// A (possibly-qualified) java identifier.  We start with the first IDENT
644
//   and expand its name by adding dots and following IDENTS
645

    
646
identifier
647
  :
648
  IDENT (DOT^ IDENT)*
649
  ;
650

    
651
// A list of one or more modifiers.
652

    
653
modifiers
654
  :
655
  modifier+
656
    -> ^(MODIFIERS modifier+ )
657
  ;
658

    
659
// modifiers for Java classes, interfaces, class/instance vars and methods
660

    
661
modifier
662
  :
663
  'private'
664
  | 'public'
665
  | 'protected'
666
  | 'static'
667
  | 'transient'
668
  | 'final'
669
  | 'abstract'
670
  | 'native'
671
  | 'threadsafe'
672
  | 'synchronized'
673
  | 'volatile'
674
  | 'strictfp'
675
  ;
676

    
677
// Definition of a Java class
678

    
679
classDefinition[Object ama]
680
  :
681
  'class' id=IDENT fp=formalTypeParameters? // types parameters for generics
682
  sc=superClassClause? // optional extends clause
683
  ic=implementsClause? // optional implement clause
684
  cb=classBlock // body of the class
685
    -> ^(CLASS_DEF {$ama} $id $fp? $sc? $ic? $cb )
686
  ;
687

    
688
// Generic formal parameters for class, interface and operation
689

    
690
formalTypeParameters
691
  :
692
  lt=LT typeParameter (COMMA typeParameter)* GT
693
    -> ^(FORMAL_TYPE_PARAMS[$lt] typeParameter+ )
694
  ;
695

    
696
typeParameter
697
@after {
698
// Get the source code
699
$typeParameter.tree.setSourceCode($text);
700
}
701
  :
702
  id=IDENT tp=typeParameterBound?
703
    -> ^(TYPE_PARAM[$id] $id $tp? )
704
  ;
705

    
706
typeParameterBound
707
@after {
708
// Get the source code escaping 'extends' keyword
709
$typeParameterBound.tree.setSourceCode($tpbr.text);
710
}
711
  :
712
  e='extends' tpbr=typeParameterBoundRest
713
    -> ^(GENERIC_EXTENDS[$e] $tpbr+ )
714
  ;
715

    
716
typeParameterBoundRest
717
  :
718
  classOrInterfaceType (BAND classOrInterfaceType)*
719
  ;
720

    
721
// actual type argument for generic parameters
722

    
723
typeArguments
724
  :
725
  lt=LT typeArgument? (COMMA typeArgument)* GT
726
    -> ^(TYPE_ARGS[$lt] typeArgument* )
727
  ;
728

    
729
// either reference type or wildcard type with optional lower or upper bound
730

    
731
typeArgument
732
@after {
733
$typeArgument.tree.setSourceCode($typeArgument.text);
734
}
735
  :
736
  (
737
    q=QUESTION
738
    (
739
      (
740
        m='extends'
741
        | m='super'
742
      )
743
      typeSpec
744
    )?
745
  )
746
    -> ^(
747
        TYPE
748
        ^(
749
          WILDCARD[$q]
750
          ^($m typeSpec )?
751
          )
752
        )
753
  | rts=typeSpec
754
  ;
755

    
756
superClassClause
757
  :
758
  ('extends' id=classOrInterfaceType)
759
    -> ^(EXTENDS_CLAUSE $id )
760
  ;
761

    
762
// Definition of a Java Interface
763

    
764
interfaceDefinition[Object ama]
765
  :
766
  'interface' id=IDENT fp=formalTypeParameters? // optional generic parameters
767
  ie=interfaceExtends? // optional extends clause
768
  cb=classBlock // interface body
769
    -> ^(INTERFACE_DEF $id {$ama} $fp? $ie? $cb )
770
  ;
771

    
772
// This is the body of a class.  You can have fields and extra semicolons,
773
// That's about it (until you see what a field is...)
774

    
775
classBlock
776
@after {
777
attachAboveComments($classBlock.tree, $rc);
778
}
779
  :
780
  LCURLY
781
  (
782
    field[false]
783
    | SEMI
784
  )*
785
  rc=RCURLY
786
    -> ^(OBJBLOCK field* )
787
  ;
788

    
789
// An interface can extend several other interfaces...
790

    
791
interfaceExtends
792
  :
793
  'extends' classOrInterfaceType (COMMA classOrInterfaceType)*
794
    -> ^(EXTENDS_CLAUSE classOrInterfaceType+ )
795
  ;
796

    
797
// A class can implement several interfaces...
798

    
799
implementsClause
800
  :
801
  'implements' classOrInterfaceType (COMMA classOrInterfaceType)*
802
    -> ^(IMPLEMENTS_CLAUSE classOrInterfaceType+)
803
  ;
804

    
805
// field defined inside an interface, class or enumeration
806
// attachSource tells if the source code should be attached to the field
807
// TODO : remove attachSource as soon as EnumMemberXMLGenerator is corrected to handle attribute/assoc
808
// and sub-stuff in enumeration as model element
809

    
810
field[boolean attachSource]
811
@init {
812
   ASTTree annotationsNode = null;
813
}
814
@after {
815
attachAboveComments($field.tree, $field.start);
816
if (attachSource) {
817
   $field.tree.setSourceCode(this.getSource(
818
			this.adjustStartToken($field.start), $field.stop));
819
}
820
}
821
  :
822
  (
823
    // (Note : the syntaxic predicates are to work around
824
    // an antlr3.4.1 generation error that produces non compilable code)
825
    ama=annotmodannot
826
    (
827
      (attributeDefinitions[null]) => def=attributeDefinitions[$ama.tree] // attribute definition
828
      | def=classDefinition[$ama.tree] // inner class
829
      | def=interfaceDefinition[$ama.tree] // inner interface
830
      | def=enumDefinition[$ama.tree] // inner enumeration
831
      | def=annotationTypeDefinition[$ama.tree] // inner annotation definition
832
      | (constructorDefinition[null]) => def=constructorDefinition[$ama.tree] // constructor
833
      | (operationDefinition[null]) => def=operationDefinition[$ama.tree] // operation definition
834
    )
835
    | def=staticInitializer // 'static { ... }' class initializer
836
    | def=instanceInitializer // '{ ... }' instance initializer
837
  )
838
    -> $def
839
  ;
840

    
841
constructorDefinition[Object ama]
842
  :
843
  fp=formalTypeParameters? // generic parameter
844
  id=IDENT // method name
845
  LPAREN pa=parameterDeclarationList? RPAREN // parameters list
846
  tc=throwsClause? // thrown exceptions
847
  st=compoundStatement[true] // operation body or final semi
848
    -> ^(METHOD_DEF $id $fp? {$ama} $pa? $tc? $st? )
849
  ;
850

    
851
operationDefinition[Object ama]
852
  :
853
  fp=formalTypeParameters? // generic parameter
854
  ty=typeSpec // method return type
855
  id=IDENT // method name
856
  LPAREN pa=parameterDeclarationList? RPAREN // parameters list
857
  rt=declaratorBrackets[$ty.tree] // return type can be an array (yes it's weird here !)
858
  tc=throwsClause? // thrown exceptions
859
  (
860
    st=compoundStatement[true]
861
    | SEMI
862
  ) // operation body or final semi
863
    -> ^(METHOD_DEF $id $fp? {$ama} $rt? $pa? $tc? $st? )
864
  ;
865

    
866
attributeDefinitions[Object ama]
867
@after {
868
attachTrailingComments($attributeDefinitions.tree, $sm);
869
}
870
  :
871
  ty=typeSpec // type
872
  va=variableDefinitions[ama, $ty.tree] sm=SEMI
873
    -> $va
874
  ;
875

    
876
staticInitializer
877
@after {
878
$staticInitializer.tree.setSourceCode($text);
879
}
880
  :
881
  'static' cs=compoundStatement[false]
882
    -> ^(STATIC_INIT $cs )
883
  ;
884

    
885
instanceInitializer
886
@after {
887
$instanceInitializer.tree.setSourceCode($text);
888
}
889
  :
890
  cs=compoundStatement[false]
891
    -> ^(INSTANCE_INIT $cs )
892
  ;
893

    
894
variableDefinitions[Object ama, Object t]
895
  :
896
  va+=variableDeclarator[ama, t] (COMMA va+=variableDeclarator[ama, t])*
897
    -> $va+
898
  ;
899

    
900
/** Declaration of a variable.  This can be a class/instance variable,
901
 *   or a local variable in a method
902
 * It can also include possible initialization.
903
 */
904
variableDeclarator[Object ama, Object t]
905
  :
906
  id=IDENT d=declaratorBrackets[t] v=varInitializer
907
    -> ^(VARIABLE_DEF $id {$ama} $d $v? )
908
  ;
909

    
910
declaratorBrackets[Object typ]
911
@init {
912
boolean arraySeen = false;
913
}
914
  :
915
  ( -> {$typ})
916
  (lb=LBRACK RBRACK {arraySeen = true;}
917
    -> ^(ARRAY_DECLARATOR[$lb] $declaratorBrackets ))*
918
  -> {arraySeen}? ^(TYPE $declaratorBrackets )
919
  -> $declaratorBrackets
920
  ;
921

    
922
varInitializer
923
  :
924
  (as=ASSIGN^ i=initializer 
925
                           {
926
                            $as.tree.setSourceCode(this.getSource(this.adjustStartToken($i.start), $i.stop));
927
                           })?
928
  ;
929

    
930
arrayInitializer
931
  :
932
  lc=LCURLY (initializer (
933
    // CONFLICT: does a COMMA after an initializer start a new
934
  //           initializer or start the option ',' at end?
935
  //           ANTLR generates proper code by matching
936
  //       the comma as soon as possible.
937
  options {greedy=true;}: COMMA initializer)* COMMA?)? RCURLY
938
    -> ^(ARRAY_INIT[$lc] initializer* )
939
  ;
940

    
941
// The two 'things' that can initialize an array element are an expression
942
//   and another (nested) array initializer.
943

    
944
initializer
945
  :
946
  expression
947
  | arrayInitializer
948
  ;
949

    
950
// This is a list of exception classes that the method is declared to throw
951

    
952
throwsClause
953
  :
954
  'throws' identifier (COMMA identifier)*
955
    -> ^(THROWS identifier+ )
956
  ;
957

    
958
// A list of formal parameters
959

    
960
parameterDeclarationList
961
  :
962
  (parameterDeclaration (COMMA parameterDeclaration)*)
963
    -> ^(PARAMETERS parameterDeclaration+ )
964
  ;
965

    
966
// A formal parameter.
967
// The ellipsis is the support for varargs (JSR 201)
968
// This rule allows ellipsis on any parameter, not just the last (as specified
969
// by JSR 201), so a semantic check is needed for that.
970

    
971
parameterDeclaration
972
  :
973
  ann+=annotation* pm=parameterModifier? ann+=annotation* t=typeSpec el=ELLIPSIS? id=IDENT pd=declaratorBrackets[$t.tree]
974
    -> ^(PARAMETER_DEF $pm? $ann* $pd $el? $id )
975
  ;
976

    
977
parameterModifier
978
  :
979
  f='final'
980
    -> ^(MODIFIERS $f )
981
  ;
982

    
983
// Compound statement.  This is used in many contexts:
984
//   Inside a class definition prefixed with 'static':
985
//      it is a class initializer
986
//   Inside a class definition without 'static':
987
//      it is an instance initializer
988
//   As the body of a method
989
//   As a completely independent braced block of code inside a method
990
//      it starts a new scope for variable definitions
991

    
992
compoundStatement[boolean top]
993
@after {
994
if (top) {
995
	$compoundStatement.tree.setSourceCode(this.getSource(
996
			this.adjustStartToken($stmtl.start),
997
			this.adjustStopToken($stmtl.stop)));
998
}
999
}
1000
  :
1001
  LCURLY
1002
    // include the (possibly-empty) list of statements
1003
  stmtl=statementList RCURLY
1004
    -> ^(SLIST $stmtl? )
1005
  ;
1006

    
1007
statementList
1008
  :
1009
  explicitConstructorInvocation? statement*
1010
  ;
1011

    
1012
/** Catch obvious constructor calls, but not the expr.super(...) calls */
1013
explicitConstructorInvocation
1014
  :
1015
  'this' lp1=LPAREN argList RPAREN SEMI
1016
    -> ^(CTOR_CALL argList )
1017
  | 'super' lp2=LPAREN argList RPAREN SEMI
1018
    -> ^(SUPER_CTOR_CALL argList )
1019
  ;
1020

    
1021
//statement
1022

    
1023
statement
1024
  // A list of statements in curly braces -- start a new scope!
1025
  :
1026
  compoundStatement[false]
1027
    -> compoundStatement
1028
  // declarations are ambiguous with 'ID DOT' relative to expression
1029
  // statements.  Must backtrack to be sure.  Could use a semantic
1030
  // predicate to test symbol table to see what the type was coming
1031
  // up, but that's pretty hard without a symbol table ;)
1032
  | (declaration) => declaration SEMI
1033
    -> declaration
1034

    
1035
  // An expression statement.  This could be a method call,
1036
  // assignment statement, or any other expression evaluated for
1037
  // side-effects.
1038
  | expression SEMI
1039
    -> expression
1040

    
1041
  // class definition
1042
  | ama=annotmodannot classDefinition[$ama.tree]
1043
    -> classDefinition
1044

    
1045
  // Attach a label to the front of a statement
1046
  | IDENT COLON statement
1047
    -> ^(LABELED_STAT IDENT statement )
1048

    
1049
  // If-else statement
1050
  | 'if' LPAREN expression RPAREN ths=statement
1051
  ( options {k=1;}: ('else') => 'else' els=statement
1052
  )?
1053
    -> ^('if' expression $ths $els? )
1054

    
1055
  // For statement
1056
  | 'for' LPAREN
1057
  (
1058
    (parameterDeclaration COLON) => parameterDeclaration COLON expression
1059
    | forInit SEMI // initializer
1060
    forCond SEMI // condition test
1061
    forIter // updater
1062
  )
1063
  RPAREN statement // statement to loop over
1064
    -> ^('for' parameterDeclaration? expression? forInit? forCond? forIter? statement )
1065

    
1066
  // While statement
1067
  | 'while' LPAREN expression RPAREN statement
1068
    -> ^('while' expression statement )
1069

    
1070
  // do-while statement
1071
  | 'do' statement 'while' LPAREN expression RPAREN SEMI
1072
    -> ^('do' statement expression )
1073

    
1074
  // get out of a loop (or switch)
1075
  | 'break' IDENT? SEMI
1076
    -> ^('break' IDENT? )
1077

    
1078
  // do next iteration of a loop
1079
  | 'continue' IDENT? SEMI
1080
    -> ^('continue' IDENT? )
1081

    
1082
  // Return an expression
1083
  | ret='return' expression? SEMI
1084
    -> ^(RETURN[$ret] expression? )
1085

    
1086
  // switch/case statement
1087
  | 'switch' LPAREN expression RPAREN LCURLY casesGroup* RCURLY
1088
    -> ^('switch' expression casesGroup* )
1089

    
1090
  // exception try-catch block
1091
  | tryBlock
1092
    -> tryBlock
1093

    
1094
  // throw an exception
1095
  | 'throw' expression SEMI
1096
    -> ^('throw' expression )
1097

    
1098
  // synchronize a statement
1099
  | 'synchronized' LPAREN expression RPAREN compoundStatement[false]
1100
    -> ^('synchronized' expression compoundStatement )
1101

    
1102
  // asserts (uncomment if you want 1.4 compatibility)
1103
  | 'assert' expression (COLON expression)? SEMI
1104
    -> ^('assert' expression expression? )
1105

    
1106
  // empty statement
1107
  | SEMI
1108
    -> EMPTY_STAT
1109
  ;
1110

    
1111
casesGroup
1112
  :
1113
  ( // CONFLICT: to which case group do the statements bind?
1114
  //           ANTLR generates proper code: it groups the
1115
  //           many 'case'/'default' labels together then
1116
  //           follows them with the statements
1117
  options {greedy=true;}: aCase)+ caseSList
1118
    -> ^(CASE_GROUP aCase+ caseSList )
1119
  ;
1120

    
1121
aCase
1122
  :
1123
  (
1124
    'case'^ expression
1125
    | 'default'
1126
  )
1127
  COLON!
1128
  ;
1129

    
1130
caseSList
1131
  :
1132
  statement*
1133
    -> ^(SLIST statement* )
1134
  ;
1135

    
1136
// The initializer for a for loop
1137

    
1138
forInit
1139
  // if it looks like a declaration, it is
1140
  :
1141
  (
1142
    (declaration) => declaration
1143
    // otherwise it could be an expression list...
1144
    | expressionList
1145
  )?
1146
    -> ^(FOR_INIT declaration? expressionList? )
1147
  ;
1148

    
1149
forCond
1150
  :
1151
  expression?
1152
    -> ^(FOR_CONDITION expression? )
1153
  ;
1154

    
1155
forIter
1156
  :
1157
  expressionList?
1158
    -> ^(FOR_ITERATOR expressionList? )
1159
  ;
1160

    
1161
// an exception handler try/catch block
1162

    
1163
tryBlock
1164
  :
1165
  'try'^ resourceDeclarations? compoundStatement[false] handler* finallyClause?
1166
  ;
1167

    
1168
// Java7 resourceStatement in try-block
1169
resourceDeclarations
1170
  :
1171
  LPAREN declaration? (SEMI declaration?)* RPAREN
1172
  ;
1173

    
1174
finallyClause
1175
  :
1176
  'finally'^ compoundStatement[false]
1177
  ;
1178

    
1179
// an exception handler
1180

    
1181
handler
1182
  :
1183
  'catch'^ LPAREN! caughtExceptionDeclarations IDENT RPAREN! compoundStatement[false]
1184
  ;
1185

    
1186
caughtExceptionDeclarations
1187
  :
1188
  caughtExceptionDeclaration (BOR! caughtExceptionDeclaration)*
1189
  ;
1190

    
1191
caughtExceptionDeclaration!
1192
  :
1193
  annotation* parameterModifier? annotation* typeSpec
1194
  ;
1195

    
1196
// This is a list of expressions.
1197

    
1198
expressionList
1199
  :
1200
  expression (COMMA expression)*
1201
    -> ^(ELIST expression+ )
1202
  ;
1203

    
1204
// expressions
1205
// Note that most of these expressions follow the pattern
1206
//   thisLevelExpression :
1207
//       nextHigherPrecedenceExpression
1208
//           (OPERATOR nextHigherPrecedenceExpression)*
1209
// which is a standard recursive definition for a parsing an expression.
1210
// The operators in java have the following precedences:
1211
//    lowest  (13)  = *= /= %= += -= <<= >>= >>>= &= ^= |=
1212
//            (12)  ?:
1213
//            (11)  ||
1214
//            (10)  &&
1215
//            ( 9)  |
1216
//            ( 8)  ^
1217
//            ( 7)  &
1218
//            ( 6)  == !=
1219
//            ( 5)  < <= > >=
1220
//            ( 4)  << >>
1221
//            ( 3)  +(binary) -(binary)
1222
//            ( 2)  * / %
1223
//            ( 1)  ++ -- +(unary) -(unary)  ~  !  (type)
1224
//                  []   () (method call)  . (dot -- identifier qualification)
1225
//                  new   ()  (explicit parenthesis)
1226
//
1227
// the last two are not usually on a precedence chart; I put them in
1228
// to point out that new has a higher precedence than '.', so you
1229
// can validy use
1230
//     new Frame().show()
1231
//
1232
// Note that the above precedence levels map to the rules below...
1233
// Once you have a precedence chart, writing the appropriate rules as below
1234
//   is usually very straightfoward
1235

    
1236
// the mother of all expressions
1237

    
1238
expression
1239
  :
1240
  as=assignmentExpression
1241
    -> ^(EXPR $as )
1242
  ;
1243

    
1244
// assignment expression (level 13)
1245

    
1246
assignmentExpression
1247
  :
1248
  conditionalExpression[false] (assignmentOperator assignmentExpression)?
1249
  ;
1250

    
1251
assignmentOperator
1252
  :
1253
  ASSIGN
1254
    -> ASSIGN
1255
  | PLUS_ASSIGN
1256
    -> PLUS_ASSIGN
1257
  | MINUS_ASSIGN
1258
    -> MINUS_ASSIGN
1259
  | STAR_ASSIGN
1260
    -> STAR_ASSIGN
1261
  | DIV_ASSIGN
1262
    -> DIV_ASSIGN
1263
  | MOD_ASSIGN
1264
    -> MOD_ASSIGN
1265
  | GT GT '='
1266
    -> SR_ASSIGN
1267
  | GT GT GT '='
1268
    -> BSR_ASSIGN
1269
  | LT LT '='
1270
    -> SL_ASSIGN
1271
  | BAND_ASSIGN
1272
    -> BAND_ASSIGN
1273
  | BXOR_ASSIGN
1274
    -> BXOR_ASSIGN
1275
  | BOR_ASSIGN
1276
    -> BOR_ASSIGN
1277
  ;
1278

    
1279
// conditional test (level 12)
1280

    
1281
conditionalExpression[boolean storeSrcCode]
1282
@after {
1283
if (storeSrcCode) {
1284
  $conditionalExpression.tree.setSourceCode($text);
1285
}
1286
}
1287
  :
1288
  logicalOrExpression (QUESTION^ assignmentExpression COLON! conditionalExpression[false])?
1289
  ;
1290

    
1291
// logical or (||)  (level 11)
1292

    
1293
logicalOrExpression
1294
  :
1295
  logicalAndExpression (LOR^ logicalAndExpression)*
1296
  ;
1297

    
1298
// logical and (&&)  (level 10)
1299

    
1300
logicalAndExpression
1301
  :
1302
  inclusiveOrExpression (LAND^ inclusiveOrExpression)*
1303
  ;
1304

    
1305
// bitwise or non-short-circuiting or (|)  (level 9)
1306

    
1307
inclusiveOrExpression
1308
  :
1309
  exclusiveOrExpression (BOR^ exclusiveOrExpression)*
1310
  ;
1311

    
1312
// exclusive or (^)  (level 8)
1313

    
1314
exclusiveOrExpression
1315
  :
1316
  andExpression (BXOR^ andExpression)*
1317
  ;
1318

    
1319
// bitwise or non-short-circuiting and (&)  (level 7)
1320

    
1321
andExpression
1322
  :
1323
  equalityExpression (BAND^ equalityExpression)*
1324
  ;
1325

    
1326
// equality/inequality (==/!=) (level 6)
1327

    
1328
equalityExpression
1329
  :
1330
  instanceOfExpression
1331
  (
1332
    (
1333
      NOT_EQUAL^
1334
      | EQUAL^
1335
    )
1336
    instanceOfExpression
1337
  )*
1338
  ;
1339

    
1340
// 'instanceof' Expression(level 5)
1341

    
1342
instanceOfExpression
1343
  :
1344
  relationalExpression ('instanceof'^ typeSpec)?
1345
  ;
1346

    
1347
// boolean relational expressions (level 5bis)
1348

    
1349
relationalExpression
1350
  :
1351
  additiveExpression (relationalOperator^ additiveExpression)*
1352
  ;
1353

    
1354
relationalOperator
1355
  :
1356
  LT
1357
    -> LT
1358
  | LT LT
1359
    -> SL
1360
  | LT '='
1361
    -> LE
1362
  | GT
1363
    -> GT
1364
  | GT GT
1365
    -> SR
1366
  | GT GT GT
1367
    -> BSR
1368
  | GT '='
1369
    -> GE
1370
  ;
1371
// binary addition/subtraction (level 3)
1372

    
1373
additiveExpression
1374
  :
1375
  multiplicativeExpression
1376
  (
1377
    (
1378
      PLUS^
1379
      | MINUS^
1380
    )
1381
    multiplicativeExpression
1382
  )*
1383
  ;
1384

    
1385
// multiplication/division/modulo (level 2)
1386

    
1387
multiplicativeExpression
1388
  :
1389
  unaryExpression
1390
  (
1391
    (
1392
      STAR^
1393
      | DIV^
1394
      | MOD^
1395
    )
1396
    unaryExpression
1397
  )*
1398
  ;
1399

    
1400
unaryExpression
1401
  :
1402
  INC^ unaryExpression
1403
  | DEC^ unaryExpression
1404
  | MINUS^ 
1405
          {
1406
           $MINUS.setType(UNARY_MINUS);
1407
          }
1408
  unaryExpression
1409
  | PLUS^ 
1410
         {
1411
          $PLUS.setType(UNARY_PLUS);
1412
         }
1413
  unaryExpression
1414
  | unaryExpressionNotPlusMinus
1415
  ;
1416

    
1417
unaryExpressionNotPlusMinus
1418
  :
1419
  BNOT unaryExpression
1420
    -> ^(BNOT unaryExpression )
1421
  | LNOT unaryExpression
1422
    -> ^(LNOT unaryExpression )
1423
  |
1424
  ( // subrule allows option to shut off warnings
1425
  options {
1426
      // '(int' ambig with postfixExpr due to lack of sequence
1427
  // info in linear approximate LL(k).  It's ok.  Shut up.
1428
  greedy=true;}:
1429
      // If typecast is built in type, must be numeric operand
1430
  // Also, no reason to backtrack if type keyword like int, float...
1431
  LPAREN builtInTypeSpec RPAREN unaryExpression
1432
      -> ^(TYPECAST builtInTypeSpec unaryExpression )
1433
    // Have to backtrack to see if operator follows.  If no operator
1434
    // follows, it's a typecast.  No semantic checking needed to parse.
1435
    // if it _looks_ like a cast, it _is_ a cast; else it's a '(expr)'
1436
    | (LPAREN classTypeSpec RPAREN unaryExpressionNotPlusMinus) => LPAREN classTypeSpec RPAREN unaryExpressionNotPlusMinus
1437
      -> ^(TYPECAST classTypeSpec unaryExpressionNotPlusMinus )
1438
    | postfixExpression
1439
      -> postfixExpression
1440
  )
1441
  ;
1442

    
1443
// qualified names, array expressions, method invocation, post inc/dec
1444

    
1445
postfixExpression!
1446
  :
1447
  primaryExpression
1448
  (
1449
    DOT typeArguments? IDENT (LPAREN argList RPAREN)?
1450
    | DOT 'this'
1451
    | DOT 'super'
1452
    ( // (new Outer()).super()  (create enclosing instance)
1453
      LPAREN argList RPAREN
1454
      | DOT IDENT (LPAREN argList RPAREN)?
1455
    )
1456
    | DOT newExpression
1457
    | lb=LBRACK expression RBRACK
1458
  )*
1459
  ( // possibly add on a post-increment or post-decrement.
1460
    // allows INC/DEC on too much, but semantics can check
1461
    INC
1462
    | DEC
1463
  )?
1464
  ;
1465

    
1466
// the basic element of an expression
1467

    
1468
primaryExpression
1469
  :
1470
  identPrimary (options {greedy=true;}: DOT^ 'class')?
1471
  | constant
1472
  | 'true'
1473
  | 'false'
1474
  | 'null'
1475
  | newExpression
1476
  | 'this'
1477
  | 'super'
1478
  | LPAREN! assignmentExpression RPAREN!
1479
  // look for int.class and int[].class
1480
  |
1481
  builtInType
1482
  (lbt=LBRACK^ 
1483
              {
1484
               $lbt.setType(ARRAY_DECLARATOR);
1485
              }
1486
    RBRACK!)* DOT^ 'class'
1487
  ;
1488

    
1489
/** Match a, a.b.c refs, a.b.c(...) refs, a.b.c[], a.b.c[].class,
1490
 *  and a.b.c.class refs.  Also this(...) and super(...).  Match
1491
 *  this or super.
1492
 */
1493
identPrimary
1494
  :
1495
  IDENT (options {greedy=true;}: DOT^ IDENT)*
1496
  ( options {greedy=true;}: (lp=LPAREN^ 
1497
                                       {
1498
                                        $lp.setType(METHOD_CALL);
1499
                                       }
1500
      argList RPAREN!)
1501
    | (options {greedy=true;}: lbc=LBRACK^ 
1502
                                          {
1503
                                           $lbc.setType(ARRAY_DECLARATOR);
1504
                                          }
1505
      RBRACK!)+
1506
  )?
1507
  ;
1508

    
1509
newExpression!
1510
  :
1511
  'new'
1512
  (
1513
    classOrInterfaceType
1514
    | builtInType
1515
  )
1516
  (
1517
    LPAREN argList RPAREN classBlock?
1518
    | newArrayDeclarator arrayInitializer?
1519
  )
1520
  ;
1521

    
1522
argList
1523
  :
1524
  el=expressionList
1525
  |
1526
    /* nothing */
1527
    -> ^(ELIST )
1528
  ;
1529

    
1530
newArrayDeclarator
1531
  :
1532
  (
1533
                                     // CONFLICT:
1534
  // newExpression is a primaryExpression which can be
1535
  // followed by an array index reference.  This is ok,
1536
  // as the generated code will stay in this loop as
1537
  // long as it sees an LBRACK (proper behavior)
1538
  options {greedy=true;}: lb=LBRACK^ 
1539
                                     {
1540
                                      $lb.setType(ARRAY_DECLARATOR);
1541
                                     }
1542
    (expression)? RBRACK!)+
1543
  ;
1544

    
1545
constant
1546
  :
1547
  NUM_LITERAL
1548
  | CHAR_LITERAL
1549
  | STRING_LITERAL
1550
  ;
1551

    
1552
//----------------------------------------------------------------------------
1553
// The Java scanner
1554
//----------------------------------------------------------------------------
1555

    
1556
// OPERATORS
1557

    
1558
QUESTION
1559
  :
1560
  '?'
1561
  ;
1562

    
1563
LPAREN
1564
  :
1565
  '('
1566
  ;
1567

    
1568
RPAREN
1569
  :
1570
  ')'
1571
  ;
1572

    
1573
LBRACK
1574
  :
1575
  '['
1576
  ;
1577

    
1578
RBRACK
1579
  :
1580
  ']'
1581
  ;
1582

    
1583
LCURLY
1584
  :
1585
  '{'
1586
  ;
1587

    
1588
RCURLY
1589
  :
1590
  '}'
1591
  ;
1592

    
1593
COLON
1594
  :
1595
  ':'
1596
  ;
1597

    
1598
COMMA
1599
  :
1600
  ','
1601
  ;
1602

    
1603
DOT
1604
  :
1605
  '.'
1606
  ;
1607

    
1608
ASSIGN
1609
  :
1610
  '='
1611
  ;
1612

    
1613
EQUAL
1614
  :
1615
  '=='
1616
  ;
1617

    
1618
LNOT
1619
  :
1620
  '!'
1621
  ;
1622

    
1623
BNOT
1624
  :
1625
  '~'
1626
  ;
1627

    
1628
NOT_EQUAL
1629
  :
1630
  '!='
1631
  ;
1632

    
1633
DIV
1634
  :
1635
  '/'
1636
  ;
1637

    
1638
DIV_ASSIGN
1639
  :
1640
  '/='
1641
  ;
1642

    
1643
PLUS
1644
  :
1645
  '+'
1646
  ;
1647

    
1648
PLUS_ASSIGN
1649
  :
1650
  '+='
1651
  ;
1652

    
1653
INC
1654
  :
1655
  '++'
1656
  ;
1657

    
1658
MINUS
1659
  :
1660
  '-'
1661
  ;
1662

    
1663
MINUS_ASSIGN
1664
  :
1665
  '-='
1666
  ;
1667

    
1668
DEC
1669
  :
1670
  '--'
1671
  ;
1672

    
1673
STAR
1674
  :
1675
  '*'
1676
  ;
1677

    
1678
STAR_ASSIGN
1679
  :
1680
  '*='
1681
  ;
1682

    
1683
MOD
1684
  :
1685
  '%'
1686
  ;
1687

    
1688
MOD_ASSIGN
1689
  :
1690
  '%='
1691
  ;
1692

    
1693
GT
1694
  :
1695
  '>'
1696
  ;
1697

    
1698
LT
1699
  :
1700
  '<'
1701
  ;
1702

    
1703
BXOR
1704
  :
1705
  '^'
1706
  ;
1707

    
1708
BXOR_ASSIGN
1709
  :
1710
  '^='
1711
  ;
1712

    
1713
BOR
1714
  :
1715
  '|'
1716
  ;
1717

    
1718
BOR_ASSIGN
1719
  :
1720
  '|='
1721
  ;
1722

    
1723
LOR
1724
  :
1725
  '||'
1726
  ;
1727

    
1728
BAND
1729
  :
1730
  '&'
1731
  ;
1732

    
1733
BAND_ASSIGN
1734
  :
1735
  '&='
1736
  ;
1737

    
1738
LAND
1739
  :
1740
  '&&'
1741
  ;
1742

    
1743
SEMI
1744
  :
1745
  ';'
1746
  ;
1747

    
1748
AT
1749
  :
1750
  '@'
1751
  ;
1752

    
1753
ELLIPSIS
1754
  :
1755
  '...'
1756
  ;
1757

    
1758
// Whitespace -- hidden
1759

    
1760
WS
1761
  :
1762
  (
1763
    ' '
1764
    | '\t'
1765
    | '\f'
1766
  )+
1767
  
1768
  {
1769
   $channel = HIDDEN;
1770
  }
1771
  ;
1772

    
1773
// Newlines -- hidden
1774
// (Distinguishing whitespace from newline produces more tokens but gives more control
1775
// in functions that recognize comments and javadocs)
1776

    
1777
NL
1778
  :
1779
  (
1780
    ( options {greedy=true;}: '\r\n' // Evil DOS
1781
      | '\r' // Macintosh
1782
      | '\n' // Unix (the right way)
1783
    )
1784
  )+
1785
  
1786
  {
1787
   $channel = HIDDEN;
1788
  }
1789
  ;
1790

    
1791
COMMENT
1792
@init {
1793
boolean isJavaDoc = false;
1794
}
1795
  :
1796
  ('/*' 
1797
       {
1798
        if ((char) input.LA(1) == '*') {
1799
        	isJavaDoc = true;
1800
        }
1801
       }
1802
    (options {greedy=false;}: .)* '*/' 
1803
                                      {
1804
                                       if (isJavaDoc == true) {
1805
                                       	$type = JAVADOC;
1806
                                       }
1807
                                       $channel = HIDDEN;
1808
                                      })
1809
  |
1810
  (
1811
    '//'
1812
    ~(
1813
      '\n'
1814
      | '\r'
1815
     )*
1816
    (
1817
      '\r\n'
1818
      | '\r'
1819
      | '\n'
1820
    )
1821
    
1822
    {
1823
     $channel = HIDDEN;
1824
    }
1825
    | '//'
1826
    ~(
1827
      '\n'
1828
      | '\r'
1829
     )* // a line comment could appear at the end of the file without CR/LF
1830
    
1831
    {
1832
     $channel = HIDDEN;
1833
    }
1834
  )
1835
  ;
1836

    
1837
// character literals
1838

    
1839
CHAR_LITERAL
1840
  :
1841
  '\''
1842
  (
1843
    ESC
1844
    | ~'\''
1845
  )
1846
  '\''
1847
  ;
1848

    
1849
// string literals
1850

    
1851
STRING_LITERAL
1852
  :
1853
  '"'
1854
  (
1855
    ESC
1856
    |
1857
    ~(
1858
      '"'
1859
      | '\\'
1860
     )
1861
  )*
1862
  '"'
1863
  ;
1864

    
1865
// escape sequence
1866
// There are various ambiguities hushed in this rule.  The optional
1867
// '0'...'9' digit matches should be matched here rather than letting
1868
// them go back to STRING_LITERAL to be matched.  ANTLR does the
1869
// right thing by matching immediately; hence, it's ok to shut off
1870
// the FOLLOW ambig warnings.
1871

    
1872
fragment
1873
ESC
1874
  :
1875
  '\\'
1876
  (
1877
    'n'
1878
    | 'r'
1879
    | 't'
1880
    | 'b'
1881
    | 'f'
1882
    | '\''
1883
    | '"'
1884
    | '\\'
1885
    | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
1886
    | '0'..'3' (options {greedy=true;}: '0'..'7' (options {greedy=true;}: '0'..'7')?)?
1887
    | '4'..'7' (options {greedy=true;}: '0'..'7')?
1888
  )
1889
  ;
1890

    
1891
// binary digit
1892

    
1893
fragment
1894
BIN_DIGIT
1895
  :
1896
  '0'..'1'
1897
  ;
1898

    
1899
fragment
1900
BIN_NUM
1901
  :
1902
  BIN_DIGIT
1903
  ( options {greedy=true;}: BIN_DIGIT
1904
    | '_'
1905
  )*
1906
  ;
1907

    
1908
// decimal digit
1909

    
1910
fragment
1911
DEC_DIGIT
1912
  :
1913
  '0'..'9'
1914
  ;
1915

    
1916
fragment
1917
DEC_NUM
1918
  :
1919
  DEC_DIGIT
1920
  ( options {greedy=true;}: DEC_DIGIT
1921
    | '_'
1922
  )*
1923
  ;
1924

    
1925
// hexadecimal digit (again, note it's fragment!)
1926

    
1927
fragment
1928
HEX_DIGIT
1929
  :
1930
  (
1931
    '0'..'9'
1932
    | 'A'..'F'
1933
    | 'a'..'f'
1934
  )
1935
  ;
1936

    
1937
fragment
1938
HEX_NUM
1939
  :
1940
  HEX_DIGIT
1941
  ( options {greedy=true;}: HEX_DIGIT
1942
    | '_'
1943
  )*
1944
  ;
1945

    
1946
// an identifier
1947

    
1948
IDENT
1949
  :
1950
  (
1951
    'a'..'z'
1952
    | 'A'..'Z'
1953
    | '\u00C0'..'\u00D6'
1954
    | '\u00D8'..'\u00F6'
1955
    | '\u00F8'..'\u00FF'
1956
    | '_'
1957
    | '$'
1958
  )
1959
  (
1960
    'a'..'z'
1961
    | 'A'..'Z'
1962
    | '\u00C0'..'\u00D6'
1963
    | '\u00D8'..'\u00F6'
1964
    | '\u00F8'..'\u00FF'
1965
    | '_'
1966
    | '0'..'9'
1967
    | '$'
1968
  )*
1969
  ;
1970

    
1971
// a numeric literal
1972

    
1973
NUM_LITERAL
1974
  :
1975
  '.' DEC_NUM EXPONENT? FLOAT_SUFFIX? // Note DEC_NUM behind '.' is mandatory
1976
  |
1977
  (
1978
    '0x'
1979
    | '0X'
1980
  )
1981
  HEX_NUM*
1982
  (
1983
    LONG_SUFFIX
1984
    | '.' HEX_NUM*
1985
    (
1986
      'p'
1987
      | 'P'
1988
    )
1989
    (
1990
      '+'
1991
      | '-'
1992
    )?
1993
    DEC_NUM FLOAT_SUFFIX?
1994
  )?
1995
  |
1996
  (
1997
    '0b'
1998
    | '0B'
1999
  )
2000
  BIN_NUM
2001
  | DEC_NUM DEC_END?
2002
  ;
2003

    
2004
fragment
2005
DEC_END
2006
  :
2007
  LONG_SUFFIX
2008
  | '.' DEC_NUM? EXPONENT? FLOAT_SUFFIX? // Note DEC_NUM behind '.' is optionnal
2009
  | EXPONENT FLOAT_SUFFIX?
2010
  | FLOAT_SUFFIX
2011
  ;
2012

    
2013
fragment
2014
EXPONENT
2015
  :
2016
  (
2017
    'e'
2018
    | 'E'
2019
  )
2020
  (
2021
    '+'
2022
    | '-'
2023
  )?
2024
  ('0'..'9')+
2025
  ;
2026

    
2027
fragment
2028
FLOAT_SUFFIX
2029
  :
2030
  'f'
2031
  | 'F'
2032
  | 'd'
2033
  | 'D'
2034
  ;
2035

    
2036
fragment
2037
LONG_SUFFIX
2038
  :
2039
  'l'
2040
  | 'L'
2041
  ;