blob: a3ee7e8bbaed71d3a471b29dc3604cbdfa4c0a3f [file] [log] [blame]
/*
* 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')*
;