/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
- /*
- * PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g)
- *
- * Authors: Sumana Srinivasan, NeXT Inc.; sumana_srinivasan@next.com
- * Terence Parr, Parr Research Corporation; parrt@parr-research.com
- * Russell Quong, Purdue University; quong@ecn.purdue.edu
- *
- * VERSION 1.2
- *
- * SOFTWARE RIGHTS
- *
- * This file is a part of the ANTLR-based C++ grammar and is free
- * software. We do not reserve any LEGAL rights to its use or
- * distribution, but you may NOT claim ownership or authorship of this
- * grammar or support code. An individual or company may otherwise do
- * whatever they wish with the grammar distributed herewith including the
- * incorporation of the grammar or the output generated by ANTLR into
- * commerical software. You may redistribute in source or binary form
- * without payment of royalties to us as long as this header remains
- * in all source distributions.
- *
- * We encourage users to develop parsers/tools using this grammar.
- * In return, we ask that credit is given to us for developing this
- * grammar. By "credit", we mean that if you incorporate our grammar or
- * the generated code into one of your programs (commercial product,
- * research project, or otherwise) that you acknowledge this fact in the
- * documentation, research report, etc.... In addition, you should say nice
- * things about us at every opportunity.
- *
- * As long as these guidelines are kept, we expect to continue enhancing
- * this grammar. Feel free to send us enhancements, fixes, bug reports,
- * suggestions, or general words of encouragement at parrt@parr-research.com.
- *
- * NeXT Computer Inc.
- * 900 Chesapeake Dr.
- * Redwood City, CA 94555
- * 12/02/1994
- *
- * Restructured for public consumption by Terence Parr late February, 1995.
- *
- * DISCLAIMER: we make no guarantees that this grammar works, makes sense,
- * or can be used to do anything useful.
- */
- /* 2001-2002
- * Version 1.0
- * This C++ grammar file has been converted from PCCTS to run under
- * ANTLR to generate lexer and parser in C++ code by
- * Jianguo Zuo and David Wigg at
- * The Centre for Systems and Software Engineering
- * London South Bank University
- * London, UK.
- *
- */
- /* 2003
- * Version 2.0 was published by David Wigg in September 2003
- */
- /* 2004
- * Version 3.0 July 2004
- * This is version 3.0 of the C++ grammar definition for ANTLR to
- * generate lexer and parser in C++ code updated by
- * David Wigg at
- * The Centre for Systems and Software Engineering
- * London South Bank University
- * London, UK.
- *
- * wiggjd@bcs.ac.uk
- * blackse@lsbu.ac.uk
- *
- * See MyReadMe.txt for further information
- *
- * This file is best viewed in courier font with tabs set to 4 spaces
- */
- /* 2005
- * Version 0.01 February 2005
- * This is version 0.01 of the C++ grammar definition for ANTLR to
- * generate lexer and parser in Java code. This grammar was based
- * in the above version of the grammar by David Wigg, having been
- * ported to work in java programs.
- * The grammar file name is now different to enable diferentiation
- * from the original C++ grammar for C++ output. Many of the original
- * C++ grammar support files were removed, being for now the only
- * needed file the CPPvariables.java.
- *
- * This grammar is being developed in the context of the ArgoUML
- * project, being the basis for the C++ reverse engineering
- * functionalities of the C++ module.
- *
- * TODO: provide more documentation.
- * TODO: send to the ANTLR users list to enable review.
- * TODO: improve stand-alone use.
- *
- * www.argouml.org
- */
- header
- {
- /*REMOVE_BEGIN*/
- package com.google.test.metric.cpp;
- /*REMOVE_END*/
- import java.util.Hashtable;
- import java.util.List;
- import java.util.ArrayList;
- }
- class InternalParser extends Parser;
- options
- {
- k = 2;
- exportVocab = STDC;
- codeGenMakeSwitchThreshold = 2;
- codeGenBitsetTestThreshold = 3;
- defaultErrorHandler=false;
- //analyzerDebug = true;
- }
- {
- private Builder b;
- String enclosingClass="";//name of current class
- boolean _td=false; // is type declaration?
- Hashtable symbols=new Hashtable();
- public boolean qualifiedItemIsOneOf(java.util.BitSet qiFlags, int lookahead_offset) throws TokenStreamException
- {
- java.util.BitSet qi = qualifiedItemIs(lookahead_offset);
- java.util.BitSet aux=(java.util.BitSet) qi.clone();
- aux.and(qiFlags);
- return (!aux.isEmpty());
- }
- // This is an important function, but will be replaced with
- // an enhanced predicate in the future, once predicates
- // and/or predicate guards can contain loops.
- //
- // Scan past the ::T::B:: to see what lies beyond.
- // Return QI_TYPE if the qualified item can pose as type name.
- // Note that T::T is NOT a type; it is a constructor. Also,
- // class T { ... T...} yields the enclosed T as a ctor. This
- // is probably a type as I separate out the constructor defs/decls,
- // I want it consistent with T::T.
- //
- // In the below examples, I use A,B,T and example types, and
- // a,b as example ids.
- // In the below examples, any A or B may be a
- // qualified template, i.e., A<...>
- //
- // T::T outside of class T yields QI_CTOR.
- // T<...>::T outside of class T yields QI_CTOR.
- // T inside of class T {...} yields QI_CTOR.
- // T, ::T, A::T outside of class T yields QI_TYPE.
- // a, ::a, A::B::a yields qiId
- // a::b yields QI_INVALID
- // ::operator, operator, A::B::operator yield qiOPerator
- // A::*, A::B::* yield QI_PTR_MEMBER
- // ::*, * yields QI_INVALID
- // ::~T, ~T, A::~T yield QI_DTOR
- // ~a, ~A::a, A::~T::, ~T:: yield QI_INVALID
- public java.util.BitSet qualifiedItemIs(int lookahead_offset) throws TokenStreamException
- {
- int value;
- int k = lookahead_offset + 1;
- int final_type_idx = 0;
- boolean scope_found = false;
- // Skip leading "::"
- if (LT(k).getType() == SCOPE)
- {
- k++;
- scope_found = true;
- }
- // Skip sequences of T:: or T<...>::
- //printf("support.cpp qualifiedItemIs while reached k %d type %d isType %d, isClass %d, guessing %d\n",
- // k,LT(k)->getType(),isTypeName((LT(k)->getText()).data()),isClassName((LT(k)->getText()).data()),inputState->guessing);
- while ((LT(k).getType() == ID) && (isTypeName(LT(k).getText())))
- {// If this type is the same as the last type, then ctor
- if ((final_type_idx != 0) && (LT(final_type_idx).getText().equals(LT(k).getText())))
- {// Like T::T
- // As an extra check, do not allow T::T::
- if (LT(k+1).getType() == SCOPE)
- { //printf("support.cpp qualifiedItemIs QI_INVALID returned\n");
- return CPPvariables.QI_INVALID;
- }
- else
- {//printf("support.cpp qualifiedItemIs QI_CTOR returned\n");
- return CPPvariables.QI_CTOR;
- }
- }
- // Record this as the most recent type seen in the series
- final_type_idx = k;
- //printf("support.cpp qualifiedItemIs if step reached final_type_idx %d\n",final_type_idx);
- // Skip this token
- k++;
- // Skip over any template qualifiers <...>
- // I believe that "T<..." cannot be anything valid but a template
- if (LT(k).getType() == LESSTHAN)
- {
- value=skipTemplateQualifiers(k);
- if (value==k)
- {//printf("support.cpp qualifiedItemIs QI_INVALID(2) returned\n");
- return CPPvariables.QI_INVALID;
- }
- else
- k=value;
- //printf("support.cpp qualifiedItemIs template skipped, k %d\n",k);
- // k has been updated to token following <...>
- }
- if (LT(k).getType() == SCOPE)
- // Skip the "::" and keep going
- {
- k++;
- scope_found = true;
- }
- else
- {// Series terminated -- last ID in the sequence was a type
- // Return ctor if last type is in containing class
- // We already checked for T::T inside loop
- if ( enclosingClass.equals(LT(final_type_idx).getText()))
- { // Like class T T()
- //printf("support.cpp qualifiedItemIs QI_CTOR(2) returned\n");
- return CPPvariables.QI_CTOR;
- }
- else
- {//printf("support.cpp qualifiedItemIs QI_TYPE returned\n");
- return CPPvariables.QI_TYPE;
- }
- }
- }
- // LT(k) is not an ID, or it is an ID but not a typename.
- //printf("support.cpp qualifiedItemIs second switch reached\n");
- switch (LT(k).getType())
- {
- case ID:
- // ID but not a typename
- // Do not allow id::
- if (LT(k+1).getType() == SCOPE)
- {
- //printf("support.cpp qualifiedItemIs QI_INVALID(3) returned\n");
- return CPPvariables.QI_INVALID;
- }
- if (enclosingClass.equals(LT(k).getText()))
- { // Like class T T()
- //printf("support.cpp qualifiedItemIs QI_CTOR(3) returned\n");
- return CPPvariables.QI_CTOR;
- }
- else
- {
- if (scope_found)
- // DW 25/10/03 Assume type if at least one SCOPE present (test12.i)
- return CPPvariables.QI_TYPE;
- else
- //printf("support.cpp qualifiedItemIs QI_VAR returned\n");
- return CPPvariables.QI_VAR; // DW 19/03/04 was QI_ID Could be function?
- }
- case TILDE:
- // check for dtor
- if ((LT(k+1).getType() == ID) && (isTypeName(LT(k+1).getText())) &&(LT(k+2).getType() != SCOPE))
- { // Like ~B or A::B::~B
- // Also (incorrectly?) matches ::~A.
- //printf("support.cpp qualifiedItemIs QI_DTOR returned\n");
- return CPPvariables.QI_DTOR;
- }
- else
- { // ~a or ~A::a is QI_INVALID
- //printf("support.cpp qualifiedItemIs QI_INVALID(4) returned\n");
- return CPPvariables.QI_INVALID;
- }
- case STAR:
- // Like A::*
- // Do not allow * or ::*
- if (final_type_idx == 0)
- { // Haven't seen a type yet
- //printf("support.cpp qualifiedItemIs QI_INVALID(5) returned\n");
- return CPPvariables.QI_INVALID;
- }
- else
- { //printf("support.cpp qualifiedItemIs QI_PTR_MEMBER returned\n");
- return CPPvariables.QI_PTR_MEMBER;
- }
- case OPERATOR:
- // Like A::operator, ::operator, or operator
- //printf("support.cpp qualifiedItemIs QI_OPERATOR returned\n");
- return CPPvariables.QI_OPERATOR;
- default:
- // Something that neither starts with :: or ID, or
- // a :: not followed by ID, operator, ~, or *
- //printf("support.cpp qualifiedItemIs QI_INVALID(6) returned\n");
- return CPPvariables.QI_INVALID;
- }
- }
- // Skip over <...>. This correctly handles nested <> and (), e.g:
- // <T>
- // < (i>3) >
- // < T2<...> >
- // but not
- // < i>3 >
- //
- // On input, kInOut is the index of the "<"
- // On output, if the return is true, then
- // kInOut is the index of the token after ">"
- // else
- // kInOut is unchanged
- public int skipTemplateQualifiers(int kInOut) throws TokenStreamException
- {
- // Start after "<"
- int k = kInOut + 1;
- int value;
- while (LT(k).getType() != GREATERTHAN) // scan to end of <...>
- {
- switch (LT(k).getType())
- {
- case EOF:
- return kInOut;
- case LESSTHAN:
- value=skipTemplateQualifiers(k);
- if (value==k)
- {
- return kInOut;
- }
- else
- k=value;
- break;
- case LPAREN:
- value=skipNestedParens(k);
- if (value==k)
- {
- return kInOut;
- }
- else
- k=value;
- break;
- default:
- k++; // skip everything else
- break;
- }
- if (k > CPPvariables.MAX_TEMPLATE_TOKEN_SCAN)
- {
- return kInOut;
- }
- }
- // Update output argument to point past ">"
- kInOut = k + 1;
- return kInOut;
- }
- // Skip over (...). This correctly handles nested (), e.g:
- // (i>3, (i>5))
- //
- // On input, kInOut is the index of the "("
- // On output, if the return is true, then
- // kInOut is the index of the token after ")"
- // else
- // kInOut is unchanged
- public int skipNestedParens(int kInOut) throws TokenStreamException
- {
- // Start after "("
- int k = kInOut + 1;
- int value;
- while (LT(k).getType() != RPAREN) // scan to end of (...)
- {
- switch (LT(k).getType())
- {
- case EOF:
- return kInOut;
- case LPAREN:
- value=skipNestedParens(k);
- if (value==k)
- {
- return kInOut;
- }
- else
- k=value;
- break;
- default:
- k++; // skip everything else
- break;
- }
- if (k > CPPvariables.MAX_TEMPLATE_TOKEN_SCAN)
- {
- return kInOut;
- }
- }
- // Update output argument to point past ")"
- kInOut = k + 1;
- return kInOut;
- }
- // Return true if "::blah" or "fu::bar<args>::..." found.
- public boolean scopedItem(int k) throws TokenStreamException
- {
- //printf("support.cpp scopedItem k %d\n",k);
- return (LT(k).getType()==SCOPE ||
- (LT(k).getType()==ID && !finalQualifier(k)));
- }
- // Return true if ID<...> or ID is last item in qualified item list.
- // Return false if LT(k) is not an ID.
- // ID must be a type to check for ID<...>,
- // or else we would get confused by "i<3"
- public boolean finalQualifier(int k) throws TokenStreamException
- {
- if (LT(k).getType()==ID)
- {
- if ((isTypeName(LT(k).getText())) && (LT(k+1).getType()==LESSTHAN))
- {
- // Starts with "T<". Skip <...>
- k++;
- k=skipTemplateQualifiers(k);
- }
- else
- {
- // skip ID;
- k++;
- }
- return (LT(k).getType() != SCOPE );
- }
- else
- { // not an ID
- return false;
- }
- }
- /*
- * Return true if 's' can pose as a type name
- */
- public boolean isTypeName(String s)
- {
- String type="";
- if (!symbols.containsKey(s))
- {
- //printf("support.cpp isTypeName %s not found\n",s);
- return false;
- }
- else
- type=(String) symbols.get(s);
- if (type.equals(CPPvariables.OT_TYPE_DEF)||
- type.equals(CPPvariables.OT_ENUM)||
- type.equals(CPPvariables.OT_CLASS)||
- type.equals(CPPvariables.OT_STRUCT)||
- type.equals(CPPvariables.OT_UNION))
- {
- return true;
- }
- return false;
- }
- public void declaratorID(String id, java.util.BitSet qi)
- {
- if ((qi.equals(CPPvariables.QI_TYPE)) || (_td)) // Check for type declaration
- {
- if (!symbols.containsKey(id))
- symbols.put(id, CPPvariables.OT_TYPE_DEF);
- }
- }
- }
- translation_unit [Builder builder]
- {
- if(!symbols.containsKey("std"))
- symbols.put("std",CPPvariables.OT_TYPE_DEF);
- b = builder;
- }
- : {b.beginTranslationUnit();}
- (external_declaration)+ EOF
- {b.endTranslationUnit();}
- ;
- external_declaration
- {String s="";}
- :
- (
- // Template explicit specialisation (DW 14/04/03)
- ("template" LESSTHAN GREATERTHAN)=>"template" LESSTHAN GREATERTHAN declaration
- |
- // Class definition (templates too)
- // This is separated out otherwise the next alternative
- // would look for "class A { ... } f() {...}" which is
- // an unacceptable level of backtracking.
- // JEL Note: Rule body does not need typedef, because
- // that is internal to "declaration", and it is invalid
- // to say "typedef template..."
- // Class definition
- (("typedef")? class_head)=> declaration
- |
- // Class template definition
- (template_head class_head)=>template_head declaration
- |
- // Enum definition (don't want to backtrack over this in other alts)
- ("enum" (ID)? LCURLY)=>enum_specifier (init_declarator_list)? SEMICOLON
- |
- // Destructor DEFINITION (templated or non-templated)
- ((template_head)? dtor_head LCURLY)=>(template_head)? dtor_head dtor_body
- |
- // Constructor DEFINITION (non-templated)
- // JEL 4/3/96 Added predicate that works, once the
- // restriction is added that ctor cannot be virtual
- // and ctor_declarator uses a more restrictive id
- ( (options {warnWhenFollowAmbig = false;}:
- ctor_decl_spec)?
- {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}?)=>ctor_definition
- /*(ID SCOPE)=>ctor_definition*/
- |
- // User-defined type cast
- (("inline")? scope_override conversion_function_decl_or_def)=>
- ("inline")? s = scope_override conversion_function_decl_or_def
- |
- // Function declaration
- (declaration_specifiers function_declarator SEMICOLON)=>
- {b.beginFunctionDeclaration();}
- declaration
- {b.endFunctionDeclaration();}
- |
- // Function definition
- (declaration_specifiers function_declarator LCURLY)=>
- {b.beginFunctionDefinition(LT(2).getLine());}
- function_definition
- {b.endFunctionDefinition();}
- |
- // K & R Function definition
- (declaration_specifiers function_declarator declaration)=>function_definition
- |
- // templated forward class decl, init/decl of static member in template
- (template_head declaration_specifiers (init_declarator_list)? SEMICOLON )=>
- template_head declaration_specifiers (init_declarator_list)? SEMICOLON
- |
- // Templated FUNCTIONS and CONSTRUCTORS matched here.
- template_head
- (
- // Templated CONSTRUCTOR definition
- // JEL 4/3/96 Added predicate that works once the
- // restriction is added that ctor cannot be virtual
- ( ctor_decl_spec {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}?)=>ctor_definition
- |
- // Templated function declaration
- (declaration_specifiers function_declarator SEMICOLON)=> declaration
- |
- // Templated function definition
- (declaration_specifiers function_declarator LCURLY)=> function_definition
- )
- |
- decl_namespace
- |
- // everything else (except templates)
- declaration
- |
- SEMICOLON
- )
- ; // end of external_declaration
- decl_namespace
- {String qid="";}
- :
- "namespace"
- (
- (ns:ID{ _td = true;declaratorID(ns.getText(),CPPvariables.QI_TYPE);})?
- // The following statement can be invoked to trigger selective antlr trace
- // Also see below
- //{if (strcmp((ns->getText()).data(),"xyz")==0) antlrTrace(true);} // Used for diagnostic trigger
- LCURLY
- {if(ns == null) { b.enterNamespaceScope(null); }
- else { b.enterNamespaceScope(ns.getText()); }}
- (external_declaration)*
- {b.exitNamespaceScope();}
- RCURLY
- // The following should be implemented to match the optional statement above
- //{antlrTrace(false);}
- |
- ns2:ID {_td=true;declaratorID(ns2.getText(),CPPvariables.QI_TYPE);}
- ASSIGNEQUAL qid = qualified_id SEMICOLON
- {b.makeNamespaceAlias(qid, ns2.getText());}
- )
- ;
- member_declaration
- {String q="";}
- :
- {b.beginMemberDeclaration();}
- (
- // Class definition
- // This is separated out otherwise the next alternative
- // would look for "class A { ... } f() {...}" which is
- // an unacceptable level of backtracking.
- ( ("typedef")? class_head) => declaration
- |
- // Enum definition (don't want to backtrack over this in other alts)
- ("enum" (ID)? LCURLY)=>enum_specifier (member_declarator_list)? SEMICOLON
- |
- (template_head class_head)=>template_head declaration
- |
- // Constructor declarator
- ( ctor_decl_spec {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}? ctor_declarator SEMICOLON)=>
- ctor_decl_spec ctor_declarator SEMICOLON // Constructor declarator
- |
- // JEL Predicate to distinguish ctor from function
- // This works now that ctor cannot have VIRTUAL
- // It unfortunately matches A::A where A is not enclosing
- // class -- this will have to be checked semantically
- ( ctor_decl_spec
- {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}?
- ctor_declarator
- (COLON // DEFINITION :ctor_initializer
- |LCURLY // DEFINITION (compound Statement) ?
- )
- )=>ctor_definition
- |
- // No template_head allowed for dtor member
- // Backtrack if not a dtor (no TILDE)
- (dtor_head SEMICOLON)=>dtor_head SEMICOLON // Declaration
- |
- // No template_head allowed for dtor member
- // Backtrack if not a dtor (no TILDE)
- (dtor_head LCURLY)=>dtor_head dtor_body // Definition
- |
- // Function declaration
- (declaration_specifiers function_declarator SEMICOLON)=>
- {b.beginFunctionDeclaration();}
- declaration
- {b.endFunctionDeclaration();}
- |
- // Function definition
- (declaration_specifiers function_declarator LCURLY)=>
- {b.beginFunctionDefinition(LT(2).getLine());}
- function_definition
- {b.endFunctionDefinition();}
- |
- // User-defined type cast
- (("inline")? conversion_function_decl_or_def)=>("inline")? conversion_function_decl_or_def
- |
- // Hack to handle decls like "superclass::member",
- // to redefine access to private base class public members
- (qualified_id SEMICOLON)=>q = qualified_id SEMICOLON
- |
- // Member with a type or just a type def
- // A::T a(), ::T a, ::B a, void a, E a (where E is the enclosing class)
- (declaration_specifiers)=>declaration_specifiers (member_declarator_list)? SEMICOLON
- |
- // Member without a type (I guess it can only be a function declaration or definition)
- (function_declarator SEMICOLON)=> function_declarator SEMICOLON
- | // Member without a type (I guess it can only be a function definition)
- function_declarator compound_statement
- |
- // templated forward class decl, init/decl of static member in template
- // DW 27/06/03 Copied here from external_declaration since templates can now be nested
- (template_head declaration_specifiers (init_declarator_list)? SEMICOLON)=>
- template_head declaration_specifiers (init_declarator_list)? SEMICOLON
- |
- // Templated FUNCTIONS and CONSTRUCTORS matched here.
- // DW 27/06/03 Copied here from external_declaration since templates can now be nested
- template_head
- (
- // Templated CONSTRUCTOR definition
- // JEL 4/3/96 Added predicate that works once the
- // restriction is added that ctor cannot be virtual
- (ctor_decl_spec {qualifiedItemIsOneOf(CPPvariables.QI_CTOR,0)}?)=>ctor_definition
- |
- // Templated function declaration
- (declaration_specifiers function_declarator SEMICOLON)=>declaration
- |
- // Templated function definition
- // Function definition DW 2/6/97
- (declaration_specifiers function_declarator LCURLY)=> function_definition
- |
- conversion_function_decl_or_def
- )
- |
- access_specifier COLON
- |
- SEMICOLON
- )
- {b.endMemberDeclaration();}
- ; // end member_declaration
- function_definition
- {java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); auxBitSet.or(CPPvariables.QI_CTOR);}
- : // don't want next action as an init-action due to (...)=> caller
- ( // Next line is equivalent to guarded predicate in PCCTS
- // (SCOPE | ID)? => <<qualifiedItemisOneOf(QI_TYPE|QI_CTOR)>>?
- {( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(auxBitSet,0) )}?
- declaration_specifiers function_declarator
- ( options{warnWhenFollowAmbig = false;}:
- (declaration)* // Possible for K & R definition
- )? compound_statement
- | // Next line is equivalent to guarded predicate in PCCTS
- // (SCOPE | ID)? => <<qualifiedItemisOneOf(QI_PTR_MEMBER)>>?
- //{( !(LA(1)==SCOPE||LA(1)==ID) || (qualifiedItemIsOneOf(QI_PTR_MEMBER)) )}?
- function_declarator
- ( options{warnWhenFollowAmbig = false;}:
- (declaration)* // Possible for K & R definition
- )? compound_statement
- )
- ;
- declaration
- :
- ("extern" StringLiteral)=> linkage_specification
- |
- // LL 31/1/97: added (COMMA) ? below. This allows variables to typedef'ed more than once. DW 18/08/03 ?
- declaration_specifiers ((COMMA)? init_declarator_list)? SEMICOLON
- |
- using_declaration // DW 19/04/04
- ;
- linkage_specification
- : "extern"
- StringLiteral
- (LCURLY (external_declaration)* RCURLY
- |declaration
- )
- ;
- declaration_specifiers
- {_td=false; boolean td=false; List declSpecs = new ArrayList();}
- :
- ( (options {warnWhenFollowAmbig = false;}
- : storage_class_specifier
- | type_qualifier
- | ("inline"|"_inline"|"__inline") {declSpecs.add("inline");}
- | "virtual" {declSpecs.add("virtual");}
- | "explicit" {declSpecs.add("explicit");}
- | "typedef" {td=true; declSpecs.add("typedef");}
- | "friend" {declSpecs.add("friend");}
- | ("_stdcall"|"__stdcall") {declSpecs.add("__stdcall");}
- | ("_declspec"|"__declspec") LPAREN ID RPAREN // euluis: ignore
- )* {if (!declSpecs.isEmpty()) b.declarationSpecifiers(declSpecs);}
- type_specifier
- |
- "typename" {td=true;} direct_declarator
- )
- {_td=td;}
- ;
- storage_class_specifier
- : "auto" {b.storageClassSpecifier("auto");}
- | "register" {b.storageClassSpecifier("register");}
- | "static" {b.storageClassSpecifier("static");}
- | "extern" {b.storageClassSpecifier("extern");}
- | "mutable" {b.storageClassSpecifier("mutable");}
- ;
- type_qualifier // aka cv_qualifier
- : ("const"|"const_cast") {b.typeQualifier("const");} // euluis TODO: const_cast ?!?
- | "volatile" {b.typeQualifier("volatile");}
- ;
- type_specifier
- : simple_type_specifier
- | class_specifier
- | enum_specifier
- ;
- simple_type_specifier
- { String s="";
- java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone();
- auxBitSet.or(CPPvariables.QI_CTOR);
- List sts = new ArrayList();
- }
- : ( {qualifiedItemIsOneOf(auxBitSet,0)}?
- s = qualified_type
- {sts.add(s); b.simpleTypeSpecifier(sts);}
- |
- ( "char" {sts.add("char");}
- | "wchar_t" {sts.add("wchar_t");}
- | "bool" {sts.add("bool");}
- | "short" {sts.add("short");}
- | "int" {sts.add("int");}
- | ("_int64"|"__int64") {sts.add("__int64");}
- | "__w64" {sts.add("__w64");}
- | "long" {sts.add("long");}
- | "signed" {sts.add("signed");}
- | "unsigned" {sts.add("unsigned");}
- | "float" {sts.add("float");}
- | "double" {sts.add("double");}
- | "void" {sts.add("void");}
- | ("_declspec"|"__declspec") LPAREN ID RPAREN //euluis: ignore
- )+ {b.simpleTypeSpecifier(sts);}
- )
- ;
- qualified_type returns [String q=""]
- {String s=""; String qitem="";}
- :
- // JEL 3/29/96 removed this predicate and moved it upwards to
- // simple_type_specifier. This was done to allow parsing of ~ID to
- // be a unary_expression, which was never reached with this
- // predicate on
- //{qualifiedItemIsOneOf(QI_TYPE|QI_CTOR,0)}?
- s = scope_override
- id:ID
- (options {warnWhenFollowAmbig = false;}:
- LESSTHAN template_argument_list GREATERTHAN)?
- {
- qitem=s;
- qitem=qitem+id.getText();
- q=qitem;
- }
- ;
- class_specifier
- {String saveClass="";String id="";String type="";}
- : ("class" {type=CPPvariables.OT_CLASS;}
- |"struct" {type=CPPvariables.OT_STRUCT;}
- |"union" {type=CPPvariables.OT_UNION;}
- )
- ( id = qualified_id
- (options{generateAmbigWarnings = false;}:
- { saveClass = enclosingClass;
- enclosingClass = id;
- }
- {b.beginClassDefinition(type, id);}
- (base_clause)?
- LCURLY
- {
- if(!symbols.containsKey(id))
- symbols.put(id,type);
- }
- (member_declaration )*
- {b.endClassDefinition();}
- RCURLY
- { enclosingClass = saveClass;}
- |
- {
- String auxName=id;
- int pos = auxName.indexOf("::");
- while(pos>=0)
- {
- if(!symbols.containsKey(auxName.substring(0,pos)))
- symbols.put(auxName.substring(0,pos),type);
- auxName=auxName.substring(pos+2,auxName.length());
- pos=auxName.indexOf("::");
- }
- if(!symbols.containsKey(auxName))
- symbols.put(auxName,type);
- }
- )
- |
- LCURLY
- { id="anonymous";
- saveClass = enclosingClass; enclosingClass = "anonymous";
- if(!symbols.containsKey(id))
- symbols.put(id,type);
- }
- (member_declaration)* RCURLY
- {enclosingClass = saveClass;}
- )
- ;
- enum_specifier
- : "enum"
- ( LCURLY
- enumerator_list RCURLY
- | id:ID // DW 22/04/03 Suggest qualified_id here to satisfy elaborated_type_specifier
- { if(!symbols.containsKey(id.getText()))
- symbols.put(id.getText(),CPPvariables.OT_ENUM);
- }
- ( LCURLY enumerator_list RCURLY)?
- )
- ;
- enumerator_list
- : enumerator (COMMA enumerator)*
- ;
- enumerator
- : id:ID (ASSIGNEQUAL constant_expression)?
- ;
- /* This matches a generic qualified identifier ::T::B::foo
- * (including OPERATOR).
- * It might be a good idea to put T::~dtor in here
- * as well, but id_expression in expr.g puts it in manually.
- * Maybe not, 'cause many people use this assuming only A::B.
- * How about a 'qualified_complex_id'?
- */
- qualified_id returns [String q=""]
- {
- String so="";
- String qitem="";
- }
- :
- so = scope_override
- {qitem=so; }
- (
- id:ID
- (options{warnWhenFollowAmbig = false;}:
- LESSTHAN template_argument_list GREATERTHAN)?
- {
- qitem=qitem+id.getText();
- }
- |
- OPERATOR optor
- {qitem=qitem+"operator"+"NYI";}
- |
- "this" // DW 21/07/03 fix to pass test8.i
- |
- ("true"|"false") // DW 21/07/03 fix to pass test8.i
- )
- {q = qitem;}
- ;
- typeID
- : {isTypeName(LT(1).getText())}?
- ID
- ;
- init_declarator_list
- : {b.beginInitDeclaratorList();}
- init_declarator (COMMA init_declarator)*
- {b.endInitDeclaratorList();}
- ;
- init_declarator
- : declarator
- (
- ASSIGNEQUAL
- // check for initialisation and assignment (e.g. int x = 10;)
- initializer
- |
- LPAREN expression_list RPAREN
- )?
- ;
- initializer
- :
- {b.beginInitializer();}
- (
- remainder_expression // DW 18/4/01 assignment_expression
- |
- LCURLY initializer (COMMA initializer)* RCURLY
- )
- {b.endInitializer();}
- ;
- class_head
- : // Used only by predicates
- ("struct"
- |"union"
- |"class"
- )
- (ID
- (LESSTHAN template_argument_list GREATERTHAN)?
- (base_clause)?
- )? LCURLY
- ;
- base_clause
- :
- COLON base_specifier (COMMA base_specifier)*
- ;
- base_specifier
- {String qt=""; b.beginBaseSpecifier();}
- : // DW 13/08/03 Should check qualified_type for class-name?
- ( "virtual" ( access_specifier)? qt = qualified_type {b.baseSpecifier(qt, true);}
- | access_specifier "virtual" qt = qualified_type {b.baseSpecifier(qt, true);}
- | access_specifier qt = qualified_type {b.baseSpecifier(qt, false);}
- | qt = qualified_type {b.baseSpecifier(qt, false);}
- )
- {b.endBaseSpecifier();}
- ;
- access_specifier
- : "public" {b.accessSpecifier("public");}
- | "protected" {b.accessSpecifier("protected");}
- | "private" {b.accessSpecifier("private");}
- ;
- member_declarator_list
- : member_declarator (ASSIGNEQUAL OCTALINT)? // The value must be 0 (pure virt.)
- (COMMA member_declarator (ASSIGNEQUAL OCTALINT)? )*
- ;
- member_declarator
- :
- ((ID)? COLON constant_expression)=>(ID)? COLON constant_expression
- |
- declarator
- ;
- conversion_function_decl_or_def
- : OPERATOR
- declaration_specifiers
- (STAR | AMPERSAND)? // DW 01/08/03 Use type_specifier here? see syntax
- (LESSTHAN template_parameter_list GREATERTHAN)?
- LPAREN (parameter_list)? RPAREN
- (type_qualifier)?
- (exception_specification)?
- ( compound_statement
- | SEMICOLON
- )
- ;
- // JEL note: does not use (const|volatile)* to avoid lookahead problems
- cv_qualifier_seq
- :
- (type_qualifier)*
- ;
- declarator
- :
- //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}?
- (ptr_operator)=>ptr_operator // AMPERSAND or STAR
- declarator
- |
- direct_declarator
- ;
- direct_declarator
- {String id="";}
- :
- (qualified_id LPAREN (RPAREN|declaration_specifiers) )=> // Must be function declaration
- id = qualified_id {declaratorID(id,CPPvariables.QI_FUN); b.directDeclarator(id);}
- LPAREN (parameter_list)? RPAREN (type_qualifier)* (exception_specification)?
- | (qualified_id LPAREN qualified_id)=> // Must be class instantiation
- id = qualified_id {declaratorID(id,CPPvariables.QI_VAR);}LPAREN expression_list RPAREN
- |
- (qualified_id LSQUARE)=> // Must be array declaration
- id = qualified_id
- {
- if (_td==true)
- declaratorID(id,CPPvariables.QI_TYPE);
- else
- declaratorID(id,CPPvariables.QI_VAR);
- }
- (options {warnWhenFollowAmbig = false;}:
- LSQUARE (constant_expression)? RSQUARE)+
- |
- id = qualified_id
- {
- if (_td==true)
- declaratorID(id,CPPvariables.QI_TYPE);
- else {
- declaratorID(id,CPPvariables.QI_VAR);
- b.directDeclarator(id);
- }
- }
- |
- // DW 24/05/04 This block probably never entered as dtor selected out earlier
- // Note In fact no dictionary entries for ctor or dtor
- TILDE dtor:ID {declaratorID(dtor.getText(),CPPvariables.QI_DTOR);}// Note "class" not recorded in CPPSymbol
- LPAREN (parameter_list)? RPAREN
- |
- LPAREN declarator RPAREN declarator_suffixes
- ;
- declarator_suffixes
- {java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); auxBitSet.or(CPPvariables.QI_CTOR);}
- :
- (
- (options {warnWhenFollowAmbig = false;}:
- LSQUARE (constant_expression)? RSQUARE)+
- | {(!((LA(1)==LPAREN)&&(LA(2)==ID))||(qualifiedItemIsOneOf(auxBitSet,1)))}?
- LPAREN (parameter_list)? RPAREN (type_qualifier)* (exception_specification)?
- // | // DW 28/06/04 deleted Assume either following bracketed declaration
- // // empty
- )
- ;
- /* I think something is weird with the context-guards for predicates;
- * as a result I manually hoist the appropriate pred from ptr_to_member
- *
- * TER: warning: seems that "ID::" will always bypass and go to 2nd alt :(
- */
- function_declarator
- :
- //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}?
- (ptr_operator)=> ptr_operator function_declarator
- |
- function_direct_declarator
- ;
- function_direct_declarator
- { String q="";}
- :
- /* predicate indicate that plain ID is ok here; this counteracts any
- * other predicate that gets hoisted (along with this one) that
- * indicates that an ID is a type or whatever. E.g.,
- * another rule testing isTypeName() alone, implies that the
- * the ID *MUST* be a type name. Combining isTypeName() and
- * this predicate in an OR situation like this one:
- * ( declaration_specifiers ... | function_declarator ... )
- * would imply that ID can be a type name OR a plain ID.
- */
- ( // fix prompted by (isdigit)() in xlocnum
- LPAREN
- q = qualified_id
- {
- declaratorID(q,CPPvariables.QI_FUN);
- }
- RPAREN
- |
- q = qualified_id
- {
- declaratorID(q,CPPvariables.QI_FUN);
- }
- )
- {b.functionDirectDeclarator(q);}
- LPAREN (parameter_list)? RPAREN
- (options{warnWhenFollowAmbig = false;}:
- type_qualifier)*
- (ASSIGNEQUAL OCTALINT)? // The value of the octal must be 0
- (exception_specification)?
- ;
- ctor_definition
- :
- {b.beginCtorDefinition();}
- ctor_head
- ctor_body
- {b.endCtorDefinition();}
- ;
- ctor_head
- :
- ctor_decl_spec ctor_declarator
- ;
- ctor_decl_spec
- {List declSpecs = new ArrayList();}
- :
- ( ("inline"|"_inline"|"__inline") {declSpecs.add("inline");}
- |
- "explicit" {declSpecs.add("explicit");}
- )*
- {b.declarationSpecifiers(declSpecs);}
- ;
- ctor_declarator
- { String q="";}
- :
- // JEL 4/3/96 qualified_id too broad DW 10/06/03 ?
- q = qualified_ctor_id {b.qualifiedCtorId(q);}
- LPAREN (parameter_list)? RPAREN (exception_specification)?
- ;
- // This matches a generic qualified identifier ::T::B::foo
- // that is satisfactory for a ctor (no operator, no trailing <>)
- qualified_ctor_id returns [String q=""]
- {
- String so="";
- String qitem="";
- }
- :
- so = scope_override
- {qitem=so;}
- id:ID // DW 24/05/04 Note. Neither Ctor or Dtor recorded in dictionary
- {qitem=qitem+id.getText();
- q = qitem;}
- ;
- ctor_body
- :
- (ctor_initializer)? compound_statement
- ;
- ctor_initializer
- :
- COLON superclass_init (COMMA superclass_init)*
- ;
- superclass_init
- {String q="";}
- :
- q = qualified_id LPAREN (expression_list)? RPAREN
- ;
- dtor_head
- :
- {b.beginDtorHead();}
- dtor_decl_spec dtor_declarator
- {b.endDtorHead();}
- ;
- dtor_decl_spec
- {List declSpecs = new ArrayList();}
- :
- (
- ("inline"|"_inline"|"__inline") {declSpecs.add("inline");}
- |
- "virtual" {declSpecs.add("virtual");}
- )*
- {b.declarationSpecifiers(declSpecs);}
- ;
- dtor_declarator
- {String s="";}
- :
- s = scope_override
- TILDE id:ID
- {b.dtorDeclarator(s+"~"+id.getText());}
- LPAREN RPAREN (exception_specification)?
- ;
- dtor_body
- :
- compound_statement
- ;
- parameter_list
- : parameter_declaration_list (ELLIPSIS)?
- ;
- parameter_declaration_list
- :
- ( parameter_declaration
- (// Have not been able to find way of stopping warning of non-determinism between alt 1 and exit branch of block
- COMMA parameter_declaration
- )*
- )
- ;
- parameter_declaration
- {java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); auxBitSet.or(CPPvariables.QI_CTOR);}
- : {b.beginParameterDeclaration();}
- (
- {!((LA(1)==SCOPE) && (LA(2)==STAR||LA(2)==OPERATOR))&&( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(auxBitSet,0) )}?
- declaration_specifiers // DW 24/3/98 Mods for K & R
- (
- (declarator)=> declarator // if arg name given
- |
- abstract_declarator // if arg name not given // can be empty
- )
- |
- (declarator)=> declarator // DW 24/3/98 Mods for K & R
- |
- ELLIPSIS
- )
- (ASSIGNEQUAL
- remainder_expression // DW 18/4/01 assignment_expression
- )?
- {b.endParameterDeclaration();}
- ;
- type_name // aka type_id
- :
- declaration_specifiers abstract_declarator
- ;
- /* This rule looks a bit weird because (...) can happen in two
- * places within the declaration such as "void (*)()" (ptr to
- * function returning nothing). However, the () of a function
- * can only occur after having seen either a (abstract_declarator)
- * and not after a [..] or simple '*'. These are the only two
- * valid () func-groups:
- * int (*)(); // ptr to func
- * int (*[])(); // array of ptr to func
- */
- abstract_declarator
- : //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}?
- ptr_operator abstract_declarator
- |
- LPAREN abstract_declarator RPAREN
- (abstract_declarator_suffix)+
- |
- (LSQUARE (constant_expression )? RSQUARE )+
- |
- /* empty */
- ;
- abstract_declarator_suffix
- :
- LSQUARE (constant_expression)? RSQUARE
- |
- LPAREN (parameter_list)? RPAREN cv_qualifier_seq (exception_specification)?
- ;
- exception_specification
- {String so="";}
- : "throw" LPAREN
- ( (so = scope_override ID (COMMA so = scope_override ID)* )?
- | ELLIPSIS
- )
- RPAREN
- ;
- template_head
- :
- "template"
- LESSTHAN template_parameter_list GREATERTHAN
- ;
- template_parameter_list
- :
- template_parameter (COMMA template_parameter)*
- ;
- /* Rule requires >2 lookahead tokens. The ambiguity is resolved
- * correctly, however. According to the manual "...A template argument
- * that can be interpreted either as a parameter-declaration or a
- * type-argument (because its identifier is the name of an
- * already existing class) is taken as type-argument."
- * Therefore, any "class ID" that is seen on the input, should
- * match the first alternative here (it should be a type-argument).
- */
- template_parameter
- :
- (options{generateAmbigWarnings = false;}:
- ("class"|"typename")
- (id:ID (ASSIGNEQUAL assigned_type_name)? )?
- { if(!symbols.containsKey(id.getText()))
- symbols.put(id.getText(),CPPvariables.OT_TYPE_DEF);
- }
- |
- parameter_declaration // DW 30/06/03 This doesn't seem to match the current standard
- )
- ;
- /* This is to allow an assigned type_name in a template parameter
- * list to be defined previously in the same parameter list,
- * as type setting is ineffective whilst guessing
- */
- assigned_type_name
- {String s=""; }
- :
- (options{generateAmbigWarnings = false;}:
- s = qualified_type abstract_declarator
- |
- simple_type_specifier abstract_declarator
- )
- ;
- // This rule refers to an instance of a template class or function
- template_id // aka template_class_name
- : ID LESSTHAN template_argument_list GREATERTHAN
- ;
- template_argument_list
- : template_argument (COMMA template_argument)*
- ;
- /* Here assignment_expression was changed to shift_expression to rule out
- * x< 1<2 > which causes ambiguities. As a result, these can be used only
- * by enclosing parentheses x<(1<2)>. This is true for x<1+2> ==> bad,
- * x<(1+2)> ==> ok.
- */
- template_argument
- {java.util.BitSet auxBitSet=(java.util.BitSet)CPPvariables.QI_TYPE.clone(); auxBitSet.or(CPPvariables.QI_CTOR);}
- :
- {( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(auxBitSet,0) )}?
- type_name
- |
- shift_expression // failed in iosfwd
- // | assignment_expression // Inserted as per grammar summary
- ;
- ///////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
- ////////////////////////////// STATEMENTS ////////////////////////////
- ///////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
- statement_list
- : (statement)+
- ;
- statement
- :
- ( (declaration)=>declaration
- | labeled_statement
- | case_statement
- | default_statement
- |
- {b.beginExpressionStatement();}
- expression SEMICOLON
- {b.endExpressionStatement();}
- | compound_statement
- | selection_statement
- | iteration_statement
- | jump_statement
- | SEMICOLON
- | try_block
- | throw_statement
- | asm_block
- )
- ;
- labeled_statement
- : ID COLON statement
- ;
- case_statement
- : {b.beginCaseStatement();}
- "case"
- constant_expression COLON statement
- {b.endCaseStatement();}
- ;
- default_statement
- : {b.beginDefaultStatement();}
- "default" COLON statement
- {b.endDefaultStatement();}
- ;
- compound_statement
- :
- {b.beginCompoundStatement();}
- LCURLY (statement_list)? RCURLY
- {b.endCompoundStatement();}
- ;
- /* NOTE: cannot remove ELSE ambiguity, but it parses correctly.
- * The warning is removed with the options statement
- */
- selection_statement
- :
- {b.beginIfStatement();}
- "if" LPAREN expression RPAREN statement
- {b.endIfStatement();}
- (options {warnWhenFollowAmbig = false;}:
- {b.beginElseStatement();}
- "else" statement
- {b.endElseStatement();}
- )?
- |
- {b.beginSwitchStatement();}
- "switch" LPAREN expression RPAREN statement
- {b.endSwitchStatement();}
- ;
- iteration_statement
- :
- {b.beginWhileStatement();}
- "while" LPAREN expression RPAREN statement
- {b.endWhileStatement();}
- |
- {b.beginDoStatement();}
- "do" statement "while" LPAREN expression RPAREN SEMICOLON
- {b.endDoStatement();}
- |
- {b.beginForStatement();}
- "for" LPAREN
- ( (declaration)=> declaration
- | expression SEMICOLON
- | SEMICOLON
- )
- (expression)? SEMICOLON
- (expression)?
- RPAREN statement
- {b.endForStatement();}
- ;
- jump_statement
- :
- ( "goto" ID SEMICOLON
- {b.gotoStatement();}
- | "continue" SEMICOLON
- {b.continueStatement();}
- | "break" SEMICOLON
- {b.breakStatement();}
- // DW 16/05/03 May be problem here if return is followed by a cast expression
- | {b.beginReturnStatement(LT(1).getLine());}
- "return"
- ( options{warnWhenFollowAmbig = false;}:
- (LPAREN {(qualifiedItemIsOneOf(CPPvariables.QI_TYPE,0) )}? ID RPAREN)=>
- LPAREN ID RPAREN (expression)? // This is an unsatisfactory fix for problem in xstring re "return (allocator);"
- // and in xlocale re return (_E)(_Tolower((unsigned char)_C, &_Ctype));
- //{printf("%d CPP_parser.g jump_statement Return fix used\n",LT(1)->getLine());}
- | expression
- )? SEMICOLON
- {b.endReturnStatement();}
- )
- ;
- try_block
- : "try" compound_statement (handler)*
- ;
- handler
- : "catch" LPAREN exception_declaration RPAREN compound_statement
- ;
- exception_declaration
- : parameter_declaration_list
- ;
- /* This is an expression of type void according to the ARM, which
- * to me means "statement"; it removes some ambiguity to put it in
- * as a statement also.
- */
- throw_statement
- : "throw" (assignment_expression) ? SEMICOLON
- ;
- using_declaration
- {String qid="";}
- : "using"
- ("namespace" qid = qualified_id // Using-directive
- |qid = qualified_id // Using-declaration
- )
- SEMICOLON
- ;
- asm_block
- : ("_asm"|"__asm") LCURLY (~RCURLY)* RCURLY
- ;
- ///////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
- ////////////////////////////// EXPRESSIONS ///////////////////////////
- ///////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
- expression
- :
- {b.beginExpression();}
- assignment_expression (COMMA assignment_expression)*
- {b.endExpression();}
- ;
- expression_list
- : assignment_expression (COMMA assignment_expression)*
- ;
- /* right-to-left for assignment op */
- assignment_expression
- :
- conditional_expression
- (
- {b.beginAssignmentExpression(LT(1).getLine());}
- (ASSIGNEQUAL
- |TIMESEQUAL|DIVIDEEQUAL|MINUSEQUAL|PLUSEQUAL
- |MODEQUAL
- |SHIFTLEFTEQUAL
- |SHIFTRIGHTEQUAL
- |BITWISEANDEQUAL
- |BITWISEXOREQUAL
- |BITWISEOREQUAL
- )
- remainder_expression
- {b.endAssignmentExpression();}
- )?
- ;
- remainder_expression
- :
- ( (conditional_expression (COMMA|SEMICOLON|RPAREN)
- )=>
- assignment_expression
- |
- assignment_expression
- )
- ;
- conditional_expression
- :
- logical_or_expression
- (
- {b.beginTernaryOperator();}
- QUESTIONMARK expression COLON conditional_expression
- {b.endTernaryOperator();}
- )?
- ;
- constant_expression
- :
- conditional_expression
- ;
- logical_or_expression
- :
- logical_and_expression (OR logical_and_expression)*
- ;
- logical_and_expression
- :
- inclusive_or_expression (AND inclusive_or_expression)*
- ;
- inclusive_or_expression
- :
- exclusive_or_expression (BITWISEOR exclusive_or_expression)*
- ;
- exclusive_or_expression
- :
- and_expression (BITWISEXOR and_expression)*
- ;
- and_expression
- :
- equality_expression (AMPERSAND equality_expression)*
- ;
- equality_expression
- :
- relational_expression ((NOTEQUAL | EQUAL) relational_expression)*
- ;
- relational_expression
- : shift_expression
- (options {warnWhenFollowAmbig = false;}:
- ( LESSTHAN
- | GREATERTHAN
- | LESSTHANOREQUALTO
- | GREATERTHANOREQUALTO
- )
- shift_expression
- )*
- ;
- shift_expression
- : additive_expression ((SHIFTLEFT | SHIFTRIGHT) additive_expression)*
- ;
- /* See comment for multiplicative_expression regarding #pragma */
- additive_expression
- : multiplicative_expression
- (options{warnWhenFollowAmbig = false;}:
- (PLUS | MINUS) multiplicative_expression
- )*
- ;
- /* ANTLR has trouble dealing with the analysis of the confusing unary/binary
- * operators such as STAR, AMPERSAND, PLUS, etc... With the #pragma (now "(options{warnWhenFollowAmbig = false;}:" etc.)
- * we simply tell ANTLR to use the "quick-to-analyze" approximate lookahead
- * as full LL(k) lookahead will not resolve the ambiguity anyway. Might
- * as well not bother. This has the side-benefit that ANTLR doesn't go
- * off to lunch here (take infinite time to read grammar).
- */
- multiplicative_expression
- : pm_expression
- (options{warnWhenFollowAmbig = false;}:
- (STAR | DIVIDE | MOD) pm_expression
- )*
- ;
- pm_expression
- : cast_expression ((DOTMBR | POINTERTOMBR) cast_expression)*
- ;
- /* The string "( ID" can be either the start of a cast or
- * the start of a unary_expression. However, the ID must
- * be a type name for it to be a cast. Since ANTLR can only hoist
- * semantic predicates that are visible without consuming a token,
- * the semantic predicate in rule type_name is not hoisted--hence, the
- * rule is reported to be ambiguous. I am manually putting in the
- * correctly hoisted predicate.
- *
- * Ack! Actually "( ID" might be the start of "(T(expr))" which makes
- * the first parens just an ordinary expression grouping. The solution
- * is to look at what follows the type, T. Note, this could be a
- * qualified type. Yucko. I believe that "(T(" can only imply
- * function-style type cast in an expression (...) grouping.
- *
- * We DO NOT handle the following situation correctly at the moment:
- * Suppose you have
- * struct rusage rusage;
- * return (rusage.fp);
- * return (rusage*)p;
- * Now essentially there is an ambiguity here. If rusage is followed by any
- * postix operators then it is an identifier else it is a type name. This
- * problem does not occur in C because, unless the tag struct is attached,
- * rusage is not a type name. However in C++ that restriction is removed.
- * No *real* programmer would do this, but it's in the C++ standard just for
- * fun..
- *
- * Another fun one (from an LL standpoint):
- *
- * (A::B::T *)v; // that's a cast of v to type A::B::T
- * (A::B::foo); // that's a simple member access
- *
- * The qualifiedItemIs(1) function scans ahead to what follows the
- * final "::" and returns QI_TYPE if the item is a type. The offset of
- * '1' makes it ignore the initial LPAREN; normally, the offset is 0.
- */
- cast_expression
- :
- // DW 23/06/03
- (LPAREN (type_qualifier)? simple_type_specifier (ptr_operator)? RPAREN)=>
- LPAREN (type_qualifier)? simple_type_specifier (ptr_operator)? RPAREN cast_expression
- |
- unary_expression // handles outer (...) of "(T(expr))"
- ;
- unary_expression
- :
- ( //{!(LA(1)==TILDE && LA(2)==ID)||qualifiedItemIsOneOf(QI_VAR|QI_FUN|QI_DTOR|QI_CTOR)}?
- (postfix_expression)=> postfix_expression
- | PLUSPLUS unary_expression
- | MINUSMINUS unary_expression
- | unary_operator cast_expression
- | "sizeof"
- (// see comment for rule cast_expression for info on predicate
- // JEL NOTE 3/31/96 -- This won't work -- you really need to
- // call qualifiedItemIsOneOf(QI_TYPE|QI_CTOR,1)
- // The context should also be ( LPAREN (SCOPE|ID) )
- // ( LPAREN ID ) => {isTypeName((LT(2)->getText()).data())}?
- {(!(((LA(1)==LPAREN&&(LA(2)==ID))))||(isTypeName(LT(2).getText())))}?
- LPAREN type_name RPAREN
- | unary_expression
- )
- |
- (SCOPE)?
- (new_expression
- |delete_expression
- )
- )
- ;
- postfix_expression
- {String function_name="";}
- :
- (
- options {warnWhenFollowAmbig = false;}:
- // Function-style cast must have a leading type
- {!(LA(1)==LPAREN)}?
- (simple_type_specifier LPAREN RPAREN LPAREN)=> // DW 01/08/03 To cope with problem in xtree (see test10.i)
- simple_type_specifier LPAREN RPAREN LPAREN (expression_list)? RPAREN
- |
- {!(LA(1)==LPAREN)}?
- (simple_type_specifier LPAREN)=>
- simple_type_specifier LPAREN (expression_list)? RPAREN
- |
- {b.beginPostfixExpression();}
- primary_expression
- (options {warnWhenFollowAmbig = false;}:
- LSQUARE expression RSQUARE
- | LPAREN
- {b.beginParameterList();}
- (expression_list)?
- {b.endParameterList();}
- RPAREN
- | DOT
- {b.beginMemberAccess();}
- id_expression
- {b.endMemberAccess();}
- | POINTERTO
- {b.beginMemberAccess();}
- id_expression
- {b.endMemberAccess();}
- | PLUSPLUS
- | MINUSMINUS
- )*
- {b.endPostfixExpression();}
- |
- ("dynamic_cast"|"static_cast"|"reinterpret_cast"|"const_cast") // Note const_cast in elsewhere
- LESSTHAN type_specifier (ptr_operator)? GREATERTHAN
- LPAREN expression RPAREN
- )
- ;
- primary_expression
- :
- {b.beginPrimaryExpression();}
- id_expression
- | constant
- | "this"
- | LPAREN expression RPAREN
- {b.endPrimaryExpression();}
- ;
- id_expression
- {String s="";}
- :
- s = scope_override
- (
- t:ID
- {b.idExpression(t.getText());}
- | OPERATOR optor
- | TILDE (STAR)? ID // DW 29/07/03 STAR included to allow for *_S = ~*_S; seen in vector
- )
- ;
- unary_operator
- : AMPERSAND
- | STAR
- | PLUS
- | MINUS
- | TILDE
- | NOT
- ;
- /* JEL The first ()? is used to resolve "new (expr) (type)" because both
- * (expr) and (type) look identical until you've seen the whole thing.
- *
- * new_initializer appears to be conflicting with function arguments as
- * function arguments can follow a primary_expression. [This is a full
- * LL(k) versus LALL(k) problem. Enhancing context by duplication of
- * some rules might handle this.]
- */
- new_expression
- :
- (
- "new"
- ((LPAREN expression_list RPAREN)=>
- LPAREN expression_list RPAREN)?
- (new_type_id | LPAREN type_name RPAREN)
- (options{warnWhenFollowAmbig = false;}:
- (new_initializer)=> new_initializer)?
- )
- ;
- new_initializer
- : LPAREN (expression_list)? RPAREN
- ;
- new_type_id
- : declaration_specifiers
- (options {warnWhenFollowAmbig = false;}:
- //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}?
- new_declarator
- )?
- ;
- new_declarator
- : //{( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(QI_PTR_MEMBER) )}?
- //ptr_to_member cv_qualifier_seq
- ptr_operator
- (options {warnWhenFollowAmbig = false;}:
- new_declarator ) ?
- | direct_new_declarator
- ;
- ptr_operator
- :
- {b.beginPtrOperator();}
- ( AMPERSAND {b.ptrOperator("&");}
- | ("_cdecl"|"__cdecl")
- | ("_near"|"__near")
- | ("_far"|"__far")
- | "__interrupt"
- | ("pascal"|"_pascal"|"__pascal")
- | ("_stdcall"|"__stdcall")
- | ptr_to_member // e.g. STAR; euluis (2005-07-13): calls
- // b.ptrOperator("*") or b.ptrToMember(s, "*").
- )
- {b.endPtrOperator();}
- ;
- // Match A::B::*
- ptr_to_member
- {String s="";}
- :
- s = scope_override STAR
- {
- if (s.length() != 0) b.ptrToMember(s, "*");
- else b.ptrOperator("*");
- }
- cv_qualifier_seq
- ;
- // Match the A::B::C:: or nothing
- scope_override returns [String s=""]
- {
- String sitem="";
- }
- :
- //{!(qualifiedItemIsOneOf(QI_TYPE))}?
- (SCOPE {sitem=sitem+"::";})?
- ( options {warnWhenFollowAmbig = false;}:
- {scopedItem(1)}?
- id:ID (LESSTHAN template_argument_list GREATERTHAN)? SCOPE
- {
- sitem=sitem+id.getText();
- sitem=sitem+"::";
- }
- )*
- {s = sitem;}
- ;
- /* The "[expression]" construct conflicts with the "new []" construct
- * (and possibly others). We used approximate lookahead for the "new []"
- * construct so that it would not try to compute full LL(2) lookahead.
- * Here, we use #pragma approx again because anytime we see a [ followed
- * by token that can begin an expression, we always want to loop.
- * Approximate lookahead handles this correctly. In fact, approximate
- * lookahead is the same as full lookahead when all but the last lookahead
- * depth are singleton sets; e.g., {"["} followed by FIRST(expression).
- */
- direct_new_declarator
- :
- (options {warnWhenFollowAmbig = false;}:
- LSQUARE expression RSQUARE
- )+
- ;
- delete_expression
- : "delete" (LSQUARE RSQUARE)? cast_expression
- ;
- constant
- : OCTALINT
- | DECIMALINT
- | HEXADECIMALINT
- | CharLiteral
- | (StringLiteral)+
- | FLOATONE
- | FLOATTWO
- | "true"
- | "false"
- ;
- optor
- :
- "new"
- (options {warnWhenFollowAmbig = false;}:
- LSQUARE RSQUARE | ) // check syntax
- |
- "delete"
- (options {warnWhenFollowAmbig = false;}:
- LSQUARE RSQUARE | ) // check syntax
- | LPAREN RPAREN
- | LSQUARE RSQUARE
- | optor_simple_tokclass //OPTOR_SIMPLE_TOKCLASS
- ;
- //Zuo 5/11/2001
- // This is the equivalent to "#tokclass OPTOR_SIMPLE_TOKCLASS" in cplusplus.g
- optor_simple_tokclass
- :
- (PLUS
- |MINUS
- |STAR
- |DIVIDE
- |MOD
- |BITWISEXOR
- |AMPERSAND
- |BITWISEOR
- |TILDE
- |NOT
- |SHIFTLEFT
- |SHIFTRIGHT
- |ASSIGNEQUAL
- |TIMESEQUAL
- |DIVIDEEQUAL
- |MODEQUAL
- |PLUSEQUAL
- |MINUSEQUAL
- |SHIFTLEFTEQUAL
- |SHIFTRIGHTEQUAL
- |BITWISEANDEQUAL
- |BITWISEXOREQUAL
- |BITWISEOREQUAL
- |EQUAL
- |NOTEQUAL
- |LESSTHAN
- |GREATERTHAN
- |LESSTHANOREQUALTO
- |GREATERTHANOREQUALTO
- |OR
- |AND
- |PLUSPLUS
- |MINUSMINUS
- |COMMA
- |POINTERTO
- |POINTERTOMBR
- )
- ;
- // Zuo 19/11/01 from next line, the Lexer is derived from stdCParser.g
- class InternalLexer extends Lexer;
- options
- {
- k = 3;
- exportVocab = STDC;
- testLiterals = true;
- }
- // DW 4/11/02 put in to support manual hoisting
- tokens
- {
- OPERATOR = "operator";
- }
- /* Operators: */
- ASSIGNEQUAL : '=' ;
- COLON : ':' ;
- COMMA : ',' ;
- QUESTIONMARK : '?' ;
- SEMICOLON : ';' ;
- POINTERTO : "->" ;
- /*
- // DOT & ELLIPSIS are commented out since they are generated as part of
- // the Number rule below due to some bizarre lexical ambiguity shme.
- // DOT : '.' ;
- // ELLIPSIS : "..." ;
- */
- LPAREN : '(' ;
- RPAREN : ')' ;
- LSQUARE : '[' ;
- RSQUARE : ']' ;
- LCURLY : '{' ;
- RCURLY : '}' ;
- EQUAL : "==" ;
- NOTEQUAL : "!=" ;
- LESSTHANOREQUALTO : "<=" ;
- LESSTHAN : "<" ;
- GREATERTHANOREQUALTO : ">=" ;
- GREATERTHAN : ">" ;
- DIVIDE : '/' ;
- DIVIDEEQUAL : "/=" ;
- PLUS : '+' ;
- PLUSEQUAL : "+=" ;
- PLUSPLUS : "++" ;
- MINUS : '-' ;
- MINUSEQUAL : "-=" ;
- MINUSMINUS : "--" ;
- STAR : '*' ;
- TIMESEQUAL : "*=" ;
- MOD : '%' ;
- MODEQUAL : "%=" ;
- SHIFTRIGHT : ">>" ;
- SHIFTRIGHTEQUAL : ">>=" ;
- SHIFTLEFT : "<<" ;
- SHIFTLEFTEQUAL : "<<=" ;
- AND : "&&" ;
- NOT : '!' ;
- OR : "||" ;
- AMPERSAND : '&' ;
- BITWISEANDEQUAL : "&=" ;
- TILDE : '~' ;
- BITWISEOR : '|' ;
- BITWISEOREQUAL : "|=" ;
- BITWISEXOR : '^' ;
- BITWISEXOREQUAL : "^=" ;
- //Zuo: the following tokens are come from cplusplus.g
- POINTERTOMBR : "->*" ;
- DOTMBR : ".*" ;
- SCOPE : "::" ;
- // DW 10/10/02
- // Whitespace -- ignored
- Whitespace
- : ( (' ' |'\t' | '\f')
- // handle newlines
- | ( "\r\n" // MS
- | '\r' // Mac
- | '\n' // Unix
- ) { newline(); }
- // handle continuation lines
- | ( "\\\r\n" // MS
- | "\\\r" // Mac
- | "\\\n" // Unix
- )
- )
- {$setType(Token.SKIP); }
- ;
- Comment
- : "/*"
- ( {LA(2) != '/'}? '*'
- | EndOfLine {newline();}
- | ~('*'| '\r' | '\n')
- )*
- "*/"
- {$setType(Token.SKIP);}
- ;
- CPPComment
- : "//" (~('\n' | '\r'))* EndOfLine
- {$setType(Token.SKIP);newline();}
- ;
- DIRECTIVE
- : '#' ld:LineDirective
- { $setType(Token.SKIP); newline();}
- ;
- protected
- LineDirective
- :
- (~('\r'|'\n'))* EndOfLine
- ;
- /* Literals: */
- /*
- * Note that we do NOT handle tri-graphs nor multi-byte sequences.
- */
- /*
- * Note that we can't have empty character constants (even though we
- * can have empty strings :-).
- */
- CharLiteral
- : '\'' (Escape | ~( '\'' )) '\''
- ;
- /*
- * Can't have raw imbedded newlines in string constants. Strict reading of
- * the standard gives odd dichotomy between newlines & carriage returns.
- * Go figure.
- */
- StringLiteral
- : '"'
- ( Escape
- | ( "\\\r\n" // MS
- | "\\\r" // MAC
- | "\\\n" // Unix
- ) {newline();}
- | ~('"' | '\r' | '\n' | '\\')
- )*
- '"'
- ;
- protected
- EndOfLine
- : ( options{generateAmbigWarnings = false;}:
- "\r\n" // MS
- | '\r' // Mac
- | '\n' // Unix
- )
- ;
- /*
- * Handle the various escape sequences.
- *
- * Note carefully that these numeric escape *sequences* are *not* of the
- * same form as the C language numeric *constants*.
- *
- * There is no such thing as a binary numeric escape sequence.
- *
- * Octal escape sequences are either 1, 2, or 3 octal digits exactly.
- *
- * There is no such thing as a decimal escape sequence.
- *
- * Hexadecimal escape sequences are begun with a leading \x and continue
- * until a non-hexadecimal character is found.
- *
- * No real handling of tri-graph sequences, yet.
- */
- protected
- Escape
- : '\\'
- ( options{warnWhenFollowAmbig=false;}:
- 'a'
- | 'b'
- | 'f'
- | 'n'
- | 'r'
- | 't'
- | 'v'
- | '"'
- | '\''
- | '\\'
- | '?'
- | ('0'..'3') (options{warnWhenFollowAmbig=false;}: Digit (options{warnWhenFollowAmbig=false;}: Digit)? )?
- | ('4'..'7') (options{warnWhenFollowAmbig=false;}: Digit)?
- | 'x' (options{warnWhenFollowAmbig=false;}: Digit | 'a'..'f' | 'A'..'F')+
- )
- ;
- /* Numeric Constants: */
- protected
- Digit
- : '0'..'9'
- ;
- protected
- Decimal
- : ('0'..'9')+
- ;
- protected
- LongSuffix
- : 'l'
- | 'L'
- ;
- protected
- UnsignedSuffix
- : 'u'
- | 'U'
- ;
- protected
- FloatSuffix
- : 'f'
- | 'F'
- ;
- protected
- Exponent
- : ('e' | 'E') ('+' | '-')? (Digit)+
- ;
- protected
- Vocabulary
- : '\3'..'\377'
- ;
- Number
- : ( (Digit)+ ('.' | 'e' | 'E') )=> (Digit)+
- ( '.' (Digit)* (Exponent)? {$setType ( FLOATONE);} //Zuo 3/12/01
- | Exponent {$setType (FLOATTWO);} //Zuo 3/12/01
- )
- (FloatSuffix
- |LongSuffix
- )?
- | ("...")=> "..." {$setType (ELLIPSIS);}
- | '.' {$setType (DOT);}
- ( (Digit)+ (Exponent)? {$setType (FLOATONE);} //Zuo 3/12/01
- //{_ttype = DoubleDoubleConst;}
- (FloatSuffix //{_ttype = FloatDoubleConst;}
- |LongSuffix //{_ttype = LongDoubleConst;}
- )?
- )?
- | '0' ('0'..'7')* //{_ttype = IntOctalConst;}
- (LongSuffix //{_ttype = LongOctalConst;}
- |UnsignedSuffix //{_ttype = UnsignedOctalConst;}
- )* {$setType( OCTALINT);}
- | '1'..'9' (Digit)* //{_ttype = IntIntConst;}
- (LongSuffix //{_ttype = LongIntConst;}
- |UnsignedSuffix //{_ttype = UnsignedIntConst;}
- )* {$setType( DECIMALINT);}
- | '0' ('x' | 'X') ('a'..'f' | 'A'..'F' | Digit)+
- //{_ttype = IntHexConst;}
- (LongSuffix //{_ttype = LongHexConst;}
- |UnsignedSuffix //{_ttype = UnsignedHexConst;}
- )* {$setType( HEXADECIMALINT);}
- ;
- ID
- options {testLiterals = true;}
- : ( 'a'..'z' | 'A'..'Z' | '_' )
- ( 'a'..'z' | 'A'..'Z' | '_' | '0'..'9' )*
- ;