| /* |
| * 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. |
| */ |
| /* 2005 |
| * Version 3.1 November 2005 |
| * Updated by David Wigg at London South Bank University |
| * |
| * 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 |
| */ |
| |
| header |
| { |
| // File generated from CPP_parser.g |
| // Version 3.1 November 2005 |
| // This file is best viewed in courier font with tabs set to 4 spaces |
| // |
| // The statements in this block appear in both CPPLexer.hpp and CPPParser.hpp |
| #include <stdio.h> |
| #include <string.h> |
| #include "antlr/CharScanner.hpp" |
| #include "CPPDictionary.hpp" |
| |
| // Defined in main.cpp |
| extern void process_line_directive(const char *, const char *); |
| |
| // Declared in main.cpp |
| extern int deferredLineCount; |
| } |
| |
| options |
| { |
| language = "Cpp"; |
| } |
| |
| { |
| // File generated from CPP_parser.g |
| // Version 3.1 November 2005 |
| // This file is best viewed in courier font with tabs set to 4 spaces |
| // |
| // The statements in this block appear only in CPPParser.cpp and not in CPPLexer.cpp |
| |
| // These constants used in the previous version (3.0 July 2004) have now been replaced by the following, |
| //ID_VAR_NAME is now CPPSymbol::otVariable |
| //ID_FUN_NAME is now CPPSymbol::otFunction |
| //ID_INPUT_PARAMETER is now not used |
| //ID_CLASS_DEF is now CPPSymbol::otClass |
| //ID_SYSTEM_FUNCTION is now not used |
| //ID_CONST_DECL is now not used |
| //ID_TYPEDEF_VAR is now CPPSymbol::otTypedef |
| |
| int statementTrace = 2; // Used to control selected (level) tracing (see support.cpp) |
| // 1 Shows which external and member statements selected |
| // 2 Shows above plus all declarations/definitions |
| // 3 reserved for future use |
| // 4 and above available for user |
| |
| void CPPParser::init() |
| { |
| antlrTrace(false); // This is a dynamic trace facility for use with -traceParser etc. |
| // It requires modification in LLkParser.cpp and LLkParser.hpp |
| // otherwise it should be commented out (see MyReadMe.txt) |
| // true shows antlr trace (or can be set and reset during parsing) |
| // false stops showing antlr trace |
| // Provided the parser is always generated with -traceParser this |
| // facility allows trace output to be turned on or off by changing |
| // the setting here from false to true or vice versa and then |
| // recompiling and linking CPPParser only thus avoiding the need |
| // to use antlr.Tool to re-generate the lexer and parser again |
| // with (or without) -traceParser. |
| // Antlr trace can also be turned on and off dynamically using |
| // antlrTrace_on or antlrTrace_off statements inserted into the |
| // source code being parsed (See below). |
| |
| // Creates a dictionary to hold symbols with 4001 buckets, 200 scopes and 800,000 characters |
| // These can be changed to suit the size of program(s) being parsed |
| symbols = new CPPDictionary(4001, 200, 800000); |
| |
| // Set template parameter scope - Not used at present |
| templateParameterScope = symbols->getCurrentScopeIndex(); // Set template parameter scope to 0 |
| |
| symbols->saveScope(); // Advance currentScope from 0 to 1 |
| // Set "external" scope for all types |
| externalScope = symbols->getCurrentScopeIndex(); // Set "external" scope to 1 for types |
| |
| // Declare predefined scope "std" in external scope |
| CPPSymbol *a = new CPPSymbol("std", CPPSymbol::otTypedef); |
| symbols->define("std", a); |
| |
| symbols->saveScope(); // Advance currentScope from 1 to 2 (and higher) for all other symbols |
| // treated as locals |
| |
| // Global flags to allow for nested declarations |
| _td = false; // For typedef |
| _fd = false; // For friend |
| _sc = scInvalid; // For StorageClass |
| _tq = tqInvalid; // For TypeQualifier |
| _ts = tsInvalid; // For TypeSpecifier |
| _fs = fsInvalid; // For FunctionSpecifier |
| |
| functionDefinition = 0; |
| qualifierPrefix[0] = '\0'; |
| enclosingClass = (char *) ""; |
| assign_stmt_RHS_found = 0; |
| in_parameter_list = false; |
| K_and_R = false; // used to distinguish old K & R parameter definitions |
| in_return = false; |
| is_address = false; |
| is_pointer = false; |
| } |
| |
| } // End of CPPParser.cpp block |
| |
| class CPPParser extends Parser; |
| |
| options |
| { |
| k = 2; |
| exportVocab = STDC; |
| buildAST =false; |
| codeGenMakeSwitchThreshold = 2; |
| codeGenBitsetTestThreshold = 3; |
| } |
| |
| { |
| public: |
| #define CPPParser_MaxQualifiedItemSize 500 |
| |
| // These codes are not stored with symbol names in CPPSymbol, |
| // but they are available for development |
| // Can't bitwise-OR enum elements together, this must be an int |
| typedef unsigned long TypeSpecifier; // note: must be at least 16 bits |
| typedef unsigned long TypeQualifier; |
| |
| #define tsInvalid 0x0 |
| #define tsVOID 0x1 |
| #define tsCHAR 0x2 |
| #define tsSHORT 0x4 |
| #define tsINT 0x8 |
| #define tsLONG 0x10 |
| #define tsFLOAT 0x20 |
| #define tsDOUBLE 0x40 |
| #define tsSIGNED 0x80 |
| #define tsUNSIGNED 0x100 |
| #define tsTYPEID 0x200 |
| #define tsSTRUCT 0x400 |
| #define tsENUM 0x800 |
| #define tsUNION 0x1000 |
| #define tsCLASS 0x2000 |
| #define tsWCHAR_T 0x4000 |
| #define tsBOOL 0x8000 |
| |
| |
| #define tqInvalid 0x0 |
| #define tqCONST 0x1 |
| #define tqVOLATILE 0x2 |
| #define tqGFEXCLUDE 0x4 |
| #define tqGFINCLUDE 0x8 |
| #define tqGFID 0x10 |
| #define tqGFUNREAD 0x20 |
| |
| enum StorageClass |
| { |
| scInvalid=0, scAUTO=1, scREGISTER, |
| scSTATIC, scEXTERN, scMUTABLE |
| }; |
| |
| enum FunctionSpecifier |
| { |
| fsInvalid=0, |
| fsVIRTUAL, fsINLINE, fsEXPLICIT, fsFRIEND |
| }; |
| |
| // JEL 3/26/96 changed to allow ORing of values |
| // DW 10/04/05 These codes are stored with the item in CPPSymbol in the dictionary See declaratorID |
| typedef int QualifiedItem; |
| #define qiInvalid 0x0 |
| #define qiType 0x1 // includes enum, class, typedefs, namespace |
| #define qiDtor 0x2 |
| #define qiCtor 0x4 |
| #define qiOperator 0x8 |
| #define qiPtrMember 0x10 |
| #define qiVar 0x20 |
| #define qiFun 0x40 |
| #define qiNamespace 0x50 |
| |
| protected: |
| // Symbol table management stuff |
| CPPDictionary *symbols; |
| int templateParameterScope; |
| int externalScope; |
| int anyType; |
| int anyNonType; |
| |
| bool _td; // For typedef |
| bool _fd; // For friend |
| StorageClass _sc; // For storage class |
| TypeQualifier _tq; // For type qualifier |
| TypeSpecifier _ts; // For type specifier |
| FunctionSpecifier _fs; // For declaration specifier |
| |
| int functionDefinition; // 0 = Function definition not being parsed |
| // 1 = Parsing function name |
| // 2 = Parsing function parameter list |
| // 3 = Parsing function block |
| |
| char qualifierPrefix[CPPParser_MaxQualifiedItemSize+1]; |
| char *enclosingClass; |
| int assign_stmt_RHS_found; |
| bool in_parameter_list; |
| bool K_and_R; // used to distinguish old K & R parameter definitions |
| bool in_return; |
| bool is_address; |
| bool is_pointer; |
| |
| // Limit lookahead for qualifiedItemIs() |
| enum |
| { |
| MaxTemplateTokenScan = 200 |
| }; |
| |
| public: |
| void init(); |
| |
| protected: |
| // Semantic interface in Support.cpp; |
| // You could subclass and redefine these functions |
| // so you don't have to mess with the grammar itself. |
| |
| // Symbol stuff |
| virtual int qualifiedItemIsOneOf(QualifiedItem qiFlags, int lookahead_offset=0); |
| virtual QualifiedItem qualifiedItemIs(int lookahead_offset=0); |
| virtual int skipTemplateQualifiers(int& kInOut); |
| virtual int skipNestedParens(int& kInOut); |
| virtual int scopedItem(int k=1); |
| virtual int finalQualifier(int k=1); |
| virtual int isTypeName(const char *s); |
| virtual int isClassName(const char *s); |
| virtual void end_of_stmt(); |
| |
| // Scoping stuff |
| virtual void enterNewLocalScope(); |
| virtual void exitLocalScope(); |
| virtual void enterExternalScope(); |
| virtual void exitExternalScope(); |
| |
| // namespaceEnd stuff |
| virtual void exitNamespaceScope(); |
| |
| // Aggregate stuff |
| virtual void classForwardDeclaration(TypeSpecifier, FunctionSpecifier,const char *); |
| virtual void beginClassDefinition(TypeSpecifier,const char *); |
| virtual void endClassDefinition(); |
| virtual void beginEnumDefinition(const char *); |
| virtual void endEnumDefinition(); |
| virtual void enumElement(const char *); |
| |
| // Declaration and definition stuff |
| virtual void declarationSpecifier(bool,bool,StorageClass,TypeQualifier,TypeSpecifier,FunctionSpecifier); |
| virtual void beginDeclaration(); |
| virtual void endDeclaration(); |
| virtual void beginConstructorDeclaration(const char *); |
| virtual void endConstructorDeclaration(); |
| virtual void beginDestructorDeclaration(const char *); |
| virtual void endDestructorDeclaration(); |
| virtual void beginParameterDeclaration(); |
| virtual void beginFieldDeclaration(); |
| virtual void beginFunctionDefinition(); |
| virtual void endFunctionDefinition(); |
| virtual void functionParameterList(); |
| virtual void functionEndParameterList(int def); |
| virtual void beginConstructorDefinition(); |
| virtual void endConstructorDefinition(); |
| virtual void beginDestructorDefinition(); |
| virtual void endDestructorDefinition(); |
| |
| // Declarator stuff |
| virtual void declaratorID(const char *, QualifiedItem); // This stores new symbol with its type. |
| virtual void declaratorArray(); |
| virtual void declaratorParameterList(int def); |
| virtual void declaratorEndParameterList(int def); |
| |
| // template stuff |
| virtual void templateTypeParameter(const char *); |
| virtual void beginTemplateDeclaration(); |
| virtual void endTemplateDeclaration(); |
| virtual void beginTemplateDefinition(); |
| virtual void endTemplateDefinition(); |
| virtual void beginTemplateParameterList(); |
| virtual void endTemplateParameterList(); |
| |
| // exception stuff |
| virtual void exceptionBeginHandler(); |
| virtual void exceptionEndHandler(); |
| virtual void panic(const char *); |
| |
| // myCode functions ready for overriding in MyCode subclass |
| // Include application code functions here |
| virtual void myCode_pre_processing(int, char *[]); |
| virtual void myCode_post_processing(); |
| virtual void myCode_end_of_stmt(); |
| virtual void myCode_function_direct_declarator(const char *); |
| |
| // Auto-serializer specific stuff |
| virtual void gfArraySize(const char* id) { } |
| virtual void gfArrayElemSize(const char* id) { } |
| } |
| |
| translation_unit |
| : {enterExternalScope();} |
| (external_declaration)+ EOF |
| {exitExternalScope();} |
| ; |
| |
| external_declaration |
| {char *s; |
| K_and_R = false; |
| FunctionSpecifier fs = fsInvalid; // inline,virtual,explicit |
| } |
| : |
| ( |
| // Template explicit specialisation |
| ("template" LESSTHAN GREATERTHAN)=> |
| {if(statementTrace>=1) |
| printf("%d external_declaration template explicit-specialisation\n",LT(1)->getLine()); |
| } |
| "template" LESSTHAN GREATERTHAN external_declaration |
| | |
| // All typedefs |
| ("typedef")=> |
| ( |
| ("typedef" class_specifier)=> |
| {if(statementTrace>=1) |
| printf("%d external_declaration Typedef class type\n",LT(1)->getLine()); |
| } |
| "typedef" class_decl_or_def[fs] {_td = true;} (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| ("typedef" "enum")=> |
| {if(statementTrace>=1) |
| printf("%d external_declaration Typedef enum type\n",LT(1)->getLine()); |
| } |
| "typedef" enum_specifier {_td = true;} (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| (declaration_specifiers function_declarator[0] SEMICOLON)=> // DW 11/02/05 This may not be possible |
| {if(statementTrace>=1) |
| printf("%d external_declaration Typedef function type\n",LT(1)->getLine()); |
| } |
| declaration |
| | |
| {if(statementTrace>=1) |
| printf("%d external_declaration Typedef variable type\n",LT(1)->getLine()); |
| } |
| declaration |
| ) |
| | |
| // Class template declaration or definition |
| (template_head (fs = function_specifier)* class_specifier)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Templated class decl or def\n",LT(1)->getLine()); |
| } |
| template_head (fs = function_specifier)* class_decl_or_def[fs] (init_declarator_list)? SEMICOLON {end_of_stmt();} // declaration |
| | |
| // Enum definition (don't want to backtrack over this in other alts) |
| ("enum" (ID)? LCURLY)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Enum definition\n",LT(1)->getLine()); |
| } |
| enum_specifier (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| // Destructor definition (templated or non-templated) |
| ((template_head)? dtor_head[1] LCURLY)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Destructor definition\n",LT(1)->getLine()); |
| } |
| (template_head)? dtor_head[1] 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(qiCtor)}? |
| )=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Constructor definition\n",LT(1)->getLine()); |
| } |
| ctor_definition |
| | |
| // User-defined type cast |
| (("inline")? scope_override conversion_function_decl_or_def)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Operator function\n",LT(1)->getLine()); |
| } |
| ("inline")? s = scope_override conversion_function_decl_or_def |
| | |
| // Function declaration |
| (declaration_specifiers function_declarator[0] SEMICOLON)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Function declaration\n",LT(1)->getLine()); |
| } |
| declaration_specifiers function_declarator[0] SEMICOLON {end_of_stmt();} |
| | |
| // Function definition |
| (declaration_specifiers function_declarator[1] LCURLY)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Function definition\n",LT(1)->getLine()); |
| } |
| function_definition |
| | |
| // K & R Function definition |
| (declaration_specifiers function_declarator[1] declaration)=> |
| {K_and_R = true; |
| if (statementTrace>=1) |
| printf("%d external_declaration K & R function definition\n",LT(1)->getLine()); |
| } |
| function_definition |
| | |
| // K & R Function definition with int return assumed |
| (function_declarator[1] declaration)=> |
| {K_and_R = true; |
| if (statementTrace>=1) |
| printf("%d external_declaration K & R function definition without return type\n",LT(1)->getLine()); |
| } |
| function_definition |
| | |
| // Class declaration or definition |
| (("friend")? (fs = function_specifier)* class_specifier)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Class decl or def\n",LT(1)->getLine()); |
| } |
| ("friend")? (fs = function_specifier)* class_decl_or_def[fs] (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| // Templated functions and constructors matched here. |
| {beginTemplateDeclaration();} |
| template_head |
| ( |
| // templated forward class decl, init/decl of static member in template |
| (declaration_specifiers (init_declarator_list)? SEMICOLON {end_of_stmt();})=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Templated class forward declaration\n",LT(1)->getLine()); |
| } |
| declaration_specifiers (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| // Templated function declaration |
| (declaration_specifiers function_declarator[0] SEMICOLON)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Templated function declaration\n",LT(1)->getLine()); |
| } |
| declaration |
| | |
| // Templated function definition |
| (declaration_specifiers function_declarator[1] LCURLY)=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration_10c Templated function definition\n",LT(1)->getLine()); |
| } |
| function_definition |
| | |
| // 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(qiCtor)}? |
| )=> |
| {if (statementTrace>=1) |
| printf("%d external_declaration Templated constructor definition\n",LT(1)->getLine()); |
| } |
| ctor_definition |
| ) |
| {endTemplateDeclaration();} |
| | |
| // Namespace definition |
| {if (statementTrace>=1) |
| printf("%d external_declaration Namespace definition\n",LT(1)->getLine()); |
| } |
| "namespace" namespace_definition |
| | |
| // Anything else |
| {if (statementTrace>=1) |
| printf("%d external_declaration Declaration\n",LT(1)->getLine()); |
| } |
| declaration |
| | |
| // Semicolon |
| {if (statementTrace>=1) |
| printf("%d external_declaration Semicolon\n",LT(1)->getLine()); |
| } |
| SEMICOLON {end_of_stmt();} |
| | |
| // The next two entries may be used for debugging |
| // Use this statement in the source code to turn antlr trace on (See note above) |
| "antlrTrace_on" {antlrTrace(true);} |
| | |
| // Use this statement in the source code to turn antlr trace off (See note above) |
| "antlrTrace_off" {antlrTrace(false);} |
| ) |
| ; // end of external_declaration |
| |
| //namespace_definition |
| namespace_definition |
| : |
| (ns:ID{declaratorID((ns->getText()).data(),qiNamespace);})? |
| LCURLY |
| {enterNewLocalScope();} |
| (external_declaration)* |
| {exitNamespaceScope();exitLocalScope();} |
| RCURLY |
| ; |
| |
| //namespace_alias_definition |
| namespace_alias_definition |
| {char *qid;} |
| : |
| "namespace" |
| ns2:ID {declaratorID((ns2->getText()).data(),qiNamespace);} |
| ASSIGNEQUAL qid = qualified_id SEMICOLON {end_of_stmt();} |
| ; |
| |
| member_declaration |
| {char *q; |
| FunctionSpecifier fs = fsInvalid; // inline,virtual,explicit |
| } |
| : |
| ( |
| // Template explicit specialisation |
| ("template" LESSTHAN GREATERTHAN)=> |
| {if(statementTrace>=1) |
| printf("%d member_declaration Template explicit-specialisation\n",LT(1)->getLine()); |
| } |
| "template" LESSTHAN GREATERTHAN member_declaration |
| | |
| // All typedefs |
| ("typedef")=> |
| ( |
| ("typedef" class_specifier)=> |
| {if(statementTrace>=1) |
| printf("%d member_declaration Typedef class type\n",LT(1)->getLine()); |
| } |
| "typedef" class_decl_or_def[fs] {_td = true;}(init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| ("typedef" "enum")=> |
| {if(statementTrace>=1) |
| printf("%d member_declaration Typedef enum type\n",LT(1)->getLine()); |
| } |
| "typedef" enum_specifier {_td = true;} (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| (declaration_specifiers function_declarator[0] SEMICOLON)=> // DW 11/02/05 This may not be possible member declaration |
| {if(statementTrace>=1) |
| printf("%d member_declaration Typedef function type\n",LT(1)->getLine()); |
| } |
| declaration |
| | |
| {if(statementTrace>=1) |
| printf("%d member_declaration Typedef variable type\n",LT(1)->getLine()); |
| } |
| declaration |
| ) |
| | |
| // Templated class declaration or definition |
| (template_head (fs = function_specifier)* class_specifier)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Templated class decl or def\n",LT(1)->getLine()); |
| } |
| template_head (fs = function_specifier)* class_decl_or_def[fs] (init_declarator_list)? SEMICOLON {end_of_stmt();} // declaration |
| | |
| // Enum definition (don't want to backtrack over this in other alts) |
| ("enum" (ID)? LCURLY)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Enum definition\n",LT(1)->getLine()); |
| } |
| enum_specifier (member_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| // Constructor declarator |
| ( ctor_decl_spec |
| {qualifiedItemIsOneOf(qiCtor)}? |
| ctor_declarator[0] SEMICOLON |
| )=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Constructor declarator\n",LT(1)->getLine()); |
| } |
| ctor_decl_spec ctor_declarator[0] SEMICOLON {end_of_stmt();} |
| | |
| // 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 |
| // Constructor definition |
| ( ctor_decl_spec |
| {qualifiedItemIsOneOf(qiCtor)}? |
| ctor_declarator[1] |
| (COLON // DEFINITION :ctor_initializer |
| |LCURLY // DEFINITION (compound Statement) ? |
| ) |
| )=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Constructor definition\n",LT(1)->getLine()); |
| } |
| ctor_definition |
| | |
| // No template_head allowed for dtor member |
| // Backtrack if not a dtor (no TILDE) |
| // Destructor declaration |
| (dtor_head[0] SEMICOLON)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Destructor declaration\n",LT(1)->getLine()); |
| } |
| dtor_head[0] SEMICOLON {end_of_stmt();} |
| | |
| // No template_head allowed for dtor member |
| // Backtrack if not a dtor (no TILDE) |
| // Destructor definition |
| (dtor_head[1] LCURLY)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Destructor definition\n",LT(1)->getLine()); |
| } |
| dtor_head[1] dtor_body |
| | |
| // Function declaration |
| (declaration_specifiers function_declarator[0] SEMICOLON)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Function declaration\n",LT(1)->getLine()); |
| } |
| declaration_specifiers function_declarator[0] SEMICOLON {end_of_stmt();} |
| | |
| // Function definition |
| (declaration_specifiers function_declarator[1] LCURLY)=> |
| {beginFieldDeclaration(); |
| if (statementTrace>=1) |
| printf("%d member_declaration Function definition\n",LT(1)->getLine()); |
| } |
| function_definition |
| | |
| // User-defined type cast |
| (("inline")? conversion_function_decl_or_def)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Operator function\n",LT(1)->getLine()); |
| } |
| ("inline")? conversion_function_decl_or_def |
| | |
| // Hack to handle decls like "superclass::member", |
| // to redefine access to private base class public members |
| // Qualified identifier |
| (qualified_id SEMICOLON)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Qualified ID\n",LT(1)->getLine()); |
| } |
| q = qualified_id SEMICOLON {end_of_stmt();} |
| | |
| // 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 (init_declarator_list)? SEMICOLON)=> |
| {beginFieldDeclaration(); |
| if (statementTrace>=1) |
| printf("%d member_declaration Declaration\n",LT(1)->getLine()); |
| } |
| declaration |
| | |
| // Class declaration or definition |
| (("friend")? (fs = function_specifier)* class_specifier)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Class decl or def\n",LT(1)->getLine()); |
| } |
| ("friend")? (fs = function_specifier)* class_decl_or_def[fs] (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| // Member without a type (I guess it can only be a function declaration or definition) |
| ((fs = function_specifier)* function_declarator[0] SEMICOLON)=> |
| {beginFieldDeclaration(); |
| fprintf(stderr,"%d warning Function declaration found without return type\n",LT(1)->getLine()); |
| if (statementTrace>=1) |
| printf("%d member_declaration Function declaration\n",LT(1)->getLine()); |
| } |
| (fs = function_specifier)* function_declarator[0] SEMICOLON {end_of_stmt();} |
| |
| | |
| // Member without a type (I guess it can only be a function definition) |
| { |
| fprintf(stderr,"%d warning Function definition found without return type\n",LT(1)->getLine()); |
| if (statementTrace>=1) |
| printf("%d member_declaration Function definition without return type\n",LT(1)->getLine()); |
| } |
| function_declarator[1] compound_statement {endFunctionDefinition();} |
| | |
| // Templated functions and constructors matched here. |
| {beginTemplateDeclaration();} |
| template_head |
| ( |
| // templated forward class decl, init/decl of static member in template |
| (declaration_specifiers (init_declarator_list)? SEMICOLON)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Templated forward declaration\n",LT(1)->getLine()); |
| } |
| declaration_specifiers (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| | |
| // Templated function declaration |
| (declaration_specifiers function_declarator[0] SEMICOLON)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Templated function declaration\n",LT(1)->getLine()); |
| } |
| declaration |
| | |
| // Templated function definition |
| (declaration_specifiers function_declarator[1] LCURLY)=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Templated function definition\n",LT(1)->getLine()); |
| } |
| function_definition |
| | |
| // 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(qiCtor)}? |
| )=> |
| {if (statementTrace>=1) |
| printf("%d member_declaration Templated constructor definition\n",LT(1)->getLine()); |
| } |
| ctor_definition |
| | |
| // Templated operator function |
| {if (statementTrace>=1) |
| printf("%d member_declaration Templated operator function\n",LT(1)->getLine()); |
| } |
| conversion_function_decl_or_def |
| | |
| // Templated class definition |
| {if (statementTrace>=1) |
| printf("%d member_declaration Templated class definition\n",LT(1)->getLine()); |
| } |
| class_head declaration_specifiers (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| ) |
| {endTemplateDeclaration();} |
| | |
| // Access specifier |
| {if (statementTrace>=1) |
| printf("%d member_declaration Access specifier\n",LT(1)->getLine()); |
| } |
| access_specifier COLON |
| | |
| // Semicolon |
| {if (statementTrace>=1) |
| printf("%d member_declaration Semicolon\n",LT(1)->getLine()); |
| } |
| SEMICOLON {end_of_stmt();} |
| | |
| // The next two entries may be used for debugging |
| // Use this statement in the source code to turn antlr trace on (See note above) |
| "antlrTrace_on" {antlrTrace(true);} |
| | |
| // Use this statement in the source code to turn antlr trace off (See note above) |
| "antlrTrace_off" {antlrTrace(false);} |
| ) |
| ; // end member_declaration |
| |
| //function_definition |
| function_definition |
| : // don't want next action as an init-action due to (...)=> caller |
| { |
| beginFunctionDefinition(); |
| } |
| ( // Next line is equivalent to guarded predicate in PCCTS |
| // (SCOPE | ID)? => <<qualifiedItemIsOneOf(qiType|qiCtor)>>? |
| {( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(qiType|qiCtor) )}? |
| declaration_specifiers function_declarator[1] |
| ( options{warnWhenFollowAmbig = false;}: |
| (declaration)* // Possible for K & R definition |
| {in_parameter_list = false;} |
| )? |
| compound_statement |
| | // Next line is equivalent to guarded predicate in PCCTS |
| // (SCOPE | ID)? => <<qualifiedItemIsOneOf(qiPtrMember)>>? |
| //{( !(LA(1)==SCOPE||LA(1)==ID) || (qualifiedItemIsOneOf(qiPtrMember)) )}? |
| function_declarator[1] |
| ( options{warnWhenFollowAmbig = false;}: |
| (declaration)* // Possible for K & R definition |
| {in_parameter_list = false;} |
| )? |
| compound_statement |
| ) |
| {endFunctionDefinition();} |
| ; |
| |
| //declaration |
| declaration |
| : |
| ("extern" StringLiteral)=> |
| linkage_specification |
| | |
| {beginDeclaration();} |
| declaration_specifiers (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| {endDeclaration();} |
| | |
| using_statement |
| ; |
| |
| //linkage_specification |
| linkage_specification |
| : |
| "extern" |
| StringLiteral |
| (LCURLY (external_declaration)* RCURLY |
| |declaration |
| ) |
| ; |
| |
| //class_head |
| class_head |
| : // Used only by predicates |
| ( "struct" |
| | "union" |
| | "class" |
| ) |
| (ID |
| (LESSTHAN template_argument_list GREATERTHAN)? |
| (base_clause)? |
| )? |
| LCURLY |
| ; |
| |
| //declaration_specifiers |
| declaration_specifiers |
| {// Locals |
| bool td = false; // For typedef |
| bool fd = false; // For friend |
| StorageClass sc = scInvalid; // auto,register,static,extern,mutable |
| TypeQualifier tq = tqInvalid; // const,volatile // aka cv_qualifier See type_qualifier |
| TypeSpecifier ts = tsInvalid; // char,int,double, etc., class,struct,union |
| FunctionSpecifier fs = fsInvalid; // inline,virtual,explicit |
| } |
| : |
| { |
| // Global flags to allow for nested declarations |
| _td = false; // For typedef |
| _fd = false; // For friend |
| _sc = scInvalid; // For StorageClass // auto,register,static,extern,mutable |
| _tq = tqInvalid; // For TypeQualifier // aka cv_qualifier See type_qualifier |
| _ts = tsInvalid; // For TypeSpecifier |
| _fs = fsInvalid; // For FunctionSpecifier // inline,virtual,explicit |
| |
| } |
| ( (options {warnWhenFollowAmbig = false;} |
| : "typedef" {td=true;} |
| | "friend" {fd=true;} |
| | sc = storage_class_specifier // auto,register,static,extern,mutable |
| | tq = type_qualifier // const,volatile // aka cv_qualifier See type_qualifier |
| | ts = class_specifier // Only here for disambiguation |
| | "enum" // Only here for disambiguation |
| | fs = function_specifier // inline,virtual,explicit |
| | ("_stdcall"|"__stdcall") |
| | "GFEXCLUDE" {tq |= tqGFEXCLUDE; _tq |= tqGFEXCLUDE;} |
| | "GFINCLUDE" {tq |= tqGFINCLUDE; _tq |= tqGFINCLUDE;} |
| | "GFID" {tq |= tqGFID; _tq |= tqGFID;} |
| | "GFUNREAD" {tq |= tqGFUNREAD; _tq |= tqGFUNREAD;} |
| | "GFARRAYSIZE" LPAREN gfArr:ID RPAREN {gfArraySize(gfArr->getText().data());} |
| | "GFARRAYSIZES" LPAREN gfArrList:StringLiteral RPAREN {gfArraySize(gfArrList->getText().data());} |
| | "GFARRAYELEMSIZE" LPAREN gfArrElem:ID RPAREN {gfArrayElemSize(gfArrElem->getText().data());} |
| )* |
| ts = type_specifier |
| ) |
| {declarationSpecifier(td,fd,sc,tq,ts,fs);} |
| ; |
| |
| //storage_class_specifier |
| storage_class_specifier returns [CPPParser::StorageClass sc = scInvalid] |
| : "auto" {sc = scAUTO;} |
| | "register" {sc = scREGISTER;} |
| | "static" {sc = scSTATIC;} |
| | "extern" {sc = scEXTERN;} |
| | "mutable" {sc = scMUTABLE;} |
| ; |
| |
| //function_specifier |
| function_specifier returns [CPPParser::FunctionSpecifier fs = fsInvalid] |
| : ("inline"|"_inline"|"__inline") {fs = fsINLINE;} |
| | "virtual" {fs = fsVIRTUAL;} |
| | "explicit" {fs = fsEXPLICIT;} |
| ; |
| |
| //type_specifier |
| type_specifier returns [CPPParser::TypeSpecifier ts = tsInvalid] |
| { |
| TypeQualifier tq = tqInvalid; |
| } |
| : |
| ts = simple_type_specifier |
| ; |
| |
| //simple_type_specifier |
| simple_type_specifier returns [CPPParser::TypeSpecifier ts = tsInvalid] |
| {char *s; |
| ts = tsInvalid; |
| } |
| : ( {qualifiedItemIsOneOf(qiType|qiCtor)}? |
| s = qualified_type |
| | |
| "typename" |
| s = qualified_type |
| {declaratorID(s,qiType);} // This stores typename name in dictionary |
| | |
| ( "char" {ts |= tsCHAR;} |
| | "wchar_t" {ts |= tsWCHAR_T;} |
| | "bool" {ts |= tsBOOL;} |
| | "short" {ts |= tsSHORT;} |
| | "int" {ts |= tsINT;} |
| | ("_int8"|"__int8"|"int8_t") {ts |= tsINT;} |
| | ("_int16"|"__int16"|"int16_t") {ts |= tsINT;} |
| | ("_int32"|"__int32"|"int32_t") {ts |= tsLONG;} |
| | ("_int64"|"__int64"|"int64_t") {ts |= tsLONG;} |
| | ("uint8_t") {ts |= (tsUNSIGNED | tsINT);} |
| | ("uint16_t") {ts |= (tsUNSIGNED | tsINT);} |
| | ("uint32_t") {ts |= (tsUNSIGNED | tsLONG);} |
| | ("uint64_t") {ts |= (tsUNSIGNED | tsLONG);} |
| | ("_w64"|"__w64") {ts |= tsLONG;} |
| | "long" {ts |= tsLONG;} |
| | "signed" {ts |= tsSIGNED;} |
| | "unsigned" {ts |= tsUNSIGNED;} |
| | "float" {ts |= tsFLOAT;} |
| | "double" {ts |= tsDOUBLE;} |
| | "void" {ts |= tsVOID;} |
| | ("_declspec"|"__declspec") LPAREN ID RPAREN |
| )+ |
| //| |
| // Possible fix towards allowing us to parse *.cpp files directly |
| //(qualified_type qualified_id)=> s = qualified_type {ts |= tsTYPEID;} |
| //{printf("simple_type_specifier third option entered\n");} |
| ) |
| ; |
| |
| //qualified_type |
| qualified_type returns [char *q = NULL] |
| {char *s; static char qitem[CPPParser_MaxQualifiedItemSize+1];} |
| : |
| // 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(qiType|qiCtor)}? |
| |
| s = scope_override |
| id:ID |
| (options {warnWhenFollowAmbig = false;}: |
| LESSTHAN template_argument_list GREATERTHAN |
| )? |
| { |
| strcpy(qitem, s); |
| strcat(qitem, (id->getText()).data()); |
| q = qitem; |
| } |
| ; |
| |
| //class_specifier |
| class_specifier returns [CPPParser::TypeSpecifier ts = tsInvalid] |
| : |
| ( "class" {ts = tsCLASS;} |
| | "struct" {ts = tsSTRUCT;} |
| | "union" {ts = tsUNION;} |
| ) |
| ; |
| |
| //type_qualifier |
| type_qualifier returns [CPPParser::TypeQualifier tq = tqInvalid] // aka cv_qualifier |
| : |
| ( ("const"|"__const") {tq = tqCONST;} |
| | ("volatile"|"__volatile__") {tq = tqVOLATILE;} |
| ) |
| ; |
| |
| //class_prefix |
| class_prefix |
| : |
| (("_declspec"!|"__declspec"!) LPAREN! expression RPAREN!)* |
| { |
| } |
| ; |
| |
| |
| //class_decl_or_def |
| class_decl_or_def [FunctionSpecifier fs] |
| {char *saveClass; |
| char *id; |
| TypeSpecifier ts = tsInvalid; // Available for use |
| } |
| : |
| ( "class" {ts = tsCLASS;} |
| | "struct" {ts = tsSTRUCT;} |
| | "union" {ts = tsUNION;} |
| ) |
| class_prefix // for decltypes |
| ("GFIGNORE" LPAREN expression RPAREN {})* |
| ( id = qualified_id |
| (options{generateAmbigWarnings = false;}: |
| (SEMICOLON)=> |
| // Empty |
| {classForwardDeclaration(ts, fs, id);} |
| | |
| {saveClass = enclosingClass; |
| enclosingClass = symbols->strdup(id); |
| } |
| (base_clause)? |
| LCURLY |
| {beginClassDefinition(ts, id);} // This stores class name in dictionary |
| (member_declaration)* |
| {endClassDefinition();} |
| RCURLY |
| {enclosingClass = saveClass;} |
| ) |
| | |
| LCURLY |
| {saveClass = enclosingClass; enclosingClass = (char *) "__anonymous";} |
| {beginClassDefinition(ts, "anonymous");} // This stores "anonymous" name in dictionary |
| (member_declaration)* |
| {endClassDefinition();} |
| RCURLY |
| {enclosingClass = saveClass;} |
| ) |
| ; |
| |
| //base_clause |
| base_clause |
| : |
| COLON base_specifier (COMMA base_specifier)* |
| ; |
| |
| //base_specifier |
| base_specifier |
| {char *qt;} |
| : |
| ( "virtual" (access_specifier)? qt = qualified_type |
| | access_specifier ("virtual")? qt = qualified_type |
| | qt = qualified_type |
| ) |
| ; |
| |
| //access_specifier |
| access_specifier |
| : |
| ( "public" |
| | "protected" |
| | "private" |
| ) |
| ; |
| |
| //enum_specifier |
| enum_specifier |
| {char *id;} |
| : |
| "enum" |
| ( |
| LCURLY enumerator_list RCURLY |
| | |
| id = qualified_id |
| {beginEnumDefinition(id);} // This stores id name as an enum type in dictionary |
| (LCURLY enumerator_list RCURLY)? |
| {endEnumDefinition();} |
| ) |
| ; |
| |
| //enumerator_list |
| enumerator_list |
| : |
| enumerator (COMMA enumerator)* |
| ; |
| |
| //enumerator |
| enumerator |
| : |
| id:ID (ASSIGNEQUAL constant_expression)? |
| {enumElement((id->getText()).data());} |
| ; |
| |
| /* 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 |
| qualified_id returns [char *q = NULL] |
| { |
| char *so = NULL; |
| static char qitem[CPPParser_MaxQualifiedItemSize+1]; |
| } |
| : |
| so = scope_override |
| {strcpy(qitem, so);} |
| ( |
| id:ID |
| (options{warnWhenFollowAmbig = false;}: |
| LESSTHAN template_argument_list GREATERTHAN)? |
| {strcat(qitem,(id->getText()).data());} |
| | |
| OPERATOR optor |
| {strcat(qitem,"operator"); strcat(qitem,"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 |
| typeID |
| : |
| {isTypeName((LT(1)->getText()).data())}? |
| ID |
| ; |
| |
| //init_declarator_list |
| init_declarator_list |
| : |
| init_declarator (COMMA init_declarator)* |
| ; |
| |
| //init_declarator |
| init_declarator |
| : |
| declarator |
| ( |
| ASSIGNEQUAL |
| initializer |
| | |
| LPAREN expression_list RPAREN |
| )? |
| ; |
| |
| //initializer |
| initializer |
| : |
| remainder_expression // assignment_expression |
| | |
| LCURLY initializer (COMMA (initializer)? )* RCURLY // Allows comma at end of list |
| ; |
| |
| //member_declarator_list |
| member_declarator_list |
| : |
| member_declarator (ASSIGNEQUAL OCTALINT)? // The value must be 0 (pure virt.) |
| (COMMA member_declarator (ASSIGNEQUAL OCTALINT)? )* |
| ; |
| |
| //member_declarator |
| member_declarator |
| : |
| ((ID)? COLON constant_expression)=>(ID)? COLON constant_expression |
| | |
| declarator |
| ; |
| |
| //declarator |
| declarator |
| : |
| (ptr_operator)=> ptr_operator // AMPERSAND or STAR etc. |
| declarator |
| | |
| direct_declarator |
| ; |
| |
| //direct_declarator |
| direct_declarator |
| {char *id; |
| CPPParser::TypeQualifier tq;} |
| : |
| (qualified_id LPAREN (RPAREN|declaration_specifiers) )=> // Must be function declaration |
| id = qualified_id |
| {if (_td==true) // This statement is a typedef |
| declaratorID(id,qiType); |
| else |
| declaratorID(id,qiFun); |
| } |
| LPAREN {declaratorParameterList(0);} |
| (parameter_list)? |
| RPAREN {declaratorEndParameterList(0);} |
| (tq = type_qualifier)* |
| (exception_specification)? |
| | |
| (qualified_id LPAREN qualified_id)=> // Must be class instantiation |
| id = qualified_id |
| {declaratorID(id,qiVar);} |
| LPAREN |
| expression_list |
| RPAREN |
| | |
| (qualified_id LSQUARE)=> // Must be array declaration |
| id = qualified_id |
| {if (_td==true) // This statement is a typedef |
| declaratorID(id,qiType); // This statement is a typedef |
| else |
| declaratorID(id,qiVar); |
| is_address = false; is_pointer = false; |
| } |
| (options {warnWhenFollowAmbig = false;}: |
| LSQUARE (constant_expression)? RSQUARE)+ |
| {declaratorArray();} |
| | |
| id = qualified_id |
| {if (_td==true) |
| declaratorID(id,qiType); // This statement is a typedef |
| else |
| declaratorID(id,qiVar); |
| is_address = false; is_pointer = false; |
| } |
| | |
| // 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()).data(),qiDtor);} // Note "class" not recorded in CPPSymbol |
| {fprintf(stderr,"%d warning direct_declarator5 entered unexpectedly with %s\n", |
| LT(1)->getLine(),(dtor->getText()).data());} |
| LPAREN {declaratorParameterList(0);} |
| (parameter_list)? |
| RPAREN {declaratorEndParameterList(0);} |
| | |
| LPAREN declarator RPAREN |
| (options {warnWhenFollowAmbig = false;}: |
| declarator_suffix)? // DW 1/9/04 declarator_suffix made optional as failed on line 2956 in metrics.i |
| ; // According to the grammar a declarator_suffix is not required here |
| |
| //declarator_suffix |
| declarator_suffix // Note: Only used above in direct_declarator |
| {CPPParser::TypeQualifier tq;} |
| : |
| ( |
| //(options {warnWhenFollowAmbig = false;}: |
| (LSQUARE (constant_expression)? RSQUARE)+ |
| {declaratorArray();} |
| | |
| {(!((LA(1)==LPAREN)&&(LA(2)==ID))||(qualifiedItemIsOneOf(qiType|qiCtor,1)))}? |
| LPAREN {declaratorParameterList(0);} |
| (parameter_list)? |
| RPAREN {declaratorEndParameterList(0);} |
| (tq = type_qualifier)* |
| (exception_specification)? |
| ) |
| ; |
| |
| //conversion_function_decl_or_def |
| conversion_function_decl_or_def |
| {CPPParser::TypeQualifier tq;} |
| : |
| OPERATOR declaration_specifiers (STAR | AMPERSAND)? // DW 01/08/03 Use type_specifier here? see syntax |
| (LESSTHAN template_parameter_list GREATERTHAN)? |
| LPAREN (parameter_list)? RPAREN |
| (tq = type_qualifier)* // DW 29/07/05 ? changed to * |
| (exception_specification)? |
| ( compound_statement |
| | SEMICOLON {end_of_stmt();} |
| ) |
| ; |
| |
| //function_declarator |
| function_declarator [int definition] |
| : |
| (ptr_operator)=> ptr_operator function_declarator[definition] |
| | |
| function_direct_declarator[definition] |
| ; |
| |
| //function_direct_declarator |
| function_direct_declarator [int definition] |
| {char *q; |
| CPPParser::TypeQualifier tq;} |
| : |
| /* 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,qiFun); |
| } |
| RPAREN |
| | |
| q = qualified_id |
| { |
| declaratorID(q,qiFun); |
| } |
| ) |
| |
| { |
| #ifdef MYCODE |
| if (definition) |
| myCode_function_direct_declarator(q); |
| #endif //MYCODE |
| } |
| |
| LPAREN |
| { |
| functionParameterList(); |
| if (K_and_R == false) |
| in_parameter_list = true; |
| } |
| (parameter_list)? |
| { |
| if (K_and_R == false) |
| in_parameter_list = false; |
| else |
| in_parameter_list = true; |
| } |
| RPAREN |
| (options{warnWhenFollowAmbig = false;}: |
| tq = type_qualifier)* |
| (ASSIGNEQUAL OCTALINT)? // The value of the octal must be 0 |
| {functionEndParameterList(definition);} |
| (exception_specification)? |
| ; |
| |
| |
| //ctor_definition |
| ctor_definition |
| : |
| ctor_head |
| ctor_body |
| {endConstructorDefinition();} |
| ; |
| |
| //ctor_head |
| ctor_head |
| : |
| ctor_decl_spec |
| ctor_declarator[1] |
| ; |
| |
| //ctor_decl_spec |
| ctor_decl_spec |
| : |
| (("inline"|"_inline"|"__inline")|"explicit")* |
| ; |
| |
| //ctor_declarator |
| ctor_declarator[int definition] |
| {char *q;} |
| : |
| q = qualified_ctor_id |
| {declaratorParameterList(definition);} |
| LPAREN (parameter_list)? RPAREN |
| {declaratorEndParameterList(definition);} |
| (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 [char *q = NULL] |
| { |
| char *so; |
| static char qitem[CPPParser_MaxQualifiedItemSize+1]; |
| } |
| : |
| so = scope_override |
| {strcpy(qitem, so);} |
| id:ID // DW 24/05/04 Note. Neither Ctor or Dtor recorded in dictionary |
| {strcat(qitem,(id->getText()).data()); |
| q = qitem;} |
| ; |
| |
| //ctor_body |
| ctor_body |
| : |
| (ctor_initializer)? |
| compound_statement |
| ; |
| |
| //ctor_initializer |
| ctor_initializer |
| : |
| COLON superclass_init (COMMA superclass_init)* |
| ; |
| |
| //superclass_init |
| superclass_init |
| {char *q;} |
| : |
| q = qualified_id LPAREN (expression_list)? RPAREN |
| ; |
| |
| //dtor_head |
| dtor_head[int definition] |
| : |
| dtor_decl_spec |
| dtor_declarator[definition] |
| ; |
| |
| //dtor_decl_spec |
| dtor_decl_spec |
| : |
| (("inline"|"_inline"|"__inline")|"virtual")* |
| ; |
| |
| //dtor_declarator |
| dtor_declarator[int definition] |
| {char *s;} |
| : |
| s = scope_override |
| TILDE ID |
| {declaratorParameterList(definition);} |
| LPAREN ("void")? RPAREN |
| {declaratorEndParameterList(definition);} |
| (exception_specification)? |
| ; |
| |
| //dtor_body |
| dtor_body |
| : |
| compound_statement |
| {endDestructorDefinition();} |
| ; |
| |
| //parameter_list |
| parameter_list |
| : |
| parameter_declaration_list (ELLIPSIS)? |
| ; |
| |
| //parameter_declaration_list |
| parameter_declaration_list |
| : |
| (parameter_declaration (COMMA parameter_declaration)* ) |
| ; |
| |
| //parameter_declaration |
| parameter_declaration |
| : |
| {beginParameterDeclaration();} |
| ( |
| {!((LA(1)==SCOPE) && (LA(2)==STAR||LA(2)==OPERATOR)) && |
| (!(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(qiType|qiCtor) )}? |
| |
| 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 |
| )? |
| ; |
| |
| //type_id |
| 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 |
| abstract_declarator |
| : |
| ptr_operator abstract_declarator |
| | |
| (LPAREN (ptr_operator)+ RPAREN)=> LPAREN (ptr_operator)+ RPAREN |
| (options {warnWhenFollowAmbig = false;}: |
| abstract_declarator_suffix)? |
| | |
| // DW 13/06/05 |
| (options {warnWhenFollowAmbig = false;}: |
| abstract_declarator_suffix)? |
| ; |
| |
| //abstract_declarator_suffix |
| abstract_declarator_suffix |
| : |
| (LSQUARE (constant_expression)? RSQUARE)+ |
| {declaratorArray();} |
| | |
| LPAREN |
| {declaratorParameterList(0);} |
| (parameter_list)? |
| RPAREN |
| {declaratorEndParameterList(0);} |
| cv_qualifier_seq |
| (exception_specification)? |
| ; |
| |
| //exception_specification |
| exception_specification |
| {char *so;} |
| : |
| "throw" |
| LPAREN |
| ( (so = scope_override ID (COMMA so = scope_override ID)* )? |
| | ELLIPSIS |
| ) |
| RPAREN |
| ; |
| |
| //template_head |
| template_head |
| : |
| "template" |
| LESSTHAN template_parameter_list GREATERTHAN |
| ; |
| |
| //template_parameter_list |
| template_parameter_list |
| : |
| {beginTemplateParameterList();} |
| template_parameter (COMMA template_parameter)* |
| {endTemplateParameterList();} |
| ; |
| |
| /* 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 |
| template_parameter |
| : |
| (options{generateAmbigWarnings = false;}: |
| type_parameter |
| | |
| parameter_declaration |
| ) |
| ; |
| |
| //type_parameter |
| type_parameter |
| : |
| ( |
| ("class"|"typename") |
| (id:ID |
| { |
| templateTypeParameter((id->getText()).data()); |
| } |
| (ASSIGNEQUAL assigned_type_name)? |
| )? |
| | |
| template_head "class" |
| (id2:ID |
| { |
| templateTypeParameter((id2->getText()).data()); |
| } |
| (ASSIGNEQUAL assigned_type_name)? |
| )? |
| ) |
| ; |
| |
| /* 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 |
| assigned_type_name |
| {char* qt; TypeSpecifier ts;} |
| : |
| (options{generateAmbigWarnings = false;}: |
| qt = qualified_type abstract_declarator |
| | |
| ts = simple_type_specifier abstract_declarator |
| ) |
| ; |
| |
| // This rule refers to an instance of a template class or function |
| //template_id |
| template_id // aka template_class_name |
| : |
| ID LESSTHAN template_argument_list GREATERTHAN |
| ; |
| |
| //template_argument_list |
| 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 |
| template_argument |
| : |
| // DW 07/04/05 This predicate only used here if next is SCOPE or ID |
| {( !(LA(1)==SCOPE||LA(1)==ID) || qualifiedItemIsOneOf(qiType|qiCtor) )}? |
| type_id |
| | |
| shift_expression // failed in iosfwd |
| ; |
| |
| /////////////////////////////////////////////////////////////////////// |
| /////////////////////////////////////////////////////////////////////// |
| ////////////////////////////// STATEMENTS //////////////////////////// |
| /////////////////////////////////////////////////////////////////////// |
| /////////////////////////////////////////////////////////////////////// |
| |
| statement_list |
| : |
| (statement)+ |
| ; |
| |
| statement |
| { |
| FunctionSpecifier fs = fsInvalid; // inline,virtual,explicit |
| } |
| : |
| ( ("namespace"|"using")=> |
| block_declaration |
| | (("typedef")? class_specifier (qualified_id)? LCURLY)=> |
| member_declaration |
| | (declaration_specifiers LPAREN ptr_operator qualified_id RPAREN)=> |
| member_declaration |
| | (declaration_specifiers (ptr_operator ptr_operator) qualified_id)=> |
| member_declaration |
| | (declaration_specifiers ((ptr_operator)=>ptr_operator)? qualified_id)=> |
| member_declaration |
| | labeled_statement |
| | case_statement |
| | default_statement |
| | expression SEMICOLON! {end_of_stmt();} |
| | compound_statement |
| | selection_statement |
| | iteration_statement |
| | jump_statement |
| | SEMICOLON! {end_of_stmt();} |
| | try_block |
| | throw_statement |
| // The next two entries may be used for debugging |
| // Use this statement in the source code to turn antlr trace on (See note above) |
| | "antlrTrace_on" {antlrTrace(true);} |
| // Use this statement in the source code to turn antlr trace off (See note above) |
| | "antlrTrace_off" {antlrTrace(false);} |
| ) |
| ; |
| |
| //block_declaration |
| block_declaration |
| : simple_declaration |
| | asm_definition |
| | namespace_alias_definition |
| | using_statement |
| ; |
| |
| //simple_definition |
| simple_declaration |
| : |
| declaration_specifiers (init_declarator_list)? SEMICOLON {end_of_stmt();} |
| ; |
| |
| labeled_statement |
| : |
| ID COLON statement |
| ; |
| |
| case_statement |
| : "case" |
| constant_expression COLON statement |
| ; |
| |
| default_statement |
| : |
| "default" COLON statement |
| ; |
| |
| compound_statement |
| : |
| LCURLY |
| {end_of_stmt(); |
| enterNewLocalScope(); |
| } |
| (statement_list)? |
| RCURLY |
| {exitLocalScope();} |
| ; |
| |
| /* NOTE: cannot remove ELSE ambiguity, but it parses correctly. |
| * The warning is removed with the options statement |
| */ |
| selection_statement |
| : |
| "if" LPAREN |
| expression RPAREN |
| statement |
| (options {warnWhenFollowAmbig = false;}: |
| "else" statement)? |
| | |
| "switch" LPAREN expression RPAREN statement |
| ; |
| |
| iteration_statement |
| : |
| "while" |
| LPAREN expression RPAREN |
| statement |
| | |
| "do" |
| statement "while" |
| LPAREN expression RPAREN |
| SEMICOLON {end_of_stmt();} |
| | |
| "for" LPAREN |
| ( (declaration)=> declaration |
| | expression SEMICOLON {end_of_stmt();} |
| | SEMICOLON {end_of_stmt();} |
| ) |
| (expression)? SEMICOLON {end_of_stmt();} |
| (expression)? |
| RPAREN statement |
| ; |
| |
| jump_statement |
| : |
| ( "goto" ID SEMICOLON {end_of_stmt();} |
| | "continue" SEMICOLON {end_of_stmt();} |
| | "break" SEMICOLON {end_of_stmt();} |
| | // DW 16/05/03 May be problem here if return is followed by a cast expression |
| "return" {in_return = true;} |
| ( options{warnWhenFollowAmbig = false;}: |
| (LPAREN {(qualifiedItemIsOneOf(qiType) )}? 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 {in_return = false,end_of_stmt();} |
| ) |
| ; |
| |
| try_block |
| : |
| "try" compound_statement (handler)* |
| ; |
| |
| handler |
| : |
| "catch" |
| {exceptionBeginHandler();} |
| {declaratorParameterList(1);} |
| LPAREN exception_declaration RPAREN |
| {declaratorEndParameterList(1);} |
| compound_statement |
| {exceptionEndHandler();} |
| ; |
| |
| 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 { end_of_stmt();} |
| ; |
| |
| using_statement |
| {char *qid;} |
| : |
| "using" |
| ("namespace" qid = qualified_id // Using-directive |
| |("typename")? qid = qualified_id // Using-declaration |
| ) |
| SEMICOLON {end_of_stmt();} |
| ; |
| |
| asm_definition |
| : |
| ("asm"|"_asm"|"__asm"|"__asm__") LPAREN StringLiteral RPAREN SEMICOLON {end_of_stmt();} |
| ; |
| |
| /////////////////////////////////////////////////////////////////////// |
| /////////////////////////////////////////////////////////////////////// |
| ////////////////////////////// EXPRESSIONS /////////////////////////// |
| /////////////////////////////////////////////////////////////////////// |
| /////////////////////////////////////////////////////////////////////// |
| |
| expression |
| : |
| assignment_expression (COMMA assignment_expression)* |
| ; |
| |
| // right-to-left for assignment op |
| assignment_expression |
| : |
| conditional_expression |
| ( |
| (ASSIGNEQUAL|TIMESEQUAL|DIVIDEEQUAL|MINUSEQUAL|PLUSEQUAL |
| |MODEQUAL|SHIFTLEFTEQUAL|SHIFTRIGHTEQUAL|BITWISEANDEQUAL |
| |BITWISEXOREQUAL|BITWISEOREQUAL |
| ) |
| remainder_expression |
| )? |
| ; |
| |
| remainder_expression |
| : |
| ( |
| (conditional_expression (COMMA|SEMICOLON|RPAREN) )=> |
| {assign_stmt_RHS_found += 1;} |
| assignment_expression |
| { |
| if (assign_stmt_RHS_found > 0) |
| assign_stmt_RHS_found -= 1; |
| else |
| { |
| fprintf(stderr,"%d warning Error in assign_stmt_RHS_found = %d\n", |
| LT(1)->getLine(),assign_stmt_RHS_found); |
| fprintf(stderr,"Press return to continue\n"); |
| getchar(); |
| } |
| } |
| | |
| assignment_expression |
| ) |
| ; |
| |
| conditional_expression |
| : |
| logical_or_expression |
| (QUESTIONMARK expression COLON conditional_expression)? |
| ; |
| |
| 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 qiType if the item is a type. The offset of |
| * '1' makes it ignore the initial LPAREN; normally, the offset is 0. |
| */ |
| |
| cast_expression |
| {TypeQualifier tq; |
| TypeSpecifier ts;} |
| : |
| (LPAREN (type_qualifier)* simple_type_specifier (ptr_operator)* RPAREN unary_expression)=> |
| LPAREN (tq = type_qualifier)* ts = simple_type_specifier (ptr_operator)* RPAREN unary_expression |
| | |
| (LPAREN (type_qualifier)* simple_type_specifier (ptr_operator)* RPAREN)=> |
| // Believe it or not, you can get more than one cast expression in sequence |
| LPAREN (tq = type_qualifier)* ts = simple_type_specifier (ptr_operator)* RPAREN cast_expression |
| | |
| unary_expression // handles outer (...) of "(T(expr))" |
| ; |
| |
| unary_expression |
| : |
| ( |
| (postfix_expression)=> |
| postfix_expression |
| | |
| PLUSPLUS unary_expression |
| | |
| MINUSMINUS unary_expression |
| | |
| unary_operator cast_expression |
| | |
| ( "sizeof" |
| | "__alignof__" //Zhaojz 02/02/05 to fix bug 29 (GNU) |
| ) |
| ( (unary_expression)=> |
| unary_expression |
| | |
| LPAREN type_id RPAREN |
| ) |
| | |
| (SCOPE)? |
| (new_expression |
| |delete_expression |
| ) |
| ) |
| ; |
| |
| postfix_expression |
| { |
| TypeSpecifier ts; |
| } |
| : |
| ( |
| options {warnWhenFollowAmbig = false;}: |
| // Function-style cast must have a leading type |
| {!(LA(1)==LPAREN)}? |
| (ts = simple_type_specifier LPAREN RPAREN LPAREN)=> // DW 01/08/03 To cope with problem in xtree (see test10.i) |
| ts = simple_type_specifier LPAREN RPAREN LPAREN (expression_list)? RPAREN |
| | |
| {!(LA(1)==LPAREN)}? |
| (ts = simple_type_specifier LPAREN)=> |
| ts = simple_type_specifier LPAREN (expression_list)? RPAREN |
| | |
| primary_expression |
| (options {warnWhenFollowAmbig = false;}: |
| LSQUARE expression RSQUARE |
| | |
| LPAREN (expression_list)? RPAREN |
| | (DOT|POINTERTO) ("template")? id_expression |
| | PLUSPLUS |
| | MINUSMINUS |
| )* |
| | |
| ("dynamic_cast"|"static_cast"|"reinterpret_cast"|"const_cast") |
| LESSTHAN ("const"|"__const")? ts = type_specifier (ptr_operator)? GREATERTHAN |
| LPAREN expression RPAREN |
| | |
| "typeid" |
| LPAREN ((type_id)=>type_id|expression) RPAREN |
| ) |
| ; |
| |
| primary_expression |
| : id_expression |
| | constant |
| | "this" |
| | LPAREN expression RPAREN |
| ; |
| |
| id_expression |
| {char *s;} |
| : |
| s = scope_override |
| ( ID |
| | OPERATOR optor |
| | TILDE (STAR)? ID // DW 29/07/03 STAR included to allow for *_S = ~*_S; seen in vector |
| ) |
| ; |
| |
| constant |
| : OCTALINT |
| | DECIMALINT |
| | HEXADECIMALINT |
| | CharLiteral |
| | WCharLiteral |
| | (StringLiteral | WStringLiteral)+ |
| | FLOATONE |
| | FLOATTWO |
| | "true" |
| | "false" |
| ; |
| |
| 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_id RPAREN) |
| (options{warnWhenFollowAmbig = false;}: |
| (new_initializer)=> new_initializer)? |
| ) |
| ; |
| |
| new_initializer |
| : |
| LPAREN (expression_list)? RPAREN |
| ; |
| |
| new_type_id |
| : |
| declaration_specifiers |
| (options {warnWhenFollowAmbig = false;}: |
| new_declarator |
| )? |
| ; |
| |
| new_declarator |
| : |
| ptr_operator |
| (options {warnWhenFollowAmbig = false;}: |
| new_declarator)? |
| | |
| direct_new_declarator |
| ; |
| |
| /* 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 |
| )+ |
| ; |
| |
| //ptr_operator |
| ptr_operator |
| : |
| ( AMPERSAND {is_address = true;} |
| | ("_cdecl"|"__cdecl") |
| | ("_near"|"__near") |
| | ("_far"|"__far") |
| | "__interrupt" |
| | ("pascal"|"_pascal"|"__pascal") |
| | ("_stdcall"|"__stdcall") |
| | ptr_to_member // e.g. STAR |
| ) |
| ; |
| |
| // Match A::B::* |
| //ptr_to_member |
| ptr_to_member // Part of ptr_operator in grammar.txt |
| {char *s;} |
| : |
| s = scope_override STAR {is_pointer = true;} cv_qualifier_seq |
| ; |
| |
| // JEL note: does not use (const|volatile)* to avoid lookahead problems |
| cv_qualifier_seq |
| {CPPParser::TypeQualifier tq;} |
| : |
| (tq = type_qualifier)* |
| ; |
| |
| //scope_override |
| // Match the A::B::C:: or nothing |
| scope_override returns [char *s = NULL] |
| { |
| static char sitem[CPPParser_MaxQualifiedItemSize+1]; |
| sitem[0]='\0'; |
| } |
| : |
| (SCOPE {strcat(sitem,"::");} )? |
| ( options {warnWhenFollowAmbig = false;}: |
| {scopedItem()}? |
| id:ID (LESSTHAN template_argument_list GREATERTHAN)? |
| SCOPE |
| ("template")? // DW 04/06/05 See _Alloc::template in testMbanefo.i |
| { |
| CPPSymbol *cs = (CPPSymbol *) symbols->lookup((id->getText()).data()); |
| strcat(sitem,(id->getText()).data()); |
| strcat(sitem,"::"); |
| } |
| )* |
| {s = sitem;} |
| ; |
| |
| delete_expression |
| : |
| "delete" (LSQUARE RSQUARE)? cast_expression |
| ; |
| |
| expression_list |
| : |
| assignment_expression (COMMA assignment_expression)* |
| ; |
| |
| 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 |
| ) |
| ; |
| |
| class CPPLexer extends Lexer; |
| |
| options |
| { |
| k = 3; |
| exportVocab = STDC; |
| testLiterals = true; |
| } |
| |
| // DW 4/11/02 put in to support manual hoisting |
| tokens |
| { |
| OPERATOR = "operator"; |
| } |
| |
| { |
| void deferredNewline() |
| { |
| deferredLineCount++; // Declared and initialised in main.cpp |
| } |
| |
| void newline() |
| { |
| for (;deferredLineCount>0;deferredLineCount--) |
| { |
| CharScanner::newline(); |
| } |
| CharScanner::newline(); |
| } |
| } |
| |
| // 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 : "::" ; |
| |
| Whitespace |
| : |
| ( // whitespace ignored |
| (' ' |'\t' | '\f') |
| | // handle newlines |
| ( '\r' '\n' // MS |
| | '\r' // Mac |
| | '\n' // Unix |
| ) { newline(); } |
| | // handle continuation lines |
| ( '\\' '\r' '\n' // MS |
| | '\\' '\r' // Mac |
| | '\\' '\n' // Unix |
| ) {printf("CPP_parser.g continuation line detected\n"); |
| deferredNewline();} |
| ) |
| {_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP;} |
| ; |
| |
| Comment |
| : |
| "/*" |
| ( {LA(2) != '/'}? '*' |
| | EndOfLine {deferredNewline();} |
| | ~('*'| '\r' | '\n') |
| )* |
| "*/" {_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP;} |
| ; |
| |
| CPPComment |
| : |
| "//" (~('\n' | '\r'))* EndOfLine |
| {_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP; newline();} |
| ; |
| |
| PREPROC_DIRECTIVE |
| options{paraphrase = "a preprocessor directive";} |
| : |
| ('#' (~('\r' | '\n'))* EndOfLine) |
| {_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP; newline();} |
| ; |
| |
| protected |
| LineDirective |
| : |
| ("line")? // this would be for if the directive started "#line" |
| (Space)+ |
| n:Decimal |
| (Space)+ |
| (sl:StringLiteral) |
| ((Space)+ Decimal)* // To support cpp flags (GNU) |
| { |
| process_line_directive((sl->getText()).data(), (n->getText()).data()); // see main() |
| } |
| EndOfLine |
| ; |
| |
| protected |
| Space |
| : |
| (' '|'\t'|'\f') |
| ; |
| |
| |
| protected |
| Pragma |
| : |
| ('#' "pragma" (~('\r' | '\n'))* EndOfLine) |
| {_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP; newline();} |
| ; |
| |
| protected |
| Error |
| : |
| ('#' "error" (~('\r' | '\n'))* EndOfLine) |
| {_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP; newline();} |
| ; |
| |
| |
| // 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 | ~('\'')) '\'' |
| ; |
| |
| WCharLiteral |
| : |
| 'L' CharLiteral |
| ; |
| |
| |
| /* |
| * 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 |
| ) {deferredNewline();} |
| | |
| ~('"'|'\r'|'\n'|'\\') |
| )* |
| '"' |
| ; |
| |
| WStringLiteral |
| : |
| 'L' StringLiteral |
| ; |
| |
| 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)? {_ttype = FLOATONE;} //Zuo 3/12/01 |
| | Exponent {_ttype = FLOATTWO;} //Zuo 3/12/01 |
| ) //{_ttype = DoubleDoubleConst;} |
| (FloatSuffix //{_ttype = FloatDoubleConst;} |
| |LongSuffix //{_ttype = LongDoubleConst;} |
| )? |
| | |
| ("...")=> "..." {_ttype = ELLIPSIS;} |
| | |
| '.' {_ttype = DOT;} |
| ( (Digit)+ (Exponent)? {_ttype = FLOATONE;} //Zuo 3/12/01 |
| //{_ttype = DoubleDoubleConst;} |
| (FloatSuffix //{_ttype = FloatDoubleConst;} |
| |LongSuffix //{_ttype = LongDoubleConst;} |
| )? |
| )? |
| | |
| '0' ('0'..'7')* //{_ttype = IntOctalConst;} |
| (LongSuffix //{_ttype = LongOctalConst;} |
| |UnsignedSuffix //{_ttype = UnsignedOctalConst;} |
| )* {_ttype = OCTALINT;} |
| | |
| '1'..'9' (Digit)* //{_ttype = IntIntConst;} |
| (LongSuffix //{_ttype = LongIntConst;} |
| |UnsignedSuffix //{_ttype = UnsignedIntConst;} |
| )* {_ttype = DECIMALINT;} |
| | |
| '0' ('x' | 'X') ('a'..'f' | 'A'..'F' | Digit)+ |
| //{_ttype = IntHexConst;} |
| (LongSuffix //{_ttype = LongHexConst;} |
| |UnsignedSuffix //{_ttype = UnsignedHexConst;} |
| )* {_ttype = HEXADECIMALINT;} |
| ; |
| |
| ID |
| options {testLiterals = true;} |
| : |
| ('a'..'z'|'A'..'Z'|'_') |
| ('a'..'z'|'A'..'Z'|'_'|'0'..'9')* |
| ; |
| |