b33bf1366b65decf0e791d2c094dd969a7b25f13
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.parser / src / main / antlr3 / org / eclipse / linuxtools / ctf / parser / CTFParser.g
1 parser grammar CTFParser;
2
3 options {
4 language = Java;
5 output = AST;
6 ASTLabelType = CommonTree;
7 tokenVocab = CTFLexer;
8 }
9
10 tokens {
11 ROOT;
12
13 EVENT;
14 STREAM;
15 TRACE;
16 ENV;
17 CLOCK;
18 CALLSITE;
19
20 DECLARATION;
21 SV_DECLARATION;
22 TYPE_SPECIFIER_LIST;
23 TYPE_DECLARATOR_LIST;
24 TYPE_DECLARATOR;
25
26 STRUCT;
27 STRUCT_NAME;
28 STRUCT_BODY;
29 ALIGN;
30
31 CTF_EXPRESSION_TYPE;
32 CTF_EXPRESSION_VAL;
33 CTF_LEFT;
34 CTF_RIGHT;
35
36 UNARY_EXPRESSION_STRING;
37 UNARY_EXPRESSION_STRING_QUOTES;
38 UNARY_EXPRESSION_DEC;
39 UNARY_EXPRESSION_HEX;
40 UNARY_EXPRESSION_OCT;
41 LENGTH;
42
43 TYPEDEF;
44
45 TYPEALIAS;
46 TYPEALIAS_TARGET;
47 TYPEALIAS_ALIAS;
48
49 INTEGER;
50 STRING;
51 FLOATING_POINT;
52
53 ENUM;
54 ENUM_CONTAINER_TYPE;
55 ENUM_ENUMERATOR;
56 ENUM_NAME;
57 ENUM_VALUE;
58 ENUM_VALUE_RANGE;
59 ENUM_BODY;
60
61 VARIANT;
62 VARIANT_NAME;
63 VARIANT_TAG;
64 VARIANT_BODY;
65
66 DECLARATOR;
67 LENGTH;
68 }
69
70 /*
71 * Scope for the tracking of types.
72 * For now we just track the names (it's a simple Set), but
73 * later we will have to track the info about the target type.
74 */
75 scope Symbols {
76 Set<String> types;
77 }
78
79 @header {
80 package org.eclipse.linuxtools.ctf.parser;
81 import java.util.Set;
82 import java.util.HashSet;
83 }
84
85 @members {
86 public CTFParser(TokenStream input, boolean verbose) {
87 this(input);
88 this.verbose = verbose;
89 }
90
91 /* To disable automatic error recovery. When we have a mismatched token, simply throw an exception. */
92 @Override
93 protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException {
94 throw new MismatchedTokenException(ttype, input);
95 }
96
97 /**
98 * Checks if a given name has been defined has a type.
99 * From: http://www.antlr.org/grammar/1153358328744/C.g
100 *
101 * @param name The name to check.
102 * @return True if is is a type, false otherwise.
103 */
104 boolean isTypeName(String name) {
105 for (int i = Symbols_stack.size() - 1; i >= 0; i--) {
106 Symbols_scope scope = (Symbols_scope) Symbols_stack.get(i);
107 if (scope.types.contains(name)) {
108 return true;
109 }
110 }
111 return false;
112 }
113
114 void addTypeName(String name) {
115 $Symbols::types.add(name);
116 if (verbose) {
117 debug_print("New type: " + name);
118 }
119 }
120
121 boolean _inTypedef = false;
122
123 void typedefOn() {
124 debug_print("typedefOn");
125 _inTypedef = true;
126 }
127
128 void typedefOff() {
129 debug_print("typedefOff");
130 _inTypedef = false;
131 }
132
133 boolean inTypedef() {
134 return _inTypedef;
135 }
136
137 boolean _inTypealiasAlias = false;
138
139 void typealiasAliasOn() {
140 debug_print("typealiasAliasOn");
141 _inTypealiasAlias = true;
142 }
143
144 void typealiasAliasOff() {
145 debug_print("typealiasAliasOff");
146 _inTypealiasAlias = false;
147 }
148
149 boolean inTypealiasAlias() {
150 return _inTypealiasAlias;
151 }
152
153 void print_tabs(int n) {
154 for (int i = 0; i < n; i++) {
155 System.out.print(" ");
156 }
157 }
158
159 void enter(String name) {
160 if (verbose) {
161 if (state.backtracking == 0) {
162 print_tabs(depth);
163 debug_print("+ " + name);
164 depth++;
165 }
166 }
167 }
168
169 void exit(String name) {
170 if (verbose) {
171 depth--;
172 print_tabs(depth);
173 debug_print("- " + name);
174 }
175 }
176
177 void debug_print(String str) {
178 if (verbose) {
179 System.out.println(str);
180 }
181 }
182
183 int depth = 0;
184
185 /* Prints rule entry and exit while parsing */
186 boolean verbose = false;
187 }
188
189 /* To disable automatic error recovery. By default, the catch block of every rule simple rethrows the error. */
190 @rulecatch {
191 catch (RecognitionException e) {
192 throw e;
193 }
194 }
195
196 /* The top-level rule. */
197 parse
198 scope Symbols;
199 @init {
200 enter("parse");
201 debug_print("Scope push " + Symbols_stack.size());
202 $Symbols::types = new HashSet<String>();
203 }
204 @after {
205 debug_print("Scope pop " + Symbols_stack.size());
206 exit("parse");
207
208 debug_print("Final depth, should be 0: " + depth);
209 }
210 : declaration+ EOF -> ^(ROOT declaration+)
211 ;
212
213 numberLiteral
214 @init {
215 enter("numberLiteral");
216 }
217 @after {
218 debug_print($numberLiteral.text);
219 exit("numberLiteral");
220 }
221 : SIGN* (HEX_LITERAL -> ^(UNARY_EXPRESSION_HEX HEX_LITERAL SIGN*)
222 | DECIMAL_LITERAL -> ^(UNARY_EXPRESSION_DEC DECIMAL_LITERAL SIGN*)
223 | OCTAL_LITERAL -> ^(UNARY_EXPRESSION_OCT OCTAL_LITERAL SIGN*))
224 ;
225
226 constant
227 @init {
228 enter("constant");
229 }
230 @after {
231 exit("constant");
232 }
233 : numberLiteral
234 | enumConstant
235 | CHARACTER_LITERAL
236 ;
237
238 primaryExpression
239 @init {
240 enter("primaryExpression");
241 }
242 @after {
243 exit("primaryExpression");
244 }
245 : (IDENTIFIER) => IDENTIFIER
246 { debug_print("IDENTIFIER: " + $IDENTIFIER.text); }
247 -> ^(UNARY_EXPRESSION_STRING IDENTIFIER)
248 | (ctfKeyword) => ctfKeyword -> ^(UNARY_EXPRESSION_STRING ctfKeyword)
249 | (STRING_LITERAL) => STRING_LITERAL
250 { debug_print("STRING_LITERAL: " + $STRING_LITERAL.text); }
251 -> ^(UNARY_EXPRESSION_STRING_QUOTES STRING_LITERAL)
252 /*| (LPAREN unaryExpression RPAREN)*/ // Not supported yet
253 | constant
254 ;
255
256 reference
257 @init {
258 enter("reference");
259 }
260 @after {
261 debug_print($reference.text);
262 exit("reference");
263 }
264 : (ref=DOT | ref=ARROW) IDENTIFIER -> ^($ref ^(UNARY_EXPRESSION_STRING IDENTIFIER))
265 ;
266
267 postfixExpressionSuffix
268 @init {
269 enter("postfixExpressionSuffix");
270 }
271 @after {
272 exit("postfixExpressionSuffix");
273 }
274 : (OPENBRAC unaryExpression CLOSEBRAC!)
275 | reference
276 ;
277
278 postfixExpression
279 @init {
280 enter("postfixExpression");
281 }
282 @after {
283 exit("postfixExpression");
284 }
285 : (primaryExpression) (postfixExpressionSuffix)*
286 | ((ctfSpecifierHead) (postfixExpressionSuffix)+) // added for ctf-v1.8
287 ;
288
289 unaryExpression
290 @init {
291 enter("unaryExpression");
292 }
293 @after {
294 exit("unaryExpression");
295 }
296 : postfixExpression
297 /* | ((SIGN postfixExpression[true]) | postfixExpression[false]) */
298 ;
299
300 enumConstant
301 @init {
302 enter("enumConstant");
303 }
304 @after {
305 debug_print($enumConstant.text);
306 exit("enumConstant");
307 }
308 : STRING_LITERAL -> ^(UNARY_EXPRESSION_STRING_QUOTES STRING_LITERAL)
309 | IDENTIFIER -> ^(UNARY_EXPRESSION_STRING IDENTIFIER)
310 | ctfKeyword -> ^(UNARY_EXPRESSION_STRING ctfKeyword)
311 ;
312 // 2.2
313
314 declaration
315 @init {
316 enter("declaration");
317 }
318 @after {
319 exit("declaration");
320 if (inTypedef()) {
321 typedefOff();
322 }
323 }
324 : (declarationSpecifiers declaratorList? TERM)
325 // When the declaration is completely parsed and was a typedef,
326 // we add the declarators to the symbol table.
327 -> {inTypedef()}? ^(DECLARATION ^(TYPEDEF declaratorList declarationSpecifiers))
328 -> ^(DECLARATION declarationSpecifiers declaratorList?)
329 | (ctfSpecifier TERM!)
330 ;
331
332 declarationSpecifiers
333 @init {
334 enter("declarationSpecifiers");
335 }
336 @after {
337 debug_print($declarationSpecifiers.text);
338 exit("declarationSpecifiers");
339 }
340 : (
341 // We don't want to keep the typedef keyword in the specifier list.
342 // Instead, we keep track that we encountered a typedef in the declaration.
343 storageClassSpecifier
344 | typeQualifier
345 | typeSpecifier
346 )+ -> ^(TYPE_SPECIFIER_LIST typeQualifier* typeSpecifier*)
347 ;
348
349 declaratorList
350 @init {
351 enter("declaratorList");
352 }
353 @after {
354 exit("declaratorList");
355 }
356 : declarator (SEPARATOR declarator)* -> ^(TYPE_DECLARATOR_LIST declarator+)
357 ;
358
359 abstractDeclaratorList
360 @init {
361 enter("abstractDeclaratorList");
362 }
363 @after {
364 exit("abstractDeclaratorList");
365 }
366 : abstractDeclarator (SEPARATOR abstractDeclarator)*
367 -> ^(TYPE_DECLARATOR_LIST abstractDeclarator+)
368 ;
369
370 storageClassSpecifier
371 : TYPEDEFTOK { typedefOn(); }
372 ;
373
374 typeSpecifier
375 @init {
376 enter("typeSpecifier");
377 }
378 @after {
379 debug_print($typeSpecifier.text);
380 exit("typeSpecifier");
381 }
382 : FLOATTOK
383 | INTTOK
384 | LONGTOK
385 | SHORTTOK
386 | SIGNEDTOK
387 | UNSIGNEDTOK
388 | CHARTOK
389 | DOUBLETOK
390 | VOIDTOK
391 | BOOLTOK
392 | COMPLEXTOK
393 | IMAGINARYTOK
394 | structSpecifier
395 | variantSpecifier
396 | enumSpecifier
397 | ctfTypeSpecifier
398 | { inTypealiasAlias() || isTypeName(input.LT(1).getText()) }? => typedefName
399 ;
400
401 typeQualifier
402 @init {
403 enter("typeQualifier");
404 }
405 @after {
406 debug_print($typeQualifier.text);
407 exit("typeQualifier");
408 }
409 : CONSTTOK
410 ;
411
412 alignAttribute
413 : ALIGNTOK LPAREN unaryExpression RPAREN -> ^(ALIGN unaryExpression)
414 ;
415
416 // you can have an empty struct but not an empty variant
417 structBody
418 scope Symbols;
419 @init {
420 enter("structBody");
421 debug_print("Scope push " + Symbols_stack.size());
422 $Symbols::types = new HashSet<String>();
423 }
424 @after {
425 debug_print("Scope pop " + Symbols_stack.size());
426 exit("structBody");
427 }
428 : LCURL structOrVariantDeclarationList? RCURL
429 -> ^(STRUCT_BODY structOrVariantDeclarationList?)
430 ;
431
432 structSpecifier
433 @init {
434 enter("structSpecifier");
435 }
436 @after {
437 exit("structSpecifier");
438 }
439 : STRUCTTOK
440 (
441 // We have an IDENTIFIER after 'struct'
442 (
443 structName
444 (
445 alignAttribute
446 |
447 (
448 structBody
449 ( /* structBody can return an empty tree, so we need those ? */
450 alignAttribute
451 |
452 /* empty */
453 )
454 )
455 |
456 /* empty */
457 )
458 )
459 |
460 // We have a body after 'struct'
461 (
462 structBody
463 (
464 alignAttribute
465 |
466 /* empty */
467 )
468 )
469 ) -> ^(STRUCT structName? structBody? alignAttribute?)
470 ;
471
472 structName
473 @init {
474 enter("structName");
475 }
476 @after {
477 debug_print($structName.text);
478 exit("structName");
479 }
480 : IDENTIFIER -> ^(STRUCT_NAME IDENTIFIER)
481 ;
482
483 structOrVariantDeclarationList
484 @init {
485 enter("structOrVariantDeclarationList");
486 }
487 @after {
488 exit("structOrVariantDeclarationList");
489 }
490 : structOrVariantDeclaration+
491 ;
492
493 structOrVariantDeclaration
494 @init {
495 enter("structOrVariantDeclaration");
496 }
497 @after {
498 exit("structOrVariantDeclaration");
499 }
500 :
501 (
502 (
503 declarationSpecifiers
504 (
505 /* If we met a "typedef" */
506 {inTypedef()}? => declaratorList {typedefOff();}
507 -> ^(TYPEDEF declaratorList declarationSpecifiers)
508 | structOrVariantDeclaratorList
509 -> ^(SV_DECLARATION declarationSpecifiers structOrVariantDeclaratorList)
510 )
511 )
512 |
513 // Lines 3 and 4
514 typealiasDecl -> typealiasDecl
515 )
516 TERM
517 ;
518
519 specifierQualifierList
520 @init {
521 enter("specifierQualifierList");
522 }
523 @after {
524 exit("specifierQualifierList");
525 }
526 : (typeQualifier | typeSpecifier)+
527 -> ^(TYPE_SPECIFIER_LIST typeQualifier* typeSpecifier*)
528 ;
529
530 structOrVariantDeclaratorList
531 @init {
532 enter("structOrVariantDeclaratorList");
533 }
534 @after {
535 exit("structOrVariantDeclaratorList");
536 }
537 : structOrVariantDeclarator (SEPARATOR structOrVariantDeclarator)*
538 -> ^(TYPE_DECLARATOR_LIST structOrVariantDeclarator+)
539 ;
540
541 structOrVariantDeclarator
542 @init {
543 enter("structOrVariantDeclarator");
544 }
545 @after {
546 exit("structOrVariantDeclarator");
547 }
548 :
549 /* Bitfields not supported yet */
550 (declarator (COLON numberLiteral)?) -> declarator
551 /*| (COLON numberLiteral)*/
552 ;
553
554 variantSpecifier
555 @init {
556 enter("variantSpecifier");
557 }
558 @after {
559 exit("variantSpecifier");
560 }
561 :
562 VARIANTTOK
563 (
564 (
565 variantName
566 (
567 (
568 variantTag
569 (
570 variantBody
571 |
572 /* empty */
573 )
574 )
575 |
576 variantBody
577 )
578 )
579 |
580 (variantTag variantBody)
581 |
582 variantBody
583 ) -> ^(VARIANT variantName? variantTag? variantBody?)
584 ;
585
586 variantName
587 @init {
588 enter("variantName");
589 }
590 @after {
591 debug_print($variantName.text);
592 exit("variantName");
593 }
594 : IDENTIFIER -> ^(VARIANT_NAME IDENTIFIER)
595 ;
596
597 variantBody
598 scope Symbols;
599 @init {
600 enter("variantBody");
601 debug_print("Scope push " + Symbols_stack.size());
602 $Symbols::types = new HashSet<String>();
603 }
604 @after {
605 debug_print("Scope pop " + Symbols_stack.size());
606 exit("variantBody");
607 }
608 : LCURL structOrVariantDeclarationList RCURL
609 -> ^(VARIANT_BODY structOrVariantDeclarationList)
610 ;
611
612 variantTag
613 @init {
614 enter("variantTag");
615 }
616 @after {
617 debug_print($variantTag.text);
618 exit("variantTag");
619 }
620 : LT IDENTIFIER GT -> ^(VARIANT_TAG IDENTIFIER)
621 ;
622
623 enumSpecifier
624 @init {
625 enter("enumSpecifier");
626 }
627 @after {
628 exit("enumSpecifier");
629 }
630 :
631 ENUMTOK
632 (
633 // Lines 1 to 5, when we have "ENUMTOK IDENTIFIER".
634 (
635 enumName
636 (
637 enumContainerType enumBody
638 |
639 enumBody
640 |
641 // no enumDeclarator or enumBodym
642 )
643 )
644 |
645 // Lines 1, 2, 4, 5, when we have no IDENTIFIER.
646 (
647 enumContainerType enumBody
648 |
649 enumBody
650 )
651 ) -> ^(ENUM enumName? enumContainerType? enumBody?)
652 ;
653
654 enumName
655 @init {
656 enter("enumName");
657 }
658 @after {
659 debug_print($enumName.text);
660 exit("enumName");
661 }
662 :
663 IDENTIFIER -> ^(ENUM_NAME IDENTIFIER)
664 ;
665
666 enumBody
667 @init {
668 enter("enumBody");
669 }
670 @after {
671 exit("enumBody");
672 }
673 : LCURL enumeratorList (SEPARATOR RCURL | RCURL) -> ^(ENUM_BODY enumeratorList)
674 ;
675
676 enumContainerType
677 @init {
678 enter("enumContainerType");
679 }
680 @after {
681 exit("enumContainerType");
682 }
683 : COLON declarationSpecifiers -> ^(ENUM_CONTAINER_TYPE declarationSpecifiers)
684 ;
685
686 enumeratorList
687 @init {
688 enter("enumeratorList");
689 }
690 @after {
691 exit("enumeratorList");
692 }
693 : enumerator (SEPARATOR enumerator)* -> (^(ENUM_ENUMERATOR enumerator))+
694 ;
695
696 enumerator
697 @init {
698 enter("enumerator");
699 }
700 @after {
701 exit("enumerator");
702 }
703 : enumConstant enumeratorValue?
704 ;
705
706 enumeratorValue
707 @init {
708 enter("enumeratorValue");
709 }
710 @after {
711 exit("enumeratorValue");
712 }
713 : ASSIGNMENT e1=unaryExpression
714 (
715 -> ^(ENUM_VALUE $e1)
716 | ELIPSES e2=unaryExpression -> ^(ENUM_VALUE_RANGE $e1 $e2)
717 )
718 ;
719
720
721 declarator
722 @init {
723 enter("declarator");
724 }
725 @after {
726 exit("declarator");
727 }
728 : pointer* directDeclarator -> ^(TYPE_DECLARATOR pointer* directDeclarator)
729 ;
730
731 directDeclarator
732 @init {
733 enter("directDeclarator");
734 }
735 @after {
736 exit("directDeclarator");
737 }
738 : (
739 IDENTIFIER
740 { if (inTypedef()) addTypeName($IDENTIFIER.text); }
741 { debug_print($IDENTIFIER.text); }
742 /*| LPAREN declarator RPAREN*/ /* Not supported yet */
743 )
744 directDeclaratorSuffix*
745 ;
746
747 directDeclaratorSuffix
748 : OPENBRAC directDeclaratorLength CLOSEBRAC -> ^(LENGTH directDeclaratorLength)
749 ;
750
751 directDeclaratorLength
752 : unaryExpression
753 ;
754
755 abstractDeclarator
756 @init {
757 enter("abstractDeclarator");
758 }
759 @after {
760 exit("abstractDeclarator");
761 }
762 : (pointer+ directAbstractDeclarator?)
763 -> ^(TYPE_DECLARATOR pointer+ directAbstractDeclarator?)
764 | directAbstractDeclarator
765 -> ^(TYPE_DECLARATOR directAbstractDeclarator)
766 ;
767
768 /*
769 In the CTF grammar, direct-abstract-declarator can be empty (because of identifier-opt).
770 We take care of that by appending a '?' to each use of "abstractDeclaratorList".
771 */
772 directAbstractDeclarator
773 @init {
774 enter("directAbstractDeclarator");
775 }
776 @after {
777 debug_print($directAbstractDeclarator.text);
778 exit("directAbstractDeclarator");
779 }
780 : (
781 IDENTIFIER
782 | (LPAREN abstractDeclarator RPAREN)
783 ) (
784 OPENBRAC unaryExpression? CLOSEBRAC
785 )?
786 ;
787
788 pointer
789 @init {
790 enter("pointer");
791 }
792 @after {
793 debug_print($pointer.text);
794 exit("pointer");
795 }
796 : POINTER typeQualifierList? -> ^(POINTER typeQualifierList?)
797 ;
798
799 typeQualifierList
800 : typeQualifier+
801 ;
802
803 typedefName
804 @init {
805 enter("typedefName");
806 }
807 @after {
808 debug_print("typedefName: " + $typedefName.text);
809 exit("typedefName");
810 }
811 :
812 {inTypealiasAlias() || isTypeName(input.LT(1).getText())}? IDENTIFIER { if ((inTypedef() || inTypealiasAlias()) && !isTypeName($IDENTIFIER.text)) { addTypeName($IDENTIFIER.text); } }
813 ;
814
815 /**
816 * What goes in the target part of a typealias.
817 *
818 * For example, the integer part in:
819 * typealias integer {...} := my_new_integer;
820 */
821 typealiasTarget
822 @init {
823 enter("typealiasTarget");
824 }
825 @after {
826 exit("typealiasTarget");
827 }
828 : declarationSpecifiers abstractDeclaratorList?
829 ;
830
831 /**
832 * What goes in the alias part of a typealias.
833 *
834 * For example, the my_new_integer part in:
835 * typealias integer {...} := my_new_integer;
836 */
837 typealiasAlias
838 @init {
839 enter("typealiasAlias");
840 typealiasAliasOn();
841 }
842 @after {
843 exit("typealiasAlias");
844 typealiasAliasOff();
845 }
846 : ( abstractDeclaratorList
847 | (declarationSpecifiers abstractDeclaratorList?)
848 )
849 ;
850
851 typealiasDecl
852 @init {
853 enter("typealiasDecl");
854 }
855 @after {
856 exit("typealiasDecl");
857 }
858 : TYPEALIASTOK typealiasTarget TYPE_ASSIGNMENT typealiasAlias
859 -> ^(TYPEALIAS ^(TYPEALIAS_TARGET typealiasTarget) ^(TYPEALIAS_ALIAS typealiasAlias))
860 ;
861
862 // 2.3 CTF stuff
863
864 // TODO: Ajouter ceux qui manquent
865 ctfKeyword
866 @init {
867 enter("ctfKeyword");
868 }
869 @after {
870 debug_print($ctfKeyword.text);
871 exit("ctfKeyword");
872 }
873 : ALIGNTOK
874 | EVENTTOK
875 | SIGNEDTOK
876 | STRINGTOK
877 ;
878
879 ctfSpecifier
880 @init {
881 enter("ctfSpecifier");
882 }
883 @after {
884 exit("ctfSpecifier");
885 }
886 // event {...}, stream {...}, trace {...}
887 : ctfSpecifierHead ctfBody -> ^(ctfSpecifierHead ctfBody)
888 // typealias
889 | typealiasDecl -> ^(DECLARATION typealiasDecl)
890 ;
891
892 ctfSpecifierHead
893 @init {
894 enter("ctfSpecifierHead");
895 }
896 @after {
897 debug_print($ctfSpecifierHead.text);
898 exit("ctfSpecifierHead");
899 }
900 : EVENTTOK -> EVENT
901 | STREAMTOK -> STREAM
902 | TRACETOK -> TRACE
903 | ENVTOK -> ENV
904 | CLOCKTOK -> CLOCK
905 | CALLSITETOK -> CALLSITE
906 ;
907
908 ctfTypeSpecifier
909 @init {
910 enter("ctfTypeSpecifier");
911 }
912 @after {
913 exit("ctfTypeSpecifier");
914 }
915 /* ctfBody can return an empty tree if the body is empty */
916 : FLOATINGPOINTTOK ctfBody -> ^(FLOATING_POINT ctfBody?)
917 | INTEGERTOK ctfBody -> ^(INTEGER ctfBody?)
918 | STRINGTOK ctfBody? -> ^(STRING ctfBody?)
919 ;
920
921 ctfBody
922 scope Symbols;
923 @init {
924 enter("ctfBody");
925 debug_print("Scope push " + + Symbols_stack.size());
926 $Symbols::types = new HashSet<String>();
927 }
928 @after {
929 debug_print("Scope pop " + + Symbols_stack.size());
930 exit("ctfBody");
931 }
932 : LCURL ctfAssignmentExpressionList? RCURL -> ctfAssignmentExpressionList?
933 ;
934
935 ctfAssignmentExpressionList
936 : (ctfAssignmentExpression TERM!)+
937 ;
938
939 ctfAssignmentExpression
940 @init {
941 enter("ctfAssignmentExpression");
942 }
943 @after {
944 if (inTypedef()) {
945 typedefOff();
946 }
947 exit("ctfAssignmentExpression");
948 }
949 :
950 (
951 left=unaryExpression
952 (
953 (assignment=ASSIGNMENT right1=unaryExpression) -> ^(CTF_EXPRESSION_VAL ^(CTF_LEFT $left) ^(CTF_RIGHT $right1))
954 | (type_assignment=TYPE_ASSIGNMENT right2=typeSpecifier) -> ^(CTF_EXPRESSION_TYPE ^(CTF_LEFT $left) ^(CTF_RIGHT ^(TYPE_SPECIFIER_LIST $right2)))
955 )
956 )
957
958 |
959
960 (declarationSpecifiers {inTypedef()}? declaratorList)
961 -> ^(TYPEDEF declaratorList declarationSpecifiers)
962 |
963
964 typealiasDecl
965 ;
This page took 0.052988 seconds and 4 git commands to generate.