Home | History | Annotate | Download | only in Framework
      1 // [The "BSD licence"]
      2 // Copyright (c) 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 #import "ANTLRBaseTreeAdaptor.h"
     28 #import "ANTLRRuntimeException.h"
     29 #import "ANTLRUniqueIDMap.h"
     30 #import "ANTLRMapElement.h"
     31 #import "ANTLRCommonTree.h"
     32 
     33 @implementation ANTLRBaseTreeAdaptor
     34 
     35 @synthesize treeToUniqueIDMap;
     36 @synthesize uniqueNodeID;
     37 
     38 + (id<ANTLRTree>) newEmptyTree
     39 {
     40     return [[ANTLRCommonTree alloc] init];
     41 }
     42 
     43 - (id) init
     44 {
     45     self = [super init];
     46     if ( self != nil ) {
     47     }
     48     return self;
     49 }
     50 
     51 - (id) copyWithZone:(NSZone *)aZone
     52 {
     53     ANTLRBaseTreeAdaptor *copy;
     54     
     55     copy = [[[self class] alloc] init];
     56     if (treeToUniqueIDMap)
     57         copy.treeToUniqueIDMap = [treeToUniqueIDMap copyWithZone:aZone];
     58     copy.uniqueNodeID = uniqueNodeID;
     59     return copy;
     60 }
     61     
     62 
     63 - (id) createNil
     64 {
     65     return [ANTLRCommonTree newTreeWithToken:nil];
     66 }
     67 
     68 - (id) emptyNode
     69 {
     70     return [ANTLRCommonTree newTreeWithToken:nil];
     71 }
     72 
     73 /** create tree node that holds the start and stop tokens associated
     74  *  with an error.
     75  *
     76  *  If you specify your own kind of tree nodes, you will likely have to
     77  *  override this method. CommonTree returns Token.INVALID_TOKEN_TYPE
     78  *  if no token payload but you might have to set token type for diff
     79  *  node type.
     80  *
     81  *  You don't have to subclass CommonErrorNode; you will likely need to
     82  *  subclass your own tree node class to avoid class cast exception.
     83  */
     84 - (id) errorNode:(id<ANTLRTokenStream>)anInput
     85             From:(id<ANTLRToken>)startToken
     86               To:(id<ANTLRToken>)stopToken
     87        Exception:(ANTLRRecognitionException *) e;
     88 {
     89     //System.out.println("returning error node '"+t+"' @index="+anInput.index());
     90     return [ANTLRCommonErrorNode newANTLRCommonErrorNode:anInput
     91                                                     From:startToken
     92                                                       To:stopToken
     93                                                Exception:e];
     94 }
     95 
     96 - (BOOL) isNil:(id) tree
     97 {
     98     return [(id)tree isNil];
     99 }
    100 
    101 - (id)dupTree:(id)tree
    102 {
    103     return [self dupTree:(id)tree Parent:nil];
    104 }
    105 
    106 /** This is generic in the sense that it will work with any kind of
    107  *  tree (not just Tree interface).  It invokes the adaptor routines
    108  *  not the tree node routines to do the construction.  
    109  */
    110 - (id)dupTree:(id)t Parent:(id)parent
    111 {
    112     if ( t==nil ) {
    113         return nil;
    114     }
    115     id newTree = [self dupNode:t];
    116     // ensure new subtree root has parent/child index set
    117     [self setChildIndex:newTree With:[self getChildIndex:t]]; // same index in new tree
    118     [self setParent:newTree With:parent];
    119     NSInteger n = [self getChildCount:t];
    120     for (NSInteger i = 0; i < n; i++) {
    121         id child = [self getChild:t At:i];
    122         id newSubTree = [self dupTree:child Parent:t];
    123         [self addChild:newSubTree toTree:newTree];
    124     }
    125     return newTree;
    126 }
    127 
    128 - (id)dupNode:(id)aNode
    129 {
    130     return aNode; // override for better results :>)
    131 }
    132 /** Add a child to the tree t.  If child is a flat tree (a list), make all
    133  *  in list children of t.  Warning: if t has no children, but child does
    134  *  and child isNil then you can decide it is ok to move children to t via
    135  *  t.children = child.children; i.e., without copying the array.  Just
    136  *  make sure that this is consistent with have the user will build
    137  *  ASTs.
    138  */
    139 - (void) addChild:(id)child toTree:(id)t
    140 {
    141     if ( t != nil && child != nil ) {
    142         [(id)t addChild:child];
    143     }
    144 }
    145 
    146 /** If oldRoot is a nil root, just copy or move the children to newRoot.
    147  *  If not a nil root, make oldRoot a child of newRoot.
    148  *
    149  *    old=^(nil a b c), new=r yields ^(r a b c)
    150  *    old=^(a b c), new=r yields ^(r ^(a b c))
    151  *
    152  *  If newRoot is a nil-rooted single child tree, use the single
    153  *  child as the new root node.
    154  *
    155  *    old=^(nil a b c), new=^(nil r) yields ^(r a b c)
    156  *    old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
    157  *
    158  *  If oldRoot was null, it's ok, just return newRoot (even if isNil).
    159  *
    160  *    old=null, new=r yields r
    161  *    old=null, new=^(nil r) yields ^(nil r)
    162  *
    163  *  Return newRoot.  Throw an exception if newRoot is not a
    164  *  simple node or nil root with a single child node--it must be a root
    165  *  node.  If newRoot is ^(nil x) return x as newRoot.
    166  *
    167  *  Be advised that it's ok for newRoot to point at oldRoot's
    168  *  children; i.e., you don't have to copy the list.  We are
    169  *  constructing these nodes so we should have this control for
    170  *  efficiency.
    171  */
    172 - (id)becomeRoot:(id)newRoot old:(id)oldRoot
    173 {
    174     if ( oldRoot == nil ) {
    175         return newRoot;
    176     }
    177     //System.out.println("becomeroot new "+newRoot.toString()+" old "+oldRoot);
    178     id newRootTree = (id)newRoot;
    179     id oldRootTree = (id)oldRoot;
    180     // handle ^(nil real-node)
    181     if ( [newRootTree isNil] ) {
    182         NSInteger nc = [newRootTree getChildCount];
    183         if ( nc == 1 ) newRootTree = [(id)newRootTree getChild:0];
    184         else if ( nc > 1 ) {
    185             // TODO: make tree run time exceptions hierarchy
    186             @throw [ANTLRRuntimeException newException:NSStringFromClass([self class]) reason:@"more than one node as root (TODO: make exception hierarchy)"];
    187         }
    188     }
    189     // add oldRoot to newRoot; addChild takes care of case where oldRoot
    190     // is a flat list (i.e., nil-rooted tree).  All children of oldRoot
    191     // are added to newRoot.
    192     [newRootTree addChild:oldRootTree];
    193     return newRootTree;
    194 }
    195 
    196 /** Transform ^(nil x) to x and nil to null */
    197 - (id)rulePostProcessing:(id)root
    198 {
    199     //System.out.println("rulePostProcessing: "+((Tree)root).toStringTree());
    200     id r = (id)root;
    201     if ( r != nil && [r isNil] ) {
    202         if ( [r getChildCount] == 0 ) {
    203             r = nil;
    204         }
    205         else if ( [r getChildCount] == 1 ) {
    206             r = (id)[r getChild:0];
    207             // whoever invokes rule will set parent and child index
    208             [r setParent:nil];
    209             [r setChildIndex:-1];
    210         }
    211     }
    212     return r;
    213 }
    214 
    215 - (id)becomeRootfromToken:(id<ANTLRToken>)newRoot old:(id)oldRoot
    216 {
    217     return [self becomeRoot:(id)[self create:newRoot] old:oldRoot];
    218 }
    219 
    220 - (id) create:(id<ANTLRToken>)aToken
    221 {
    222     return [ANTLRCommonTree newTreeWithToken:aToken];
    223 }
    224 
    225 - (id)createTree:(NSInteger)tokenType FromToken:(id<ANTLRToken>)fromToken
    226 {
    227     fromToken = [self createToken:fromToken];
    228     //((ClassicToken)fromToken).setType(tokenType);
    229     [fromToken setType:tokenType];
    230     id t = [self create:fromToken];
    231     return t;
    232 }
    233 
    234 - (id)createTree:(NSInteger)tokenType FromToken:(id<ANTLRToken>)fromToken Text:(NSString *)text
    235 {
    236     if (fromToken == nil)
    237         return [self createTree:tokenType Text:text];
    238     fromToken = [self createToken:fromToken];
    239     [fromToken setType:tokenType];
    240     [fromToken setText:text];
    241     id t = [self create:fromToken];
    242     return t;
    243 }
    244 
    245 - (id)createTree:(NSInteger)tokenType Text:(NSString *)text
    246 {
    247     id<ANTLRToken> fromToken = [self createToken:tokenType Text:text];
    248     id t = (id)[self create:fromToken];
    249     return t;
    250 }
    251 
    252 - (NSInteger) getType:(ANTLRCommonTree *) t
    253 {
    254     return [t type];
    255 }
    256 
    257 - (void) setType:(id)t Type:(NSInteger)type
    258 {
    259     @throw [ANTLRNoSuchElementException newException:@"don't know enough about Tree node"];
    260 }
    261 
    262 /** What is the Token associated with this node?  If
    263  *  you are not using ANTLRCommonTree, then you must
    264  *  override this in your own adaptor.
    265  */
    266 - (id<ANTLRToken>) getToken:(ANTLRCommonTree *) t
    267 {
    268     if ( [t isKindOfClass:[ANTLRCommonTree class]] ) {
    269         return [t getToken];
    270     }
    271     return nil; // no idea what to do
    272 }
    273 
    274 - (NSString *)getText:(ANTLRCommonTree *)t
    275 {
    276     return [t text];
    277 }
    278 
    279 - (void) setText:(id)t Text:(NSString *)text
    280 {
    281     @throw [ANTLRNoSuchElementException newException:@"don't know enough about Tree node"];
    282 }
    283 
    284 - (id) getChild:(id)t At:(NSInteger)index
    285 {
    286     return [(id)t getChild:index ];
    287 }
    288 
    289 - (void) setChild:(id)t At:(NSInteger)index Child:(id)child
    290 {
    291     [(id)t setChild:index With:(id)child];
    292 }
    293 
    294 - (id) deleteChild:(id)t Index:(NSInteger)index
    295 {
    296     return [(id)t deleteChild:index];
    297 }
    298 
    299 - (NSInteger) getChildCount:(id)t
    300 {
    301     return [(id)t getChildCount];
    302 }
    303 
    304 - (id<ANTLRBaseTree>) getParent:(id<ANTLRBaseTree>) t
    305 {
    306     if ( t == nil )
    307         return nil;
    308     return (id<ANTLRBaseTree>)[t getParent];
    309 }
    310 
    311 - (void) setParent:(id<ANTLRBaseTree>)t With:(id<ANTLRBaseTree>) parent
    312 {
    313     if ( t != nil )
    314         [(id<ANTLRBaseTree>) t setParent:(id<ANTLRBaseTree>)parent];
    315 }
    316 
    317 /** What index is this node in the child list? Range: 0..n-1
    318  *  If your node type doesn't handle this, it's ok but the tree rewrites
    319  *  in tree parsers need this functionality.
    320  */
    321 - (NSInteger) getChildIndex:(id)t
    322 {
    323     return ((ANTLRCommonTree *)t).childIndex;
    324 }
    325 
    326 - (void) setChildIndex:(id)t With:(NSInteger)index
    327 {
    328     ((ANTLRCommonTree *)t).childIndex = index;
    329 }
    330 
    331 - (void) replaceChildren:(id)parent From:(NSInteger)startChildIndex To:(NSInteger)stopChildIndex With:(id)t
    332 {
    333     return;
    334 }
    335 
    336 - (NSInteger) getUniqueID:(id)node
    337 {
    338     if ( treeToUniqueIDMap == nil ) {
    339         treeToUniqueIDMap = [ANTLRUniqueIDMap newANTLRUniqueIDMap];
    340     }
    341     NSNumber *prevID = [treeToUniqueIDMap getNode:node];
    342     if ( prevID != nil ) {
    343         return [prevID integerValue];
    344     }
    345     NSInteger anID = uniqueNodeID;
    346     // ANTLRMapElement *aMapNode = [ANTLRMapElement newANTLRMapElementWithObj1:[NSNumber numberWithInteger:anID] Obj2:node];
    347     [treeToUniqueIDMap putID:[NSNumber numberWithInteger:anID] Node:node];
    348     uniqueNodeID++;
    349     return anID;
    350     // GCC makes these nonunique:
    351     // return System.identityHashCode(node);
    352 }
    353 
    354 /** Tell me how to create a token for use with imaginary token nodes.
    355  *  For example, there is probably no input symbol associated with imaginary
    356  *  token DECL, but you need to create it as a payload or whatever for
    357  *  the DECL node as in ^(DECL type ID).
    358  *
    359  *  If you care what the token payload objects' type is, you should
    360  *  override this method and any other createToken variant.
    361  */
    362 - (id<ANTLRToken>) createToken:(NSInteger)aTType Text:(NSString *)text
    363 {
    364     return nil;
    365 }
    366 
    367 /** Tell me how to create a token for use with imaginary token nodes.
    368  *  For example, there is probably no input symbol associated with imaginary
    369  *  token DECL, but you need to create it as a payload or whatever for
    370  *  the DECL node as in ^(DECL type ID).
    371  *
    372  *  This is a variant of createToken where the new token is derived from
    373  *  an actual real input token.  Typically this is for converting '{'
    374  *  tokens to BLOCK etc...  You'll see
    375  *
    376  *    r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;
    377  *
    378  *  If you care what the token payload objects' type is, you should
    379  *  override this method and any other createToken variant.
    380  */
    381 - (id<ANTLRToken>) createToken:(id<ANTLRToken>) fromToken
    382 {
    383     return nil;
    384 }
    385 
    386 /** Track start/stop token for subtree root created for a rule.
    387  *  Only works with Tree nodes.  For rules that match nothing,
    388  *  seems like this will yield start=i and stop=i-1 in a nil node.
    389  *  Might be useful info so I'll not force to be i..i.
    390  */
    391 - (void) setTokenBoundaries:(id)aTree From:(id<ANTLRToken>)startToken To:(id<ANTLRToken>)stopToken
    392 {
    393     return;
    394 }
    395 
    396 - (NSInteger) getTokenStartIndex:(id)aTree
    397 {
    398     return -1;
    399 }
    400 
    401 - (NSInteger) getTokenStopIndex:(id)aTree
    402 {
    403     return -1;
    404 }
    405 
    406 #ifdef DONTUSENOMO
    407 - (NSInteger)getUniqueID
    408 {
    409     return uniqueNodeID;
    410 }
    411 
    412 - (void) setUniqueNodeID:(NSInteger)aUniqueNodeID
    413 {
    414     uniqueNodeID = aUniqueNodeID;
    415 }
    416 
    417 - (ANTLRUniqueIDMap *)getTreeToUniqueIDMap
    418 {
    419     return treeToUniqueIDMap;
    420 }
    421 
    422 - (void) setTreeToUniqueIDMap:(ANTLRUniqueIDMap *)aMapListNode
    423 {
    424     treeToUniqueIDMap = aMapListNode;
    425 }
    426 
    427 #endif
    428 
    429 @end
    430