⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 support.cpp

📁 C Preprocessor,antlr的grammar语言描述,用于学习词法分析,语法分析
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -