📄 support.cpp
字号:
/*
* 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.1
*
* 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-2003 Version 2.0 September 2003
*
* Some modifications were made to this file to support a project by
* Jianguo Zuo and David Wigg at
* The Centre for Systems and Software Engineering
* South Bank University
* London, UK.
* wiggjd@bcs.ac.uk
* blackse@lsbu.ac.uk
*
* These C++ functions are required to support the correct functioning of
* the CPP_parser.g definition of the C++ language.
*/
/* 2003-2004 Version 3.0 July 2004
* Modified by David Wigg at London South Bank University for CPP_parser.g
*/
/* 2004-2005 Version 3.1 November 2005
* Modified by David Wigg at London South Bank University for CPP_parser.g
*/
/* 2005-2007 Version 3.2 November 2007
* Modified by David Wigg at London South Bank University for CPP_parser.g
*
* See MyReadMe.txt for further information
*
* This file is best viewed in courier font with tabs set to 4 spaces
*/
#include <iostream>
#include "CPPParser.hpp"
extern int statementTrace; // Used to control selected tracing at statement level
// for testing and program verification purposes
// Shorthand for a string of (qualifiedItemIs()==xxx||...)
int CPPParser::
qualifiedItemIsOneOf(QualifiedItem qiFlags, // Ored combination of flags
int lookahead_offset)
{
QualifiedItem qi = qualifiedItemIs(lookahead_offset);
return (qi & qiFlags) != 0;
}
// This is an important function, but will be replaced with
// an enhanced predicate in the future, once predicates
// and/or predicate guards can contain loops.
//
// Scan past the ::T::B:: to see what lies beyond.
// Return qiType if the qualified item can pose as type name.
// Note that T::T is NOT a type; it is a constructor. Also,
// class T { ... T...} yields the enclosed T as a ctor. This
// is probably a type as I separate out the constructor defs/decls,
// I want it consistent with T::T.
//
// In the below examples, I use A,B,T and example types, and
// a,b as example ids.
// In the below examples, any A or B may be a
// qualified template, i.e., A<...>
//
// T::T outside of class T yields qiCtor.
// T<...>::T outside of class T yields qiCtor.
// T inside of class T {...} yields qiCtor.
// T, ::T, A::T outside of class T yields qiType.
// a, ::a, A::B::a yields qiId
// a::b yields qiInvalid
// ::operator, operator, A::B::operator yield qiOPerator
// A::*, A::B::* yield qiPtrMember
// ::*, * yields qiInvalid
// ::~T, ~T, A::~T yield qiDtor
// ~a, ~A::a, A::~T::, ~T:: yield qiInvalid
CPPParser::QualifiedItem
CPPParser::qualifiedItemIs(int lookahead_offset)
{
int k = lookahead_offset + 1;
int final_type_idx = 0;
// Skip leading "::"
if (LT(k)->getType() == SCOPE)
{k++;}
// Skip sequences of T:: or T<...>::
// DW 11/02/05 Note that LT(k)->getType() is not a "type" but a type of token, eg. ID, See STDCTokenTypes.hpp
//firstIsTypeName((LT(k)->getText()).data());
//printf("support.cpp qualifiedItemIs while reached k %d %s token %d isType %d, isClass %d, guessing %d\n",
// k,(LT(k)->getText()).data(),LT(k)->getType(),isTypeName((LT(k)->getText()).data()),isClassName((LT(k)->getText()).data()), inputState->guessing);
while (LT(k)->getType() == ID && isTypeName((LT(k)->getText()).data()))
{// If this type is the same as the last type, then ctor
if (final_type_idx != 0 &&
strcmp((LT(final_type_idx)->getText()).data(), (LT(k)->getText()).data()) == 0)
{// Like T::T
// As an extra check, do not allow T::T::
if (LT(k+1)->getType() == SCOPE)
{//printf("support.cpp qualifiedItemIs qiInvalid returned\n");
return qiInvalid;
}
else
{//printf("support.cpp qualifiedItemIs qiCtor_1 returned %s %s %s \n",
//enclosingClass,(LT(lookahead_offset+1)->getText()).data(),
//(LT(final_type_idx)->getText()).data());
return qiCtor;
}
}
// Record this as the most recent type seen in the series
final_type_idx = k;
// Skip this token
k++;
// Skip over any template qualifiers <...>
// I believe that "T<..." cannot be anything valid but a template
if (LT(k)->getType() == LESSTHAN)
{
if (!skipTemplateQualifiers(k))
{//printf("support.cpp qualifiedItemIs qiInvalid_2 returned\n");
return qiInvalid;}
//printf("support.cpp qualifiedItemIs template skipped, k %d\n",k);
// k has been updated to token following <...>
}
// Skip any "::" and keep going
if (LT(k)->getType() == SCOPE)
{k++;}
// Otherwise series terminated -- last ID in the sequence was a type
else
{
// Return ctor if last type is in containing class
// We already checked for T::T inside loop
//printf("support.cpp qualifiedItemIs qiCtor_2 entered %s %s %s\n",
// enclosingClass,(LT(lookahead_offset+1)->getText()).data(),
// (LT(final_type_idx)->getText()).data());
if (strcmp(enclosingClass,(LT(final_type_idx)->getText()).data())==0)
{//printf("support.cpp qualifiedItemIs qiCtor_2 returned\n");
return qiCtor;
}
else
{//printf("support.cpp qualifiedItemIs qiType_1 returned\n");
return qiType;
}
}
}
// LT(k) is not an ID, or it is an ID but not a typename.
//printf("support.cpp qualifiedItemIs second switch reached with type %d\n",LT(k)->getType());
switch (LT(k)->getType())
{
case ID:
// ID but not a typename
// Do not allow id::
if (LT(k+1)->getType() == SCOPE)
{
//printf("support.cpp qualifiedItemIs qiInvalid_3 returned\n");
return qiInvalid;
}
if (strcmp(enclosingClass,(LT(k)->getText()).data())==0 )
{// Like class T T()
//printf("support.cpp qualifiedItemIs qiCtor_3 returned %s\n",enclosingClass);
return qiCtor;
}
else
{
if (isTypeName((LT(k)->getText()).data()))
{
//printf("support.cpp qualifiedItemIs qiType_2 returned\n");
return qiType;
}
else
{
//printf("support.cpp qualifiedItemIs qiVar returned\n");
return qiVar; // DW 19/03/04 was qiVar Could be function, qiFun?
}
}
case TILDE:
// check for dtor
if (LT(k+1)->getType() == ID &&
isTypeName((LT(k+1)->getText()).data()) &&
LT(k+2)->getType() != SCOPE)
{// Like ~B or A::B::~B
// Also (incorrectly?) matches ::~A.
//printf("support.cpp qualifiedItemIs qiDtor returned\n");
return qiDtor;
}
else
{// ~a or ~A::a is qiInvalid
//printf("support.cpp qualifiedItemIs qiInvalid_4 returned\n");
return qiInvalid;
}
break;
case STAR:
// Like A::*
// Do not allow * or ::*
if (final_type_idx == 0)
{// Haven't seen a type yet
//printf("support.cpp qualifiedItemIs qiInvalid_5 returned\n");
return qiInvalid;
}
else
{//printf("support.cpp qualifiedItemIs qiPtrMember returned\n");
return qiPtrMember;}
case OPERATOR:
// Like A::operator, ::operator, or operator
//printf("support.cpp qualifiedItemIs qiOperator returned\n");
return qiOperator;
default:
// Something that neither starts with :: or ID, or
// a :: not followed by ID, operator, ~, or *
//printf("support.cpp qualifiedItemIs qiInvalid_6 returned\n");
return qiInvalid;
}
}
// Skip over <...>. This correctly handles nested <> and (), e.g:
// <T>
// < (i>3) >
// < T2<...> >
// but not
// < i>3 >
//
// On input, kInOut is the index of the "<"
// On output, if the return is true, then
// kInOut is the index of the token after ">"
// else
// kInOut is unchanged
int CPPParser::
skipTemplateQualifiers(int& kInOut)
{// Start after "<"
int k = kInOut + 1;
while (LT(k)->getType() != GREATERTHAN) // scan to end of <...>
{
switch (LT(k)->getType())
{
case EOF:
return 0;
case LESSTHAN:
if (!skipTemplateQualifiers(k))
{return 0;}
break;
case LPAREN:
if (!skipNestedParens(k))
{return 0;}
break;
default:
k++; // skip everything else
break;
}
if (k > MaxTemplateTokenScan)
{return 0;}
}
// Update output argument to point past ">"
kInOut = k + 1;
return 1;
}
// Skip over (...). This correctly handles nested (), e.g:
// (i>3, (i>5))
//
// On input, kInOut is the index of the "("
// On output, if the return is true, then
// kInOut is the index of the token after ")"
// else
// kInOut is unchanged
int CPPParser::
skipNestedParens(int& kInOut)
{// Start after "("
int k = kInOut + 1;
while (LT(k)->getType() != RPAREN) // scan to end of (...)
{
switch (LT(k)->getType())
{
case EOF:
return 0;
case LPAREN:
if (!skipNestedParens(k))
{return 0;}
break;
default:
k++; // skip everything else
break;
}
if (k > MaxTemplateTokenScan)
{return 0;}
}
// Update output argument to point past ")"
kInOut = k+1;
return 1;
}
// This was only used in scope_override but has now been replaced by a
// proper syntactic predicate
// DW 21/06/06 I think this can now be replaced by !finalqualifier(k) below
// Return true if "blah::" or "fu::bar<args>::..." found.
int CPPParser::
scopedItem(int k)
{
printf("support.cpp scopedItem k %d\n",k);
printf("support.cpp type %d finalQualifier %d\n",ID,!finalQualifier(k));
printf("support.cpp return %d \n",(LT(k)->getType()==ID && !finalQualifier(k)));
return (LT(k)->getType()==ID && !finalQualifier(k));
// return (LT(k)->getType()==SCOPE ||
// (LT(k)->getType()==ID && !finalQualifier(k)));
}
// This was only used by scopedItem() above which is now not used (See above)
// Return true if ID<...> or ID is last item in qualified item list.
// Return false if LT(k) is not an ID.
// ID must be a type to check for ID<...>,
// or else we would get confused by "i<3"
int CPPParser::
finalQualifier(int k)
{
if (LT(k)->getType()==ID)
{
if (isTypeName((LT(k)->getText()).data()) && LT(k+1)->getType()==LESSTHAN)
{// Starts with "T<". Skip <...>
k++;
skipTemplateQualifiers(k);
}
else
{// skip ID;
k++;
}
return (LT(k)->getType() != SCOPE );
}
else
{// not an ID
return 0;
}
}
/*
* Return true if 's' can pose as a type name
*/
int CPPParser::
isTypeName(const char *s)
{
//printf("isTypeName entered with %s\n",s);
// To look for any type name only
CPPSymbol *cs = (CPPSymbol *) symbols->lookup(s,CPPSymbol::otTypename);
if (cs==NULL)
{
//printf("support.cpp isTypeName %s not found in dictionary\n",s);
return 0;
}
// This should now be redundant
if (cs->getType()==CPPSymbol::otTypedef||
cs->getType()==CPPSymbol::otEnum||
cs->getType()==CPPSymbol::otClass||
cs->getType()==CPPSymbol::otStruct||
cs->getType()==CPPSymbol::otUnion)
{
return 1;
}
else
{// Warning to detect any failure of above 07/06/06
printf("Support isTypeName warning symbol %s not type name\n",s);
}
return 0;
}
/*
* Return true if the most recently added matching entry 's' can pose as a type name
*/
/*
int CPPParser::
firstIsTypeName(const char *s)
{
CPPSymbol *cs = (CPPSymbol *) symbols->lookup(s,CPPSymbol::otInvalid); // otInvalid is zero
if (cs==NULL)
{
//printf("support.cpp isTypeName %s not found in dictionary\n",s);
return 0;
}
//printf("support firstIsClassName this-scope %d\n",cs->this_scope);
if (cs->getType()==CPPSymbol::otTypedef||
cs->getType()==CPPSymbol::otEnum||
cs->getType()==CPPSymbol::otClass||
cs->getType()==CPPSymbol::otStruct||
cs->getType()==CPPSymbol::otUnion)
{
return 1;
}
return 0;
}
*/
/*
* Return true if 's' is a class name (or a struct which is a class
* with all members public).
*/
int CPPParser::
isClassName(const char *s)
{
// To look for any type name omly
CPPSymbol *cs = (CPPSymbol *) symbols->lookup(s,CPPSymbol::otTypename);
if ( cs==NULL ) return 0;
if (cs->getType()==CPPSymbol::otClass||
cs->getType()==CPPSymbol::otStruct||
cs->getType()==CPPSymbol::otUnion)
{
return 1;
}
return 0;
}
void CPPParser::
beginDeclaration()
{
}
void CPPParser::
endDeclaration()
{
}
void CPPParser::
beginFunctionDefinition()
{
functionDefinition = 1;
}
void CPPParser::
endFunctionDefinition()
{
// Remove parameter scope
symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp
//printf("endFunctionDefinition remove parameter scope(%d):\n",symbols->getCurrentScopeIndex());
symbols->removeScope(); // Remove symbols stored in current scope
symbols->restoreScope(); // Reduce currentScope (higher level)
//printf("endFunctionDefinition restoreScope() now %d\n",symbols->getCurrentScopeIndex());
functionDefinition = 0;
}
void CPPParser::
beginConstructorDefinition()
{functionDefinition = 1;}
void CPPParser::
endConstructorDefinition()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -