Home | History | Annotate | Download | only in Framework
      1 // [The "BSD licence"]
      2 // Copyright (c) 2006-2007 Kay Roepke 2010 Alan Condit
      3 // All rights reserved.
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions
      7 // are met:
      8 // 1. Redistributions of source code must retain the above copyright
      9 //    notice, this list of conditions and the following disclaimer.
     10 // 2. Redistributions in binary form must reproduce the above copyright
     11 //    notice, this list of conditions and the following disclaimer in the
     12 //    documentation and/or other materials provided with the distribution.
     13 // 3. The name of the author may not be used to endorse or promote products
     14 //    derived from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 
     28 #import "ANTLRStringStream.h"
     29 
     30 extern NSInteger debug;
     31 
     32 @implementation ANTLRStringStream
     33 
     34 @synthesize data;
     35 @synthesize n;
     36 @synthesize index;
     37 @synthesize line;
     38 @synthesize charPositionInLine;
     39 @synthesize markDepth;
     40 @synthesize markers;
     41 @synthesize lastMarker;
     42 @synthesize name;
     43 @synthesize charState;
     44 
     45 + newANTLRStringStream
     46 {
     47     return [[ANTLRStringStream alloc] init];
     48 }
     49 
     50 + newANTLRStringStream:(NSString *)aString;
     51 {
     52     return [[ANTLRStringStream alloc] initWithString:aString];
     53 }
     54 
     55 
     56 + newANTLRStringStream:(char *)myData Count:(NSInteger)numBytes;
     57 {
     58     return [[ANTLRStringStream alloc] initWithData:myData Count:numBytes];
     59 }
     60 
     61 
     62 - (id) init
     63 {
     64 	if ((self = [super init]) != nil) {
     65         n = 0;
     66         index = 0;
     67         line = 1;
     68         charPositionInLine = 0;
     69         markDepth = 0;
     70 		markers = [ANTLRPtrBuffer newANTLRPtrBufferWithLen:10];
     71         [markers retain];
     72         [markers addObject:[NSNull null]]; // ANTLR generates code that assumes markers to be 1-based,
     73         charState = [[ANTLRCharStreamState newANTLRCharStreamState] retain];
     74 	}
     75 	return self;
     76 }
     77 
     78 - (id) initWithString:(NSString *) theString
     79 {
     80 	if ((self = [super init]) != nil) {
     81 		//[self setData:[NSString stringWithString:theString]];
     82         data = [theString retain];
     83         n = [data length];
     84         index = 0;
     85         line = 1;
     86         charPositionInLine = 0;
     87         markDepth = 0;
     88 		markers = [[ANTLRPtrBuffer newANTLRPtrBufferWithLen:10] retain];
     89         [markers addObject:[NSNull null]]; // ANTLR generates code that assumes markers to be 1-based,
     90         charState = [[ANTLRCharStreamState newANTLRCharStreamState] retain];
     91 	}
     92 	return self;
     93 }
     94 
     95 - (id) initWithStringNoCopy:(NSString *) theString
     96 {
     97 	if ((self = [super init]) != nil) {
     98 		//[self setData:theString];
     99         data = [theString retain];
    100         n = [data length];
    101         index = 0;
    102         line = 1;
    103         charPositionInLine = 0;
    104         markDepth = 0;
    105 		markers = [ANTLRPtrBuffer newANTLRPtrBufferWithLen:100];
    106         [markers retain];
    107         [markers addObject:[NSNull null]]; // ANTLR generates code that assumes markers to be 1-based,
    108         charState = [[ANTLRCharStreamState newANTLRCharStreamState] retain];
    109 	}
    110 	return self;
    111 }
    112 
    113 - (id) initWithData:(char *)myData Count:(NSInteger)numBytes
    114 {
    115     if ((self = [super init]) != nil) {
    116         data = [NSString stringWithCString:myData encoding:NSASCIIStringEncoding];
    117         n = numBytes;
    118         index = 0;
    119         line = 1;
    120         charPositionInLine = 0;
    121         markDepth = 0;
    122 		markers = [ANTLRPtrBuffer newANTLRPtrBufferWithLen:100];
    123         [markers retain];
    124         [markers addObject:[NSNull null]]; // ANTLR generates code that assumes markers to be 1-based,
    125         charState = [[ANTLRCharStreamState newANTLRCharStreamState] retain];
    126     }
    127     return( self );
    128 }
    129 
    130 - (void) dealloc
    131 {
    132 #ifdef DEBUG_DEALLOC
    133     NSLog( @"called dealloc in ANTLRStringStream" );
    134 #endif
    135     if ( markers && [markers count] ) {
    136         [markers removeAllObjects];
    137         [markers release];
    138         markers = nil;
    139     }
    140     if ( data ) {
    141         [data release];
    142         data = nil;
    143     }
    144 	[super dealloc];
    145 }
    146 
    147 - (id) copyWithZone:(NSZone *)aZone
    148 {
    149     ANTLRStringStream *copy;
    150 	
    151     copy = [[[self class] allocWithZone:aZone] init];
    152     //    copy = [super copyWithZone:aZone]; // allocation occurs here
    153     if ( data != nil )
    154         copy.data = [self.data copyWithZone:aZone];
    155     copy.n = n;
    156     copy.index = index;
    157     copy.line = line;
    158     copy.charPositionInLine = charPositionInLine;
    159     copy.markDepth = markDepth;
    160     if ( markers != nil )
    161         copy.markers = [markers copyWithZone:nil];
    162     copy.lastMarker = lastMarker;
    163     if ( name != nil )
    164         copy.name = [self.name copyWithZone:aZone];
    165     return copy;
    166 }
    167 
    168 // reset the streams charState
    169 // the streams content is not reset!
    170 - (void) reset
    171 {
    172 	index = 0;
    173 	line = 1;
    174 	charPositionInLine = 0;
    175 	markDepth = 0;
    176     if ( markers && [markers count] )
    177         [markers removeAllObjects];
    178     [markers addObject:[NSNull null]];  // ANTLR generates code that assumes markers to be 1-based,
    179                                         // thus the initial null in the array!
    180 }
    181 
    182 // read one character off the stream, tracking line numbers and character positions
    183 // automatically.
    184 // Override this in subclasses if you want to avoid the overhead of automatic line/pos
    185 // handling. Do not call super in that case.
    186 - (void) consume 
    187 {
    188 	if ( index < n ) {
    189 		charPositionInLine++;
    190 		if ( [data characterAtIndex:index] == '\n' ) {
    191 			line++;
    192 			charPositionInLine=0;
    193 		}
    194 		index++;
    195 	}
    196 }
    197 
    198 // implement the lookahead method used in lexers
    199 - (NSInteger) LA:(NSInteger) i 
    200 {
    201     NSInteger c;
    202     if ( i == 0 )
    203         return 0; // undefined
    204     if ( i < 0 ) {
    205         i++;
    206         if ( index+i-1 < 0 ) {
    207 		    return ANTLRCharStreamEOF;
    208 		}
    209 	}
    210     if ( (index+i-1) >= n ) {
    211 		return ANTLRCharStreamEOF;
    212 	}
    213     c = [data characterAtIndex:index+i-1];
    214 	return (NSInteger)c;
    215 }
    216 
    217 - (NSInteger) LT:(NSInteger)i
    218 {
    219     return [self LA:i];
    220 }
    221 
    222 - (NSInteger) size 
    223 {
    224 	return n;
    225 }
    226 
    227 // push the current charState of the stream onto a stack
    228 // returns the depth of the stack, to be used as a marker to rewind the stream.
    229 // Note: markers are 1-based!
    230 - (NSInteger) mark 
    231 {
    232     if (debug > 1) NSLog(@"mark entry -- markers=%x, markDepth=%d\n", (int)markers, markDepth);
    233     if ( markers == nil ) {
    234         markers = [ANTLRPtrBuffer newANTLRPtrBufferWithLen:100];
    235 		[markers addObject:[NSNull null]]; // ANTLR generates code that assumes markers to be 1-based,
    236         markDepth = markers.ptr;
    237     }
    238     markDepth++;
    239 	ANTLRCharStreamState *State = nil;
    240 	if ( (markDepth) >= [markers count] ) {
    241         if ( markDepth > 1 ) {
    242             State = [ANTLRCharStreamState newANTLRCharStreamState];
    243             [State retain];
    244         }
    245         if ( markDepth == 1 )
    246             State = charState;
    247 		[markers insertObject:State atIndex:markDepth];
    248         if (debug > 1) NSLog(@"mark save State %x at %d, index=%d, line=%d, charPositionInLine=%d\n", (NSUInteger)State, markDepth, State.index, State.line, State.charPositionInLine);
    249 	}
    250 	else {
    251         if (debug > 1) NSLog(@"mark retrieve markers=%x markDepth=%d\n", (NSUInteger)markers, markDepth);
    252         State = [markers objectAtIndex:markDepth];
    253         [State retain];
    254         State = (ANTLRCharStreamState *)[markers objectAtIndex:markDepth];
    255         if (debug > 1) NSLog(@"mark retrieve charState %x from %d, index=%d, line=%d, charPositionInLine=%d\n", (NSUInteger)State, markDepth, State.index, State.line, State.charPositionInLine);
    256 	}
    257     State.index = index;
    258 	State.line = line;
    259 	State.charPositionInLine = charPositionInLine;
    260 	lastMarker = markDepth;
    261     if (debug > 1) NSLog(@"mark exit -- markers=%x, charState=%x, index=%d, line=%d, charPositionInLine=%d\n", (NSUInteger)markers, (NSUInteger)State, State.index, State.line, State.charPositionInLine);
    262 	return markDepth;
    263 }
    264 
    265 - (void) rewind:(NSInteger) marker 
    266 {
    267     ANTLRCharStreamState *State;
    268     if (debug > 1) NSLog(@"rewind entry -- markers=%x marker=%d\n", (NSUInteger)markers, marker);
    269     if ( marker == 1 )
    270         State = charState;
    271     else
    272         State = (ANTLRCharStreamState *)[markers objectAtIndex:marker];
    273     if (debug > 1) NSLog(@"rewind entry -- marker=%d charState=%x, index=%d, line=%d, charPositionInLine=%d\n", marker, (NSUInteger)charState, charState.index, charState.line, charState.charPositionInLine);
    274 	// restore stream charState
    275 	[self seek:State.index];
    276 	line = State.line;
    277 	charPositionInLine = charState.charPositionInLine;
    278 	[self release:marker];
    279     if (debug > 1) NSLog(@"rewind exit -- marker=%d charState=%x, index=%d, line=%d, charPositionInLine=%d\n", marker, (NSUInteger)charState, charState.index, charState.line, charState.charPositionInLine);
    280 }
    281 
    282 - (void) rewind
    283 {
    284 	[self rewind:lastMarker];
    285 }
    286 
    287 // remove stream states on top of 'marker' from the marker stack
    288 // returns the new markDepth of the stack.
    289 // Note: unfortunate naming for Objective-C, but to keep close to the Java target this is named release:
    290 - (void) release:(NSInteger) marker 
    291 {
    292 	// unwind any other markers made after marker and release marker
    293 	markDepth = marker;
    294 	markDepth--;
    295     if (debug > 1) NSLog(@"release:marker= %d, markDepth = %d\n", marker, markDepth);
    296 }
    297 
    298 // when seeking forward we must handle character position and line numbers.
    299 // seeking backward already has the correct line information on the markers stack, 
    300 // so we just take it from there.
    301 - (void) seek:(NSInteger) anIndex 
    302 {
    303     if (debug > 1) NSLog(@"seek entry -- seekIndex=%d index=%d\n", anIndex, index);
    304 	if ( anIndex <= index ) {
    305 		index = anIndex; // just jump; don't update stream charState (line, ...)
    306         if (debug > 1) NSLog(@"seek exit return -- index=%d index=%d\n", anIndex, index);
    307 		return;
    308 	}
    309 	// seek forward, consume until index hits anIndex
    310 	while ( index < anIndex ) {
    311 		[self consume];
    312 	}
    313     if (debug > 1) NSLog(@"seek exit end -- index=%d index=%d\n", anIndex, index);
    314 }
    315 
    316 // get a substring from our raw data.
    317 - (NSString *) substring:(NSInteger)startIndex To:(NSInteger)stopIndex 
    318 {
    319     NSRange theRange = NSMakeRange(startIndex, stopIndex-startIndex);
    320 	return [data substringWithRange:theRange];
    321 }
    322 
    323 // get a substring from our raw data.
    324 - (NSString *) substringWithRange:(NSRange) theRange 
    325 {
    326 	return [data substringWithRange:theRange];
    327 }
    328 
    329 
    330 - (ANTLRPtrBuffer *)getMarkers
    331 {
    332     return markers;
    333 }
    334 
    335 - (void) setMarkers:(ANTLRPtrBuffer *)aMarkerList
    336 {
    337     markers = aMarkerList;
    338 }
    339 
    340 - (NSString *)getSourceName
    341 {
    342     return name;
    343 }
    344 
    345 - (void) setSourceName:(NSString *)aName
    346 {
    347     if ( name != aName ) {
    348         if ( name ) [name release];
    349         if ( aName ) [aName retain];
    350         name = aName;
    351     }
    352 }
    353 
    354 
    355 - (ANTLRCharStreamState *)getCharState
    356 {
    357     return charState;
    358 }
    359 
    360 - (void) setCharState:(ANTLRCharStreamState *)aCharState
    361 {
    362     charState = aCharState;
    363 }
    364 
    365 - (NSString *)toString
    366 {
    367     return [NSString stringWithString:data];
    368 }
    369 
    370 //---------------------------------------------------------- 
    371 //  data 
    372 //---------------------------------------------------------- 
    373 - (NSString *) getData
    374 {
    375     return data; 
    376 }
    377 
    378 - (void) setData: (NSString *) aData
    379 {
    380     if (data != aData) {
    381         if ( data ) [data release];
    382         data = [NSString stringWithString:aData];
    383         [data retain];
    384     }
    385 }
    386 
    387 @end
    388