PageRenderTime 103ms CodeModel.GetById 2ms app.highlight 88ms RepoModel.GetById 1ms app.codeStats 1ms

/cpp/src/main/antlr/cppparser.g

http://testability-explorer.googlecode.com/
Unknown | 2273 lines | 2067 code | 206 blank | 0 comment | 0 complexity | 817f19aceb922d7cb54e0a5b35fa2250 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   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)

Large files files are truncated, but you can click here to view the full file