/cpp/src/main/antlr/cppparser.g
Unknown | 2273 lines | 2067 code | 206 blank | 0 comment | 0 complexity | 817f19aceb922d7cb54e0a5b35fa2250 MD5 | raw file
Possible License(s): Apache-2.0
1/* 2 * PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g) 3 * 4 * Authors: Sumana Srinivasan, NeXT Inc.; sumana_srinivasan@next.com 5 * Terence Parr, Parr Research Corporation; parrt@parr-research.com 6 * Russell Quong, Purdue University; quong@ecn.purdue.edu 7 * 8 * VERSION 1.2 9 * 10 * SOFTWARE RIGHTS 11 * 12 * This file is a part of the ANTLR-based C++ grammar and is free 13 * software. We do not reserve any LEGAL rights to its use or 14 * distribution, but you may NOT claim ownership or authorship of this 15 * grammar or support code. An individual or company may otherwise do 16 * whatever they wish with the grammar distributed herewith including the 17 * incorporation of the grammar or the output generated by ANTLR into 18 * commerical software. You may redistribute in source or binary form 19 * without payment of royalties to us as long as this header remains 20 * in all source distributions. 21 * 22 * We encourage users to develop parsers/tools using this grammar. 23 * In return, we ask that credit is given to us for developing this 24 * grammar. By "credit", we mean that if you incorporate our grammar or 25 * the generated code into one of your programs (commercial product, 26 * research project, or otherwise) that you acknowledge this fact in the 27 * documentation, research report, etc.... In addition, you should say nice 28 * things about us at every opportunity. 29 * 30 * As long as these guidelines are kept, we expect to continue enhancing 31 * this grammar. Feel free to send us enhancements, fixes, bug reports, 32 * suggestions, or general words of encouragement at parrt@parr-research.com. 33 * 34 * NeXT Computer Inc. 35 * 900 Chesapeake Dr. 36 * Redwood City, CA 94555 37 * 12/02/1994 38 * 39 * Restructured for public consumption by Terence Parr late February, 1995. 40 * 41 * DISCLAIMER: we make no guarantees that this grammar works, makes sense, 42 * or can be used to do anything useful. 43 */ 44/* 2001-2002 45 * Version 1.0 46 * This C++ grammar file has been converted from PCCTS to run under 47 * ANTLR to generate lexer and parser in C++ code by 48 * Jianguo Zuo and David Wigg at 49 * The Centre for Systems and Software Engineering 50 * London South Bank University 51 * London, UK. 52 * 53 */ 54/* 2003 55 * Version 2.0 was published by David Wigg in September 2003 56 */ 57/* 2004 58 * Version 3.0 July 2004 59 * This is version 3.0 of the C++ grammar definition for ANTLR to 60 * generate lexer and parser in C++ code updated by 61 * David Wigg at 62 * The Centre for Systems and Software Engineering 63 * London South Bank University 64 * London, UK. 65 * 66 * wiggjd@bcs.ac.uk 67 * blackse@lsbu.ac.uk 68 * 69 * See MyReadMe.txt for further information 70 * 71 * This file is best viewed in courier font with tabs set to 4 spaces 72 */ 73/* 2005 74 * Version 0.01 February 2005 75 * This is version 0.01 of the C++ grammar definition for ANTLR to 76 * generate lexer and parser in Java code. This grammar was based 77 * in the above version of the grammar by David Wigg, having been 78 * ported to work in java programs. 79 * The grammar file name is now different to enable diferentiation 80 * from the original C++ grammar for C++ output. Many of the original 81 * C++ grammar support files were removed, being for now the only 82 * needed file the CPPvariables.java. 83 * 84 * This grammar is being developed in the context of the ArgoUML 85 * project, being the basis for the C++ reverse engineering 86 * functionalities of the C++ module. 87 * 88 * TODO: provide more documentation. 89 * TODO: send to the ANTLR users list to enable review. 90 * TODO: improve stand-alone use. 91 * 92 * www.argouml.org 93 */ 94 95header 96{ 97/*REMOVE_BEGIN*/ 98package com.google.test.metric.cpp; 99/*REMOVE_END*/ 100 101import java.util.Hashtable; 102import java.util.List; 103import java.util.ArrayList; 104} 105 106class InternalParser extends Parser; 107 108options 109 { 110 k = 2; 111 exportVocab = STDC; 112 codeGenMakeSwitchThreshold = 2; 113 codeGenBitsetTestThreshold = 3; 114 defaultErrorHandler=false; 115 //analyzerDebug = true; 116 } 117 118{ 119 120 private Builder b; 121 122 String enclosingClass="";//name of current class 123 boolean _td=false; // is type declaration? 124 Hashtable symbols=new Hashtable(); 125 126 127 public boolean qualifiedItemIsOneOf(java.util.BitSet qiFlags, int lookahead_offset) throws TokenStreamException 128 { 129 java.util.BitSet qi = qualifiedItemIs(lookahead_offset); 130 java.util.BitSet aux=(java.util.BitSet) qi.clone(); 131 aux.and(qiFlags); 132 return (!aux.isEmpty()); 133 } 134 135 136 // This is an important function, but will be replaced with 137 // an enhanced predicate in the future, once predicates 138 // and/or predicate guards can contain loops. 139 // 140 // Scan past the ::T::B:: to see what lies beyond. 141 // Return QI_TYPE if the qualified item can pose as type name. 142 // Note that T::T is NOT a type; it is a constructor. Also, 143 // class T { ... T...} yields the enclosed T as a ctor. This 144 // is probably a type as I separate out the constructor defs/decls, 145 // I want it consistent with T::T. 146 // 147 // In the below examples, I use A,B,T and example types, and 148 // a,b as example ids. 149 // In the below examples, any A or B may be a 150 // qualified template, i.e., A<...> 151 // 152 // T::T outside of class T yields QI_CTOR. 153 // T<...>::T outside of class T yields QI_CTOR. 154 // T inside of class T {...} yields QI_CTOR. 155 // T, ::T, A::T outside of class T yields QI_TYPE. 156 // a, ::a, A::B::a yields qiId 157 // a::b yields QI_INVALID 158 // ::operator, operator, A::B::operator yield qiOPerator 159 // A::*, A::B::* yield QI_PTR_MEMBER 160 // ::*, * yields QI_INVALID 161 // ::~T, ~T, A::~T yield QI_DTOR 162 // ~a, ~A::a, A::~T::, ~T:: yield QI_INVALID 163 public java.util.BitSet qualifiedItemIs(int lookahead_offset) throws TokenStreamException 164 { 165 int value; 166 int k = lookahead_offset + 1; 167 int final_type_idx = 0; 168 boolean scope_found = false; 169 // Skip leading "::" 170 if (LT(k).getType() == SCOPE) 171 { 172 k++; 173 scope_found = true; 174 } 175 // Skip sequences of T:: or T<...>:: 176 //printf("support.cpp qualifiedItemIs while reached k %d type %d isType %d, isClass %d, guessing %d\n", 177 // k,LT(k)->getType(),isTypeName((LT(k)->getText()).data()),isClassName((LT(k)->getText()).data()),inputState->guessing); 178 while ((LT(k).getType() == ID) && (isTypeName(LT(k).getText()))) 179 {// If this type is the same as the last type, then ctor 180 if ((final_type_idx != 0) && (LT(final_type_idx).getText().equals(LT(k).getText()))) 181 {// Like T::T 182 // As an extra check, do not allow T::T:: 183 if (LT(k+1).getType() == SCOPE) 184 { //printf("support.cpp qualifiedItemIs QI_INVALID returned\n"); 185 return CPPvariables.QI_INVALID; 186 } 187 else 188 {//printf("support.cpp qualifiedItemIs QI_CTOR returned\n"); 189 return CPPvariables.QI_CTOR; 190 } 191 } 192 193 // Record this as the most recent type seen in the series 194 final_type_idx = k; 195 196 //printf("support.cpp qualifiedItemIs if step reached final_type_idx %d\n",final_type_idx); 197 198 // Skip this token 199 k++; 200 201 // Skip over any template qualifiers <...> 202 // I believe that "T<..." cannot be anything valid but a template 203 if (LT(k).getType() == LESSTHAN) 204 { 205 value=skipTemplateQualifiers(k); 206 if (value==k) 207 {//printf("support.cpp qualifiedItemIs QI_INVALID(2) returned\n"); 208 return CPPvariables.QI_INVALID; 209 } 210 else 211 k=value; 212 //printf("support.cpp qualifiedItemIs template skipped, k %d\n",k); 213 // k has been updated to token following <...> 214 } 215 if (LT(k).getType() == SCOPE) 216 // Skip the "::" and keep going 217 { 218 k++; 219 scope_found = true; 220 } 221 else 222 {// Series terminated -- last ID in the sequence was a type 223 // Return ctor if last type is in containing class 224 // We already checked for T::T inside loop 225 if ( enclosingClass.equals(LT(final_type_idx).getText())) 226 { // Like class T T() 227 //printf("support.cpp qualifiedItemIs QI_CTOR(2) returned\n"); 228 return CPPvariables.QI_CTOR; 229 } 230 else 231 {//printf("support.cpp qualifiedItemIs QI_TYPE returned\n"); 232 return CPPvariables.QI_TYPE; 233 } 234 } 235 } 236 // LT(k) is not an ID, or it is an ID but not a typename. 237 //printf("support.cpp qualifiedItemIs second switch reached\n"); 238 switch (LT(k).getType()) 239 { 240 case ID: 241 // ID but not a typename 242 // Do not allow id:: 243 if (LT(k+1).getType() == SCOPE) 244 { 245 //printf("support.cpp qualifiedItemIs QI_INVALID(3) returned\n"); 246 return CPPvariables.QI_INVALID; 247 } 248 if (enclosingClass.equals(LT(k).getText())) 249 { // Like class T T() 250 //printf("support.cpp qualifiedItemIs QI_CTOR(3) returned\n"); 251 return CPPvariables.QI_CTOR; 252 } 253 else 254 { 255 if (scope_found) 256 // DW 25/10/03 Assume type if at least one SCOPE present (test12.i) 257 return CPPvariables.QI_TYPE; 258 else 259 //printf("support.cpp qualifiedItemIs QI_VAR returned\n"); 260 return CPPvariables.QI_VAR; // DW 19/03/04 was QI_ID Could be function? 261 } 262 case TILDE: 263 // check for dtor 264 if ((LT(k+1).getType() == ID) && (isTypeName(LT(k+1).getText())) &&(LT(k+2).getType() != SCOPE)) 265 { // Like ~B or A::B::~B 266 // Also (incorrectly?) matches ::~A. 267 //printf("support.cpp qualifiedItemIs QI_DTOR returned\n"); 268 return CPPvariables.QI_DTOR; 269 } 270 else 271 { // ~a or ~A::a is QI_INVALID 272 //printf("support.cpp qualifiedItemIs QI_INVALID(4) returned\n"); 273 return CPPvariables.QI_INVALID; 274 } 275 case STAR: 276 // Like A::* 277 // Do not allow * or ::* 278 if (final_type_idx == 0) 279 { // Haven't seen a type yet 280 //printf("support.cpp qualifiedItemIs QI_INVALID(5) returned\n"); 281 return CPPvariables.QI_INVALID; 282 } 283 else 284 { //printf("support.cpp qualifiedItemIs QI_PTR_MEMBER returned\n"); 285 return CPPvariables.QI_PTR_MEMBER; 286 } 287 case OPERATOR: 288 // Like A::operator, ::operator, or operator 289 //printf("support.cpp qualifiedItemIs QI_OPERATOR returned\n"); 290 return CPPvariables.QI_OPERATOR; 291 default: 292 // Something that neither starts with :: or ID, or 293 // a :: not followed by ID, operator, ~, or * 294 //printf("support.cpp qualifiedItemIs QI_INVALID(6) returned\n"); 295 return CPPvariables.QI_INVALID; 296 } 297 } 298 299 // Skip over <...>. This correctly handles nested <> and (), e.g: 300 // <T> 301 // < (i>3) > 302 // < T2<...> > 303 // but not 304 // < i>3 > 305 // 306 // On input, kInOut is the index of the "<" 307 // On output, if the return is true, then 308 // kInOut is the index of the token after ">" 309 // else 310 // kInOut is unchanged 311 312 public int skipTemplateQualifiers(int kInOut) throws TokenStreamException 313 { 314 // Start after "<" 315 int k = kInOut + 1; 316 int value; 317 while (LT(k).getType() != GREATERTHAN) // scan to end of <...> 318 { 319 switch (LT(k).getType()) 320 { 321 case EOF: 322 return kInOut; 323 case LESSTHAN: 324 value=skipTemplateQualifiers(k); 325 if (value==k) 326 { 327 return kInOut; 328 } 329 else 330 k=value; 331 break; 332 case LPAREN: 333 value=skipNestedParens(k); 334 if (value==k) 335 { 336 return kInOut; 337 } 338 else 339 k=value; 340 break; 341 default: 342 k++; // skip everything else 343 break; 344 } 345 if (k > CPPvariables.MAX_TEMPLATE_TOKEN_SCAN) 346 { 347 return kInOut; 348 } 349 } 350 351 // Update output argument to point past ">" 352 kInOut = k + 1; 353 return kInOut; 354 } 355 356 // Skip over (...). This correctly handles nested (), e.g: 357 // (i>3, (i>5)) 358 // 359 // On input, kInOut is the index of the "(" 360 // On output, if the return is true, then 361 // kInOut is the index of the token after ")" 362 // else 363 // kInOut is unchanged 364 public int skipNestedParens(int kInOut) throws TokenStreamException 365 { 366 // Start after "(" 367 int k = kInOut + 1; 368 int value; 369 while (LT(k).getType() != RPAREN) // scan to end of (...) 370 { 371 switch (LT(k).getType()) 372 { 373 case EOF: 374 return kInOut; 375 case LPAREN: 376 value=skipNestedParens(k); 377 if (value==k) 378 { 379 return kInOut; 380 } 381 else 382 k=value; 383 break; 384 default: 385 k++; // skip everything else 386 break; 387 } 388 if (k > CPPvariables.MAX_TEMPLATE_TOKEN_SCAN) 389 { 390 return kInOut; 391 } 392 } 393 // Update output argument to point past ")" 394 kInOut = k + 1; 395 return kInOut; 396 } 397 398 // Return true if "::blah" or "fu::bar<args>::..." found. 399 public boolean scopedItem(int k) throws TokenStreamException 400 { 401 //printf("support.cpp scopedItem k %d\n",k); 402 return (LT(k).getType()==SCOPE || 403 (LT(k).getType()==ID && !finalQualifier(k))); 404 } 405 406 // Return true if ID<...> or ID is last item in qualified item list. 407 // Return false if LT(k) is not an ID. 408 // ID must be a type to check for ID<...>, 409 // or else we would get confused by "i<3" 410 public boolean finalQualifier(int k) throws TokenStreamException 411 { 412 if (LT(k).getType()==ID) 413 { 414 if ((isTypeName(LT(k).getText())) && (LT(k+1).getType()==LESSTHAN)) 415 { 416 // Starts with "T<". Skip <...> 417 k++; 418 k=skipTemplateQualifiers(k); 419 } 420 else 421 { 422 // skip ID; 423 k++; 424 } 425 return (LT(k).getType() != SCOPE ); 426 } 427 else 428 { // not an ID 429 return false; 430 } 431 } 432 433 /* 434 * Return true if 's' can pose as a type name 435 */ 436 public boolean isTypeName(String s) 437 { 438 String type=""; 439 if (!symbols.containsKey(s)) 440 { 441 //printf("support.cpp isTypeName %s not found\n",s); 442 return false; 443 } 444 else 445 type=(String) symbols.get(s); 446 if (type.equals(CPPvariables.OT_TYPE_DEF)|| 447 type.equals(CPPvariables.OT_ENUM)|| 448 type.equals(CPPvariables.OT_CLASS)|| 449 type.equals(CPPvariables.OT_STRUCT)|| 450 type.equals(CPPvariables.OT_UNION)) 451 { 452 return true; 453 } 454 return false; 455 } 456 457 public void declaratorID(String id, java.util.BitSet qi) 458 { 459 if ((qi.equals(CPPvariables.QI_TYPE)) || (_td)) // Check for type declaration 460 { 461 if (!symbols.containsKey(id)) 462 symbols.put(id, CPPvariables.OT_TYPE_DEF); 463 } 464 } 465} 466 467 468translation_unit [Builder builder] 469 { 470 if(!symbols.containsKey("std")) 471 symbols.put("std",CPPvariables.OT_TYPE_DEF); 472 b = builder; 473 } 474 : {b.beginTranslationUnit();} 475 (external_declaration)+ EOF 476 {b.endTranslationUnit();} 477 ; 478 479 480external_declaration 481 {String s="";} 482 : 483 ( 484 // Template explicit specialisation (DW 14/04/03) 485 ("template" LESSTHAN GREATERTHAN)=>"template" LESSTHAN GREATERTHAN declaration 486 | 487 // Class definition (templates too) 488 // This is separated out otherwise the next alternative 489 // would look for "class A { ... } f() {...}" which is 490 // an unacceptable level of backtracking. 491 492 // JEL Note: Rule body does not need typedef, because 493 // that is internal to "declaration", and it is invalid 494 // to say "typedef template..." 495 // Class definition 496 (("typedef")? class_head)=> declaration 497 | 498 // Class template definition 499 (template_head class_head)=>template_head declaration 500 | 501 // Enum definition (don't want to backtrack over this in other alts) 502 ("enum" (ID)? LCURLY)=>enum_specifier (init_declarator_list)? SEMICOLON 503 | 504 // Destructor DEFINITION (templated or non-templated) 505 ((template_head)? dtor_head LCURLY)=>(template_head)? dtor_head dtor_body 506 | 507 // Constructor DEFINITION (non-templated) 508 // JEL 4/3/96 Added predicate that works, once the 509 // restriction is added that ctor cannot be virtual 510 // and ctor_declarator uses a more restrictive id 511 ( (options {warnWhenFollowAmbig = false;}: 512 ctor_decl_spec)? 513 {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}?)=>ctor_definition 514 /*(ID SCOPE)=>ctor_definition*/ 515 | 516 // User-defined type cast 517 (("inline")? scope_override conversion_function_decl_or_def)=> 518 ("inline")? s = scope_override conversion_function_decl_or_def 519 | 520 // Function declaration 521 (declaration_specifiers function_declarator SEMICOLON)=> 522 {b.beginFunctionDeclaration();} 523 declaration 524 {b.endFunctionDeclaration();} 525 | 526 // Function definition 527 (declaration_specifiers function_declarator LCURLY)=> 528 {b.beginFunctionDefinition(LT(2).getLine());} 529 function_definition 530 {b.endFunctionDefinition();} 531 | 532 // K & R Function definition 533 (declaration_specifiers function_declarator declaration)=>function_definition 534 | 535 // templated forward class decl, init/decl of static member in template 536 (template_head declaration_specifiers (init_declarator_list)? SEMICOLON )=> 537 template_head declaration_specifiers (init_declarator_list)? SEMICOLON 538 | 539 // Templated FUNCTIONS and CONSTRUCTORS matched here. 540 template_head 541 ( 542 // Templated CONSTRUCTOR definition 543 // JEL 4/3/96 Added predicate that works once the 544 // restriction is added that ctor cannot be virtual 545 ( ctor_decl_spec {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}?)=>ctor_definition 546 | 547 // Templated function declaration 548 (declaration_specifiers function_declarator SEMICOLON)=> declaration 549 | 550 // Templated function definition 551 (declaration_specifiers function_declarator LCURLY)=> function_definition 552 ) 553 | 554 decl_namespace 555 | 556 // everything else (except templates) 557 declaration 558 | 559 SEMICOLON 560 ) 561 ; // end of external_declaration 562 563decl_namespace 564 {String qid="";} 565 : 566 "namespace" 567 ( 568 (ns:ID{ _td = true;declaratorID(ns.getText(),CPPvariables.QI_TYPE);})? 569 570 // The following statement can be invoked to trigger selective antlr trace 571 // Also see below 572 //{if (strcmp((ns->getText()).data(),"xyz")==0) antlrTrace(true);} // Used for diagnostic trigger 573 LCURLY 574 {if(ns == null) { b.enterNamespaceScope(null); } 575 else { b.enterNamespaceScope(ns.getText()); }} 576 (external_declaration)* 577 {b.exitNamespaceScope();} 578 RCURLY 579 // The following should be implemented to match the optional statement above 580 //{antlrTrace(false);} 581 | 582 ns2:ID {_td=true;declaratorID(ns2.getText(),CPPvariables.QI_TYPE);} 583 ASSIGNEQUAL qid = qualified_id SEMICOLON 584 {b.makeNamespaceAlias(qid, ns2.getText());} 585 ) 586 ; 587 588member_declaration 589 {String q="";} 590 : 591 {b.beginMemberDeclaration();} 592 ( 593 // Class definition 594 // This is separated out otherwise the next alternative 595 // would look for "class A { ... } f() {...}" which is 596 // an unacceptable level of backtracking. 597 ( ("typedef")? class_head) => declaration 598 | 599 // Enum definition (don't want to backtrack over this in other alts) 600 ("enum" (ID)? LCURLY)=>enum_specifier (member_declarator_list)? SEMICOLON 601 | 602 (template_head class_head)=>template_head declaration 603 | 604 // Constructor declarator 605 ( ctor_decl_spec {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}? ctor_declarator SEMICOLON)=> 606 ctor_decl_spec ctor_declarator SEMICOLON // Constructor declarator 607 | 608 // JEL Predicate to distinguish ctor from function 609 // This works now that ctor cannot have VIRTUAL 610 // It unfortunately matches A::A where A is not enclosing 611 // class -- this will have to be checked semantically 612 ( ctor_decl_spec 613 {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}? 614 ctor_declarator 615 (COLON // DEFINITION :ctor_initializer 616 |LCURLY // DEFINITION (compound Statement) ? 617 ) 618 )=>ctor_definition 619 | 620 // No template_head allowed for dtor member 621 // Backtrack if not a dtor (no TILDE) 622 (dtor_head SEMICOLON)=>dtor_head SEMICOLON // Declaration 623 | 624 // No template_head allowed for dtor member 625 // Backtrack if not a dtor (no TILDE) 626 (dtor_head LCURLY)=>dtor_head dtor_body // Definition 627 | 628 // Function declaration 629 (declaration_specifiers function_declarator SEMICOLON)=> 630 {b.beginFunctionDeclaration();} 631 declaration 632 {b.endFunctionDeclaration();} 633 | 634 // Function definition 635 (declaration_specifiers function_declarator LCURLY)=> 636 {b.beginFunctionDefinition(LT(2).getLine());} 637 function_definition 638 {b.endFunctionDefinition();} 639 | 640 // User-defined type cast 641 (("inline")? conversion_function_decl_or_def)=>("inline")? conversion_function_decl_or_def 642 | 643 // Hack to handle decls like "superclass::member", 644 // to redefine access to private base class public members 645 (qualified_id SEMICOLON)=>q = qualified_id SEMICOLON 646 | 647 // Member with a type or just a type def 648 // A::T a(), ::T a, ::B a, void a, E a (where E is the enclosing class) 649 (declaration_specifiers)=>declaration_specifiers (member_declarator_list)? SEMICOLON 650 651 | 652 // Member without a type (I guess it can only be a function declaration or definition) 653 (function_declarator SEMICOLON)=> function_declarator SEMICOLON 654 655 | // Member without a type (I guess it can only be a function definition) 656 function_declarator compound_statement 657 658 | 659 // templated forward class decl, init/decl of static member in template 660 // DW 27/06/03 Copied here from external_declaration since templates can now be nested 661 (template_head declaration_specifiers (init_declarator_list)? SEMICOLON)=> 662 template_head declaration_specifiers (init_declarator_list)? SEMICOLON 663 | 664 // Templated FUNCTIONS and CONSTRUCTORS matched here. 665 // DW 27/06/03 Copied here from external_declaration since templates can now be nested 666 template_head 667 ( 668 // Templated CONSTRUCTOR definition 669 // JEL 4/3/96 Added predicate that works once the 670 // restriction is added that ctor cannot be virtual 671 (ctor_decl_spec {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}?)=>ctor_definition 672 | 673 // Templated function declaration 674 (declaration_specifiers function_declarator SEMICOLON)=>declaration 675 | 676 // Templated function definition 677 // Function definition DW 2/6/97 678 (declaration_specifiers function_declarator LCURLY)=> function_definition 679 | 680 conversion_function_decl_or_def 681 ) 682 | 683 access_specifier COLON 684 | 685 SEMICOLON 686 ) 687 {b.endMemberDeclaration();} 688 ; // end member_declaration 689 690 691function_definition 692{java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); auxBitSet.or(CPPvariables.QI_CTOR);} 693 : // don't want next action as an init-action due to (...)=> caller 694 ( // Next line is equivalent to guarded predicate in PCCTS 695 // (SCOPE | ID)? => <<qualifiedItemisOneOf(QI_TYPE|QI_CTOR)>>? 696 {( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(auxBitSet,0) )}? 697 declaration_specifiers function_declarator 698 ( options{warnWhenFollowAmbig = false;}: 699 (declaration)* // Possible for K & R definition 700 )? compound_statement 701 | // Next line is equivalent to guarded predicate in PCCTS 702 // (SCOPE | ID)? => <<qualifiedItemisOneOf(QI_PTR_MEMBER)>>? 703 //{( !(LA(1)==SCOPE||LA(1)==ID) || (qualifiedItemIsOneOf(QI_PTR_MEMBER)) )}? 704 function_declarator 705 ( options{warnWhenFollowAmbig = false;}: 706 (declaration)* // Possible for K & R definition 707 )? compound_statement 708 ) 709 ; 710 711declaration 712 : 713 ("extern" StringLiteral)=> linkage_specification 714 | 715 // LL 31/1/97: added (COMMA) ? below. This allows variables to typedef'ed more than once. DW 18/08/03 ? 716 declaration_specifiers ((COMMA)? init_declarator_list)? SEMICOLON 717 | 718 using_declaration // DW 19/04/04 719 ; 720 721linkage_specification 722 : "extern" 723 StringLiteral 724 (LCURLY (external_declaration)* RCURLY 725 |declaration 726 ) 727 ; 728 729declaration_specifiers 730 {_td=false; boolean td=false; List declSpecs = new ArrayList();} 731 : 732 ( (options {warnWhenFollowAmbig = false;} 733 : storage_class_specifier 734 | type_qualifier 735 | ("inline"|"_inline"|"__inline") {declSpecs.add("inline");} 736 | "virtual" {declSpecs.add("virtual");} 737 | "explicit" {declSpecs.add("explicit");} 738 | "typedef" {td=true; declSpecs.add("typedef");} 739 | "friend" {declSpecs.add("friend");} 740 | ("_stdcall"|"__stdcall") {declSpecs.add("__stdcall");} 741 | ("_declspec"|"__declspec") LPAREN ID RPAREN // euluis: ignore 742 )* {if (!declSpecs.isEmpty()) b.declarationSpecifiers(declSpecs);} 743 type_specifier 744 | 745 "typename" {td=true;} direct_declarator 746 ) 747 {_td=td;} 748 ; 749 750storage_class_specifier 751 : "auto" {b.storageClassSpecifier("auto");} 752 | "register" {b.storageClassSpecifier("register");} 753 | "static" {b.storageClassSpecifier("static");} 754 | "extern" {b.storageClassSpecifier("extern");} 755 | "mutable" {b.storageClassSpecifier("mutable");} 756 ; 757 758type_qualifier // aka cv_qualifier 759 : ("const"|"const_cast") {b.typeQualifier("const");} // euluis TODO: const_cast ?!? 760 | "volatile" {b.typeQualifier("volatile");} 761 ; 762 763type_specifier 764 : simple_type_specifier 765 | class_specifier 766 | enum_specifier 767 ; 768 769simple_type_specifier 770 { String s=""; 771 java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); 772 auxBitSet.or(CPPvariables.QI_CTOR); 773 List sts = new ArrayList(); 774 } 775 : ( {qualifiedItemIsOneOf(auxBitSet,0)}? 776 s = qualified_type 777 {sts.add(s); b.simpleTypeSpecifier(sts);} 778 | 779 ( "char" {sts.add("char");} 780 | "wchar_t" {sts.add("wchar_t");} 781 | "bool" {sts.add("bool");} 782 | "short" {sts.add("short");} 783 | "int" {sts.add("int");} 784 | ("_int64"|"__int64") {sts.add("__int64");} 785 | "__w64" {sts.add("__w64");} 786 | "long" {sts.add("long");} 787 | "signed" {sts.add("signed");} 788 | "unsigned" {sts.add("unsigned");} 789 | "float" {sts.add("float");} 790 | "double" {sts.add("double");} 791 | "void" {sts.add("void");} 792 | ("_declspec"|"__declspec") LPAREN ID RPAREN //euluis: ignore 793 )+ {b.simpleTypeSpecifier(sts);} 794 ) 795 796 ; 797 798qualified_type returns [String q=""] 799 {String s=""; String qitem="";} 800 : 801 // JEL 3/29/96 removed this predicate and moved it upwards to 802 // simple_type_specifier. This was done to allow parsing of ~ID to 803 // be a unary_expression, which was never reached with this 804 // predicate on 805 //{qualifiedItemIsOneOf(QI_TYPE|QI_CTOR,0)}? 806 807 s = scope_override 808 id:ID 809 (options {warnWhenFollowAmbig = false;}: 810 LESSTHAN template_argument_list GREATERTHAN)? 811 { 812 qitem=s; 813 qitem=qitem+id.getText(); 814 q=qitem; 815 } 816 ; 817 818class_specifier 819 {String saveClass="";String id="";String type="";} 820 : ("class" {type=CPPvariables.OT_CLASS;} 821 |"struct" {type=CPPvariables.OT_STRUCT;} 822 |"union" {type=CPPvariables.OT_UNION;} 823 ) 824 ( id = qualified_id 825 (options{generateAmbigWarnings = false;}: 826 { saveClass = enclosingClass; 827 enclosingClass = id; 828 } 829 {b.beginClassDefinition(type, id);} 830 (base_clause)? 831 LCURLY 832 { 833 if(!symbols.containsKey(id)) 834 symbols.put(id,type); 835 } 836 (member_declaration )* 837 {b.endClassDefinition();} 838 RCURLY 839 { enclosingClass = saveClass;} 840 | 841 { 842 843 String auxName=id; 844 int pos = auxName.indexOf("::"); 845 while(pos>=0) 846 { 847 if(!symbols.containsKey(auxName.substring(0,pos))) 848 symbols.put(auxName.substring(0,pos),type); 849 auxName=auxName.substring(pos+2,auxName.length()); 850 pos=auxName.indexOf("::"); 851 } 852 if(!symbols.containsKey(auxName)) 853 symbols.put(auxName,type); 854 } 855 ) 856 | 857 LCURLY 858 { id="anonymous"; 859 saveClass = enclosingClass; enclosingClass = "anonymous"; 860 if(!symbols.containsKey(id)) 861 symbols.put(id,type); 862 } 863 (member_declaration)* RCURLY 864 {enclosingClass = saveClass;} 865 ) 866 ; 867 868enum_specifier 869 : "enum" 870 ( LCURLY 871 enumerator_list RCURLY 872 | id:ID // DW 22/04/03 Suggest qualified_id here to satisfy elaborated_type_specifier 873 { if(!symbols.containsKey(id.getText())) 874 symbols.put(id.getText(),CPPvariables.OT_ENUM); 875 } 876 ( LCURLY enumerator_list RCURLY)? 877 ) 878 ; 879 880enumerator_list 881 : enumerator (COMMA enumerator)* 882 883 ; 884 885enumerator 886 : id:ID (ASSIGNEQUAL constant_expression)? 887 888 ; 889 890/* This matches a generic qualified identifier ::T::B::foo 891 * (including OPERATOR). 892 * It might be a good idea to put T::~dtor in here 893 * as well, but id_expression in expr.g puts it in manually. 894 * Maybe not, 'cause many people use this assuming only A::B. 895 * How about a 'qualified_complex_id'? 896 */ 897qualified_id returns [String q=""] 898 { 899 String so=""; 900 String qitem=""; 901 } 902 : 903 so = scope_override 904 {qitem=so; } 905 ( 906 id:ID 907 (options{warnWhenFollowAmbig = false;}: 908 LESSTHAN template_argument_list GREATERTHAN)? 909 { 910 qitem=qitem+id.getText(); 911 } 912 | 913 OPERATOR optor 914 {qitem=qitem+"operator"+"NYI";} 915 | 916 "this" // DW 21/07/03 fix to pass test8.i 917 | 918 ("true"|"false") // DW 21/07/03 fix to pass test8.i 919 ) 920 {q = qitem;} 921 ; 922 923typeID 924 : {isTypeName(LT(1).getText())}? 925 ID 926 ; 927 928init_declarator_list 929 : {b.beginInitDeclaratorList();} 930 init_declarator (COMMA init_declarator)* 931 {b.endInitDeclaratorList();} 932 ; 933 934init_declarator 935 : declarator 936 ( 937 ASSIGNEQUAL 938 // check for initialisation and assignment (e.g. int x = 10;) 939 initializer 940 | 941 LPAREN expression_list RPAREN 942 )? 943 ; 944 945initializer 946 : 947 {b.beginInitializer();} 948 ( 949 remainder_expression // DW 18/4/01 assignment_expression 950 | 951 LCURLY initializer (COMMA initializer)* RCURLY 952 ) 953 {b.endInitializer();} 954 ; 955 956class_head 957 : // Used only by predicates 958 ("struct" 959 |"union" 960 |"class" 961 ) 962 (ID 963 (LESSTHAN template_argument_list GREATERTHAN)? 964 (base_clause)? 965 )? LCURLY 966 ; 967 968base_clause 969 : 970 COLON base_specifier (COMMA base_specifier)* 971 ; 972 973base_specifier 974 {String qt=""; b.beginBaseSpecifier();} 975 : // DW 13/08/03 Should check qualified_type for class-name? 976 ( "virtual" ( access_specifier)? qt = qualified_type {b.baseSpecifier(qt, true);} 977 | access_specifier "virtual" qt = qualified_type {b.baseSpecifier(qt, true);} 978 | access_specifier qt = qualified_type {b.baseSpecifier(qt, false);} 979 | qt = qualified_type {b.baseSpecifier(qt, false);} 980 ) 981 {b.endBaseSpecifier();} 982 ; 983 984access_specifier 985 : "public" {b.accessSpecifier("public");} 986 | "protected" {b.accessSpecifier("protected");} 987 | "private" {b.accessSpecifier("private");} 988 ; 989 990member_declarator_list 991 : member_declarator (ASSIGNEQUAL OCTALINT)? // The value must be 0 (pure virt.) 992 (COMMA member_declarator (ASSIGNEQUAL OCTALINT)? )* 993 ; 994 995member_declarator 996 : 997 ((ID)? COLON constant_expression)=>(ID)? COLON constant_expression 998 | 999 declarator 1000 ; 1001 1002conversion_function_decl_or_def 1003 : OPERATOR 1004 declaration_specifiers 1005 (STAR | AMPERSAND)? // DW 01/08/03 Use type_specifier here? see syntax 1006 (LESSTHAN template_parameter_list GREATERTHAN)? 1007 LPAREN (parameter_list)? RPAREN 1008 (type_qualifier)? 1009 (exception_specification)? 1010 ( compound_statement 1011 | SEMICOLON 1012 ) 1013 ; 1014 1015// JEL note: does not use (const|volatile)* to avoid lookahead problems 1016cv_qualifier_seq 1017 : 1018 (type_qualifier)* 1019 ; 1020 1021declarator 1022 : 1023 //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}? 1024 (ptr_operator)=>ptr_operator // AMPERSAND or STAR 1025 declarator 1026 | 1027 direct_declarator 1028 ; 1029 1030direct_declarator 1031 {String id="";} 1032 : 1033 (qualified_id LPAREN (RPAREN|declaration_specifiers) )=> // Must be function declaration 1034 id = qualified_id {declaratorID(id,CPPvariables.QI_FUN); b.directDeclarator(id);} 1035 LPAREN (parameter_list)? RPAREN (type_qualifier)* (exception_specification)? 1036 | (qualified_id LPAREN qualified_id)=> // Must be class instantiation 1037 id = qualified_id {declaratorID(id,CPPvariables.QI_VAR);}LPAREN expression_list RPAREN 1038 | 1039 (qualified_id LSQUARE)=> // Must be array declaration 1040 id = qualified_id 1041 { 1042 if (_td==true) 1043 declaratorID(id,CPPvariables.QI_TYPE); 1044 else 1045 declaratorID(id,CPPvariables.QI_VAR); 1046 } 1047 (options {warnWhenFollowAmbig = false;}: 1048 LSQUARE (constant_expression)? RSQUARE)+ 1049 | 1050 id = qualified_id 1051 { 1052 if (_td==true) 1053 declaratorID(id,CPPvariables.QI_TYPE); 1054 else { 1055 declaratorID(id,CPPvariables.QI_VAR); 1056 b.directDeclarator(id); 1057 } 1058 } 1059 | 1060 // DW 24/05/04 This block probably never entered as dtor selected out earlier 1061 // Note In fact no dictionary entries for ctor or dtor 1062 TILDE dtor:ID {declaratorID(dtor.getText(),CPPvariables.QI_DTOR);}// Note "class" not recorded in CPPSymbol 1063 LPAREN (parameter_list)? RPAREN 1064 1065 | 1066 1067 LPAREN declarator RPAREN declarator_suffixes 1068 ; 1069 1070 1071 1072declarator_suffixes 1073 {java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); auxBitSet.or(CPPvariables.QI_CTOR);} 1074 : 1075 ( 1076 (options {warnWhenFollowAmbig = false;}: 1077 LSQUARE (constant_expression)? RSQUARE)+ 1078 | {(!((LA(1)==LPAREN)&&(LA(2)==ID))||(qualifiedItemIsOneOf(auxBitSet,1)))}? 1079 LPAREN (parameter_list)? RPAREN (type_qualifier)* (exception_specification)? 1080// | // DW 28/06/04 deleted Assume either following bracketed declaration 1081// // empty 1082 ) 1083 ; 1084 1085/* I think something is weird with the context-guards for predicates; 1086 * as a result I manually hoist the appropriate pred from ptr_to_member 1087 * 1088 * TER: warning: seems that "ID::" will always bypass and go to 2nd alt :( 1089 */ 1090function_declarator 1091 : 1092 //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}? 1093 (ptr_operator)=> ptr_operator function_declarator 1094 | 1095 function_direct_declarator 1096 ; 1097 1098function_direct_declarator 1099 { String q="";} 1100 : 1101 /* predicate indicate that plain ID is ok here; this counteracts any 1102 * other predicate that gets hoisted (along with this one) that 1103 * indicates that an ID is a type or whatever. E.g., 1104 * another rule testing isTypeName() alone, implies that the 1105 * the ID *MUST* be a type name. Combining isTypeName() and 1106 * this predicate in an OR situation like this one: 1107 * ( declaration_specifiers ... | function_declarator ... ) 1108 * would imply that ID can be a type name OR a plain ID. 1109 */ 1110 ( // fix prompted by (isdigit)() in xlocnum 1111 LPAREN 1112 q = qualified_id 1113 { 1114 declaratorID(q,CPPvariables.QI_FUN); 1115 } 1116 RPAREN 1117 | 1118 q = qualified_id 1119 { 1120 declaratorID(q,CPPvariables.QI_FUN); 1121 } 1122 ) 1123 {b.functionDirectDeclarator(q);} 1124 1125 LPAREN (parameter_list)? RPAREN 1126 (options{warnWhenFollowAmbig = false;}: 1127 type_qualifier)* 1128 (ASSIGNEQUAL OCTALINT)? // The value of the octal must be 0 1129 (exception_specification)? 1130 ; 1131 1132ctor_definition 1133 : 1134 {b.beginCtorDefinition();} 1135 ctor_head 1136 ctor_body 1137 {b.endCtorDefinition();} 1138 ; 1139 1140ctor_head 1141 : 1142 ctor_decl_spec ctor_declarator 1143 ; 1144 1145ctor_decl_spec 1146 {List declSpecs = new ArrayList();} 1147 : 1148 ( ("inline"|"_inline"|"__inline") {declSpecs.add("inline");} 1149 | 1150 "explicit" {declSpecs.add("explicit");} 1151 )* 1152 {b.declarationSpecifiers(declSpecs);} 1153 ; 1154 1155ctor_declarator 1156 { String q="";} 1157 : 1158 // JEL 4/3/96 qualified_id too broad DW 10/06/03 ? 1159 q = qualified_ctor_id {b.qualifiedCtorId(q);} 1160 LPAREN (parameter_list)? RPAREN (exception_specification)? 1161 ; 1162 1163// This matches a generic qualified identifier ::T::B::foo 1164// that is satisfactory for a ctor (no operator, no trailing <>) 1165qualified_ctor_id returns [String q=""] 1166 { 1167 String so=""; 1168 String qitem=""; 1169 } 1170 : 1171 so = scope_override 1172 {qitem=so;} 1173 id:ID // DW 24/05/04 Note. Neither Ctor or Dtor recorded in dictionary 1174 {qitem=qitem+id.getText(); 1175 q = qitem;} 1176 ; 1177 1178ctor_body 1179 : 1180 (ctor_initializer)? compound_statement 1181 ; 1182 1183ctor_initializer 1184 : 1185 COLON superclass_init (COMMA superclass_init)* 1186 ; 1187 1188superclass_init 1189 {String q="";} 1190 : 1191 q = qualified_id LPAREN (expression_list)? RPAREN 1192 ; 1193 1194dtor_head 1195 : 1196 {b.beginDtorHead();} 1197 dtor_decl_spec dtor_declarator 1198 {b.endDtorHead();} 1199 ; 1200 1201dtor_decl_spec 1202 {List declSpecs = new ArrayList();} 1203 : 1204 ( 1205 ("inline"|"_inline"|"__inline") {declSpecs.add("inline");} 1206 | 1207 "virtual" {declSpecs.add("virtual");} 1208 )* 1209 {b.declarationSpecifiers(declSpecs);} 1210 ; 1211 1212dtor_declarator 1213 {String s="";} 1214 : 1215 s = scope_override 1216 1217 TILDE id:ID 1218 {b.dtorDeclarator(s+"~"+id.getText());} 1219 LPAREN RPAREN (exception_specification)? 1220 ; 1221 1222dtor_body 1223 : 1224 compound_statement 1225 ; 1226 1227parameter_list 1228 : parameter_declaration_list (ELLIPSIS)? 1229 ; 1230 1231parameter_declaration_list 1232 : 1233 ( parameter_declaration 1234 (// Have not been able to find way of stopping warning of non-determinism between alt 1 and exit branch of block 1235 COMMA parameter_declaration 1236 )* 1237 ) 1238 ; 1239 1240parameter_declaration 1241 {java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); auxBitSet.or(CPPvariables.QI_CTOR);} 1242 : {b.beginParameterDeclaration();} 1243 ( 1244 {!((LA(1)==SCOPE) && (LA(2)==STAR||LA(2)==OPERATOR))&&( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(auxBitSet,0) )}? 1245 declaration_specifiers // DW 24/3/98 Mods for K & R 1246 ( 1247 (declarator)=> declarator // if arg name given 1248 | 1249 abstract_declarator // if arg name not given // can be empty 1250 ) 1251 | 1252 (declarator)=> declarator // DW 24/3/98 Mods for K & R 1253 | 1254 ELLIPSIS 1255 ) 1256 (ASSIGNEQUAL 1257 remainder_expression // DW 18/4/01 assignment_expression 1258 )? 1259 {b.endParameterDeclaration();} 1260 ; 1261 1262type_name // aka type_id 1263 : 1264 declaration_specifiers abstract_declarator 1265 ; 1266 1267/* This rule looks a bit weird because (...) can happen in two 1268 * places within the declaration such as "void (*)()" (ptr to 1269 * function returning nothing). However, the () of a function 1270 * can only occur after having seen either a (abstract_declarator) 1271 * and not after a [..] or simple '*'. These are the only two 1272 * valid () func-groups: 1273 * int (*)(); // ptr to func 1274 * int (*[])(); // array of ptr to func 1275 */ 1276abstract_declarator 1277 : //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}? 1278 ptr_operator abstract_declarator 1279 1280 | 1281 LPAREN abstract_declarator RPAREN 1282 (abstract_declarator_suffix)+ 1283 | 1284 (LSQUARE (constant_expression )? RSQUARE )+ 1285 | 1286 /* empty */ 1287 ; 1288 1289abstract_declarator_suffix 1290 : 1291 LSQUARE (constant_expression)? RSQUARE 1292 | 1293 LPAREN (parameter_list)? RPAREN cv_qualifier_seq (exception_specification)? 1294 ; 1295 1296exception_specification 1297 {String so="";} 1298 : "throw" LPAREN 1299 ( (so = scope_override ID (COMMA so = scope_override ID)* )? 1300 | ELLIPSIS 1301 ) 1302 RPAREN 1303 ; 1304 1305template_head 1306 : 1307 "template" 1308 LESSTHAN template_parameter_list GREATERTHAN 1309 ; 1310 1311template_parameter_list 1312 : 1313 template_parameter (COMMA template_parameter)* 1314 ; 1315 1316/* Rule requires >2 lookahead tokens. The ambiguity is resolved 1317 * correctly, however. According to the manual "...A template argument 1318 * that can be interpreted either as a parameter-declaration or a 1319 * type-argument (because its identifier is the name of an 1320 * already existing class) is taken as type-argument." 1321 * Therefore, any "class ID" that is seen on the input, should 1322 * match the first alternative here (it should be a type-argument). 1323 */ 1324template_parameter 1325 : 1326 (options{generateAmbigWarnings = false;}: 1327 ("class"|"typename") 1328 (id:ID (ASSIGNEQUAL assigned_type_name)? )? 1329 { if(!symbols.containsKey(id.getText())) 1330 symbols.put(id.getText(),CPPvariables.OT_TYPE_DEF); 1331 } 1332 | 1333 parameter_declaration // DW 30/06/03 This doesn't seem to match the current standard 1334 ) 1335 ; 1336 1337/* This is to allow an assigned type_name in a template parameter 1338 * list to be defined previously in the same parameter list, 1339 * as type setting is ineffective whilst guessing 1340 */ 1341assigned_type_name 1342 {String s=""; } 1343 : 1344 (options{generateAmbigWarnings = false;}: 1345 s = qualified_type abstract_declarator 1346 | 1347 simple_type_specifier abstract_declarator 1348 ) 1349 ; 1350 1351// This rule refers to an instance of a template class or function 1352template_id // aka template_class_name 1353 : ID LESSTHAN template_argument_list GREATERTHAN 1354 ; 1355 1356template_argument_list 1357 : template_argument (COMMA template_argument)* 1358 ; 1359 1360/* Here assignment_expression was changed to shift_expression to rule out 1361 * x< 1<2 > which causes ambiguities. As a result, these can be used only 1362 * by enclosing parentheses x<(1<2)>. This is true for x<1+2> ==> bad, 1363 * x<(1+2)> ==> ok. 1364 */ 1365template_argument 1366{java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); auxBitSet.or(CPPvariables.QI_CTOR);} 1367 : 1368 {( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(auxBitSet,0) )}? 1369 type_name 1370 | 1371 shift_expression // failed in iosfwd 1372// | assignment_expression // Inserted as per grammar summary 1373 ; 1374 1375/////////////////////////////////////////////////////////////////////// 1376/////////////////////////////////////////////////////////////////////// 1377////////////////////////////// STATEMENTS //////////////////////////// 1378/////////////////////////////////////////////////////////////////////// 1379/////////////////////////////////////////////////////////////////////// 1380 1381statement_list 1382 : (statement)+ 1383 ; 1384 1385statement 1386 : 1387 ( (declaration)=>declaration 1388 | labeled_statement 1389 | case_statement 1390 | default_statement 1391 | 1392 {b.beginExpressionStatement();} 1393 expression SEMICOLON 1394 {b.endExpressionStatement();} 1395 | compound_statement 1396 | selection_statement 1397 | iteration_statement 1398 | jump_statement 1399 | SEMICOLON 1400 | try_block 1401 | throw_statement 1402 | asm_block 1403 ) 1404 ; 1405 1406labeled_statement 1407 : ID COLON statement 1408 ; 1409 1410case_statement 1411 : {b.beginCaseStatement();} 1412 "case" 1413 constant_expression COLON statement 1414 {b.endCaseStatement();} 1415 ; 1416 1417default_statement 1418 : {b.beginDefaultStatement();} 1419 "default" COLON statement 1420 {b.endDefaultStatement();} 1421 ; 1422 1423compound_statement 1424 : 1425 {b.beginCompoundStatement();} 1426 LCURLY (statement_list)? RCURLY 1427 {b.endCompoundStatement();} 1428 ; 1429 1430/* NOTE: cannot remove ELSE ambiguity, but it parses correctly. 1431 * The warning is removed with the options statement 1432 */ 1433selection_statement 1434 : 1435 {b.beginIfStatement();} 1436 "if" LPAREN expression RPAREN statement 1437 {b.endIfStatement();} 1438 (options {warnWhenFollowAmbig = false;}: 1439 {b.beginElseStatement();} 1440 "else" statement 1441 {b.endElseStatement();} 1442 )? 1443 | 1444 {b.beginSwitchStatement();} 1445 "switch" LPAREN expression RPAREN statement 1446 {b.endSwitchStatement();} 1447 ; 1448 1449iteration_statement 1450 : 1451 {b.beginWhileStatement();} 1452 "while" LPAREN expression RPAREN statement 1453 {b.endWhileStatement();} 1454 | 1455 {b.beginDoStatement();} 1456 "do" statement "while" LPAREN expression RPAREN SEMICOLON 1457 {b.endDoStatement();} 1458 | 1459 {b.beginForStatement();} 1460 "for" LPAREN 1461 ( (declaration)=> declaration 1462 | expression SEMICOLON 1463 | SEMICOLON 1464 ) 1465 (expression)? SEMICOLON 1466 (expression)? 1467 RPAREN statement 1468 {b.endForStatement();} 1469 ; 1470 1471jump_statement 1472 : 1473 ( "goto" ID SEMICOLON 1474 {b.gotoStatement();} 1475 | "continue" SEMICOLON 1476 {b.continueStatement();} 1477 | "break" SEMICOLON 1478 {b.breakStatement();} 1479 // DW 16/05/03 May be problem here if return is followed by a cast expression 1480 | {b.beginReturnStatement(LT(1).getLine());} 1481 "return" 1482 ( options{warnWhenFollowAmbig = false;}: 1483 (LPAREN {(qualifiedItemIsOneOf(CPPvariables.QI_TYPE,0) )}? ID RPAREN)=> 1484 LPAREN ID RPAREN (expression)? // This is an unsatisfactory fix for problem in xstring re "return (allocator);" 1485 // and in xlocale re return (_E)(_Tolower((unsigned char)_C, &_Ctype)); 1486 //{printf("%d CPP_parser.g jump_statement Return fix used\n",LT(1)->getLine());} 1487 | expression 1488 )? SEMICOLON 1489 {b.endReturnStatement();} 1490 ) 1491 ; 1492 1493try_block 1494 : "try" compound_statement (handler)* 1495 ; 1496 1497 1498handler 1499 : "catch" LPAREN exception_declaration RPAREN compound_statement 1500 ; 1501 1502exception_declaration 1503 : parameter_declaration_list 1504 ; 1505 1506/* This is an expression of type void according to the ARM, which 1507 * to me means "statement"; it removes some ambiguity to put it in 1508 * as a statement also. 1509 */ 1510throw_statement 1511 : "throw" (assignment_expression) ? SEMICOLON 1512 ; 1513 1514using_declaration 1515 {String qid="";} 1516 : "using" 1517 ("namespace" qid = qualified_id // Using-directive 1518 |qid = qualified_id // Using-declaration 1519 ) 1520 SEMICOLON 1521 ; 1522 1523asm_block 1524 : ("_asm"|"__asm") LCURLY (~RCURLY)* RCURLY 1525 ; 1526 1527/////////////////////////////////////////////////////////////////////// 1528/////////////////////////////////////////////////////////////////////// 1529////////////////////////////// EXPRESSIONS /////////////////////////// 1530/////////////////////////////////////////////////////////////////////// 1531/////////////////////////////////////////////////////////////////////// 1532 1533expression 1534 : 1535 {b.beginExpression();} 1536 assignment_expression (COMMA assignment_expression)* 1537 {b.endExpression();} 1538 ; 1539 1540expression_list 1541 : assignment_expression (COMMA assignment_expression)* 1542 ; 1543 1544/* right-to-left for assignment op */ 1545assignment_expression 1546 : 1547 conditional_expression 1548 ( 1549 {b.beginAssignmentExpression(LT(1).getLine());} 1550 (ASSIGNEQUAL 1551 |TIMESEQUAL|DIVIDEEQUAL|MINUSEQUAL|PLUSEQUAL 1552 |MODEQUAL 1553 |SHIFTLEFTEQUAL 1554 |SHIFTRIGHTEQUAL 1555 |BITWISEANDEQUAL 1556 |BITWISEXOREQUAL 1557 |BITWISEOREQUAL 1558 ) 1559 remainder_expression 1560 {b.endAssignmentExpression();} 1561 )? 1562 ; 1563 1564remainder_expression 1565 : 1566 ( (conditional_expression (COMMA|SEMICOLON|RPAREN) 1567 )=> 1568 assignment_expression 1569 | 1570 assignment_expression 1571 ) 1572 ; 1573 1574conditional_expression 1575 : 1576 logical_or_expression 1577 ( 1578 {b.beginTernaryOperator();} 1579 QUESTIONMARK expression COLON conditional_expression 1580 {b.endTernaryOperator();} 1581 )? 1582 ; 1583 1584constant_expression 1585 : 1586 conditional_expression 1587 ; 1588 1589logical_or_expression 1590 : 1591 logical_and_expression (OR logical_and_expression)* 1592 ; 1593 1594logical_and_expression 1595 : 1596 inclusive_or_expression (AND inclusive_or_expression)* 1597 ; 1598 1599inclusive_or_expression 1600 : 1601 exclusive_or_expression (BITWISEOR exclusive_or_expression)* 1602 ; 1603 1604exclusive_or_expression 1605 : 1606 and_expression (BITWISEXOR and_expression)* 1607 ; 1608 1609and_expression 1610 : 1611 equality_expression (AMPERSAND equality_expression)* 1612 ; 1613 1614equality_expression 1615 : 1616 relational_expression ((NOTEQUAL | EQUAL) relational_expression)* 1617 ; 1618 1619relational_expression 1620 : shift_expression 1621 (options {warnWhenFollowAmbig = false;}: 1622 ( LESSTHAN 1623 | GREATERTHAN 1624 | LESSTHANOREQUALTO 1625 | GREATERTHANOREQUALTO 1626 ) 1627 shift_expression 1628 )* 1629 ; 1630 1631shift_expression 1632 : additive_expression ((SHIFTLEFT | SHIFTRIGHT) additive_expression)* 1633 ; 1634 1635/* See comment for multiplicative_expression regarding #pragma */ 1636additive_expression 1637 : multiplicative_expression 1638 (options{warnWhenFollowAmbig = false;}: 1639 (PLUS | MINUS) multiplicative_expression 1640 )* 1641 ; 1642 1643/* ANTLR has trouble dealing with the analysis of the confusing unary/binary 1644 * operators such as STAR, AMPERSAND, PLUS, etc... With the #pragma (now "(options{warnWhenFollowAmbig = false;}:" etc.) 1645 * we simply tell ANTLR to use the "quick-to-analyze" approximate lookahead 1646 * as full LL(k) lookahead will not resolve the ambiguity anyway. Might 1647 * as well not bother. This has the side-benefit that ANTLR doesn't go 1648 * off to lunch here (take infinite time to read grammar). 1649 */ 1650multiplicative_expression 1651 : pm_expression 1652 (options{warnWhenFollowAmbig = false;}: 1653 (STAR | DIVIDE | MOD) pm_expression 1654 )* 1655 ; 1656 1657pm_expression 1658 : cast_expression ((DOTMBR | POINTERTOMBR) cast_expression)* 1659 ; 1660 1661/* The string "( ID" can be either the start of a cast or 1662 * the start of a unary_expression. However, the ID must 1663 * be a type name for it to be a cast. Since ANTLR can only hoist 1664 * semantic predicates that are visible without consuming a token, 1665 * the semantic predicate in rule type_name is not hoisted--hence, the 1666 * rule is reported to be ambiguous. I am manually putting in the 1667 * correctly hoisted predicate. 1668 * 1669 * Ack! Actually "( ID" might be the start of "(T(expr))" which makes 1670 * the first parens just an ordinary expression grouping. The solution 1671 * is to look at what follows the type, T. Note, this could be a 1672 * qualified type. Yucko. I believe that "(T(" can only imply 1673 * function-style type cast in an expression (...) grouping. 1674 * 1675 * We DO NOT handle the following situation correctly at the moment: 1676 * Suppose you have 1677 * struct rusage rusage; 1678 * return (rusage.fp); 1679 * return (rusage*)p; 1680 * Now essentially there is an ambiguity here. If rusage is followed by any 1681 * postix operators then it is an identifier else it is a type name. This 1682 * problem does not occur in C because, unless the tag struct is attached, 1683 * rusage is not a type name. However in C++ that restriction is removed. 1684 * No *real* programmer would do this, but it's in the C++ standard just for 1685 * fun.. 1686 * 1687 * Another fun one (from an LL standpoint): 1688 * 1689 * (A::B::T *)v; // that's a cast of v to type A::B::T 1690 * (A::B::foo); // that's a simple member access 1691 * 1692 * The qualifiedItemIs(1) function scans ahead to what follows the 1693 * final "::" and returns QI_TYPE if the item is a type. The offset of 1694 * '1' makes it ignore the initial LPAREN; normally, the offset is 0. 1695 */ 1696 1697cast_expression 1698 : 1699 // DW 23/06/03 1700 (LPAREN (type_qualifier)? simple_type_specifier (ptr_operator)? RPAREN)=> 1701 LPAREN (type_qualifier)? simple_type_specifier (ptr_operator)? RPAREN cast_expression 1702 | 1703 unary_expression // handles outer (...) of "(T(expr))" 1704 ; 1705 1706unary_expression 1707 : 1708 ( //{!(LA(1)==TILDE && LA(2)==ID)||qualifiedItemIsOneOf(QI_VAR|QI_FUN|QI_DTOR|QI_CTOR)}? 1709 (postfix_expression)=> postfix_expression 1710 | PLUSPLUS unary_expression 1711 | MINUSMINUS unary_expression 1712 | unary_operator cast_expression 1713 | "sizeof" 1714 (// see comment for rule cast_expression for info on predicate 1715 // JEL NOTE 3/31/96 -- This won't work -- you really need to 1716 // call qualifiedItemIsOneOf(QI_TYPE|QI_CTOR,1) 1717 // The context should also be ( LPAREN (SCOPE|ID) ) 1718 // ( LPAREN ID ) => {isTypeName((LT(2)->getText()).data())}? 1719 {(!(((LA(1)==LPAREN&&(LA(2)==ID))))||(isTypeName(LT(2).getText())))}? 1720 LPAREN type_name RPAREN 1721 | unary_expression 1722 ) 1723 | 1724 (SCOPE)? 1725 (new_expression 1726 |delete_expression 1727 ) 1728 ) 1729 ; 1730 1731postfix_expression 1732 {String function_name="";} 1733 : 1734 ( 1735 options {warnWhenFollowAmbig = false;}: 1736 // Function-style cast must have a leading type 1737 {!(LA(1)==LPAREN)}? 1738 (simple_type_specifier LPAREN RPAREN LPAREN)=> // DW 01/08/03 To cope with problem in xtree (see test10.i) 1739 simple_type_specifier LPAREN RPAREN LPAREN (expression_list)? RPAREN 1740 | 1741 {!(LA(1)==LPAREN)}? 1742 (simple_type_specifier LPAREN)=> 1743 simple_type_specifier LPAREN (expression_list)? RPAREN 1744 | 1745 {b.beginPostfixExpression();} 1746 primary_expression 1747 (options {warnWhenFollowAmbig = false;}: 1748 LSQUARE expression RSQUARE 1749 | LPAREN 1750 {b.beginParameterList();} 1751 (expression_list)? 1752 {b.endParameterList();} 1753 RPAREN 1754 | DOT 1755 {b.beginMemberAccess();} 1756 id_expression 1757 {b.endMemberAccess();} 1758 | POINTERTO 1759 {b.beginMemberAccess();} 1760 id_expression 1761 {b.endMemberAccess();} 1762 | PLUSPLUS 1763 | MINUSMINUS 1764 )* 1765 {b.endPostfixExpression();} 1766 | 1767 ("dynamic_cast"|"static_cast"|"reinterpret_cast"|"const_cast") // Note const_cast in elsewhere 1768 LESSTHAN type_specifier (ptr_operator)? GREATERTHAN 1769 LPAREN expression RPAREN 1770 ) 1771 ; 1772 1773primary_expression 1774 : 1775 {b.beginPrimaryExpression();} 1776 id_expression 1777 | constant 1778 | "this" 1779 | LPAREN expression RPAREN 1780 {b.endPrimaryExpression();} 1781 ; 1782 1783id_expression 1784 {String s="";} 1785 : 1786 s = scope_override 1787 ( 1788 t:ID 1789 {b.idExpression(t.getText());} 1790 | OPERATOR optor 1791 | TILDE (STAR)? ID // DW 29/07/03 STAR included to allow for *_S = ~*_S; seen in vector 1792 ) 1793 ; 1794 1795unary_operator 1796 : AMPERSAND 1797 | STAR 1798 | PLUS 1799 | MINUS 1800 | TILDE 1801 | NOT 1802 ; 1803 1804/* JEL The first ()? is used to resolve "new (expr) (type)" because both 1805 * (expr) and (type) look identical until you've seen the whole thing. 1806 * 1807 * new_initializer appears to be conflicting with function arguments as 1808 * function arguments can follow a primary_expression. [This is a full 1809 * LL(k) versus LALL(k) problem. Enhancing context by duplication of 1810 * some rules might handle this.] 1811 */ 1812new_expression 1813 : 1814 ( 1815 "new" 1816 ((LPAREN expression_list RPAREN)=> 1817 LPAREN expression_list RPAREN)? 1818 (new_type_id | LPAREN type_name RPAREN) 1819 (options{warnWhenFollowAmbig = false;}: 1820 (new_initializer)=> new_initializer)? 1821 ) 1822 ; 1823 1824new_initializer 1825 : LPAREN (expression_list)? RPAREN 1826 ; 1827 1828new_type_id 1829 : declaration_specifiers 1830 (options {warnWhenFollowAmbig = false;}: 1831 //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}? 1832 new_declarator 1833 )? 1834 ; 1835 1836new_declarator 1837 : //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}? 1838 //ptr_to_member cv_qualifier_seq 1839 ptr_operator 1840 (options {warnWhenFollowAmbig = false;}: 1841 new_declarator ) ? 1842 | direct_new_declarator 1843 ; 1844 1845ptr_operator 1846 : 1847 {b.beginPtrOperator();} 1848 ( AMPERSAND {b.ptrOperator("&");} 1849 | ("_cdecl"|"__cdecl") 1850 | ("_near"|"__near") 1851 | ("_far"|"__far") 1852 | "__interrupt" 1853 | ("pascal"|"_pascal"|"__pascal") 1854 | ("_stdcall"|"__stdcall") 1855 | ptr_to_member // e.g. STAR; euluis (2005-07-13): calls 1856 // b.ptrOperator("*") or b.ptrToMember(s, "*"). 1857 ) 1858 {b.endPtrOperator();} 1859 ; 1860 1861// Match A::B::* 1862ptr_to_member 1863 {String s="";} 1864 : 1865 s = scope_override STAR 1866 { 1867 if (s.length() != 0) b.ptrToMember(s, "*"); 1868 else b.ptrOperator("*"); 1869 } 1870 cv_qualifier_seq 1871 ; 1872 1873// Match the A::B::C:: or nothing 1874scope_override returns [String s=""] 1875 { 1876 String sitem=""; 1877 } 1878 : 1879 //{!(qualifiedItemIsOneOf(QI_TYPE))}? 1880 (SCOPE {sitem=sitem+"::";})? 1881 ( options {warnWhenFollowAmbig = false;}: 1882 {scopedItem(1)}? 1883 id:ID (LESSTHAN template_argument_list GREATERTHAN)? SCOPE 1884 { 1885 sitem=sitem+id.getText(); 1886 sitem=sitem+"::"; 1887 } 1888 )* 1889 {s = sitem;} 1890 ; 1891 1892/* The "[expression]" construct conflicts with the "new []" construct 1893 * (and possibly others). We used approximate lookahead for the "new []" 1894 * construct so that it would not try to compute full LL(2) lookahead. 1895 * Here, we use #pragma approx again because anytime we see a [ followed 1896 * by token that can begin an expression, we always want to loop. 1897 * Approximate lookahead handles this correctly. In fact, approximate 1898 * lookahead is the same as full lookahead when all but the last lookahead 1899 * depth are singleton sets; e.g., {"["} followed by FIRST(expression). 1900 */ 1901 1902 1903direct_new_declarator 1904 : 1905 (options {warnWhenFollowAmbig = false;}: 1906 LSQUARE expression RSQUARE 1907 )+ 1908 ; 1909 1910delete_expression 1911 : "delete" (LSQUARE RSQUARE)? cast_expression 1912 ; 1913 1914constant 1915 : OCTALINT 1916 | DECIMALINT 1917 | HEXADECIMALINT 1918 | CharLiteral 1919 | (StringLiteral)+ 1920 | FLOATONE 1921 | FLOATTWO 1922 | "true" 1923 | "false" 1924 ; 1925 1926optor 1927 : 1928 "new" 1929 (options {warnWhenFollowAmbig = false;}: 1930 LSQUARE RSQUARE | ) // check syntax 1931 | 1932 "delete" 1933 (options {warnWhenFollowAmbig = false;}: 1934 LSQUARE RSQUARE | ) // check syntax 1935 | LPAREN RPAREN 1936 | LSQUARE RSQUARE 1937 | optor_simple_tokclass //OPTOR_SIMPLE_TOKCLASS 1938 ; 1939 1940//Zuo 5/11/2001 1941// This is the equivalent to "#tokclass OPTOR_SIMPLE_TOKCLASS" in cplusplus.g 1942 1943optor_simple_tokclass 1944 : 1945 (PLUS 1946 |MINUS 1947 |STAR 1948 |DIVIDE 1949 |MOD 1950 |BITWISEXOR 1951 |AMPERSAND 1952 |BITWISEOR 1953 |TILDE 1954 |NOT 1955 |SHIFTLEFT 1956 |SHIFTRIGHT 1957 |ASSIGNEQUAL 1958 |TIMESEQUAL 1959 |DIVIDEEQUAL 1960 |MODEQUAL 1961 |PLUSEQUAL 1962 |MINUSEQUAL 1963 |SHIFTLEFTEQUAL 1964 |SHIFTRIGHTEQUAL 1965 |BITWISEANDEQUAL 1966 |BITWISEXOREQUAL 1967 |BITWISEOREQUAL 1968 |EQUAL 1969 |NOTEQUAL 1970 |LESSTHAN 1971 |GREATERTHAN 1972 |LESSTHANOREQUALTO 1973 |GREATERTHANOREQUALTO 1974 |OR 1975 |AND 1976 |PLUSPLUS 1977 |MINUSMINUS 1978 |COMMA 1979 |POINTERTO 1980 |POINTERTOMBR 1981 ) 1982 ; 1983 1984 1985 1986// Zuo 19/11/01 from next line, the Lexer is derived from stdCParser.g 1987 1988class InternalLexer extends Lexer; 1989 1990options 1991 { 1992 k = 3; 1993 exportVocab = STDC; 1994 testLiterals = true; 1995 } 1996 1997// DW 4/11/02 put in to support manual hoisting 1998tokens 1999 { 2000 OPERATOR = "operator"; 2001 } 2002 2003 2004/* Operators: */ 2005 2006ASSIGNEQUAL : '=' ; 2007COLON : ':' ; 2008COMMA : ',' ; 2009QUESTIONMARK : '?' ; 2010SEMICOLON : ';' ; 2011POINTERTO : "->" ; 2012 2013/* 2014// DOT & ELLIPSIS are commented out since they are generated as part of 2015// the Number rule below due to some bizarre lexical ambiguity shme. 2016// DOT : '.' ; 2017// ELLIPSIS : "..." ; 2018*/ 2019 2020LPAREN : '(' ; 2021RPAREN : ')' ; 2022LSQUARE : '[' ; 2023RSQUARE : ']' ; 2024LCURLY : '{' ; 2025RCURLY : '}' ; 2026 2027EQUAL : "==" ; 2028NOTEQUAL : "!=" ; 2029LESSTHANOREQUALTO : "<=" ; 2030LESSTHAN : "<" ; 2031GREATERTHANOREQUALTO : ">=" ; 2032GREATERTHAN : ">" ; 2033 2034DIVIDE : '/' ; 2035DIVIDEEQUAL : "/=" ; 2036PLUS : '+' ; 2037PLUSEQUAL : "+=" ; 2038PLUSPLUS : "++" ; 2039MINUS : '-' ; 2040MINUSEQUAL : "-=" ; 2041MINUSMINUS : "--" ; 2042STAR : '*' ; 2043TIMESEQUAL : "*=" ; 2044MOD : '%' ; 2045MODEQUAL : "%=" ; 2046SHIFTRIGHT : ">>" ; 2047SHIFTRIGHTEQUAL : ">>=" ; 2048SHIFTLEFT : "<<" ; 2049SHIFTLEFTEQUAL : "<<=" ; 2050 2051AND : "&&" ; 2052NOT : '!' ; 2053OR : "||" ; 2054 2055AMPERSAND : '&' ; 2056BITWISEANDEQUAL : "&=" ; 2057TILDE : '~' ; 2058BITWISEOR : '|' ; 2059BITWISEOREQUAL : "|=" ; 2060BITWISEXOR : '^' ; 2061BITWISEXOREQUAL : "^=" ; 2062 2063//Zuo: the following tokens are come from cplusplus.g 2064 2065POINTERTOMBR : "->*" ; 2066DOTMBR : ".*" ; 2067 2068SCOPE : "::" ; 2069 2070// DW 10/10/02 2071// Whitespace -- ignored 2072Whitespace 2073 : ( (' ' |'\t' | '\f') 2074 // handle newlines 2075 | ( "\r\n" // MS 2076 | '\r' // Mac 2077 | '\n' // Unix 2078 ) { newline(); } 2079 // handle continuation lines 2080 | ( "\\\r\n" // MS 2081 | "\\\r" // Mac 2082 | "\\\n" // Unix 2083 ) 2084 ) 2085 {$setType(Token.SKIP); } 2086 ; 2087 2088Comment 2089 : "/*" 2090 ( {LA(2) != '/'}? '*' 2091 | EndOfLine {newline();} 2092 | ~('*'| '\r' | '\n') 2093 )* 2094 "*/" 2095 {$setType(Token.SKIP);} 2096 ; 2097 2098CPPComment 2099 : "//" (~('\n' | '\r'))* EndOfLine 2100 {$setType(Token.SKIP);newline();} 2101 ; 2102 2103DIRECTIVE 2104 : '#' ld:LineDirective 2105 { $setType(Token.SKIP); newline();} 2106 ; 2107 2108protected 2109LineDirective 2110 : 2111 (~('\r'|'\n'))* EndOfLine 2112 ; 2113 2114/* Literals: */ 2115 2116/* 2117 * Note that we do NOT handle tri-graphs nor multi-byte sequences. 2118 */ 2119 2120/* 2121 * Note that we can't have empty character constants (even though we 2122 * can have empty strings :-). 2123 */ 2124CharLiteral 2125 : '\'' (Escape | ~( '\'' )) '\'' 2126 ; 2127 2128/* 2129 * Can't have raw imbedded newlines in string constants. Strict reading of 2130 * the standard gives odd dichotomy between newlines & carriage returns. 2131 * Go figure. 2132 */ 2133StringLiteral 2134 : '"' 2135 ( Escape 2136 | ( "\\\r\n" // MS 2137 | "\\\r" // MAC 2138 | "\\\n" // Unix 2139 ) {newline();} 2140 | ~('"' | '\r' | '\n' | '\\') 2141 )* 2142 '"' 2143 ; 2144 2145protected 2146EndOfLine 2147 : ( options{generateAmbigWarnings = false;}: 2148 "\r\n" // MS 2149 | '\r' // Mac 2150 | '\n' // Unix 2151 ) 2152 ; 2153 2154/* 2155 * Handle the various escape sequences. 2156 * 2157 * Note carefully that these numeric escape *sequences* are *not* of the 2158 * same form as the C language numeric *constants*. 2159 * 2160 * There is no such thing as a binary numeric escape sequence. 2161 * 2162 * Octal escape sequences are either 1, 2, or 3 octal digits exactly. 2163 * 2164 * There is no such thing as a decimal escape sequence. 2165 * 2166 * Hexadecimal escape sequences are begun with a leading \x and continue 2167 * until a non-hexadecimal character is found. 2168 * 2169 * No real handling of tri-graph sequences, yet. 2170 */ 2171 2172protected 2173Escape 2174 : '\\' 2175 ( options{warnWhenFollowAmbig=false;}: 2176 'a' 2177 | 'b' 2178 | 'f' 2179 | 'n' 2180 | 'r' 2181 | 't' 2182 | 'v' 2183 | '"' 2184 | '\'' 2185 | '\\' 2186 | '?' 2187 | ('0'..'3') (options{warnWhenFollowAmbig=false;}: Digit (options{warnWhenFollowAmbig=false;}: Digit)? )? 2188 | ('4'..'7') (options{warnWhenFollowAmbig=false;}: Digit)? 2189 | 'x' (options{warnWhenFollowAmbig=false;}: Digit | 'a'..'f' | 'A'..'F')+ 2190 ) 2191 ; 2192 2193/* Numeric Constants: */ 2194 2195protected 2196Digit 2197 : '0'..'9' 2198 ; 2199 2200protected 2201Decimal 2202 : ('0'..'9')+ 2203 ; 2204 2205protected 2206LongSuffix 2207 : 'l' 2208 | 'L' 2209 ; 2210 2211protected 2212UnsignedSuffix 2213 : 'u' 2214 | 'U' 2215 ; 2216 2217protected 2218FloatSuffix 2219 : 'f' 2220 | 'F' 2221 ; 2222 2223protected 2224Exponent 2225 : ('e' | 'E') ('+' | '-')? (Digit)+ 2226 ; 2227 2228protected 2229Vocabulary 2230 : '\3'..'\377' 2231 ; 2232 2233Number 2234 : ( (Digit)+ ('.' | 'e' | 'E') )=> (Digit)+ 2235 ( '.' (Digit)* (Exponent)? {$setType ( FLOATONE);} //Zuo 3/12/01 2236 | Exponent {$setType (FLOATTWO);} //Zuo 3/12/01 2237 ) 2238 (FloatSuffix 2239 |LongSuffix 2240 )? 2241 2242 | ("...")=> "..." {$setType (ELLIPSIS);} 2243 2244 | '.' {$setType (DOT);} 2245 ( (Digit)+ (Exponent)? {$setType (FLOATONE);} //Zuo 3/12/01 2246 //{_ttype = DoubleDoubleConst;} 2247 (FloatSuffix //{_ttype = FloatDoubleConst;} 2248 |LongSuffix //{_ttype = LongDoubleConst;} 2249 )? 2250 )? 2251 2252 | '0' ('0'..'7')* //{_ttype = IntOctalConst;} 2253 (LongSuffix //{_ttype = LongOctalConst;} 2254 |UnsignedSuffix //{_ttype = UnsignedOctalConst;} 2255 )* {$setType( OCTALINT);} 2256 2257 | '1'..'9' (Digit)* //{_ttype = IntIntConst;} 2258 (LongSuffix //{_ttype = LongIntConst;} 2259 |UnsignedSuffix //{_ttype = UnsignedIntConst;} 2260 )* {$setType( DECIMALINT);} 2261 2262 | '0' ('x' | 'X') ('a'..'f' | 'A'..'F' | Digit)+ 2263 //{_ttype = IntHexConst;} 2264 (LongSuffix //{_ttype = LongHexConst;} 2265 |UnsignedSuffix //{_ttype = UnsignedHexConst;} 2266 )* {$setType( HEXADECIMALINT);} 2267 ; 2268 2269ID 2270 options {testLiterals = true;} 2271 : ( 'a'..'z' | 'A'..'Z' | '_' ) 2272 ( 'a'..'z' | 'A'..'Z' | '_' | '0'..'9' )* 2273 ;