Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
2888 lines (2652 sloc) 77.4 KB
/*
* 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
*
*/
/* 2007
* Version 3.2 November 2007
* 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 "pre_include_hpp"
{// pre_include_hpp
}
header "post_include_hpp"
{// post_include_hpp
}
header "pre_include_cpp"
{// pre_include_cpp
}
header "post_include_cpp"
{// post_include_cpp
}
header
{
// File generated from CPP_parser.g
// Version 3.2 November 2007
// 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 "antlr/CharScanner.hpp"
#include "CPPDictionary.hpp"
// Following externs declared here to be available for users
// Declared and set in CPPParser.cpp
extern int lineNo; // current line
extern bool in_user_file; // true = in principal file, false = in an include file
// Declared and set in CPPLexer.cpp
extern bool in_user_file_deferred;
extern int deferredLineCount; // used to accumulate line numbers in comments etc.
extern char principal_file[128]; // Name of user file
extern int principal_line; // Principal file's line number
extern int principal_last_set; // Where principal file's line number was last set
// in preprocessed *.i file
extern char current_included_file[128]; // Name of current include file
extern int include_line; // Included file's line number
extern int include_last_set; // Where included file's line number was last set
// in preprocessed *.i file
// The statements in this block appear in both CPPLexer.hpp and CPPParser.hpp
}
options
{
language = "Cpp";
}
{
// File generated from CPP_parser.g
// Version 3.2 November 2007
// This file is best viewed in courier font with tabs set to 4 spaces
//
// The statements in this block appear only in CPPParser.cpp
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
// (Copies of these modified files are supplied with this code)
// 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 just 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 each time before recompiling.
// 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 antlrTrace_on and antlrTrace_off 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 = "";
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::init()
int lineNo = 0;
bool in_user_file; // true = in principal file, false = in an include file
// Set from in_user_file_deferred by external_declaration in CPP_parser.g
// The statements in this block appear only in CPPParser.cpp
}
class CPPParser extends Parser;
options
{
k = 2;
exportVocab = STDC;
buildAST =false;
codeGenMakeSwitchThreshold = 2;
codeGenBitsetTestThreshold = 3;
}
{ // These declarations go into CPPParser.hpp
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; damn!
typedef unsigned long TypeSpecifier; // note: must be at least 16 bits
#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
enum TypeQualifier
{
tqInvalid=0, tqCONST=1, tqVOLATILE
};
enum StorageClass
{
scInvalid=0, scAUTO=1, scREGISTER,
scSTATIC, scEXTERN, scMUTABLE
};
enum FunctionSpecifier
{
fsInvalid=0,
fsVIRTUAL, fsINLINE, fsEXPLICIT, fsFRIEND
};
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
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(const 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();
// Aggregate stuff
virtual void classForwardDeclaration(const char *, TypeSpecifier, FunctionSpecifier);
virtual void beginClassDefinition(const char *, TypeSpecifier);
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(const 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(const int def);
virtual void declaratorEndParameterList(const 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 *);
}
translation_unit
: {enterExternalScope();}
(external_declaration)* EOF
{exitExternalScope();}
;
//external_declaration Note: These comment lines are provided to assist searching for productions
external_declaration
{
char *s;
lineNo = LT(1)->getLine();
K_and_R = false;
FunctionSpecifier fs = fsInvalid; // inline,virtual,explicit
in_user_file = in_user_file_deferred;
}
:
(
// 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" "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
|
(declaration_specifiers (init_declarator_list)? SEMICOLON)=>
{if(statementTrace>=1)
printf("%d external_declaration Typedef variable type\n",LT(1)->getLine());
}
declaration
|
("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();}
)
|
// 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
|
// Function definition with int return assumed
(function_declarator[1] LCURLY)=>
{if (statementTrace>=1)
printf("%d external_declaration Function definition without return type\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
(("extern")? (fs = function_specifier)* class_specifier)=>
{if (statementTrace>=1)
printf("%d external_declaration Class decl or def\n",LT(1)->getLine());
}
("extern")? (fs = function_specifier)* class_decl_or_def[fs] (init_declarator_list)? SEMICOLON {end_of_stmt();}
|
// Copied from member_declaration 31/05/07
(declaration_specifiers (init_declarator_list)? SEMICOLON)=>
{if (statementTrace>=1)
printf("%d external_declaration Declaration\n",LT(1)->getLine());
}
declaration
|
// 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 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
|
// Semicolon
{if (statementTrace>=1)
printf("%d external_declaration Semicolon\n",LT(1)->getLine());
}
SEMICOLON {end_of_stmt();}
|
// Anything else
{if (statementTrace>=1)
printf("%d external_declaration Other Declaration\n",LT(1)->getLine());
}
declaration
|
// 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(),qiType);})?
LCURLY
{enterNewLocalScope();}
(external_declaration)*
{exitLocalScope();}
RCURLY
;
//namespace_alias_definition
namespace_alias_definition
{
char *qid;
}
:
"namespace"
ns2:ID {declaratorID((ns2->getText()).data(),qiType);}
ASSIGNEQUAL qid = qualified_id SEMICOLON {end_of_stmt();}
;
//member_declaration
member_declaration
{
char *q;
lineNo = LT(1)->getLine();
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" "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
|
(declaration_specifiers (init_declarator_list)? SEMICOLON)=>
{if(statementTrace>=1)
printf("%d member_declaration Typedef variable type\n",LT(1)->getLine());
}
declaration
|
("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();}
)
|
// 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 (init_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)=>
{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();}
|
// 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();}
|
(declaration_specifiers (init_declarator_list)? SEMICOLON)=>
{if (statementTrace>=1)
printf("%d member_declaration Declaration\n",LT(1)->getLine());
}
declaration
|
// Member without a type (I guess it can only be a function declaration or definition)
((fs = function_specifier)* function_declarator[0] SEMICOLON)=>
{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)
((fs = function_specifier)* function_declarator[1] LCURLY)=>
{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());
}
(fs = function_specifier)* 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 declarator
( ctor_decl_spec
{qualifiedItemIsOneOf(qiCtor)}?
ctor_declarator[0] SEMICOLON
)=>
{if (statementTrace>=1)
printf("%d member_declaration Templated constructor declarator\n",LT(1)->getLine());
}
ctor_decl_spec ctor_declarator[0] SEMICOLON {end_of_stmt();}
|
// 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
:
( // 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;}:
({lineNo = LT(1)->getLine();} declaration)* // Possible for K & R definition
{in_parameter_list = false;}
)?
compound_statement
|
function_declarator[1]
( options{warnWhenFollowAmbig = false;}:
({lineNo = LT(1)->getLine();} declaration)* // Possible for K & R definition
{in_parameter_list = false;}
)?
compound_statement
)
{endFunctionDefinition();}
;
//declaration
declaration
:
("extern" StringLiteral)=>
linkage_specification
|
simple_declaration
|
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
| fs = function_specifier // inline,virtual,explicit
| ("_declspec"|"__declspec") LPAREN ID RPAREN
)*
ts = type_specifier
(tq = type_qualifier)* // const,volatile // aka cv_qualifier See type_qualifier
)
{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]
{//char *s;
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"|"enum"|ts = class_specifier)
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") {ts |= tsINT;}
| ("_int16"|"__int16") {ts |= tsINT;}
| ("_int32"|"__int32") {ts |= tsLONG;}
| ("_int64"|"__int64") {ts |= tsLONG;}
| ("_w64"|"__w64") {ts |= tsLONG;}
| "long" {ts |= tsLONG;}
| "signed" {ts |= tsSIGNED;}
| "unsigned" {ts |= tsUNSIGNED;}
| "float" {ts |= tsFLOAT;}
| "double" {ts |= tsDOUBLE;}
| "void" {ts |= tsVOID;}
)+
)
;
//qualified_type
qualified_type returns [char *qit = NULL]
{
char *so = NULL;
char qitem01[CPPParser_MaxQualifiedItemSize+1];
qitem01[0] = '\0';
}
:
// 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)}?
so = scope_override
{
strcpy(qitem01, so);
}
id:ID
{
strcat(qitem01, (id->getText()).data());
qit = qitem01;
}
(options {warnWhenFollowAmbig = false;}:
LESSTHAN template_argument_list GREATERTHAN
)?
;
//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" {tq = tqCONST;}
|"volatile" {tq = tqVOLATILE;}
)
;
//class_decl_or_def
class_decl_or_def [FunctionSpecifier fs]
{char *saveClass;
char *id;
char qid[CPPParser_MaxQualifiedItemSize+1];
TypeSpecifier ts = tsInvalid; // Available for use
}
:
("class" {ts = tsCLASS;}
|"struct" {ts = tsSTRUCT;}
|"union" {ts = tsUNION;}
)
(("_declspec"|"__declspec") LPAREN expression RPAREN)* // Temp for Evgeniy
( id = qualified_id
{strcpy(qid,id);}
(options{generateAmbigWarnings = false;}:
(SEMICOLON|member_declarator)=>
// Empty
{classForwardDeclaration(qid, ts, fs);} // This stores class name in dictionary
|
(base_clause)?
LCURLY
{saveClass = enclosingClass; enclosingClass = symbols->strdup(qid);
beginClassDefinition(qid, ts);} // This stores class name in dictionary
(member_declaration)*
{endClassDefinition();}
RCURLY
{enclosingClass = saveClass;}
)
|
LCURLY
{saveClass = enclosingClass; enclosingClass = "__anonymous";
beginClassDefinition("anonymous", ts);} // 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)? )* // Allows comma at end of list
;
//enumerator
enumerator
:
id:ID (ASSIGNEQUAL constant_expression)?
{enumElement((id->getText()).data());} // This stores id name in dictionary
;
/* 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 *qid = NULL]
{
char *so = NULL;
char *op = NULL;
char qitem02[CPPParser_MaxQualifiedItemSize+1];
qitem02[0] = '\0';
}
:
so = scope_override
{
strcpy(qitem02, so);
}
( id:ID {strcat(qitem02,(id->getText()).data());}
((LESSTHAN template_argument_list GREATERTHAN)=>
LESSTHAN template_argument_list GREATERTHAN)? // {strcat(qitem02,"<...>");}
|
OPERATOR op=optor
{strcat(qitem02,"operator"); strcat(qitem02,op);}
|
TILDE id_expression // 1/08/07
)
{
qid = qitem02;
}
;
//typeID
typeID
:
{isTypeName((LT(1)->getText()).data())}?
ID
;
//init_declarator_list
init_declarator_list
:
member_declarator (COMMA member_declarator)*
;
//member_declarator
member_declarator
:
((ID)? COLON constant_expression)=>(ID)? COLON constant_expression
|
declarator
(
(ASSIGNEQUAL OCTALINT SEMICOLON)=> ASSIGNEQUAL OCTALINT // The value must be zero (for pure virtual)
|
ASSIGNEQUAL
initializer
|
LPAREN expression_list RPAREN
)?
;
//initializer
initializer
:
remainder_expression // assignment_expression
|
LCURLY initializer (COMMA (initializer)? )* RCURLY // Allows comma at end of list
;
//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();}
|
(qualified_id RPAREN LPAREN)=> // Must be function declaration (see function_direct_declarator)
id = qualified_id
{if (_td==true) // This statement is a typedef
declaratorID(id,qiType); // This statement is a typedef
else
declaratorID(id,qiFun);
is_address = false; is_pointer = false;
}
|
id = qualified_id
{
if (_td==true)
{
declaratorID(id,qiType); // This statement is a typedef
}
else
declaratorID(id,qiVar);
is_address = false; is_pointer = false;
}
|
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;
}
:
( // fix prompted by (isdigit)() in xlocnum
LPAREN
declarator
RPAREN
|
q = qualified_id
{
declaratorID(q,qiFun);
}
)
{
#ifdef MYCODE
if (definition)
myCode_function_direct_declarator(q);
#endif MYCODE
}
LPAREN
{
functionParameterList();
if (K_and_R == true)
in_parameter_list = false;
else
in_parameter_list = true;
}
(parameter_list)?
{
if (K_and_R == true)
in_parameter_list = true;
else
in_parameter_list = false;
}
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;
char qitem03[CPPParser_MaxQualifiedItemSize+1];
qitem03[0] = '\0';
}
:
so = scope_override
{strcpy(qitem03, so);}
id:ID // DW 24/05/04 Note. Neither Ctor or Dtor recorded in dictionary
{strcat(qitem03,(id->getText()).data());
q = qitem03;
//printf("CPP_parser.g qualified_ctor_id q %s\n",q);
}
;
//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 (See also template_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 abstract_declarator RPAREN (LSQUARE|LPAREN) )=> LPAREN abstract_declarator RPAREN
(options {warnWhenFollowAmbig = false;}:
abstract_declarator_suffix)
|
(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)=>
parameter_declaration
|
template_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
)
;
//template_parameter_declaration (See also parameter_declaration)
template_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
additive_expression // DW 04/09/07 because of ambiguity of ">"
)?
;
// 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_list
:
(statement)+
;
//statement
statement
{
lineNo = LT(1)->getLine();
FunctionSpecifier fs = fsInvalid; // inline,virtual,explicit
}
:
( ("namespace"|"using")=>
block_declaration
| (("typedef")? class_specifier (qualified_id)? LCURLY)=>
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
| namespace_alias_definition
| using_statement
;
//simple_declaration
simple_declaration
:
declaration_specifiers (init_declarator_list)? SEMICOLON {end_of_stmt();}
;
//labeled_statement
labeled_statement
:
ID COLON statement
;
//case_statement
case_statement
: "case"
constant_expression COLON statement
;
//default_statement
default_statement
:
"default" COLON statement
;
//compound_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
selection_statement
:
"if" LPAREN
{enterNewLocalScope();}
condition RPAREN
statement
(options {warnWhenFollowAmbig = false;}:
"else" statement)?
{exitLocalScope();}
|
"switch" LPAREN
{enterNewLocalScope();}
condition RPAREN statement
{exitLocalScope();}
;
//iteration_statement
iteration_statement
:
"while" LPAREN
{enterNewLocalScope();}
condition RPAREN
statement
{exitLocalScope();}
|
"do"
{enterNewLocalScope();}
statement "while"
LPAREN expression RPAREN
{exitLocalScope();}
SEMICOLON {end_of_stmt();}
|
"for" LPAREN
{enterNewLocalScope();}
( (declaration)=> declaration
| (expression)? SEMICOLON {end_of_stmt();}
)
(condition)? SEMICOLON {end_of_stmt();}
(expression)?
RPAREN statement
{exitLocalScope();}
;
//condition
condition
:
( (declaration_specifiers declarator ASSIGNEQUAL)=>
declaration_specifiers declarator ASSIGNEQUAL remainder_expression
| expression
)
;
//jump_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",lineNo);}
| expression
)? SEMICOLON {in_return = false,end_of_stmt();}
)
;
//try_block
try_block
:
"try" compound_statement (handler)*
;
//handler
handler
:
"catch"
{exceptionBeginHandler();}
{declaratorParameterList(1);}
LPAREN exception_declaration RPAREN
{declaratorEndParameterList(1);}
compound_statement
{exceptionEndHandler();}
;
//exception_declaration
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_statement
:
"throw" (assignment_expression) ? SEMICOLON { end_of_stmt();}
;
//using_statement
using_statement
{char *qid;}
:
"using"
("namespace" qid = qualified_id // Using-directive
|("typename")? qid = qualified_id // Using-declaration
)
SEMICOLON {end_of_stmt();}
;
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
////////////////////////////// EXPRESSIONS ///////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// Same as expression_list
//expression
expression
{
lineNo = LT(1)->getLine();
}
:
assignment_expression (COMMA assignment_expression)*
;
// right-to-left for assignment op
//assignment_expression
assignment_expression
:
conditional_expression
(
(ASSIGNEQUAL|TIMESEQUAL|DIVIDEEQUAL|MINUSEQUAL|PLUSEQUAL
|MODEQUAL|SHIFTLEFTEQUAL|SHIFTRIGHTEQUAL|BITWISEANDEQUAL
|BITWISEXOREQUAL|BITWISEOREQUAL
)
remainder_expression
)?
;
//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",
lineNo,assign_stmt_RHS_found);
fprintf(stderr,"Press return to continue\n");
getchar();
}
}
|
assignment_expression
)
;
//conditional_expression
conditional_expression
:
logical_or_expression
(QUESTIONMARK expression COLON conditional_expression)?
;
//constant_expression
constant_expression
:
conditional_expression
;
//logical_or_expression
logical_or_expression
:
logical_and_expression (OR logical_and_expression)*
;
//logical_and_expression
logical_and_expression
:
inclusive_or_expression (AND inclusive_or_expression)*
;
//inclusive_or_expression
inclusive_or_expression
:
exclusive_or_expression (BITWISEOR exclusive_or_expression)*
;
//exclusive_or_expression
exclusive_or_expression
:
and_expression (BITWISEXOR and_expression)*
;
//and_expression
and_expression
:
equality_expression (AMPERSAND equality_expression)*
;
//equality_expression
equality_expression
:
relational_expression ( (NOTEQUAL|EQUAL) relational_expression)*
;
//relational_expression
relational_expression
:
shift_expression
(options {warnWhenFollowAmbig = false;}:
( LESSTHAN
| GREATERTHAN
| LESSTHANOREQUALTO
| GREATERTHANOREQUALTO
)
shift_expression
)*
;
//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
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
cast_expression
:
(LPAREN type_id RPAREN unary_expression)=>
LPAREN type_id RPAREN unary_expression
|
// Believe it or not, you can get more than one cast expression in sequence
(LPAREN type_id RPAREN cast_expression)=>
LPAREN type_id RPAREN cast_expression
|
unary_expression // handles outer (...) of "(T(expr))"
;
//unary_expression
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
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
// Following put in to allow for the above being a constructor as shown in test_constructors_destructors.cpp
(DOT postfix_expression)?
|
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")? ts = type_specifier (ptr_operator)? GREATERTHAN
LPAREN expression RPAREN
|
"typeid"
LPAREN ((type_id)=>type_id|expression) RPAREN
( (DOT|POINTERTO) postfix_expression)?
)
;
//primary_expression
primary_expression
: id_expression
| literal
| "this"
| LPAREN expression RPAREN
;
//id_expression
id_expression
{
char *s;
}
:
( s = qualified_id
)
;
//literal
literal
: OCTALINT
| DECIMALINT
| HEXADECIMALINT
| CharLiteral
| WCharLiteral
| (StringLiteral|WStringLiteral)+
| FLOATONE
| FLOATTWO
| "true"
| "false"
;
//unary_operator
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_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
new_initializer
:
LPAREN (expression_list)? RPAREN
;
//new_type_id
new_type_id
:
declaration_specifiers
(options {warnWhenFollowAmbig = false;}:
new_declarator
)?
;
//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
direct_new_declarator
:
(options {warnWhenFollowAmbig = false;}:
LSQUARE expression RSQUARE
)+
;
//ptr_operator
ptr_operator
{char *s;}
:
( AMPERSAND {is_address = true;}
| ("_cdecl"|"__cdecl")
| ("_near"|"__near")
| ("_far"|"__far")
| "__interrupt"
| ("pascal"|"_pascal"|"__pascal")
| ("_stdcall"|"__stdcall")
| (s = scope_override STAR cv_qualifier_seq)=>
s = scope_override STAR {is_pointer = true;} cv_qualifier_seq
)
;
// Match A::B::* // May be redundant 14/06/06
//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
cv_qualifier_seq
{CPPParser::TypeQualifier tq;}
:
(tq = type_qualifier)*
;
// Match "(::)A::B::C::(template)" or just "::"
//scope_override
scope_override returns [char *so = NULL]
{
char sitem[CPPParser_MaxQualifiedItemSize+1];
// The above statement must be non static because its calling is nested
sitem[0] = '\0';
}
:
(SCOPE {strcat(sitem,"::");} )?
( options {warnWhenFollowAmbig = false;}:
(ID LESSTHAN template_argument_list GREATERTHAN SCOPE)=>
id1:ID {strcat(sitem,(id1->getText()).data());}
LESSTHAN template_argument_list GREATERTHAN // {strcat(sitem,"<...>");}
SCOPE{strcat(sitem,"::");}
("template" {strcat(sitem,"template");})?
|
id2:ID {strcat(sitem,(id2->getText()).data());}
SCOPE {strcat(sitem,"::");}
("template" {strcat(sitem,"template");})?
)*
{
so = sitem;
}
;
//delete_expression
delete_expression
:
"delete" (LSQUARE RSQUARE)? cast_expression
;
// Same as expression
//expression_list
expression_list
:
assignment_expression (COMMA assignment_expression)*
;
//optor
optor returns [char* s=NULL]
{
char sitem[CPPParser_MaxQualifiedItemSize+1];
sitem[0]='\0';
TypeSpecifier ts=tsInvalid;
char *opitem;
}
:
( "new" {strcat(sitem," new");}
(options {warnWhenFollowAmbig = false;}:
LSQUARE RSQUARE {strcat(sitem,"[]");} )?
|
"delete" {strcat(sitem," delete");}
(options {warnWhenFollowAmbig = false;}:
LSQUARE RSQUARE {strcat(sitem,"[]");} )?
|
LPAREN RPAREN {strcat(sitem,"()");}
|
LSQUARE RSQUARE {strcat(sitem,"[]");}
|
{strcat(sitem,(LT(1)->getText()).data());}
optor_simple_tokclass
|
{strcat(sitem,"type-specifier()");}
ts = type_specifier LPAREN RPAREN
)
{
s = sitem;
}
;
// optor_simple_tokclass
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
)
;
{
// Possibility of global stuff in the lexer cpp file
bool in_user_file_deferred = false; // used to record first detection of user file
int deferredLineCount = 0; // Used to accumulate line numbers in comments etc.
char principal_file[128]; // Path and name of user file set on reading the first preprocessor #line directive
int principal_line = 0; // principal file's line number
int principal_last_set = 0; // where principal file's line number was last set
char current_included_file[128]; // Path and name of current include file
int include_line = 0; // include file's line number
int include_last_set = 0; // where included file's line number was last set
}
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 (Not true!)
}
void newline()
{
for (;deferredLineCount>0;deferredLineCount--)
{
CharScanner::newline();
}
CharScanner::newline();
}
// for processing #line .... lines (see note above)
void process_line_directive(const char *includedFile, const char *includedLineNo)
{
// See global interface variables above
// Working variables
static int line, result;
static bool principal_file_set = false;
static int x;
// Extract included file line no.
result = sscanf(includedLineNo, "%d \n", &line);
//printf("CPPLexer line directive on line %d\n",lineNo);
// remove first " from file path+name by shifting all characters left
for(x=1;includedFile[x]!='"';x++)
{
current_included_file[x-1] = includedFile[x];
}
// Check path and name are not too long
if(x>128)
{
//
printf("Path and name of included file too long\n");
printf("Increase length of current_included_file and\n");
printf(" principal_file to at least %d characters\n",x);
printf("Abandon run\n");
getchar();
}
// Replace last " from file name with null
current_included_file[x-1] = NULL;
// This will occur on reading the first preprocessor #line directive
if (!principal_file_set)
{
strcpy (principal_file, current_included_file);
principal_file_set = true;
}
// check for main file name
if (strcmp(principal_file, current_included_file) == 0)
{
principal_line = line; // this is line no. shown in line directive
principal_last_set = CharScanner::getLine(); // This is line no. in preprocessed *.i file
strcpy(current_included_file, " "); // delete include file name
in_user_file_deferred = true; // Users's .C or .CPP file (aka principal_file) detected
}
else
// Check that this is a genuine path
if(current_included_file[1]==':')
{//printf("main.cpp 222 entered\n");
//printf("main.cpp 223 %s %s\n",principal_file,current_included_file);
include_line = line; // this is line no. shown in line directive
include_last_set = CharScanner::getLine(); // This is line no. in preprocessed *.i file
in_user_file_deferred = false; // Header file file detected
}
}
}
// 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 : '~' ;
//BITWISEAND : " & " ;
BITWISEOR : '|' ;
BITWISEOREQUAL : "|=" ;
BITWISEXOR : '^' ;
BITWISEXOREQUAL : "^=" ;
//Zuo: the following tokens are come from cplusplus.g
POINTERTOMBR : "->*" ;
DOTMBR : ".*" ;
SCOPE : "::" ;
Whitespace
:
( // Ignore space
Space
| // 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 on line %d\n",lineNo);
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 line directive";}
:
'#' LineDirective
{_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' {tab();}|'\f')
;
Pragma
:
('#' "pragma" ( (EndOfContinuedLine)=>EndOfContinuedLine
| ~('\r' | '\n')
)* EndOfLine
)
{_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP; newline();}
;
Error
:
('#' "error" ( (EndOfContinuedLine)=>EndOfContinuedLine
| ~('\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 | UniversalCharacterName | ~('\''|'\\'|'\n'|'\r') ) '\''
;
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
| UniversalCharacterName
| ~('"'|'\\'|'\n'|'\r')
)*
'"'
;
WStringLiteral
:
'L' StringLiteral
;
protected
EndOfContinuedLine
:
(options{generateAmbigWarnings = false;}:
'\\' '\r' '\n' // MS
| '\\' '\r' // Mac
| '\\' '\n' // Unix
) {deferredNewline();}
;
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;}: HexadecimalDigit)+ //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
UniversalCharacterName
:
"\\u" HexQuad
| "\\U" HexQuad HexQuad
;
protected
HexQuad
:
HexadecimalDigit HexadecimalDigit HexadecimalDigit HexadecimalDigit
;
protected
HexadecimalDigit
:
('0'..'9'|'a'..'f'|'A'..'F')
;
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') (HexadecimalDigit)+ //('a'..'f' | 'A'..'F' | Digit)+
//{_ttype = IntHexConst;}
(LongSuffix //{_ttype = LongHexConst;}
|UnsignedSuffix //{_ttype = UnsignedHexConst;}
)* {_ttype = HEXADECIMALINT;}
;
ID
options {testLiterals = true;}
:
(("asm"|"_asm"|"__asm") Whitespace )=>
("asm"|"_asm"|"__asm")
(EndOfLine {deferredNewline();}
|Space
)+
(
LPAREN
( EndOfLine {deferredNewline();}
| ~(')' | '\r' | '\n')
)*
RPAREN {_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP;}
|
LCURLY
( EndOfLine {deferredNewline();}
| ~('}' | '\r' | '\n')
)*
RCURLY {_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP;}
|
// Single line asm statement
(~('(' | ')' | '{' | '}' | '\n' | '\r' | ' ' | '\t' | '\f'))
(~('(' | ')' | '{' | '}' | '\n' | '\r'))* (EndOfLine {newline();})?
{_ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP;}
)
|
('a'..'z'|'A'..'Z'|'_')
('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
;