📄 dictionary.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.
*
* Requires PCCTS 1.32b4 or higher to get past ANTLR.
*
* DISCLAIMER: we make no guarantees that this grammar works, makes sense,
* or can be used to do anything useful.
*/
/* 1999-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
*
* See NotesScopes.txt for information about storing symbol names within scope levels
*
* Symbols names are stored in lists selected by hashing
*
* Symbols are also chained in lists for each scope level,
* [0] = template scope Note: Not used at present
* [1] = external scope Note: These symbols (types) are never deleted. "std" is allocated this scope in CPPParser::init()
* [2+]= function/variable scopes Note: These symbol references are deleted when they go out of scope.
*/
#include <string>
#include <stdlib.h>
#include "Dictionary.hpp"
/* Hashing function described in */
/* "Fast Hashing of Variable-Length Text Strings," */
/* by Peter K. Pearson, CACM, June 1990. */
/* Table from p. 678.*/
/* Pseudorandom Permutation of the Integers 0 through 255: */
unsigned char Dictionary::randomNumbers[] =
{
1, 14,110, 25, 97,174,132,119,138,170,125,118, 27,233,140, 51,
87,197,177,107,234,169, 56, 68, 30, 7,173, 73,188, 40, 36, 65,
49,213,104,190, 57,211,148,223, 48,115, 15, 2, 67,186,210, 28,
12,181,103, 70, 22, 58, 75, 78,183,167,238,157,124,147,172,144,
176,161,141, 86, 60, 66,128, 83,156,241, 79, 46,168,198, 41,254,
178, 85,253,237,250,154,133, 88, 35,206, 95,116,252,192, 54,221,
102,218,255,240, 82,106,158,201, 61, 3, 89, 9, 42,155,159, 93,
166, 80, 50, 34,175,195,100, 99, 26,150, 16,145, 4, 33, 8,189,
121, 64, 77, 72,208,245,130,122,143, 55,105,134, 29,164,185,194,
193,239,101,242, 5,171,126, 11, 74, 59,137,228,108,191,232,139,
6, 24, 81, 20,127, 17, 91, 92,251,151,225,207, 21, 98,113,112,
84,226, 18,214,199,187, 13, 32, 94,220,224,212,247,204,196, 43,
249,236, 45,244,111,182,153,136,129, 90,217,202, 19,165,231, 71,
230,142, 96,227, 62,179,246,114,162, 53,160,215,205,180, 47,109,
44, 38, 31,149,135, 0,216, 52, 63, 23, 37, 69, 39,117,146,184,
163,200,222,235,248,243,219, 10,152,131,123,229,203, 76,120,209
};
char *Dictionary::strings = NULL;
char *Dictionary::strp = NULL;
unsigned Dictionary::strsize = 0;
Dictionary::
Dictionary(int nb, int ns, int nc)
{
int i;
// allocate buckets for names
bucket = new (DictEntry *[nb]);
if (bucket==NULL)
panic("can't alloc buckets");
// Initialize buckets for names
nbuckets = nb;
for (i=0; i<nb; i++)
bucket[i]=NULL;
// allocate a scope list for the start of each scope list
scope = new (DictEntry *[ns]);
if (scope==NULL)
panic("can't alloc scopes");
// allocate an endScope list for the end of each scope list
endScope = new (DictEntry *[ns]);
if (endScope==NULL)
panic("can't alloc endScope");
// Initialize scopes and endscopes
nscopes = ns;
for (i=0; i<ns; i++)
{
scope[i]=NULL;
endScope[i] = NULL;
}
currentScope = 0;
strsize = nc;
strings = new char[nc];
strp = strings;
}
Dictionary::
~Dictionary()
{
delete [] bucket;
delete [] scope;
delete [] endScope;
nbuckets = nscopes = 0;
currentScope = -1;
}
/* Hashing function described in */
/* "Fast Hashing of Variable-Length Text Strings," */
/* by Peter K. Pearson, CACM, June 1990. */
int Dictionary::
hash(const char *string)
{
int hash1 = 0;
int hash2 = 0;
int length = 0;
int r = 0;
while(*string != 0)
{
length++;
/* Hash function is XOR of successive characters randomized by
* the hash table.
*/
hash1 ^= randomNumbers[*string++];
if (*string != 0)
hash2 ^= randomNumbers[*string++];
}
r = (hash1 << 8) | hash2;
return r;
}
/* Return ptr to 1st entry found in table under key
* (return NULL if none found).
*/
DictEntry *Dictionary::
lookup(const char *key,CPPSymbol::ObjectType tp)
{
//printf("Dictionary.cpp lookup entered with %s for type %d\n",key,tp);
// tp is type to be looked for
// Default, 0, is to look for any symbol irrespective of type
// Each new DictEntry is stored at start of its list so most
// recent additions are reached first
//DictEntry *q;
CPPSymbol *q; // CPPSymbol is subclass of DictEntry
//int scope = getCurrentScopeIndex();
//if(sc != -1)
// scope = sc;
int h = hash(key) % nbuckets;
q = (CPPSymbol *) bucket[h];
// This searches symbol bucket for CPPSymbol entries
for (q; q != NULL; q = (CPPSymbol *) q->getNext())
{
//printf("Dictionary.cpp lookup symbol %s in scope %d current scope %d\n",
// q->getKey(),q->this_scope,getCurrentScopeIndex());
if (h != q->getHashCode())
fprintf(stderr,"dictionary.cpp lookup, h not equal to q->getHashCode() for %s\n",key);
if ( h==q->getHashCode() && strcmp(key, q->getKey()) == 0)
{
if(tp==0) // Search for first matching symbol
return q;
else
{
CPPSymbol::ObjectType type = q->getType();
if(tp==CPPSymbol::otTypename) // Search for first type name
{
if (type==CPPSymbol::otTypedef||
type==CPPSymbol::otEnum||
type==CPPSymbol::otClass||
type==CPPSymbol::otStruct||
type==CPPSymbol::otUnion)
return q;
}
else if(tp==CPPSymbol::otNonTypename) // Search for first non type name
{
if (type==CPPSymbol::otVariable||
type==CPPSymbol::otFunction)
return q;
}
else if(type==tp) // Search for first symbol with specific type
return q;
else
return NULL;
}
}
}
return NULL;
}
void Dictionary::
define(const char *key, DictEntry *entry)
{
defineInScope(key, entry, currentScope);
}
void Dictionary::
defineInScope(const char *key, DictEntry *entry, int sc)
{
int h = hash(key) % nbuckets; // July 2005, nbuckets = 4001 See CPP_parser.g
//printf("Dictionary.cpp defineInScope key %s hash(key) %d bucket %d scope %d\n",
// key,hash(key),h,sc);
entry->this_scope = sc;
entry->setKey(strdup(key)); // Make a local copy of key
entry->setHashCode(h);
entry->setNext(bucket[h]); // Set next pointer to current entry in bucket
bucket[h] = entry; // Replace current entry in bucket
if (endScope[sc]==NULL)
scope[sc] = endScope[sc] = entry;
else
{
endScope[sc]->setScope(entry);
endScope[sc] = entry;
}
}
int Dictionary::
getCurrentScopeIndex()
{
return currentScope;
}
DictEntry *Dictionary::
getCurrentScope()
{
if (currentScope<0 || currentScope>nscopes)
panic("getCurrentScope: no scope");
return scope[currentScope];
}
void Dictionary::
saveScope()
{
// Advance scope number (for included scope)
currentScope++;
if (currentScope>=nscopes)
panic("saveScope: overflow");
//printf("Dictionary saveScope entered. Scope now %d\n",currentScope);
}
void Dictionary::
restoreScope()
{
// Reduce scope number for next highest scope
if (currentScope==0)
panic("restoreScope: underflow");
currentScope--;
//printf("Dictionary restoreScope entered. Scope now %d\n",currentScope);
}
/* This unlinks all entries from the Dictionary that are members
* of the current scope. The scope level is not restored to the previous
* scope however. This requires use of restoreScope() above
*/
DictEntry *Dictionary::
removeScope(int sc)
{
DictEntry *de, *r;
if (sc == -1) // removeScope() without parameter value defaults sc to -1
sc = currentScope;
for (de=scope[sc]; de!=NULL; de=de->getNextInScope())
{
remove(de);
}
r = scope[sc];
scope[sc] = endScope[sc] = NULL;
return r;
}
// Remove this dictEntry from its bucket by unlinking it
DictEntry *Dictionary::
remove(DictEntry *de)
{
DictEntry *prev, *curr;
if (de==NULL)
panic("Dictionary.cpp remove: NULL ptr");
int h = hash(de->getKey()) % nbuckets; // Find pointer to bucket
for (prev=NULL, curr=bucket[h]; curr!=NULL; prev=curr, curr=curr->getNext())
{
if (de==curr)
{
if (prev==NULL)
bucket[h] = de->getNext();
else
prev->setNext(de->getNext());
de->setNext(NULL);
return de;
}
}
return NULL; // should never get here...
}
/* Lookup the object referred to by 'key' and then physically remove
* it from the Dictionary. Return the object referred to by the key.
* If more than one definition is found for 'key', then only the
* first one is removed. Return NULL if not found.
* Note: DW 12/06/03 Probably not used
*/
DictEntry *Dictionary::
remove(char *key)
{
DictEntry *q, *prev;
int h = hash(key) % nbuckets;
for (prev=NULL, q = bucket[h]; q != NULL; prev = q, q = q->getNext())
{
if (h==q->getHashCode() && strcmp(key, q->getKey()) == 0)
{
if (prev==NULL)
{
bucket[h] = q->getNext();
}
else
{
prev->setNext(q->getNext());
}
q->setNext(NULL);
return q;
}
}
return NULL; // should never get here, but make compiler happy
}
void Dictionary::
dumpScope(FILE *f, int sc)
{
DictEntry *s;
if (sc == -1) // dumpScope() without parameter value defaults sc to -1
sc = currentScope;
for (s=scope[sc]; s!=NULL; s=s->getNextInScope())
{
dumpSymbol(f, s);
}
}
// This is overridden in CPPDictionary.hpp
void Dictionary::
dumpSymbol(FILE *f, DictEntry *de)
{
fprintf(f, "%s\n", de->getKey());
}
// Diagnostic function
// Contents of first 10 scopes printed
void Dictionary::
dumpScopes()
{
DictEntry *dictEntry;
int i;
printf("Scopes");
for (i=0; i<10; i++)
{
printf(" %d ",i);
}
printf("\n");
printf(" first");
for (i=0; i<10; i++)
{
if (scope[i]!=NULL)
{
dictEntry = scope[i];
printf("%10s ",dictEntry->getKey());
}
else
{
printf(" ");
}
}
printf("\n");
printf(" last ");
for (i=0; i<10; i++)
{
if (endScope[i]!=NULL)
{
dictEntry = endScope[i];
printf("%10s ",dictEntry->getKey());
}
else
{
printf(" ");
}
}
printf("\n");
}
/* Add a string to the string table and return a pointer to it.
* Bump the pointer into the string table to next avail position.
*/
char *Dictionary::
strdup(const char *s)
{
char *start=strp;
if (s==NULL)
panic("strdup: NULL string");
if (start+strlen(s)+1 > &(strings[strsize-2]))
panic("string table overflow");
while (*s != '\0')
{
*strp++ = *s++;
}
*strp++ = '\0';
return start;
}
void Dictionary::
panic(char *err)
{
fprintf(stdout, "Dictionary panic: %s\n", err);
exit(-1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -