1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3        Copyright (c) Non, Inc. 1998 -- All Rights Reserved
4
5PROJECT:        C Compiler
6MODULE:         GnuCEmitter
7FILE:           GnuCEmitter.g
8
9AUTHOR:         Monty Zukowski (jamz@cdsnet.net) April 28, 1998
10
11DESCRIPTION:
12
13                This tree grammar is for a Gnu C AST.
14                It turns the tree back into source code.
15
16%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
17
18
19header {
20        package com.sun.gluegen.cgram;
21
22        import java.io.*;
23        import java.util.*;
24
25        import antlr.CommonAST;
26        import antlr.DumpASTVisitor;
27}
28
29
30class GnuCEmitter extends GnuCTreeParser;
31
32options
33        {
34        importVocab = GNUC;
35        buildAST = false;
36        ASTLabelType = "TNode";
37
38        // Copied following options from java grammar.
39        codeGenMakeSwitchThreshold = 2;
40        codeGenBitsetTestThreshold = 3;
41        }
42
43
44{
45
46
47int tabs = 0;
48PrintStream currentOutput = System.out;
49int lineNum = 1;
50String currentSource = "";
51LineObject trueSourceFile;
52final int lineDirectiveThreshold = Integer.MAX_VALUE;
53PreprocessorInfoChannel preprocessorInfoChannel = null;
54Stack sourceFiles = new Stack();
55
56public GnuCEmitter( PreprocessorInfoChannel preprocChannel )
57{
58        preprocessorInfoChannel = preprocChannel;
59}
60
61void initializePrinting()
62{
63    Vector preprocs = preprocessorInfoChannel.extractLinesPrecedingTokenNumber( new Integer(1) );
64    printPreprocs(preprocs);
65/*    if ( currentSource.equals("") ) {
66        trueSourceFile = new LineObject(currentSource);
67        currentOutput.println("# 1 \"" + currentSource + "\"\n");
68        sourceFiles.push(trueSourceFile);
69    }
70*/
71}
72
73void finalizePrinting() {
74    // flush any leftover preprocessing instructions to the stream
75
76    printPreprocs(
77        preprocessorInfoChannel.extractLinesPrecedingTokenNumber(
78                new Integer( preprocessorInfoChannel.getMaxTokenNumber() + 1 ) ));
79    //print a newline so file ends at a new line
80    currentOutput.println();
81}
82
83void printPreprocs( Vector preprocs )
84{
85    // if there was a preprocessingDirective previous to this token then
86    // print a newline and the directive, line numbers handled later
87    if ( preprocs.size() > 0 ) {
88        if ( trueSourceFile != null ) {
89            currentOutput.println();  //make sure we're starting a new line unless this is the first line directive
90        }
91        lineNum++;
92        Enumeration e = preprocs.elements();
93        while (e.hasMoreElements())
94        {
95            Object o = e.nextElement();
96            if ( o.getClass().getName().equals("LineObject") ) {
97                LineObject l = (LineObject) o;
98
99                // we always return to the trueSourceFile, we never enter it from another file
100                // force it to be returning if in fact we aren't currently in trueSourceFile
101                if (( trueSourceFile != null ) //trueSource exists
102                        && ( !currentSource.equals(trueSourceFile.getSource()) ) //currently not in trueSource
103                        && ( trueSourceFile.getSource().equals(l.getSource())  ) ) { //returning to trueSource
104                    l.setEnteringFile( false );
105                    l.setReturningToFile( true );
106                }
107
108
109                // print the line directive
110                currentOutput.println(l);
111                lineNum = l.getLine();
112                currentSource = l.getSource();
113
114
115                // the very first line directive always represents the true sourcefile
116                if ( trueSourceFile == null ) {
117                    trueSourceFile = new LineObject(currentSource);
118                    sourceFiles.push(trueSourceFile);
119                }
120
121                // keep our own stack of files entered
122                if ( l.getEnteringFile() ) {
123                    sourceFiles.push(l);
124                }
125
126                // if returning to a file, pop the exited files off the stack
127                if ( l.getReturningToFile() ) {
128                    LineObject top = (LineObject) sourceFiles.peek();
129                    while (( top != trueSourceFile ) && (! l.getSource().equals(top.getSource()) )) {
130                        sourceFiles.pop();
131                        top = (LineObject) sourceFiles.peek();
132                    }
133                }
134            }
135            else { // it was a #pragma or such
136                currentOutput.println(o);
137                lineNum++;
138            }
139        }
140    }
141
142}
143
144void print( TNode t ) {
145    int tLineNum = t.getLocalLineNum();
146    if ( tLineNum == 0 ) tLineNum = lineNum;
147
148    Vector preprocs = preprocessorInfoChannel.extractLinesPrecedingTokenNumber((Integer)t.getAttribute("tokenNumber"));
149    printPreprocs(preprocs);
150
151    if ( (lineNum != tLineNum) ) {
152        // we know we'll be newlines or a line directive or it probably
153        // is just the case that this token is on the next line
154        // either way start a new line and indent it
155        currentOutput.println();
156        lineNum++;
157        printTabs();
158    }
159
160    if ( lineNum == tLineNum ){
161        // do nothing special, we're at the right place
162    }
163    else {
164        int diff = tLineNum - lineNum;
165        if ( lineNum < tLineNum ) {
166            // print out the blank lines to bring us up to right line number
167            for ( ; lineNum < tLineNum ; lineNum++ ) {
168                currentOutput.println();
169            }
170            printTabs();
171        }
172        else { // just reset lineNum
173            lineNum = tLineNum;
174        }
175    }
176    currentOutput.print( t.getText() + " " );
177}
178
179
180/* This was my attempt at being smart about line numbers
181   It didn't work quite right but I don't know why, I didn't
182   have enough test cases.  Worked ok compiling rcs and ghostscript
183*/
184void printAddingLineDirectives( TNode t ) {
185    int tLineNum = t.getLocalLineNum();
186    String tSource = (String) t.getAttribute("source");
187
188    if ( tSource == null ) tSource = currentSource;
189    if ( tLineNum == 0 ) tLineNum = lineNum;
190
191    Vector preprocs = preprocessorInfoChannel.extractLinesPrecedingTokenNumber((Integer)t.getAttribute("tokenNumber"));
192    printPreprocs(preprocs);
193
194    if ( (lineNum != tLineNum) || !currentSource.equals(tSource) ) {
195        // we know we'll be newlines or a line directive or it probably
196        // is just the case that this token is on the next line
197        // either way start a new line and indent it
198        currentOutput.println();
199        lineNum++;
200        printTabs();
201    }
202
203    if ( ( lineNum == tLineNum ) && ( currentSource.equals(tSource) ) ){
204        // do nothing special, we're at the right place
205    }
206    else if ( currentSource.equals(tSource) ) {
207        int diff = tLineNum - lineNum;
208        if (diff > 0 && diff < lineDirectiveThreshold) {
209            // print out the blank lines to bring us up to right line number
210            for ( ; lineNum < tLineNum ; lineNum++ ) {
211                currentOutput.println();
212            }
213        }
214        else { // print line directive to get us to right line number
215            // preserve flags 3 and 4 if present in current file
216            if ( ! sourceFiles.empty() ) {
217                LineObject l = (LineObject) sourceFiles.peek();
218                StringBuffer tFlags = new StringBuffer("");
219                if (l.getSystemHeader()) {
220                    tFlags.append(" 3");
221                }
222                if (l.getTreatAsC()) {
223                    tFlags.append(" 4");
224                }
225                currentOutput.println("# " + tLineNum + " \"" + tSource + "\"" + tFlags.toString());
226                lineNum = tLineNum;
227            }
228        }
229
230        printTabs();
231    }
232    else { // different source
233        Enumeration sources = sourceFiles.elements();
234        // see if we're returning to a file we entered earlier
235        boolean returningToEarlierFile = false;
236        while (sources.hasMoreElements()) {
237            LineObject l = (LineObject) sources.nextElement();
238            if (l.getSource().equals(tSource)) {
239                returningToEarlierFile = true;
240                break;
241            }
242        }
243        if (returningToEarlierFile) {
244            // pop off the files we're exiting, but never pop the trueSourceFile
245            LineObject l = (LineObject) sourceFiles.peek();
246            while ( ( l != trueSourceFile ) &&(! l.getSource().equals(tSource) ) ) {
247                sourceFiles.pop();
248                l = (LineObject) sourceFiles.peek();
249            }
250
251            // put in the return flag, plus others as needed
252            StringBuffer tFlags = new StringBuffer(" 2");
253            if (l.getSystemHeader()) {
254                tFlags.append(" 3");
255            }
256            if (l.getTreatAsC()) {
257                tFlags.append(" 4");
258            }
259
260            currentOutput.println("# " + tLineNum + " \"" + tSource + "\"" + tFlags);
261            lineNum = tLineNum;
262            currentSource = tSource;
263            printTabs();
264        }
265        else {  // entering a file that wasn't in the original source
266                // pretend we're entering it from top of stack
267            currentOutput.println("# " + tLineNum + " \"" + tSource + "\"" + " 1");
268            lineNum = tLineNum;
269            currentSource = tSource;
270            printTabs();
271        }
272    }
273    currentOutput.print( t.getText() + " " );
274}
275
276/** It is not ok to print newlines from the String passed in as
277it will screw up the line number handling **/
278void print( String s ) {
279    currentOutput.print( s + " " );
280}
281
282void printTabs() {
283    for ( int i = 0; i< tabs; i++ ) {
284        currentOutput.print( "\t" );
285    }
286}
287
288void commaSep( TNode t ) {
289    print( t );
290    if ( t.getNextSibling() != null ) {
291        print( "," );
292    }
293}
294
295        int traceDepth = 0;
296        public void reportError(RecognitionException ex) {
297          if ( ex != null)   {
298                System.err.println("ANTLR Tree Parsing RecognitionException Error: " + ex.getClass().getName() + " " + ex );
299                ex.printStackTrace(System.err);
300          }
301        }
302        public void reportError(NoViableAltException ex) {
303                System.err.println("ANTLR Tree Parsing NoViableAltException Error: " + ex.toString());
304                TNode.printTree( ex.node );
305                ex.printStackTrace(System.err);
306        }
307        public void reportError(MismatchedTokenException ex) {
308          if ( ex != null)   {
309                TNode.printTree( ex.node );
310                System.err.println("ANTLR Tree Parsing MismatchedTokenException Error: " + ex );
311                ex.printStackTrace(System.err);
312          }
313        }
314        public void reportError(String s) {
315                System.err.println("ANTLR Error from String: " + s);
316        }
317        public void reportWarning(String s) {
318                System.err.println("ANTLR Warning from String: " + s);
319        }
320        protected void match(AST t, int ttype) throws MismatchedTokenException {
321                //System.out.println("match("+ttype+"); cursor is "+t);
322                super.match(t, ttype);
323        }
324        public void match(AST t, BitSet b) throws MismatchedTokenException {
325                //System.out.println("match("+b+"); cursor is "+t);
326                super.match(t, b);
327        }
328        protected void matchNot(AST t, int ttype) throws MismatchedTokenException {
329                //System.out.println("matchNot("+ttype+"); cursor is "+t);
330                super.matchNot(t, ttype);
331                }
332        public void traceIn(String rname, AST t) {
333          traceDepth += 1;
334          for (int x=0; x<traceDepth; x++) System.out.print(" ");
335          super.traceIn(rname, t);
336        }
337        public void traceOut(String rname, AST t) {
338          for (int x=0; x<traceDepth; x++) System.out.print(" ");
339          super.traceOut(rname, t);
340          traceDepth -= 1;
341        }
342
343
344
345}
346
347
348translationUnit  options {
349  defaultErrorHandler=false;
350}
351        :
352                                { initializePrinting(); }
353               ( externalList )?
354                                { finalizePrinting(); }
355        ;
356/*
357exception
358catch [RecognitionException ex]
359                        {
360                        reportError(ex);
361                        System.out.println("PROBLEM TREE:\n"
362                                                + _t.toStringList());
363                        if (_t!=null) {_t = _t.getNextSibling();}
364                        }
365*/
366
367
368externalList
369        :       ( externalDef )+
370        ;
371
372
373externalDef
374        :       declaration
375        |       functionDef
376        |       asm_expr
377        |       typelessDeclaration
378        |       s:SEMI                          { print( s ); }
379        ;
380
381typelessDeclaration
382        :       #(NTypeMissing initDeclList s: SEMI)    { print( s ); }
383        ;
384
385
386
387asm_expr
388        :       #( a:"asm"                              { print( a ); }
389                 ( v:"volatile"                         { print( v ); }
390                 )?
391                    lc:LCURLY                           { print( lc ); tabs++; }
392                    expr
393                    rc:RCURLY                           { tabs--; print( rc ); }
394                    s:SEMI                              { print( s ); }
395                )
396        ;
397
398
399declaration
400        :       #( NDeclaration
401                    declSpecifiers
402                    (
403                        initDeclList
404                    )?
405                    ( s:SEMI { print( s ); } )+
406                )
407        ;
408
409
410declSpecifiers
411        :       ( storageClassSpecifier
412                | typeQualifier
413                | typeSpecifier
414                )+
415        ;
416
417storageClassSpecifier
418        :       a:"auto"                                { print( a ); }
419        |       b:"register"                    { print( b ); }
420        |       c:"typedef"                     { print( c ); }
421        |       functionStorageClassSpecifier
422        ;
423
424
425functionStorageClassSpecifier
426        :       a:"extern"                      { print( a ); }
427        |       b:"static"                      { print( b ); }
428        |       c:"inline"                      { print( c ); }
429        ;
430
431
432typeQualifier
433        :       a:"const"                       { print( a ); }
434        |       b:"volatile"                    { print( b ); }
435        ;
436
437
438typeSpecifier
439        :       a:"void"                        { print( a ); }
440        |       b:"char"                        { print( b ); }
441        |       c:"short"                       { print( c ); }
442        |       d:"int"                         { print( d ); }
443        |       e:"long"                        { print( e ); }
444        |       f:"float"                       { print( f ); }
445        |       g:"double"                      { print( g ); }
446        |       h:"signed"                      { print( h ); }
447        |       i:"unsigned"                    { print( i ); }
448        |       structSpecifier ( attributeDecl )*
449        |       unionSpecifier  ( attributeDecl )*
450        |       enumSpecifier
451        |       typedefName
452        |       #(n:"typeof" lp:LPAREN             { print( n ); print( lp ); }
453                    ( (typeName )=> typeName
454                    | expr
455                    )
456                    rp:RPAREN                      { print( rp ); }
457                )
458        |       p:"__complex"                   { print( p ); }
459        ;
460
461
462typedefName
463        :       #(NTypedefName i:ID         { print( i ); } )
464        ;
465
466
467structSpecifier
468        :   #( a:"struct"                       { print( a ); }
469                structOrUnionBody
470            )
471        ;
472
473unionSpecifier
474        :   #( a:"union"                        { print( a ); }
475                structOrUnionBody
476            )
477        ;
478
479structOrUnionBody
480        :       ( (ID LCURLY) => i1:ID lc1:LCURLY   { print( i1 ); print ( "{" ); tabs++; }
481                        ( structDeclarationList )?
482                        rc1:RCURLY                  { tabs--; print( rc1 ); }
483                |   lc2:LCURLY                      { print( lc2 ); tabs++; }
484                    ( structDeclarationList )?
485                    rc2:RCURLY                      { tabs--; print( rc2 ); }
486                | i2:ID                     { print( i2 ); }
487                )
488        ;
489
490structDeclarationList
491        :       ( structDeclaration             { print( ";" ); }
492                )+
493        ;
494
495
496structDeclaration
497        :       specifierQualifierList structDeclaratorList
498        ;
499
500
501specifierQualifierList
502        :       (
503                typeSpecifier
504                | typeQualifier
505                )+
506        ;
507
508
509structDeclaratorList
510        :       structDeclarator
511                ( { print(","); } structDeclarator )*
512        ;
513
514
515structDeclarator
516        :
517        #( NStructDeclarator
518            ( declarator )?
519            ( c:COLON { print( c ); } expr )?
520            ( attributeDecl )*
521        )
522        ;
523
524
525enumSpecifier
526        :   #(  a:"enum"                        { print( a ); }
527                ( i:ID { print( i ); } )?
528                ( lc:LCURLY                        { print( lc ); tabs++; }
529                    enumList
530                  rc:RCURLY                        { tabs--; print( rc ); }
531                )?
532            )
533        ;
534
535
536enumList
537        :
538		enumerator ( {print(",");} enumerator)*
539        ;
540
541
542enumerator
543        :       i:ID            { print( i ); }
544                ( b:ASSIGN      { print( b ); }
545                  expr
546                )?
547        ;
548
549
550attributeDecl:
551        #( a:"__attribute"            { print( a ); }
552           (b:. { print( b ); } )*
553        )
554        | #( n:NAsmAttribute            { print( n ); }
555             lp:LPAREN                  { print( lp ); }
556             expr                       { print( ")" ); }
557             rp:RPAREN                  { print( rp ); }
558           )
559        ;
560
561initDeclList
562        :       initDecl
563		( { print( "," ); } initDecl )*
564        ;
565
566
567initDecl
568                                        { String declName = ""; }
569        :       #(NInitDecl
570                declarator
571                ( attributeDecl )*
572                ( a:ASSIGN              { print( a ); }
573                  initializer
574                | b:COLON               { print( b ); }
575                  expr
576                )?
577                )
578        ;
579
580
581pointerGroup
582        :       #( NPointerGroup
583                   ( a:STAR             { print( a ); }
584                    ( typeQualifier )*
585                   )+
586                )
587        ;
588
589
590
591idList
592        :       i:ID                            { print( i ); }
593                (  c:COMMA                      { print( c ); }
594                   id:ID                        { print( id ); }
595                )*
596        ;
597
598
599
600initializer
601        :       #( NInitializer (initializerElementLabel)? expr )
602                | lcurlyInitializer
603        ;
604
605initializerElementLabel
606        :   #( NInitializerElementLabel
607                (
608                    ( l:LBRACKET              { print( l ); }
609                        expr
610                        r:RBRACKET            { print( r ); }
611                        (a1:ASSIGN             { print( a1 ); } )?
612                    )
613                    | i1:ID c:COLON           { print( i1 ); print( c ); }
614                    | d:DOT i2:ID a2:ASSIGN      { print( d ); print( i2 ); print( a2 ); }
615                )
616            )
617        ;
618
619lcurlyInitializer
620        :     #(n:NLcurlyInitializer    { print( n ); tabs++; }
621                initializerList
622                rc:RCURLY               { tabs--; print( rc ); }
623                )
624        ;
625
626initializerList
627        :       ( i:initializer { commaSep( i ); }
628                )*
629        ;
630
631
632declarator
633        :   #( NDeclarator
634                ( pointerGroup )?
635
636                ( id:ID                         { print( id ); }
637                | lp:LPAREN { print( lp ); } declarator rp:RPAREN { print( rp ); }
638                )
639
640                (   #( n:NParameterTypeList       { print( n ); }
641                    (
642                        parameterTypeList
643                        | (idList)?
644                    )
645                    r:RPAREN                      { print( r ); }
646                    )
647                 | lb:LBRACKET { print( lb );} ( expr )? rb:RBRACKET { print( rb ); }
648                )*
649             )
650        ;
651
652
653
654parameterTypeList
655        :       ( parameterDeclaration
656                    ( c:COMMA { print( c ); }
657                      | s:SEMI { print( s ); }
658                    )?
659                )+
660                ( v:VARARGS { print( v ); } )?
661        ;
662
663
664
665parameterDeclaration
666        :       #( NParameterDeclaration
667                declSpecifiers
668                (declarator | nonemptyAbstractDeclarator)?
669                )
670        ;
671
672
673functionDef
674        :   #( NFunctionDef
675                ( functionDeclSpecifiers)?
676                declarator
677                (declaration
678                 | v:VARARGS    { print( v ); }
679                )*
680                compoundStatement
681            )
682        ;
683/*
684exception
685catch [RecognitionException ex]
686                        {
687                        reportError(ex);
688                        System.out.println("PROBLEM TREE:\n"
689                                                + _t.toStringList());
690                        if (_t!=null) {_t = _t.getNextSibling();}
691                        }
692*/
693
694functionDeclSpecifiers
695        :
696                ( functionStorageClassSpecifier
697                | typeQualifier
698                | typeSpecifier
699                )+
700        ;
701
702declarationList
703        :
704                (   //ANTLR doesn't know that declarationList properly eats all the declarations
705                    //so it warns about the ambiguity
706                    options {
707                        warnWhenFollowAmbig = false;
708                    } :
709                localLabelDecl
710                |  declaration
711                )+
712        ;
713
714localLabelDecl
715        :   #(a:"__label__"             { print( a ); }
716              ( i:ID                    { commaSep( i ); }
717              )+
718                                        { print( ";" ); }
719            )
720        ;
721
722
723
724compoundStatement
725        :       #( cs:NCompoundStatement                { print( cs ); tabs++; }
726                ( declarationList
727                | functionDef
728                )*
729                ( statementList )?
730                rc:RCURLY                               { tabs--; print( rc ); }
731                )
732
733        ;
734
735statementList
736        :       ( statement )+
737        ;
738
739statement
740        :       statementBody
741        ;
742
743statementBody
744        :       s:SEMI                          { print( s ); }
745
746        |       compoundStatement       // Group of statements
747
748        |       #(NStatementExpr
749                expr                    { print( ";" ); }
750                )                    // Expressions
751
752// Iteration statements:
753
754        |       #( w:"while" { print( w ); print( "(" ); }
755                expr { print( ")" ); }
756                statement )
757
758        |       #( d:"do" { print( d ); }
759                statement
760                        { print( " while ( " ); }
761                expr
762                        { print( " );" ); }
763                )
764
765        |       #( f:"for" { print( f ); print( "(" ); }
766                expr    { print( ";" ); }
767                expr    { print( ";" ); }
768                expr    { print( ")" ); }
769                statement
770                )
771
772
773// Jump statements:
774
775        |       #( g:"goto"             { print( g );}
776                   expr                 { print( ";" ); }
777                )
778        |       c:"continue"            { print( c ); print( ";" );}
779        |       b:"break"               { print( b ); print( ";" );}
780        |       #( r:"return"           { print( r ); }
781                ( expr )?
782                                        { print( ";" ); }
783                )
784
785
786// Labeled statements:
787        |       #( NLabel
788                ni:ID                   { print( ni ); print( ":" ); }
789                ( statement )?
790                )
791
792        |       #(
793                ca:"case"               { print( ca ); }
794                expr                    { print( ":" ); }
795                (statement)?
796                )
797
798        |       #(
799                de:"default"            { print( de ); print( ":" ); }
800                (statement)?
801                )
802
803
804
805// Selection statements:
806
807        |       #( i:"if"               { print( i ); print( "(" ); }
808                 expr                   { print( ")" ); }
809                statement
810                (   e:"else"            { print( e ); }
811                    statement
812                )?
813                )
814        |       #( sw:"switch"          { print( sw ); print( "(" ); }
815                expr                    { print( ")" ); }
816                statement
817                )
818
819
820
821        ;
822/*
823exception
824catch [RecognitionException ex]
825                        {
826                        reportError(ex);
827                        System.out.println("PROBLEM TREE:\n"
828                                                + _t.toStringList());
829                        if (_t!=null) {_t = _t.getNextSibling();}
830                        }
831*/
832
833
834
835
836
837
838expr
839        :
840                binaryExpr
841        |       conditionalExpr
842        |       castExpr
843        |       unaryExpr
844        |       postfixExpr
845        |       primaryExpr
846        |       emptyExpr
847        |       compoundStatementExpr
848        |       initializer
849        |       rangeExpr
850        |       gnuAsmExpr
851        ;
852
853emptyExpr
854        :   NEmptyExpression
855        ;
856
857compoundStatementExpr
858        :   #(l:LPAREN                  { print( l ); }
859                compoundStatement
860                r:RPAREN                { print( r ); }
861            )
862        ;
863
864rangeExpr
865        :   #(NRangeExpr expr v:VARARGS{ print( v ); } expr)
866        ;
867
868gnuAsmExpr
869        :   #(n:NGnuAsmExpr                        { print( n ); }
870                (v:"volatile" { print( v ); } )?
871                lp:LPAREN               { print( lp ); }
872                stringConst
873                (  options { warnWhenFollowAmbig = false; }:
874                    c1:COLON { print( c1 );}
875                    (strOptExprPair
876                        ( c2:COMMA { print( c2 ); } strOptExprPair)*
877                    )?
878                  (  options { warnWhenFollowAmbig = false; }:
879                    c3:COLON            { print( c3 ); }
880                      (strOptExprPair
881                        ( c4:COMMA { print( c4 ); } strOptExprPair)*
882                      )?
883                  )?
884                )?
885                ( c5:COLON              { print( c5 ); }
886                  stringConst
887                  ( c6:COMMA            { print( c6 ); }
888                    stringConst
889                  )*
890                )?
891                rp:RPAREN               { print( rp ); }
892            )
893        ;
894
895strOptExprPair
896        :   stringConst
897            (
898            l:LPAREN                    { print( l ); }
899            expr
900            r:RPAREN                    { print( r ); }
901            )?
902        ;
903
904binaryOperator
905        :       ASSIGN
906        |       DIV_ASSIGN
907        |       PLUS_ASSIGN
908        |       MINUS_ASSIGN
909        |       STAR_ASSIGN
910        |       MOD_ASSIGN
911        |       RSHIFT_ASSIGN
912        |       LSHIFT_ASSIGN
913        |       BAND_ASSIGN
914        |       BOR_ASSIGN
915        |       BXOR_ASSIGN
916        |       LOR
917        |       LAND
918        |       BOR
919        |       BXOR
920        |       BAND
921        |       EQUAL
922        |       NOT_EQUAL
923        |       LT
924        |       LTE
925        |       GT
926        |       GTE
927        |       LSHIFT
928        |       RSHIFT
929        |       PLUS
930        |       MINUS
931        |       STAR
932        |       DIV
933        |       MOD
934        |       NCommaExpr
935        ;
936
937binaryExpr
938        :       b:binaryOperator
939                    // no rules allowed as roots, so here I manually get
940                    // the first and second children of the binary operator
941                    // and then print them out in the right order
942                                        {       TNode e1, e2;
943                                                e1 = (TNode) b.getFirstChild();
944                                                e2 = (TNode) e1.getNextSibling();
945                                                expr( e1 );
946                                                print( b );
947                                                expr( e2 );
948                                        }
949
950        ;
951
952
953conditionalExpr
954        :       #( q:QUESTION
955                expr                    { print( q ); }
956                ( expr )?
957                c:COLON                 { print( c ); }
958                expr
959                )
960        ;
961
962
963castExpr
964        :       #(
965                c:NCast                 { print( c ); }
966                typeName
967                rp:RPAREN               { print( rp ); }
968                expr
969                )
970        ;
971
972
973typeName
974        :       specifierQualifierList (nonemptyAbstractDeclarator)?
975        ;
976
977nonemptyAbstractDeclarator
978        :   #( NNonemptyAbstractDeclarator
979            (   pointerGroup
980                (   (lp1:LPAREN                         { print( lp1 ); }
981                    (   nonemptyAbstractDeclarator
982                        | parameterTypeList
983                    )?
984                    rp1:RPAREN                          { print( rp1 ); }
985                    )
986                | (
987                    lb1:LBRACKET                        { print( lb1 ); }
988                    (expr)?
989                    rb1:RBRACKET                        { print( rb1 ); }
990                  )
991                )*
992
993            |  (   (lp2:LPAREN                          { print( lp2 ); }
994                    (   nonemptyAbstractDeclarator
995                        | parameterTypeList
996                    )?
997                    rp2:RPAREN                          { print( rp2 ); }
998                   )
999                | (
1000                    lb2:LBRACKET                        { print( lb2 ); }
1001                    (expr)?
1002                    rb2:RBRACKET                        { print( rb2 ); }
1003                  )
1004                )+
1005            )
1006            )
1007        ;
1008
1009
1010
1011unaryExpr
1012        :       #( i:INC { print( i ); } expr )
1013        |       #( d:DEC { print( d ); } expr )
1014        |       #( NUnaryExpr u:unaryOperator { print( u ); } expr)
1015        |       #( s:"sizeof"                           { print( s ); }
1016                    ( ( LPAREN typeName )=>
1017                        lps:LPAREN                      { print( lps ); }
1018                        typeName
1019                        rps:RPAREN                      { print( rps ); }
1020                    | expr
1021                    )
1022                )
1023        |       #( a:"__alignof"                             { print( a ); }
1024                    ( ( LPAREN typeName )=>
1025                        lpa:LPAREN                      { print( lpa ); }
1026                        typeName
1027                        rpa:RPAREN                      { print( rpa ); }
1028                    | expr
1029                    )
1030                )
1031        ;
1032/*
1033exception
1034catch [RecognitionException ex]
1035                        {
1036                        reportError(ex);
1037                        System.out.println("PROBLEM TREE:\n"
1038                                                + _t.toStringList());
1039                        if (_t!=null) {_t = _t.getNextSibling();}
1040                        }
1041*/
1042
1043    unaryOperator
1044        :       BAND
1045        |       STAR
1046        |       PLUS
1047        |       MINUS
1048        |       BNOT
1049        |       LNOT
1050        |       LAND
1051        |       "__real"
1052        |       "__imag"
1053        ;
1054
1055
1056postfixExpr
1057        :       #( NPostfixExpr
1058                    primaryExpr
1059                    ( a:PTR b:ID                                { print( a ); print( b ); }
1060                    | c:DOT d:ID                                { print( c ); print( d ); }
1061                    | #( n:NFunctionCallArgs                          { print( n ); }
1062                        (argExprList)?
1063                        rp:RPAREN                                     { print( rp ); }
1064                        )
1065                    | lb:LBRACKET                               { print( lb ); }
1066                        expr
1067                        rb:RBRACKET                             { print( rb ); }
1068                    | f:INC                                     { print( f ); }
1069                    | g:DEC                                     { print( g ); }
1070                    )+
1071                )
1072        ;
1073
1074
1075
1076primaryExpr
1077        :       i:ID                            { print( i ); }
1078        |       n:Number                        { print( n ); }
1079        |       charConst
1080        |       stringConst
1081
1082// JTC:
1083// ID should catch the enumerator
1084// leaving it in gives ambiguous err
1085//      | enumerator
1086
1087        |       #( eg:NExpressionGroup          { print( eg ); }
1088                 expr                           { print( ")" ); }
1089                )
1090        ;
1091
1092
1093
1094argExprList
1095        :       expr ( {print( "," );} expr )*
1096        ;
1097
1098
1099
1100protected
1101charConst
1102        :       c:CharLiteral                   { print( c ); }
1103        ;
1104
1105
1106protected
1107stringConst
1108        :       #( NStringSeq
1109                    (
1110                    s:StringLiteral                 { print( s ); }
1111                    )+
1112                )
1113        ;
1114
1115
1116protected
1117intConst
1118        :       IntOctalConst
1119        |       LongOctalConst
1120        |       UnsignedOctalConst
1121        |       IntIntConst
1122        |       LongIntConst
1123        |       UnsignedIntConst
1124        |       IntHexConst
1125        |       LongHexConst
1126        |       UnsignedHexConst
1127        ;
1128
1129
1130protected
1131floatConst
1132        :       FloatDoubleConst
1133        |       DoubleDoubleConst
1134        |       LongDoubleConst
1135        ;
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146