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