1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 3 Copyright (c) Non, Inc. 1998 -- All Rights Reserved 4 5PROJECT: C Compiler 6MODULE: GnuCParser 7FILE: GnuCParser.g 8 9AUTHOR: Monty Zukowski (jamz@cdsnet.net) April 28, 1998 10 11DESCRIPTION: 12 This is a grammar for the GNU C compiler. It is a 13 grammar subclass of StdCParser, overriding only those 14 rules which are different from Standard C. 15 16%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ 17 18 19header { 20 package com.sun.gluegen.cgram; 21 22 import java.io.*; 23 24 import antlr.CommonAST; 25 import antlr.DumpASTVisitor; 26} 27 28 29class GnuCParser extends StdCParser; 30 31options 32 { 33 k = 2; 34 exportVocab = GNUC; 35 buildAST = true; 36 ASTLabelType = "TNode"; 37 38 // Copied following options from java grammar. 39 codeGenMakeSwitchThreshold = 2; 40 codeGenBitsetTestThreshold = 3; 41 } 42 43 44{ 45 // Suppport C++-style single-line comments? 46 public static boolean CPPComments = true; 47 48 // access to symbol table 49 public CSymbolTable symbolTable = new CSymbolTable(); 50 51 // source for names to unnamed scopes 52 protected int unnamedScopeCounter = 0; 53 54 public boolean isTypedefName(String name) { 55 boolean returnValue = false; 56 TNode node = symbolTable.lookupNameInCurrentScope(name); 57 for (; node != null; node = (TNode) node.getNextSibling() ) { 58 if(node.getType() == LITERAL_typedef) { 59 returnValue = true; 60 break; 61 } 62 } 63 return returnValue; 64 } 65 66 67 public String getAScopeName() { 68 return "" + (unnamedScopeCounter++); 69 } 70 71 public void pushScope(String scopeName) { 72 symbolTable.pushScope(scopeName); 73 } 74 75 public void popScope() { 76 symbolTable.popScope(); 77 } 78 79 int traceDepth = 0; 80 public void reportError(RecognitionException ex) { 81 try { 82 System.err.println("ANTLR Parsing Error: "+ex + " token name:" + tokenNames[LA(1)]); 83 ex.printStackTrace(System.err); 84 } 85 catch (TokenStreamException e) { 86 System.err.println("ANTLR Parsing Error: "+ex); 87 ex.printStackTrace(System.err); 88 } 89 } 90 public void reportError(String s) { 91 System.err.println("ANTLR Parsing Error from String: " + s); 92 } 93 public void reportWarning(String s) { 94 System.err.println("ANTLR Parsing Warning from String: " + s); 95 } 96 public void match(int t) throws MismatchedTokenException { 97 boolean debugging = false; 98 99 if ( debugging ) { 100 for (int x=0; x<traceDepth; x++) System.out.print(" "); 101 try { 102 System.out.println("Match("+tokenNames[t]+") with LA(1)="+ 103 tokenNames[LA(1)] + ((inputState.guessing>0)?" [inputState.guessing "+ inputState.guessing + "]":"")); 104 } 105 catch (TokenStreamException e) { 106 System.out.println("Match("+tokenNames[t]+") " + ((inputState.guessing>0)?" [inputState.guessing "+ inputState.guessing + "]":"")); 107 108 } 109 110 } 111 try { 112 if ( LA(1)!=t ) { 113 if ( debugging ){ 114 for (int x=0; x<traceDepth; x++) System.out.print(" "); 115 System.out.println("token mismatch: "+tokenNames[LA(1)] 116 + "!="+tokenNames[t]); 117 } 118 throw new MismatchedTokenException(tokenNames, LT(1), t, false, getFilename()); 119 120 } else { 121 // mark token as consumed -- fetch next token deferred until LA/LT 122 consume(); 123 } 124 } 125 catch (TokenStreamException e) { 126 } 127 128 } 129 public void traceIn(String rname) { 130 traceDepth += 1; 131 for (int x=0; x<traceDepth; x++) System.out.print(" "); 132 try { 133 System.out.println("> "+rname+"; LA(1)==("+ tokenNames[LT(1).getType()] 134 + ") " + LT(1).getText() + " [inputState.guessing "+ inputState.guessing + "]"); 135 } 136 catch (TokenStreamException e) { 137 } 138 } 139 public void traceOut(String rname) { 140 for (int x=0; x<traceDepth; x++) System.out.print(" "); 141 try { 142 System.out.println("< "+rname+"; LA(1)==("+ tokenNames[LT(1).getType()] 143 + ") "+LT(1).getText() + " [inputState.guessing "+ inputState.guessing + "]"); 144 } 145 catch (TokenStreamException e) { 146 } 147 traceDepth -= 1; 148 } 149 150} 151 152 153translationUnit 154 : ( externalList )? /* Empty source files are allowed. */ 155 ; 156asm_expr 157 : "asm"^ 158 ("volatile")? LCURLY expr RCURLY ( SEMI )+ 159 ; 160 161idList 162 : ID ( options{warnWhenFollowAmbig=false;}: COMMA ID )* 163 ; 164 165externalDef 166 : ( "typedef" | declaration )=> declaration 167 | ( functionPrefix )=> functionDef 168 | typelessDeclaration 169 | asm_expr 170 | SEMI 171 ; 172 173/* these two are here because GCC allows "cat = 13;" as a valid program! */ 174functionPrefix 175 { String declName; } 176 : ( (functionDeclSpecifiers)=> ds:functionDeclSpecifiers 177 | //epsilon 178 ) 179 declName = d:declarator[true] 180 ( declaration )* (VARARGS)? ( SEMI )* 181 LCURLY 182 ; 183 184typelessDeclaration 185 { AST typeMissing = #[NTypeMissing]; } 186 : initDeclList[typeMissing] SEMI { ## = #( #[NTypeMissing], ##); } 187 ; 188 189initializer 190 : ( ( ( (initializerElementLabel)=> initializerElementLabel )? 191 ( assignExpr | lcurlyInitializer ) { ## = #( #[NInitializer], ## ); } 192 ) 193 | lcurlyInitializer 194 ) 195 ; 196 197// GCC allows more specific initializers 198initializerElementLabel 199 : ( ( LBRACKET ((constExpr VARARGS)=> rangeExpr | constExpr) RBRACKET (ASSIGN)? ) 200 | ID COLON 201 | DOT ID ASSIGN 202 ) 203 { ## = #( #[NInitializerElementLabel], ##) ; } 204 ; 205 206// GCC allows empty initializer lists 207lcurlyInitializer 208 : 209 LCURLY^ (initializerList ( COMMA! )? )? RCURLY 210 { ##.setType( NLcurlyInitializer ); } 211 ; 212 213initializerList 214 : initializer ( options{warnWhenFollowAmbig=false;}:COMMA! initializer )* 215 ; 216 217 218declarator[boolean isFunctionDefinition] returns [String declName] 219 { declName = ""; } 220 : 221 ( pointerGroup )? 222 223 ( id:ID { declName = id.getText(); } 224 | LPAREN declName = declarator[false] RPAREN 225 ) 226 227 ( declaratorParamaterList[isFunctionDefinition, declName] 228 | LBRACKET ( expr )? RBRACKET 229 )* 230 { ## = #( #[NDeclarator], ## ); } 231 ; 232 233declaratorParamaterList[boolean isFunctionDefinition, String declName] 234 : 235 LPAREN^ 236 { 237 if (isFunctionDefinition) { 238 pushScope(declName); 239 } 240 else { 241 pushScope("!"+declName); 242 } 243 } 244 ( 245 (declSpecifiers)=> parameterTypeList 246 | (idList)? 247 ) 248 { 249 popScope(); 250 } 251 ( COMMA! )? 252 RPAREN 253 { ##.setType(NParameterTypeList); } 254 ; 255 256parameterTypeList 257 : parameterDeclaration 258 ( options { 259 warnWhenFollowAmbig = false; 260 } : 261 ( COMMA | SEMI ) 262 parameterDeclaration 263 )* 264 ( ( COMMA | SEMI ) 265 VARARGS 266 )? 267 ; 268 269 270declarationList 271 : ( options { // this loop properly aborts when 272 // it finds a non-typedefName ID MBZ 273 warnWhenFollowAmbig = false; 274 } : 275 276 localLabelDeclaration 277 | ( declarationPredictor )=> declaration 278 )+ 279 ; 280localLabelDeclaration 281 : ( //GNU note: any __label__ declarations must come before regular declarations. 282 "__label__"^ ID (options{warnWhenFollowAmbig=false;}: COMMA! ID)* ( COMMA! )? ( SEMI! )+ 283 ) 284 ; 285 286 287declaration 288 { AST ds1 = null; } 289 : ds:declSpecifiers { ds1 = astFactory.dupList(#ds); } 290 ( 291 initDeclList[ds1] 292 )? 293 ( SEMI )+ 294 { ## = #( #[NDeclaration], ##); } 295 296 ; 297 298functionStorageClassSpecifier 299 : "extern" 300 | "static" 301 | "inline" 302 ; 303 304typeSpecifier [int specCount] returns [int retSpecCount] 305 { retSpecCount = specCount + 1; } 306 : 307 ( "void" 308 | "char" 309 | "short" 310 | "int" 311 | "__int32" 312 | "__int64" 313 | "long" 314 | "float" 315 | "double" 316 | "signed" 317 | "unsigned" 318 | structOrUnionSpecifier ( options{warnWhenFollowAmbig=false;}: attributeDecl )* 319 | enumSpecifier 320 | { specCount==0 }? typedefName 321 | "typeof"^ LPAREN 322 ( ( typeName )=> typeName 323 | expr 324 ) 325 RPAREN 326 | "__complex" 327 ) 328 ; 329 330 331structOrUnionSpecifier 332 { String scopeName; } 333 : sou:structOrUnion! 334 ( ( ID LCURLY )=> i:ID l:LCURLY 335 { 336 scopeName = #sou.getText() + " " + #i.getText(); 337 #l.setText(scopeName); 338 pushScope(scopeName); 339 } 340 ( structDeclarationList )? 341 { popScope();} 342 RCURLY 343 | l1:LCURLY 344 { 345 scopeName = getAScopeName(); 346 #l1.setText(scopeName); 347 pushScope(scopeName); 348 } 349 ( structDeclarationList )? 350 { popScope(); } 351 RCURLY 352 | ID 353 ) 354 { 355 ## = #( #sou, ## ); 356 } 357 ; 358 359 360structDeclaration 361 : specifierQualifierList structDeclaratorList ( COMMA! )? ( SEMI! )+ 362 ; 363 364structDeclaratorList 365 : structDeclarator ( options{warnWhenFollowAmbig=false;}: COMMA! structDeclarator )* 366 ; 367 368structDeclarator 369 : ( declarator[false] )? 370 ( COLON constExpr )? 371 ( attributeDecl )* 372 { ## = #( #[NStructDeclarator], ##); } 373 ; 374 375 376 377enumSpecifier 378 : "enum"^ 379 ( ( ID LCURLY )=> i:ID LCURLY enumList[i.getText()] RCURLY 380 | LCURLY enumList["anonymous"] RCURLY 381 | ID 382 ) 383 ; 384enumList[String enumName] 385 : enumerator[enumName] ( options{warnWhenFollowAmbig=false;}: COMMA! enumerator[enumName] )* ( COMMA! )? 386 ; 387 388 389initDeclList[AST declarationSpecifiers] 390 : initDecl[declarationSpecifiers] 391 ( options{warnWhenFollowAmbig=false;}: COMMA! initDecl[declarationSpecifiers] )* 392 ( COMMA! )? 393 ; 394 395initDecl[AST declarationSpecifiers] 396 { String declName = ""; } 397 : declName = d:declarator[false] 398 { AST ds1, d1; 399 ds1 = astFactory.dupList(declarationSpecifiers); 400 d1 = astFactory.dupList(#d); 401 symbolTable.add(declName, #(null, ds1, d1) ); 402 } 403 ( attributeDecl )* 404 ( ASSIGN initializer 405 | COLON expr 406 )? 407 { ## = #( #[NInitDecl], ## ); } 408 ; 409 410attributeDecl 411 : "__attribute"^ LPAREN LPAREN attributeList RPAREN RPAREN 412 | "asm"^ LPAREN stringConst RPAREN { ##.setType( NAsmAttribute ); } 413 ; 414 415attributeList 416 : attribute ( options{warnWhenFollowAmbig=false;}: COMMA attribute)* ( COMMA )? 417 ; 418 419attribute 420 : ( ~(LPAREN | RPAREN | COMMA) 421 | LPAREN attributeList RPAREN 422 )* 423 ; 424compoundStatement[String scopeName] 425 : LCURLY^ 426 427 { 428 pushScope(scopeName); 429 } 430 ( //this ambiguity is ok, declarationList and nestedFunctionDef end properly 431 options { 432 warnWhenFollowAmbig = false; 433 } : 434 ( "typedef" | "__label__" | declaration )=> declarationList 435 | (nestedFunctionDef)=> nestedFunctionDef 436 )* 437 ( statementList )? 438 { popScope(); } 439 RCURLY 440 { ##.setType( NCompoundStatement ); ##.setAttribute( "scopeName", scopeName ); } 441 ; 442 443nestedFunctionDef 444 { String declName; } 445 : ( "auto" )? //only for nested functions 446 ( (functionDeclSpecifiers)=> ds:functionDeclSpecifiers 447 )? 448 declName = d:declarator[false] 449 { 450 AST d2, ds2; 451 d2 = astFactory.dupList(#d); 452 ds2 = astFactory.dupList(#ds); 453 symbolTable.add(declName, #(null, ds2, d2)); 454 pushScope(declName); 455 } 456 ( declaration )* 457 { popScope(); } 458 compoundStatement[declName] 459 { ## = #( #[NFunctionDef], ## );} 460 ; 461 462statement 463 : SEMI // Empty statements 464 465 | compoundStatement[getAScopeName()] // Group of statements 466 467 | expr SEMI! { ## = #( #[NStatementExpr], ## );} // Expressions 468 469// Iteration statements: 470 471 | "while"^ LPAREN! expr RPAREN! statement 472 | "do"^ statement "while"! LPAREN! expr RPAREN! SEMI! 473 |! "for" 474 LPAREN ( e1:expr )? SEMI ( e2:expr )? SEMI ( e3:expr )? RPAREN 475 s:statement 476 { 477 if ( #e1 == null) { #e1 = (TNode) #[ NEmptyExpression ]; } 478 if ( #e2 == null) { #e2 = (TNode) #[ NEmptyExpression ]; } 479 if ( #e3 == null) { #e3 = (TNode) #[ NEmptyExpression ]; } 480 ## = #( #[LITERAL_for, "for"], #e1, #e2, #e3, #s ); 481 } 482 483 484// Jump statements: 485 486 | "goto"^ expr SEMI! 487 | "continue" SEMI! 488 | "break" SEMI! 489 | "return"^ ( expr )? SEMI! 490 491 492 | ID COLON! (options {warnWhenFollowAmbig=false;}: statement)? { ## = #( #[NLabel], ## ); } 493// GNU allows range expressions in case statements 494 | "case"^ ((constExpr VARARGS)=> rangeExpr | constExpr) COLON! ( options{warnWhenFollowAmbig=false;}:statement )? 495 | "default"^ COLON! ( options{warnWhenFollowAmbig=false;}: statement )? 496 497// Selection statements: 498 499 | "if"^ 500 LPAREN! expr RPAREN! statement 501 ( //standard if-else ambiguity 502 options { 503 warnWhenFollowAmbig = false; 504 } : 505 "else" statement )? 506 | "switch"^ LPAREN! expr RPAREN! statement 507 ; 508 509 510 511conditionalExpr 512 : logicalOrExpr 513 ( QUESTION^ (expr)? COLON conditionalExpr )? 514 ; 515 516rangeExpr //used in initializers only 517 : constExpr VARARGS constExpr 518 { ## = #(#[NRangeExpr], ##); } 519 ; 520 521castExpr 522 : ( LPAREN typeName RPAREN )=> 523 LPAREN^ typeName RPAREN ( castExpr | lcurlyInitializer ) 524 { ##.setType(NCast); } 525 526 | unaryExpr 527 ; 528nonemptyAbstractDeclarator 529 : ( 530 pointerGroup 531 ( (LPAREN 532 ( nonemptyAbstractDeclarator 533 | parameterTypeList 534 )? 535 ( COMMA! )? 536 RPAREN) 537 | (LBRACKET (expr)? RBRACKET) 538 )* 539 540 | ( (LPAREN 541 ( nonemptyAbstractDeclarator 542 | parameterTypeList 543 )? 544 ( COMMA! )? 545 RPAREN) 546 | (LBRACKET (expr)? RBRACKET) 547 )+ 548 ) 549 { ## = #( #[NNonemptyAbstractDeclarator], ## ); } 550 551 ; 552 553 554 555unaryExpr 556 : postfixExpr 557 | INC^ castExpr 558 | DEC^ castExpr 559 | u:unaryOperator castExpr { ## = #( #[NUnaryExpr], ## ); } 560 561 | "sizeof"^ 562 ( ( LPAREN typeName )=> LPAREN typeName RPAREN 563 | unaryExpr 564 ) 565 | "__alignof"^ 566 ( ( LPAREN typeName )=> LPAREN typeName RPAREN 567 | unaryExpr 568 ) 569 | gnuAsmExpr 570 ; 571 572unaryOperator 573 : BAND 574 | STAR 575 | PLUS 576 | MINUS 577 | BNOT //also stands for complex conjugation 578 | LNOT 579 | LAND //for label dereference (&&label) 580 | "__real" 581 | "__imag" 582 ; 583 584gnuAsmExpr 585 : "asm"^ ("volatile")? 586 LPAREN stringConst 587 ( options { warnWhenFollowAmbig = false; }: 588 COLON (strOptExprPair ( COMMA strOptExprPair)* )? 589 ( options { warnWhenFollowAmbig = false; }: 590 COLON (strOptExprPair ( COMMA strOptExprPair)* )? 591 )? 592 )? 593 ( COLON stringConst ( COMMA stringConst)* )? 594 RPAREN 595 { ##.setType(NGnuAsmExpr); } 596 ; 597 598//GCC requires the PARENs 599strOptExprPair 600 : stringConst ( LPAREN expr RPAREN )? 601 ; 602 603 604primaryExpr 605 : ID 606 | Number 607 | charConst 608 | stringConst 609// JTC: 610// ID should catch the enumerator 611// leaving it in gives ambiguous err 612// | enumerator 613 | (LPAREN LCURLY) => LPAREN^ compoundStatement[getAScopeName()] RPAREN 614 | LPAREN^ expr RPAREN { ##.setType(NExpressionGroup); } 615 ; 616 617 618{ 619 import java.io.*; 620 import java.util.*; 621 import antlr.*; 622} 623 624class GnuCLexer extends StdCLexer; 625options 626 { 627 k = 3; 628 importVocab = GNUC; 629 testLiterals = false; 630 } 631tokens { 632 LITERAL___extension__ = "__extension__"; 633} 634 635{ 636 public void initialize(String src) 637 { 638 setOriginalSource(src); 639 initialize(); 640 } 641 642 public void initialize() 643 { 644 literals.put(new ANTLRHashString("__alignof__", this), new Integer(LITERAL___alignof)); 645 literals.put(new ANTLRHashString("__asm", this), new Integer(LITERAL_asm)); 646 literals.put(new ANTLRHashString("__asm__", this), new Integer(LITERAL_asm)); 647 literals.put(new ANTLRHashString("__attribute__", this), new Integer(LITERAL___attribute)); 648 literals.put(new ANTLRHashString("__complex__", this), new Integer(LITERAL___complex)); 649 literals.put(new ANTLRHashString("__const", this), new Integer(LITERAL_const)); 650 literals.put(new ANTLRHashString("__const__", this), new Integer(LITERAL_const)); 651 literals.put(new ANTLRHashString("__imag__", this), new Integer(LITERAL___imag)); 652 literals.put(new ANTLRHashString("__inline", this), new Integer(LITERAL_inline)); 653 literals.put(new ANTLRHashString("__inline__", this), new Integer(LITERAL_inline)); 654 literals.put(new ANTLRHashString("__real__", this), new Integer(LITERAL___real)); 655 literals.put(new ANTLRHashString("__signed", this), new Integer(LITERAL_signed)); 656 literals.put(new ANTLRHashString("__signed__", this), new Integer(LITERAL_signed)); 657 literals.put(new ANTLRHashString("__typeof", this), new Integer(LITERAL_typeof)); 658 literals.put(new ANTLRHashString("__typeof__", this), new Integer(LITERAL_typeof)); 659 literals.put(new ANTLRHashString("__volatile", this), new Integer(LITERAL_volatile)); 660 literals.put(new ANTLRHashString("__volatile__", this), new Integer(LITERAL_volatile)); 661 } 662 663 664 LineObject lineObject = new LineObject(); 665 String originalSource = ""; 666 PreprocessorInfoChannel preprocessorInfoChannel = new PreprocessorInfoChannel(); 667 int tokenNumber = 0; 668 boolean countingTokens = true; 669 int deferredLineCount = 0; 670 List defines = new ArrayList(); 671 672 public void setCountingTokens(boolean ct) 673 { 674 countingTokens = ct; 675 if ( countingTokens ) { 676 tokenNumber = 0; 677 } 678 else { 679 tokenNumber = 1; 680 } 681 } 682 683 public void setOriginalSource(String src) 684 { 685 originalSource = src; 686 lineObject.setSource(src); 687 } 688 public void setSource(String src) 689 { 690 lineObject.setSource(src); 691 } 692 693 public PreprocessorInfoChannel getPreprocessorInfoChannel() 694 { 695 return preprocessorInfoChannel; 696 } 697 698 public void setPreprocessingDirective(String pre) 699 { 700 preprocessorInfoChannel.addLineForTokenNumber( pre, new Integer(tokenNumber) ); 701 } 702 703 public void addDefine(String name, String value) 704 { 705 defines.add(new Define(name, value)); 706 } 707 708 /** Returns a list of Define objects corresponding to the 709 preprocessor definitions seen during parsing. */ 710 public List getDefines() { 711 return defines; 712 } 713 714 protected Token makeToken(int t) 715 { 716 if ( t != Token.SKIP && countingTokens) { 717 tokenNumber++; 718 } 719 CToken tok = (CToken) super.makeToken(t); 720 tok.setLine(lineObject.line); 721 tok.setSource(lineObject.source); 722 tok.setTokenNumber(tokenNumber); 723 724 lineObject.line += deferredLineCount; 725 deferredLineCount = 0; 726 return tok; 727 } 728 729 public void deferredNewline() { 730 deferredLineCount++; 731 } 732 733 public void newline() { 734 lineObject.newline(); 735 } 736 737 738 739 740 741 742} 743Whitespace 744 : ( ( ' ' | '\t' | '\014') 745 | "\r\n" { newline(); } 746 | ( '\n' | '\r' ) { newline(); } 747 ) { _ttype = Token.SKIP; } 748 ; 749 750 751protected 752Escape 753 : '\\' 754 ( options{warnWhenFollowAmbig=false;}: 755 ~('0'..'7' | 'x') 756 | ('0'..'3') ( options{warnWhenFollowAmbig=false;}: Digit )* 757 | ('4'..'7') ( options{warnWhenFollowAmbig=false;}: Digit )* 758 | 'x' ( options{warnWhenFollowAmbig=false;}: Digit | 'a'..'f' | 'A'..'F' )+ 759 ) 760 ; 761 762protected IntSuffix 763 : 'L' 764 | 'l' 765 | 'U' 766 | 'u' 767 | 'I' 768 | 'i' 769 | 'J' 770 | 'j' 771 ; 772protected NumberSuffix 773 : 774 IntSuffix 775 | 'F' 776 | 'f' 777 ; 778 779Number 780 : ( ( Digit )+ ( '.' | 'e' | 'E' ) )=> ( Digit )+ 781 ( '.' ( Digit )* ( Exponent )? 782 | Exponent 783 ) 784 ( NumberSuffix 785 )* 786 787 | ( "..." )=> "..." { _ttype = VARARGS; } 788 789 | '.' { _ttype = DOT; } 790 ( ( Digit )+ ( Exponent )? 791 { _ttype = Number; } 792 ( NumberSuffix 793 )* 794 )? 795 796 | '0' ( '0'..'7' )* 797 ( NumberSuffix 798 )* 799 800 | '1'..'9' ( Digit )* 801 ( NumberSuffix 802 )* 803 804 | '0' ( 'x' | 'X' ) ( 'a'..'f' | 'A'..'F' | Digit )+ 805 ( IntSuffix 806 )* 807 ; 808 809IDMEAT 810 : 811 i:ID { 812 813 if ( i.getType() == LITERAL___extension__ ) { 814 $setType(Token.SKIP); 815 } 816 else { 817 $setType(i.getType()); 818 } 819 820 } 821 ; 822 823protected ID 824 options 825 { 826 testLiterals = true; 827 } 828 : ( 'a'..'z' | 'A'..'Z' | '_' | '$') 829 ( 'a'..'z' | 'A'..'Z' | '_' | '$' | '0'..'9' )* 830 ; 831 832WideCharLiteral 833 : 834 'L' CharLiteral 835 { $setType(CharLiteral); } 836 ; 837 838 839 840WideStringLiteral 841 : 842 'L' StringLiteral 843 { $setType(StringLiteral); } 844 ; 845 846StringLiteral 847 : 848 '"' 849 ( ('\\' ~('\n'))=> Escape 850 | ( '\r' { newline(); } 851 | '\n' { 852 newline(); 853 } 854 | '\\' '\n' { 855 newline(); 856 } 857 ) 858 | ~( '"' | '\r' | '\n' | '\\' ) 859 )* 860 '"' 861 ; 862 863 864 865 866