1//
2//  ANTLRMap.m
3//  ANTLR
4//
5//  Created by Alan Condit on 6/9/10.
6// [The "BSD licence"]
7// Copyright (c) 2010 Alan Condit
8// All rights reserved.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions
12// are met:
13// 1. Redistributions of source code must retain the above copyright
14//    notice, this list of conditions and the following disclaimer.
15// 2. Redistributions in binary form must reproduce the above copyright
16//    notice, this list of conditions and the following disclaimer in the
17//    documentation and/or other materials provided with the distribution.
18// 3. The name of the author may not be used to endorse or promote products
19//    derived from this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32#define SUCCESS (0)
33#define FAILURE (-1)
34
35#import "ANTLRMap.h"
36#import "ANTLRBaseTree.h"
37
38/*
39 * Start of ANTLRMap
40 */
41@implementation ANTLRMap
42
43@synthesize lastHash;
44
45+(id)newANTLRMap
46{
47    return [[ANTLRMap alloc] init];
48}
49
50+(id)newANTLRMapWithLen:(NSInteger)aBuffSize
51{
52    return [[ANTLRMap alloc] initWithLen:aBuffSize];
53}
54
55-(id)init
56{
57    NSInteger idx;
58    
59	self = [super initWithLen:HASHSIZE];
60    if ( self != nil ) {
61		fNext = nil;
62        for( idx = 0; idx < HASHSIZE; idx++ ) {
63            ptrBuffer[idx] = nil;
64        }
65	}
66    return( self );
67}
68
69-(id)initWithLen:(NSInteger)aBuffSize
70{
71	self = [super initWithLen:aBuffSize];
72    if ( self != nil ) {
73	}
74    return( self );
75}
76
77-(void)dealloc
78{
79#ifdef DEBUG_DEALLOC
80    NSLog( @"called dealloc in ANTLRMMap" );
81#endif
82    ANTLRMapElement *tmp, *rtmp;
83    NSInteger idx;
84	
85    if ( self.fNext != nil ) {
86        for( idx = 0; idx < BuffSize; idx++ ) {
87            tmp = ptrBuffer[idx];
88            while ( tmp ) {
89                rtmp = tmp;
90                tmp = (ANTLRMapElement *)tmp.fNext;
91                [rtmp release];
92            }
93        }
94    }
95	[super dealloc];
96}
97
98-(void)deleteANTLRMap:(ANTLRMapElement *)np
99{
100    ANTLRMapElement *tmp, *rtmp;
101    NSInteger idx;
102    
103    if ( self.fNext != nil ) {
104        for( idx = 0; idx < BuffSize; idx++ ) {
105            tmp = ptrBuffer[idx];
106            while ( tmp ) {
107                rtmp = tmp;
108                tmp = [tmp getfNext];
109                [rtmp release];
110            }
111        }
112    }
113}
114
115- (void)clear
116{
117    ANTLRMapElement *tmp, *rtmp;
118    NSInteger idx;
119
120    for( idx = 0; idx < BuffSize; idx++ ) {
121        tmp = ptrBuffer[idx];
122        while ( tmp ) {
123            rtmp = tmp;
124            tmp = [tmp getfNext];
125            [rtmp dealloc];
126        }
127        ptrBuffer[idx] = nil;
128    }
129}
130
131- (NSInteger)count
132{
133    NSInteger aCnt = 0;
134    
135    for (int i = 0; i < BuffSize; i++) {
136        if (ptrBuffer[i] != nil) {
137            aCnt++;
138        }
139    }
140    return aCnt;
141}
142
143- (NSInteger)length
144{
145    return BuffSize;
146}
147
148- (NSInteger)size
149{
150    ANTLRMapElement *anElement;
151    NSInteger aSize = 0;
152    
153    for (int i = 0; i < BuffSize; i++) {
154        if ((anElement = ptrBuffer[i]) != nil) {
155            aSize += (NSInteger)[anElement size];
156        }
157    }
158    return aSize;
159}
160                          
161#ifdef USERDOC
162/*
163 *  HASH        hash entry to get index to table
164 *  NSInteger hash( ANTLRMap *self, char *s );
165 *
166 *     Inputs:  NSString *s         string to find
167 *
168 *     Returns: NSInteger                 hashed value
169 *
170 *  Last Revision 9/03/90
171 */
172#endif
173-(NSInteger)hash:(NSString *)s       /*    form hash value for string s */
174{
175	NSInteger hashval;
176	const char *tmp;
177    
178	tmp = [s cStringUsingEncoding:NSASCIIStringEncoding];
179	for( hashval = 0; *tmp != '\0'; )
180        hashval += *tmp++;
181	self->lastHash = hashval % HASHSIZE;
182	return( self->lastHash );
183}
184
185#ifdef USERDOC
186/*
187 *  LOOKUP  search hashed list for entry
188 *  ANTLRMapElement *lookup:(NSString *)s;
189 *
190 *     Inputs:  NSString  *s       string to find
191 *
192 *     Returns: ANTLRMapElement  *        pointer to entry
193 *
194 *  Last Revision 9/03/90
195 */
196#endif
197-(id)lookup:(NSString *)s
198{
199    ANTLRMapElement *np;
200    
201    for( np = self->ptrBuffer[[self hash:s]]; np != nil; np = [np getfNext] ) {
202        if ( [s isEqualToString:[np getName]] ) {
203            return( np );        /*   found it       */
204        }
205    }
206    return( nil );              /*   not found      */
207}
208
209#ifdef USERDOC
210/*
211 *  INSTALL search hashed list for entry
212 *  NSInteger install( ANTLRMap *self, ANTLRMapElement *sym );
213 *
214 *     Inputs:  ANTLRMapElement    *sym   -- symbol ptr to install
215 *              NSInteger         scope -- level to find
216 *
217 *     Returns: Boolean     TRUE   if installed
218 *                          FALSE  if already in table
219 *
220 *  Last Revision 9/03/90
221 */
222#endif
223-(ANTLRMapElement *)install:(ANTLRMapElement *)sym
224{
225    ANTLRMapElement *np;
226    
227    np = [self lookup:[sym getName]];
228    if ( np == nil ) {
229        [sym setFNext:ptrBuffer[ lastHash ]];
230        ptrBuffer[ lastHash ] = sym;
231        [sym retain];
232        return( ptrBuffer[ lastHash ] );
233    }
234    return( nil );            /*   not found      */
235}
236
237#ifdef USERDOC
238/*
239 *  RemoveSym  search hashed list for entry
240 *  NSInteger RemoveSym( ANTLRMap *self, char *s );
241 *
242 *     Inputs:  char     *s          string to find
243 *
244 *     Returns: NSInteger      indicator of SUCCESS OR FAILURE
245 *
246 *  Last Revision 9/03/90
247 */
248#endif
249-(NSInteger)RemoveSym:(NSString *)s
250{
251    ANTLRMapElement *np, *tmp;
252    NSInteger idx;
253    
254    idx = [self hash:s];
255    for ( tmp = self->ptrBuffer[idx], np = self->ptrBuffer[idx]; np != nil; np = [np getfNext] ) {
256        if ( [s isEqualToString:[np getName]] ) {
257            tmp = [np getfNext];             /* get the next link  */
258            [np release];
259            return( SUCCESS );            /* report SUCCESS     */
260        }
261        tmp = [np getfNext];              //  BAD!!!!!!
262    }
263    return( FAILURE );                    /*   not found      */
264}
265
266-(void)delete_chain:(ANTLRMapElement *)np
267{
268    if ( [np getfNext] != nil )
269		[self delete_chain:[np getfNext]];
270	[np release];
271}
272
273#ifdef DONTUSEYET
274-(NSInteger)bld_symtab:(KW_TABLE *)toknams
275{
276    NSInteger i;
277    ANTLRMapElement *np;
278    
279    for( i = 0; *(toknams[i].name) != '\0'; i++ ) {
280        // install symbol in ptrBuffer
281        np = [ANTLRMapElement newANTLRMapElement:[NSString stringWithFormat:@"%s", toknams[i].name]];
282        //        np->fType = toknams[i].toknum;
283        [self install:np Scope:0];
284    }
285    return( SUCCESS );
286}
287#endif
288
289/*
290 * works only for maplist indexed not by name but by TokenNumber
291 */
292- (ANTLRMapElement *)getName:(NSInteger)ttype
293{
294    ANTLRMapElement *np;
295    NSInteger aTType;
296
297    aTType = ttype % HASHSIZE;
298    for( np = self->ptrBuffer[ttype]; np != nil; np = [np getfNext] ) {
299        if ( [(NSNumber *)np.node integerValue] == ttype ) {
300            return( np );        /*   found it       */
301        }
302    }
303    return( nil );              /*   not found      */
304}
305
306- (NSInteger)getNode:(id<ANTLRBaseTree>)aNode
307{
308    ANTLRMapElement *np;
309    NSInteger idx;
310
311    idx = [(id<ANTLRBaseTree>)aNode type];
312    idx %= HASHSIZE;
313    np = ptrBuffer[idx];
314    return( [(NSNumber *)np.node integerValue] );
315}
316
317- (ANTLRMapElement *)getTType:(NSString *)name
318{
319    return [self lookup:name];
320}
321
322// create node and install node in ptrBuffer
323- (void)putName:(NSString *)name TType:(NSInteger)ttype
324{
325    ANTLRMapElement *np;
326    
327    np = [ANTLRMapElement newANTLRMapElementWithName:[NSString stringWithString:name] Type:ttype];
328    [self install:np];
329}
330
331// create node and install node in ptrBuffer
332- (void)putName:(NSString *)name Node:(id)aNode
333{
334    ANTLRMapElement *np, *np1;
335    NSInteger idx;
336    
337    idx = [self hash:name];
338    np1 = [ANTLRMapElement newANTLRMapElementWithName:[NSString stringWithString:name] Type:idx];
339    np = [self lookup:name];
340    if ( np == nil ) {
341        [np1 setFNext:self->ptrBuffer[ self->lastHash ]];
342        self->ptrBuffer[ self->lastHash ] = np1;
343        [np1 retain];
344    }
345    else {
346        // ptrBuffer[idx] = np;
347    }
348    return;
349}
350
351// create node and install node in ptrBuffer
352- (void)putNode:(NSInteger)aTType Node:(id)aNode
353{
354    ANTLRMapElement *np;
355    NSInteger ttype;
356    
357    ttype = aTType % HASHSIZE;
358    np = [ANTLRMapElement newANTLRMapElementWithNode:ttype Node:(id)aNode];
359    ptrBuffer[ttype] = np;
360}
361
362@end
363