Home | History | Annotate | Download | only in Framework
      1 //
      2 //  ANTLRTreeIterator.m
      3 //  ANTLR
      4 //
      5 //  Created by Ian Michell on 26/04/2010.
      6 // Copyright (c) 2010 Ian Michell 2010 Alan Condit
      7 // All rights reserved.
      8 //
      9 // Redistribution and use in source and binary forms, with or without
     10 // modification, are permitted provided that the following conditions
     11 // are met:
     12 // 1. Redistributions of source code must retain the above copyright
     13 //    notice, this list of conditions and the following disclaimer.
     14 // 2. Redistributions in binary form must reproduce the above copyright
     15 //    notice, this list of conditions and the following disclaimer in the
     16 //    documentation and/or other materials provided with the distribution.
     17 // 3. The name of the author may not be used to endorse or promote products
     18 //    derived from this software without specific prior written permission.
     19 //
     20 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 
     32 #import "ANTLRTreeIterator.h"
     33 #import "ANTLRCommonTreeAdaptor.h"
     34 
     35 @implementation ANTLRTreeIterator
     36 
     37 + (ANTLRTreeIterator *) newANTRLTreeIterator
     38 {
     39     return [[ANTLRTreeIterator alloc] init];
     40 }
     41 
     42 + (ANTLRTreeIterator *) newANTRLTreeIteratorWithAdaptor:(ANTLRCommonTreeAdaptor *)adaptor
     43                                                 andTree:(id<ANTLRBaseTree>)tree
     44 {
     45     return [[ANTLRTreeIterator alloc] initWithTreeAdaptor:adaptor andTree:tree];
     46 }
     47 
     48 - (id) init
     49 {
     50     self = [super init];
     51     if ( self != nil ) {
     52         firstTime = YES;
     53         nodes = [[ANTLRFastQueue newANTLRFastQueue] retain];
     54         down = [[adaptor createTree:ANTLRTokenTypeDOWN Text:@"DOWN"] retain];
     55         up = [[adaptor createTree:ANTLRTokenTypeUP Text:@"UP"] retain];
     56         eof = [[adaptor createTree:ANTLRTokenTypeEOF Text:@"EOF"] retain];
     57         tree = eof;
     58         root = eof;
     59     }
     60     return self;
     61 }
     62 
     63 -(id) initWithTree:(id<ANTLRBaseTree>) t
     64 {
     65     self = [super init];
     66     if ( self != nil ) {
     67         firstTime = YES;
     68         adaptor = [[ANTLRCommonTreeAdaptor newTreeAdaptor] retain];
     69         tree = [t retain];
     70         root = t;
     71         nodes = [[ANTLRFastQueue newANTLRFastQueue] retain];
     72         down = [[adaptor createTree:ANTLRTokenTypeDOWN Text:@"DOWN"] retain];
     73         up = [[adaptor createTree:ANTLRTokenTypeUP Text:@"UP"] retain];
     74         eof = [[adaptor createTree:ANTLRTokenTypeEOF Text:@"EOF"] retain];
     75     }
     76     return self;
     77 }
     78 
     79 -(id) initWithTreeAdaptor:(id<ANTLRTreeAdaptor>)a andTree:(id<ANTLRBaseTree>)t
     80 {
     81     self = [super init];
     82     if ( self != nil ) {
     83         firstTime = YES;
     84         adaptor = [a retain];
     85         tree = [t retain];
     86         root = t;
     87         nodes = [[ANTLRFastQueue newANTLRFastQueue] retain];
     88         down = [[adaptor createTree:ANTLRTokenTypeDOWN Text:@"DOWN"] retain];
     89         up = [[adaptor createTree:ANTLRTokenTypeUP Text:@"UP"] retain];
     90         eof = [[adaptor createTree:ANTLRTokenTypeEOF Text:@"EOF"] retain];
     91     }
     92     return self;
     93 }
     94 
     95 - (void)dealloc
     96 {
     97 #ifdef DEBUG_DEALLOC
     98     NSLog( @"called dealloc in ANTLRTreeIterator" );
     99 #endif
    100     if ( adaptor ) [adaptor release];
    101     if ( nodes ) [nodes release];
    102     if ( tree && tree != eof ) [tree release];
    103     if ( root && root != eof && root != tree ) [root release];
    104     if ( down ) [down release];    
    105     if ( up ) [up release];    
    106     if ( eof ) [eof release];    
    107     [super dealloc];
    108 }
    109 
    110 - (void)reset
    111 {
    112     firstTime = YES;
    113     tree = root;
    114     [nodes clear];
    115 }
    116 
    117 -(BOOL) hasNext
    118 {
    119     if ( firstTime ) {
    120         return root != nil;
    121     }
    122     if ( nodes && [nodes size] > 0) {
    123         return YES;
    124     }
    125     if ( tree == nil ) {
    126         return NO;
    127     }
    128     if ( [adaptor getChildCount:tree] > 0 ) {
    129         return YES;
    130     }
    131     return [adaptor getParent:tree] != nil;
    132 }
    133 
    134 -(id) nextObject
    135 {
    136     // is this the first time we are using this method?
    137     if ( firstTime ) {
    138         firstTime = NO;
    139         if ( [adaptor getChildCount:tree] == 0 ) {
    140             [nodes addObject:eof];
    141             return tree;
    142         }
    143         return tree;
    144     }
    145     // do we have any objects queued up?
    146     if ( nodes && [nodes size] > 0 ) {
    147         return [nodes remove];
    148     }
    149     // no nodes left?
    150     if ( tree == nil ) {
    151         return eof;
    152     }
    153     if ( [adaptor getChildCount:tree] > 0 ) {
    154         tree = [adaptor getChild:tree At:0];
    155         [nodes addObject:tree]; // real node is next after down
    156         return self.down;
    157     }
    158     // if no children, look for next sibling of ancestor
    159     id<ANTLRBaseTree> parent = [adaptor getParent:tree];
    160     while (parent != nil && ([adaptor getChildIndex:tree] + 1) >= [adaptor getChildCount:parent]) {
    161         [nodes addObject:up];
    162         tree = parent;
    163         parent = [adaptor getParent:tree];
    164     }
    165     if ( parent == nil ) {
    166         tree = nil;
    167         [nodes addObject:self.eof];
    168         return [nodes remove];
    169     }
    170     // must have found a node with an unvisited sibling
    171     // move to it and return it
    172     NSInteger nextSiblingIndex = [adaptor getChildIndex:tree] + 1;
    173     tree = [adaptor getChild:parent At:nextSiblingIndex];
    174     [nodes addObject:tree];
    175     return [nodes remove];
    176 }
    177 
    178 -(NSArray *) allObjects
    179 {
    180     AMutableArray *array = [AMutableArray arrayWithCapacity:10];
    181     while ( [self hasNext] ) {
    182         [array addObject:[self nextObject]];
    183     }
    184     return array;
    185 }
    186 
    187 - (void)remove
    188 {
    189     @throw [ANTLRRuntimeException newException:@"ANTLRUnsupportedOperationException"];
    190 }
    191 
    192 @synthesize firstTime;
    193 @synthesize adaptor;
    194 @synthesize root;
    195 @synthesize tree;
    196 @synthesize nodes;
    197 
    198 @synthesize up;
    199 @synthesize down;
    200 @synthesize eof;
    201 
    202 @end
    203