1*16467b97STreehugger Robot// 2*16467b97STreehugger Robot// TreeWizard.m 3*16467b97STreehugger Robot// ANTLR 4*16467b97STreehugger Robot// 5*16467b97STreehugger Robot// Created by Alan Condit on 6/18/10. 6*16467b97STreehugger Robot// [The "BSD licence"] 7*16467b97STreehugger Robot// Copyright (c) 2010 Alan Condit 8*16467b97STreehugger Robot// All rights reserved. 9*16467b97STreehugger Robot// 10*16467b97STreehugger Robot// Redistribution and use in source and binary forms, with or without 11*16467b97STreehugger Robot// modification, are permitted provided that the following conditions 12*16467b97STreehugger Robot// are met: 13*16467b97STreehugger Robot// 1. Redistributions of source code must retain the above copyright 14*16467b97STreehugger Robot// notice, this list of conditions and the following disclaimer. 15*16467b97STreehugger Robot// 2. Redistributions in binary form must reproduce the above copyright 16*16467b97STreehugger Robot// notice, this list of conditions and the following disclaimer in the 17*16467b97STreehugger Robot// documentation and/or other materials provided with the distribution. 18*16467b97STreehugger Robot// 3. The name of the author may not be used to endorse or promote products 19*16467b97STreehugger Robot// derived from this software without specific prior written permission. 20*16467b97STreehugger Robot// 21*16467b97STreehugger Robot// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22*16467b97STreehugger Robot// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23*16467b97STreehugger Robot// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24*16467b97STreehugger Robot// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25*16467b97STreehugger Robot// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26*16467b97STreehugger Robot// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27*16467b97STreehugger Robot// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28*16467b97STreehugger Robot// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29*16467b97STreehugger Robot// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30*16467b97STreehugger Robot// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31*16467b97STreehugger Robot 32*16467b97STreehugger Robot#import "TreeWizard.h" 33*16467b97STreehugger Robot#import "TreePatternLexer.h" 34*16467b97STreehugger Robot#import "TreePatternParser.h" 35*16467b97STreehugger Robot#import "IntArray.h" 36*16467b97STreehugger Robot 37*16467b97STreehugger Robot@implementation ANTLRVisitor 38*16467b97STreehugger Robot 39*16467b97STreehugger Robot+ (ANTLRVisitor *)newANTLRVisitor:(NSInteger)anAction Actor:(id)anActor Object:(id)anObject1 Object:(id)anObject2 40*16467b97STreehugger Robot{ 41*16467b97STreehugger Robot return [[ANTLRVisitor alloc] initWithAction:anAction Actor:(id)anActor Object:(id)anObject1 Object:(id)anObject2]; 42*16467b97STreehugger Robot} 43*16467b97STreehugger Robot 44*16467b97STreehugger Robot- (id) initWithAction:(NSInteger)anAction Actor:(id)anActor Object:(id)anObject1 Object:(id)anObject2 45*16467b97STreehugger Robot{ 46*16467b97STreehugger Robot if ((self = [super init]) != nil) { 47*16467b97STreehugger Robot action = anAction; 48*16467b97STreehugger Robot actor = anActor; 49*16467b97STreehugger Robot if ( actor ) [actor retain]; 50*16467b97STreehugger Robot object1 = anObject1; 51*16467b97STreehugger Robot if ( object1 ) [object1 retain]; 52*16467b97STreehugger Robot object2 = anObject2; 53*16467b97STreehugger Robot if ( object2 ) [object2 retain]; 54*16467b97STreehugger Robot } 55*16467b97STreehugger Robot return self; 56*16467b97STreehugger Robot} 57*16467b97STreehugger Robot 58*16467b97STreehugger Robot- (void) dealloc 59*16467b97STreehugger Robot{ 60*16467b97STreehugger Robot#ifdef DEBUG_DEALLOC 61*16467b97STreehugger Robot NSLog( @"called dealloc in ANTLRVisitor" ); 62*16467b97STreehugger Robot#endif 63*16467b97STreehugger Robot if ( actor ) [actor release]; 64*16467b97STreehugger Robot if ( object1 ) [object1 release]; 65*16467b97STreehugger Robot if ( object2 ) [object2 release]; 66*16467b97STreehugger Robot [super dealloc]; 67*16467b97STreehugger Robot} 68*16467b97STreehugger Robot 69*16467b97STreehugger Robot- (void) visit:(CommonTree *)t Parent:(CommonTree *)parent ChildIndex:(NSInteger)childIndex Map:(Map *)labels 70*16467b97STreehugger Robot{ 71*16467b97STreehugger Robot switch (action) { 72*16467b97STreehugger Robot case 0: 73*16467b97STreehugger Robot [(Map *)object2 /* labels */ clear]; 74*16467b97STreehugger Robot if ( [(TreeWizard *)actor _parse:t Pattern:object1/* tpattern */ Map:object2 /* labels */] ) { 75*16467b97STreehugger Robot [self visit:t Parent:parent ChildIndex:childIndex Map:object2 /* labels */]; 76*16467b97STreehugger Robot } 77*16467b97STreehugger Robot break; 78*16467b97STreehugger Robot case 1: 79*16467b97STreehugger Robot if ( [(TreeWizard *)actor _parse:t Pattern:object1/* tpattern */ Map:nil] ) { 80*16467b97STreehugger Robot [(AMutableArray *)object2/* subtrees */ addObject:t]; 81*16467b97STreehugger Robot } 82*16467b97STreehugger Robot break; 83*16467b97STreehugger Robot } 84*16467b97STreehugger Robot // [self visit:t]; 85*16467b97STreehugger Robot return; 86*16467b97STreehugger Robot} 87*16467b97STreehugger Robot 88*16467b97STreehugger Robot- (void) visit:(CommonTree *)t 89*16467b97STreehugger Robot{ 90*16467b97STreehugger Robot [object1 addObject:t]; 91*16467b97STreehugger Robot return; 92*16467b97STreehugger Robot} 93*16467b97STreehugger Robot 94*16467b97STreehugger Robot@synthesize action; 95*16467b97STreehugger Robot@synthesize actor; 96*16467b97STreehugger Robot@synthesize object1; 97*16467b97STreehugger Robot@synthesize object2; 98*16467b97STreehugger Robot@end 99*16467b97STreehugger Robot 100*16467b97STreehugger Robot/** When using %label:TOKENNAME in a tree for parse(), we must 101*16467b97STreehugger Robot * track the label. 102*16467b97STreehugger Robot */ 103*16467b97STreehugger Robot@implementation TreePattern 104*16467b97STreehugger Robot 105*16467b97STreehugger Robot@synthesize label; 106*16467b97STreehugger Robot@synthesize hasTextArg; 107*16467b97STreehugger Robot 108*16467b97STreehugger Robot+ (CommonTree *)newTreePattern:(id<Token>)payload 109*16467b97STreehugger Robot{ 110*16467b97STreehugger Robot return (CommonTree *)[[TreePattern alloc] initWithToken:payload]; 111*16467b97STreehugger Robot} 112*16467b97STreehugger Robot 113*16467b97STreehugger Robot- (id) initWithToken:(id<Token>)payload 114*16467b97STreehugger Robot{ 115*16467b97STreehugger Robot self = [super initWithToken:payload]; 116*16467b97STreehugger Robot if ( self != nil ) { 117*16467b97STreehugger Robot } 118*16467b97STreehugger Robot return (CommonTree *)self; 119*16467b97STreehugger Robot} 120*16467b97STreehugger Robot 121*16467b97STreehugger Robot- (void) dealloc 122*16467b97STreehugger Robot{ 123*16467b97STreehugger Robot#ifdef DEBUG_DEALLOC 124*16467b97STreehugger Robot NSLog( @"called dealloc in TreePattern" ); 125*16467b97STreehugger Robot#endif 126*16467b97STreehugger Robot if ( label ) [label release]; 127*16467b97STreehugger Robot [super dealloc]; 128*16467b97STreehugger Robot} 129*16467b97STreehugger Robot 130*16467b97STreehugger Robot- (NSString *)toString 131*16467b97STreehugger Robot{ 132*16467b97STreehugger Robot if ( label != nil ) { 133*16467b97STreehugger Robot return [NSString stringWithFormat:@"\% %@ : %@", label, [super toString]]; 134*16467b97STreehugger Robot } 135*16467b97STreehugger Robot else { 136*16467b97STreehugger Robot return [super toString]; 137*16467b97STreehugger Robot } 138*16467b97STreehugger Robot} 139*16467b97STreehugger Robot 140*16467b97STreehugger Robot@end 141*16467b97STreehugger Robot 142*16467b97STreehugger Robot@implementation ANTLRWildcardTreePattern 143*16467b97STreehugger Robot 144*16467b97STreehugger Robot+ (ANTLRWildcardTreePattern *)newANTLRWildcardTreePattern:(id<Token>)payload 145*16467b97STreehugger Robot{ 146*16467b97STreehugger Robot return(ANTLRWildcardTreePattern *)[[ANTLRWildcardTreePattern alloc] initWithToken:(id<Token>)payload]; 147*16467b97STreehugger Robot} 148*16467b97STreehugger Robot 149*16467b97STreehugger Robot- (id) initWithToken:(id<Token>)payload 150*16467b97STreehugger Robot{ 151*16467b97STreehugger Robot self = [super initWithToken:payload]; 152*16467b97STreehugger Robot if ( self != nil ) { 153*16467b97STreehugger Robot } 154*16467b97STreehugger Robot return self; 155*16467b97STreehugger Robot} 156*16467b97STreehugger Robot 157*16467b97STreehugger Robot@end 158*16467b97STreehugger Robot 159*16467b97STreehugger Robot/** This adaptor creates TreePattern objects for use during scan() */ 160*16467b97STreehugger Robot@implementation TreePatternTreeAdaptor 161*16467b97STreehugger Robot 162*16467b97STreehugger Robot+ (TreePatternTreeAdaptor *)newTreeAdaptor 163*16467b97STreehugger Robot{ 164*16467b97STreehugger Robot return [[TreePatternTreeAdaptor alloc] init]; 165*16467b97STreehugger Robot} 166*16467b97STreehugger Robot 167*16467b97STreehugger Robot- (id) init 168*16467b97STreehugger Robot{ 169*16467b97STreehugger Robot self = [super init]; 170*16467b97STreehugger Robot if ( self != nil ) { 171*16467b97STreehugger Robot } 172*16467b97STreehugger Robot return self; 173*16467b97STreehugger Robot} 174*16467b97STreehugger Robot 175*16467b97STreehugger Robot- (CommonTree *)createTreePattern:(id<Token>)payload 176*16467b97STreehugger Robot{ 177*16467b97STreehugger Robot return (CommonTree *)[super create:payload]; 178*16467b97STreehugger Robot} 179*16467b97STreehugger Robot 180*16467b97STreehugger Robot@end 181*16467b97STreehugger Robot 182*16467b97STreehugger Robot@implementation TreeWizard 183*16467b97STreehugger Robot 184*16467b97STreehugger Robot// TODO: build indexes for the wizard 185*16467b97STreehugger Robot 186*16467b97STreehugger Robot/** During fillBuffer(), we can make a reverse index from a set 187*16467b97STreehugger Robot * of token types of interest to the list of indexes into the 188*16467b97STreehugger Robot * node stream. This lets us convert a node pointer to a 189*16467b97STreehugger Robot * stream index semi-efficiently for a list of interesting 190*16467b97STreehugger Robot * nodes such as function definition nodes (you'll want to seek 191*16467b97STreehugger Robot * to their bodies for an interpreter). Also useful for doing 192*16467b97STreehugger Robot * dynamic searches; i.e., go find me all PLUS nodes. 193*16467b97STreehugger Robot protected Map tokenTypeToStreamIndexesMap; 194*16467b97STreehugger Robot 195*16467b97STreehugger Robot ** If tokenTypesToReverseIndex set to INDEX_ALL then indexing 196*16467b97STreehugger Robot * occurs for all token types. 197*16467b97STreehugger Robot public static final Set INDEX_ALL = new HashSet(); 198*16467b97STreehugger Robot 199*16467b97STreehugger Robot ** A set of token types user would like to index for faster lookup. 200*16467b97STreehugger Robot * If this is INDEX_ALL, then all token types are tracked. If nil, 201*16467b97STreehugger Robot * then none are indexed. 202*16467b97STreehugger Robot protected Set tokenTypesToReverseIndex = nil; 203*16467b97STreehugger Robot */ 204*16467b97STreehugger Robot 205*16467b97STreehugger Robot+ (TreeWizard *) newTreeWizard:(id<TreeAdaptor>)anAdaptor 206*16467b97STreehugger Robot{ 207*16467b97STreehugger Robot return [[TreeWizard alloc] initWithAdaptor:anAdaptor]; 208*16467b97STreehugger Robot} 209*16467b97STreehugger Robot 210*16467b97STreehugger Robot+ (TreeWizard *)newTreeWizard:(id<TreeAdaptor>)anAdaptor Map:(Map *)aTokenNameToTypeMap 211*16467b97STreehugger Robot{ 212*16467b97STreehugger Robot return [[TreeWizard alloc] initWithAdaptor:anAdaptor Map:aTokenNameToTypeMap]; 213*16467b97STreehugger Robot} 214*16467b97STreehugger Robot 215*16467b97STreehugger Robot+ (TreeWizard *)newTreeWizard:(id<TreeAdaptor>)anAdaptor TokenNames:(NSArray *)theTokNams 216*16467b97STreehugger Robot{ 217*16467b97STreehugger Robot return [[TreeWizard alloc] initWithTokenNames:anAdaptor TokenNames:theTokNams]; 218*16467b97STreehugger Robot} 219*16467b97STreehugger Robot 220*16467b97STreehugger Robot+ (TreeWizard *)newTreeWizardWithTokenNames:(NSArray *)theTokNams 221*16467b97STreehugger Robot{ 222*16467b97STreehugger Robot return [[TreeWizard alloc] initWithTokenNames:theTokNams]; 223*16467b97STreehugger Robot} 224*16467b97STreehugger Robot 225*16467b97STreehugger Robot- (id) init 226*16467b97STreehugger Robot{ 227*16467b97STreehugger Robot if ((self = [super init]) != nil) { 228*16467b97STreehugger Robot } 229*16467b97STreehugger Robot return self; 230*16467b97STreehugger Robot} 231*16467b97STreehugger Robot 232*16467b97STreehugger Robot- (id) initWithAdaptor:(id<TreeAdaptor>)anAdaptor 233*16467b97STreehugger Robot{ 234*16467b97STreehugger Robot if ((self = [super init]) != nil) { 235*16467b97STreehugger Robot adaptor = anAdaptor; 236*16467b97STreehugger Robot if ( adaptor ) [adaptor retain]; 237*16467b97STreehugger Robot } 238*16467b97STreehugger Robot return self; 239*16467b97STreehugger Robot} 240*16467b97STreehugger Robot 241*16467b97STreehugger Robot- (id) initWithAdaptor:(id<TreeAdaptor>)anAdaptor Map:(Map *)aTokenNameToTypeMap 242*16467b97STreehugger Robot{ 243*16467b97STreehugger Robot if ((self = [super init]) != nil) { 244*16467b97STreehugger Robot adaptor = anAdaptor; 245*16467b97STreehugger Robot if ( adaptor ) [adaptor retain]; 246*16467b97STreehugger Robot tokenNameToTypeMap = aTokenNameToTypeMap; 247*16467b97STreehugger Robot } 248*16467b97STreehugger Robot return self; 249*16467b97STreehugger Robot} 250*16467b97STreehugger Robot 251*16467b97STreehugger Robot- (id) initWithTokenNames:(NSArray *)theTokNams 252*16467b97STreehugger Robot{ 253*16467b97STreehugger Robot if ((self = [super init]) != nil) { 254*16467b97STreehugger Robot#pragma warning Fix initWithTokenNames. 255*16467b97STreehugger Robot // adaptor = anAdaptor; 256*16467b97STreehugger Robot //tokenNameToTypeMap = aTokenNameToTypeMap; 257*16467b97STreehugger Robot tokenNameToTypeMap = [[self computeTokenTypes:theTokNams] retain]; 258*16467b97STreehugger Robot } 259*16467b97STreehugger Robot return self; 260*16467b97STreehugger Robot} 261*16467b97STreehugger Robot 262*16467b97STreehugger Robot- (id) initWithTokenNames:(id<TreeAdaptor>)anAdaptor TokenNames:(NSArray *)theTokNams 263*16467b97STreehugger Robot{ 264*16467b97STreehugger Robot if ((self = [super init]) != nil) { 265*16467b97STreehugger Robot adaptor = anAdaptor; 266*16467b97STreehugger Robot if ( adaptor ) [adaptor retain]; 267*16467b97STreehugger Robot // tokenNameToTypeMap = aTokenNameToTypeMap; 268*16467b97STreehugger Robot tokenNameToTypeMap = [[self computeTokenTypes:theTokNams] retain]; 269*16467b97STreehugger Robot } 270*16467b97STreehugger Robot return self; 271*16467b97STreehugger Robot} 272*16467b97STreehugger Robot 273*16467b97STreehugger Robot- (void) dealloc 274*16467b97STreehugger Robot{ 275*16467b97STreehugger Robot#ifdef DEBUG_DEALLOC 276*16467b97STreehugger Robot NSLog( @"called dealloc in TreePatternTreeAdaptor" ); 277*16467b97STreehugger Robot#endif 278*16467b97STreehugger Robot if ( adaptor ) [adaptor release]; 279*16467b97STreehugger Robot if ( tokenNameToTypeMap ) [tokenNameToTypeMap release]; 280*16467b97STreehugger Robot [super dealloc]; 281*16467b97STreehugger Robot} 282*16467b97STreehugger Robot 283*16467b97STreehugger Robot/** Compute a Map<String, Integer> that is an inverted index of 284*16467b97STreehugger Robot * tokenNames (which maps int token types to names). 285*16467b97STreehugger Robot */ 286*16467b97STreehugger Robot- (Map *)computeTokenTypes:(NSArray *)theTokNams 287*16467b97STreehugger Robot{ 288*16467b97STreehugger Robot Map *m = [Map newMap]; 289*16467b97STreehugger Robot if ( theTokNams == nil ) { 290*16467b97STreehugger Robot return m; 291*16467b97STreehugger Robot } 292*16467b97STreehugger Robot for (int ttype = TokenTypeMIN; ttype < [theTokNams count]; ttype++) { 293*16467b97STreehugger Robot NSString *name = (NSString *) [theTokNams objectAtIndex:ttype]; 294*16467b97STreehugger Robot [m putName:name TType:ttype]; 295*16467b97STreehugger Robot } 296*16467b97STreehugger Robot return m; 297*16467b97STreehugger Robot} 298*16467b97STreehugger Robot 299*16467b97STreehugger Robot/** Using the map of token names to token types, return the type. */ 300*16467b97STreehugger Robot- (NSInteger)getTokenType:(NSString *)tokenName 301*16467b97STreehugger Robot{ 302*16467b97STreehugger Robot if ( tokenNameToTypeMap == nil ) { 303*16467b97STreehugger Robot return TokenTypeInvalid; 304*16467b97STreehugger Robot } 305*16467b97STreehugger Robot NSInteger aTType = (NSInteger)[tokenNameToTypeMap getTType:tokenName]; 306*16467b97STreehugger Robot if ( aTType != -1 ) { 307*16467b97STreehugger Robot return aTType; 308*16467b97STreehugger Robot } 309*16467b97STreehugger Robot return TokenTypeInvalid; 310*16467b97STreehugger Robot} 311*16467b97STreehugger Robot 312*16467b97STreehugger Robot/** Walk the entire tree and make a node name to nodes mapping. 313*16467b97STreehugger Robot * For now, use recursion but later nonrecursive version may be 314*16467b97STreehugger Robot * more efficient. Returns Map<Integer, List> where the List is 315*16467b97STreehugger Robot * of your AST node type. The Integer is the token type of the node. 316*16467b97STreehugger Robot * 317*16467b97STreehugger Robot * TODO: save this index so that find and visit are faster 318*16467b97STreehugger Robot */ 319*16467b97STreehugger Robot- (Map *)index:(CommonTree *)t 320*16467b97STreehugger Robot{ 321*16467b97STreehugger Robot Map *m = [Map newMap]; 322*16467b97STreehugger Robot [self _index:t Map:m]; 323*16467b97STreehugger Robot return m; 324*16467b97STreehugger Robot} 325*16467b97STreehugger Robot 326*16467b97STreehugger Robot/** Do the work for index */ 327*16467b97STreehugger Robot- (void) _index:(CommonTree *)t Map:(Map *)m 328*16467b97STreehugger Robot{ 329*16467b97STreehugger Robot if ( t==nil ) { 330*16467b97STreehugger Robot return; 331*16467b97STreehugger Robot } 332*16467b97STreehugger Robot#pragma warning Fix _index use of Map. 333*16467b97STreehugger Robot NSInteger ttype = [adaptor getType:t]; 334*16467b97STreehugger Robot Map *elements = (Map *)[m getName:ttype]; 335*16467b97STreehugger Robot if ( elements == nil ) { 336*16467b97STreehugger Robot elements = [Map newMapWithLen:100]; 337*16467b97STreehugger Robot [m putNode:ttype Node:elements]; 338*16467b97STreehugger Robot } 339*16467b97STreehugger Robot [elements addObject:t]; 340*16467b97STreehugger Robot int n = [adaptor getChildCount:t]; 341*16467b97STreehugger Robot for (int i=0; i<n; i++) { 342*16467b97STreehugger Robot CommonTree * child = [adaptor getChild:t At:i]; 343*16467b97STreehugger Robot [self _index:child Map:m]; 344*16467b97STreehugger Robot } 345*16467b97STreehugger Robot} 346*16467b97STreehugger Robot 347*16467b97STreehugger Robot/** Return a List of tree nodes with token type ttype */ 348*16467b97STreehugger Robot- (AMutableArray *)find:(CommonTree *)t Type:(NSInteger)ttype 349*16467b97STreehugger Robot{ 350*16467b97STreehugger Robot#ifdef DONTUSENOMO 351*16467b97STreehugger Robot final List nodes = new ArrayList(); 352*16467b97STreehugger Robot visit(t, ttype, new TreeWizard.Visitor() { 353*16467b97STreehugger Robot public void visit(Object t) { 354*16467b97STreehugger Robot [nodes addObject t]; 355*16467b97STreehugger Robot } 356*16467b97STreehugger Robot } ); 357*16467b97STreehugger Robot#endif 358*16467b97STreehugger Robot AMutableArray *nodes = [AMutableArray arrayWithCapacity:100]; 359*16467b97STreehugger Robot ANTLRVisitor *contextVisitor = [ANTLRVisitor newANTLRVisitor:3 Actor:self Object:(id)nodes Object:nil]; 360*16467b97STreehugger Robot [self visit:t Type:ttype Visitor:contextVisitor]; 361*16467b97STreehugger Robot return nodes; 362*16467b97STreehugger Robot} 363*16467b97STreehugger Robot 364*16467b97STreehugger Robot/** Return a List of subtrees matching pattern. */ 365*16467b97STreehugger Robot- (AMutableArray *)find:(CommonTree *)t Pattern:(NSString *)pattern 366*16467b97STreehugger Robot{ 367*16467b97STreehugger Robot AMutableArray *subtrees = [AMutableArray arrayWithCapacity:100]; 368*16467b97STreehugger Robot // Create a TreePattern from the pattern 369*16467b97STreehugger Robot TreePatternLexer *tokenizer = [TreePatternLexer newTreePatternLexer:pattern]; 370*16467b97STreehugger Robot TreePatternParser *parser = [TreePatternParser newTreePatternParser:tokenizer 371*16467b97STreehugger Robot Wizard:self 372*16467b97STreehugger Robot Adaptor:[TreePatternTreeAdaptor newTreeAdaptor]]; 373*16467b97STreehugger Robot CommonTree *tpattern = (CommonTree *)[parser pattern]; 374*16467b97STreehugger Robot // don't allow invalid patterns 375*16467b97STreehugger Robot if ( tpattern == nil || 376*16467b97STreehugger Robot [tpattern isNil] || 377*16467b97STreehugger Robot [tpattern class] == [ANTLRWildcardTreePattern class] ) 378*16467b97STreehugger Robot { 379*16467b97STreehugger Robot return nil; 380*16467b97STreehugger Robot } 381*16467b97STreehugger Robot int rootTokenType = [tpattern type]; 382*16467b97STreehugger Robot#ifdef DONTUSENOMO 383*16467b97STreehugger Robot visit(t, rootTokenType, new TreeWizard.ContextVisitor() { 384*16467b97STreehugger Robot public void visit(Object t, Object parent, int childIndex, Map labels) { 385*16467b97STreehugger Robot if ( _parse(t, tpattern, null) ) { 386*16467b97STreehugger Robot subtrees.add(t); 387*16467b97STreehugger Robot } 388*16467b97STreehugger Robot } 389*16467b97STreehugger Robot } ); 390*16467b97STreehugger Robot#endif 391*16467b97STreehugger Robot ANTLRVisitor *contextVisitor = [ANTLRVisitor newANTLRVisitor:1 Actor:self Object:tpattern Object:subtrees]; 392*16467b97STreehugger Robot [self visit:t Type:rootTokenType Visitor:contextVisitor]; 393*16467b97STreehugger Robot return subtrees; 394*16467b97STreehugger Robot} 395*16467b97STreehugger Robot 396*16467b97STreehugger Robot- (TreeWizard *)findFirst:(CommonTree *) t Type:(NSInteger)ttype 397*16467b97STreehugger Robot{ 398*16467b97STreehugger Robot return nil; 399*16467b97STreehugger Robot} 400*16467b97STreehugger Robot 401*16467b97STreehugger Robot- (TreeWizard *)findFirst:(CommonTree *) t Pattern:(NSString *)pattern 402*16467b97STreehugger Robot{ 403*16467b97STreehugger Robot return nil; 404*16467b97STreehugger Robot} 405*16467b97STreehugger Robot 406*16467b97STreehugger Robot/** Visit every ttype node in t, invoking the visitor. This is a quicker 407*16467b97STreehugger Robot * version of the general visit(t, pattern) method. The labels arg 408*16467b97STreehugger Robot * of the visitor action method is never set (it's nil) since using 409*16467b97STreehugger Robot * a token type rather than a pattern doesn't let us set a label. 410*16467b97STreehugger Robot */ 411*16467b97STreehugger Robot- (void) visit:(CommonTree *)t Type:(NSInteger)ttype Visitor:(ANTLRVisitor *)visitor 412*16467b97STreehugger Robot{ 413*16467b97STreehugger Robot [self _visit:t Parent:nil ChildIndex:0 Type:ttype Visitor:visitor]; 414*16467b97STreehugger Robot} 415*16467b97STreehugger Robot 416*16467b97STreehugger Robot/** Do the recursive work for visit */ 417*16467b97STreehugger Robot- (void) _visit:(CommonTree *)t 418*16467b97STreehugger Robot Parent:(CommonTree *)parent 419*16467b97STreehugger Robot ChildIndex:(NSInteger)childIndex 420*16467b97STreehugger Robot Type:(NSInteger)ttype 421*16467b97STreehugger Robot Visitor:(ANTLRVisitor *)visitor 422*16467b97STreehugger Robot{ 423*16467b97STreehugger Robot if ( t == nil ) { 424*16467b97STreehugger Robot return; 425*16467b97STreehugger Robot } 426*16467b97STreehugger Robot if ( [adaptor getType:t] == ttype ) { 427*16467b97STreehugger Robot [visitor visit:t Parent:parent ChildIndex:childIndex Map:nil]; 428*16467b97STreehugger Robot } 429*16467b97STreehugger Robot int n = [adaptor getChildCount:t]; 430*16467b97STreehugger Robot for (int i=0; i<n; i++) { 431*16467b97STreehugger Robot CommonTree * child = [adaptor getChild:t At:i]; 432*16467b97STreehugger Robot [self _visit:child Parent:t ChildIndex:i Type:ttype Visitor:visitor]; 433*16467b97STreehugger Robot } 434*16467b97STreehugger Robot} 435*16467b97STreehugger Robot 436*16467b97STreehugger Robot/** For all subtrees that match the pattern, execute the visit action. 437*16467b97STreehugger Robot * The implementation uses the root node of the pattern in combination 438*16467b97STreehugger Robot * with visit(t, ttype, visitor) so nil-rooted patterns are not allowed. 439*16467b97STreehugger Robot * Patterns with wildcard roots are also not allowed. 440*16467b97STreehugger Robot */ 441*16467b97STreehugger Robot- (void)visit:(CommonTree *)t Pattern:(NSString *)pattern Visitor:(ANTLRVisitor *)visitor 442*16467b97STreehugger Robot{ 443*16467b97STreehugger Robot // Create a TreePattern from the pattern 444*16467b97STreehugger Robot TreePatternLexer *tokenizer = [TreePatternLexer newTreePatternLexer:pattern]; 445*16467b97STreehugger Robot TreePatternParser *parser = 446*16467b97STreehugger Robot [TreePatternParser newTreePatternParser:tokenizer Wizard:self Adaptor:[TreePatternTreeAdaptor newTreeAdaptor]]; 447*16467b97STreehugger Robot CommonTree *tpattern = [parser pattern]; 448*16467b97STreehugger Robot // don't allow invalid patterns 449*16467b97STreehugger Robot if ( tpattern == nil || 450*16467b97STreehugger Robot [tpattern isNil] || 451*16467b97STreehugger Robot [tpattern class] == [ANTLRWildcardTreePattern class] ) 452*16467b97STreehugger Robot { 453*16467b97STreehugger Robot return; 454*16467b97STreehugger Robot } 455*16467b97STreehugger Robot MapElement *labels = [Map newMap]; // reused for each _parse 456*16467b97STreehugger Robot int rootTokenType = [tpattern type]; 457*16467b97STreehugger Robot#pragma warning This is another one of those screwy nested constructs that I have to figure out 458*16467b97STreehugger Robot#ifdef DONTUSENOMO 459*16467b97STreehugger Robot visit(t, rootTokenType, new TreeWizard.ContextVisitor() { 460*16467b97STreehugger Robot public void visit(Object t, Object parent, int childIndex, Map unusedlabels) { 461*16467b97STreehugger Robot // the unusedlabels arg is null as visit on token type doesn't set. 462*16467b97STreehugger Robot labels.clear(); 463*16467b97STreehugger Robot if ( _parse(t, tpattern, labels) ) { 464*16467b97STreehugger Robot visitor.visit(t, parent, childIndex, labels); 465*16467b97STreehugger Robot } 466*16467b97STreehugger Robot } 467*16467b97STreehugger Robot }); 468*16467b97STreehugger Robot#endif 469*16467b97STreehugger Robot ANTLRVisitor *contextVisitor = [ANTLRVisitor newANTLRVisitor:0 Actor:self Object:tpattern Object:labels]; 470*16467b97STreehugger Robot [self visit:t Type:rootTokenType Visitor:contextVisitor]; 471*16467b97STreehugger Robot} 472*16467b97STreehugger Robot 473*16467b97STreehugger Robot/** Given a pattern like (ASSIGN %lhs:ID %rhs:.) with optional labels 474*16467b97STreehugger Robot * on the various nodes and '.' (dot) as the node/subtree wildcard, 475*16467b97STreehugger Robot * return true if the pattern matches and fill the labels Map with 476*16467b97STreehugger Robot * the labels pointing at the appropriate nodes. Return false if 477*16467b97STreehugger Robot * the pattern is malformed or the tree does not match. 478*16467b97STreehugger Robot * 479*16467b97STreehugger Robot * If a node specifies a text arg in pattern, then that must match 480*16467b97STreehugger Robot * for that node in t. 481*16467b97STreehugger Robot * 482*16467b97STreehugger Robot * TODO: what's a better way to indicate bad pattern? Exceptions are a hassle 483*16467b97STreehugger Robot */ 484*16467b97STreehugger Robot- (BOOL)parse:(CommonTree *)t Pattern:(NSString *)pattern Map:(Map *)labels 485*16467b97STreehugger Robot{ 486*16467b97STreehugger Robot#ifdef DONTUSENOMO 487*16467b97STreehugger Robot TreePatternLexer tokenizer = new TreePatternLexer(pattern); 488*16467b97STreehugger Robot TreePatternParser parser = 489*16467b97STreehugger Robot new TreePatternParser(tokenizer, this, new TreePatternTreeAdaptor()); 490*16467b97STreehugger Robot TreePattern tpattern = (TreePattern)parser.pattern(); 491*16467b97STreehugger Robot /* 492*16467b97STreehugger Robot System.out.println("t="+((Tree)t).toStringTree()); 493*16467b97STreehugger Robot System.out.println("scant="+tpattern.toStringTree()); 494*16467b97STreehugger Robot */ 495*16467b97STreehugger Robot boolean matched = _parse(t, tpattern, labels); 496*16467b97STreehugger Robot return matched; 497*16467b97STreehugger Robot#endif 498*16467b97STreehugger Robot TreePatternLexer *tokenizer = [TreePatternLexer newTreePatternLexer:pattern]; 499*16467b97STreehugger Robot TreePatternParser *parser = [TreePatternParser newTreePatternParser:tokenizer 500*16467b97STreehugger Robot Wizard:self 501*16467b97STreehugger Robot Adaptor:[TreePatternTreeAdaptor newTreeAdaptor]]; 502*16467b97STreehugger Robot CommonTree *tpattern = [parser pattern]; 503*16467b97STreehugger Robot /* 504*16467b97STreehugger Robot System.out.println("t="+((Tree)t).toStringTree()); 505*16467b97STreehugger Robot System.out.println("scant="+tpattern.toStringTree()); 506*16467b97STreehugger Robot */ 507*16467b97STreehugger Robot //BOOL matched = [self _parse:t Pattern:tpattern Map:labels]; 508*16467b97STreehugger Robot //return matched; 509*16467b97STreehugger Robot return [self _parse:t Pattern:tpattern Map:labels]; 510*16467b97STreehugger Robot} 511*16467b97STreehugger Robot 512*16467b97STreehugger Robot- (BOOL) parse:(CommonTree *)t Pattern:(NSString *)pattern 513*16467b97STreehugger Robot{ 514*16467b97STreehugger Robot return [self parse:t Pattern:pattern Map:nil]; 515*16467b97STreehugger Robot} 516*16467b97STreehugger Robot 517*16467b97STreehugger Robot/** Do the work for parse. Check to see if the t2 pattern fits the 518*16467b97STreehugger Robot * structure and token types in t1. Check text if the pattern has 519*16467b97STreehugger Robot * text arguments on nodes. Fill labels map with pointers to nodes 520*16467b97STreehugger Robot * in tree matched against nodes in pattern with labels. 521*16467b97STreehugger Robot */ 522*16467b97STreehugger Robot- (BOOL) _parse:(CommonTree *)t1 Pattern:(CommonTree *)aTPattern Map:(Map *)labels 523*16467b97STreehugger Robot{ 524*16467b97STreehugger Robot TreePattern *tpattern; 525*16467b97STreehugger Robot // make sure both are non-nil 526*16467b97STreehugger Robot if ( t1 == nil || aTPattern == nil ) { 527*16467b97STreehugger Robot return NO; 528*16467b97STreehugger Robot } 529*16467b97STreehugger Robot if ( [aTPattern isKindOfClass:[ANTLRWildcardTreePattern class]] ) { 530*16467b97STreehugger Robot tpattern = (TreePattern *)aTPattern; 531*16467b97STreehugger Robot } 532*16467b97STreehugger Robot // check roots (wildcard matches anything) 533*16467b97STreehugger Robot if ( [tpattern class] != [ANTLRWildcardTreePattern class] ) { 534*16467b97STreehugger Robot if ( [adaptor getType:t1] != [tpattern type] ) 535*16467b97STreehugger Robot return NO; 536*16467b97STreehugger Robot // if pattern has text, check node text 537*16467b97STreehugger Robot if ( tpattern.hasTextArg && ![[adaptor getText:t1] isEqualToString:[tpattern text]] ) { 538*16467b97STreehugger Robot return NO; 539*16467b97STreehugger Robot } 540*16467b97STreehugger Robot } 541*16467b97STreehugger Robot if ( tpattern.label != nil && labels!=nil ) { 542*16467b97STreehugger Robot // map label in pattern to node in t1 543*16467b97STreehugger Robot [labels putName:tpattern.label Node:t1]; 544*16467b97STreehugger Robot } 545*16467b97STreehugger Robot // check children 546*16467b97STreehugger Robot int n1 = [adaptor getChildCount:t1]; 547*16467b97STreehugger Robot int n2 = [tpattern getChildCount]; 548*16467b97STreehugger Robot if ( n1 != n2 ) { 549*16467b97STreehugger Robot return NO; 550*16467b97STreehugger Robot } 551*16467b97STreehugger Robot for (int i=0; i<n1; i++) { 552*16467b97STreehugger Robot CommonTree * child1 = [adaptor getChild:t1 At:i]; 553*16467b97STreehugger Robot CommonTree *child2 = (CommonTree *)[tpattern getChild:i]; 554*16467b97STreehugger Robot if ( ![self _parse:child1 Pattern:child2 Map:labels] ) { 555*16467b97STreehugger Robot return NO; 556*16467b97STreehugger Robot } 557*16467b97STreehugger Robot } 558*16467b97STreehugger Robot return YES; 559*16467b97STreehugger Robot} 560*16467b97STreehugger Robot 561*16467b97STreehugger Robot/** Create a tree or node from the indicated tree pattern that closely 562*16467b97STreehugger Robot * follows ANTLR tree grammar tree element syntax: 563*16467b97STreehugger Robot * 564*16467b97STreehugger Robot * (root child1 ... child2). 565*16467b97STreehugger Robot * 566*16467b97STreehugger Robot * You can also just pass in a node: ID 567*16467b97STreehugger Robot * 568*16467b97STreehugger Robot * Any node can have a text argument: ID[foo] 569*16467b97STreehugger Robot * (notice there are no quotes around foo--it's clear it's a string). 570*16467b97STreehugger Robot * 571*16467b97STreehugger Robot * nil is a special name meaning "give me a nil node". Useful for 572*16467b97STreehugger Robot * making lists: (nil A B C) is a list of A B C. 573*16467b97STreehugger Robot */ 574*16467b97STreehugger Robot- (CommonTree *) createTree:(NSString *)pattern 575*16467b97STreehugger Robot{ 576*16467b97STreehugger Robot TreePatternLexer *tokenizer = [TreePatternLexer newTreePatternLexer:pattern]; 577*16467b97STreehugger Robot TreePatternParser *parser = [TreePatternParser newTreePatternParser:tokenizer Wizard:self Adaptor:adaptor]; 578*16467b97STreehugger Robot CommonTree * t = [parser pattern]; 579*16467b97STreehugger Robot return t; 580*16467b97STreehugger Robot} 581*16467b97STreehugger Robot 582*16467b97STreehugger Robot/** Compare t1 and t2; return true if token types/text, structure match exactly. 583*16467b97STreehugger Robot * The trees are examined in their entirety so that (A B) does not match 584*16467b97STreehugger Robot * (A B C) nor (A (B C)). 585*16467b97STreehugger Robot // TODO: allow them to pass in a comparator 586*16467b97STreehugger Robot * TODO: have a version that is nonstatic so it can use instance adaptor 587*16467b97STreehugger Robot * 588*16467b97STreehugger Robot * I cannot rely on the tree node's equals() implementation as I make 589*16467b97STreehugger Robot * no constraints at all on the node types nor interface etc... 590*16467b97STreehugger Robot */ 591*16467b97STreehugger Robot- (BOOL)equals:(id)t1 O2:(id)t2 Adaptor:(id<TreeAdaptor>)anAdaptor 592*16467b97STreehugger Robot{ 593*16467b97STreehugger Robot return [self _equals:t1 O2:t2 Adaptor:anAdaptor]; 594*16467b97STreehugger Robot} 595*16467b97STreehugger Robot 596*16467b97STreehugger Robot/** Compare type, structure, and text of two trees, assuming adaptor in 597*16467b97STreehugger Robot * this instance of a TreeWizard. 598*16467b97STreehugger Robot */ 599*16467b97STreehugger Robot- (BOOL)equals:(id)t1 O2:(id)t2 600*16467b97STreehugger Robot{ 601*16467b97STreehugger Robot return [self _equals:t1 O2:t2 Adaptor:adaptor]; 602*16467b97STreehugger Robot} 603*16467b97STreehugger Robot 604*16467b97STreehugger Robot- (BOOL) _equals:(id)t1 O2:(id)t2 Adaptor:(id<TreeAdaptor>)anAdaptor 605*16467b97STreehugger Robot{ 606*16467b97STreehugger Robot // make sure both are non-nil 607*16467b97STreehugger Robot if ( t1==nil || t2==nil ) { 608*16467b97STreehugger Robot return NO; 609*16467b97STreehugger Robot } 610*16467b97STreehugger Robot // check roots 611*16467b97STreehugger Robot if ( [anAdaptor getType:t1] != [anAdaptor getType:t2] ) { 612*16467b97STreehugger Robot return NO; 613*16467b97STreehugger Robot } 614*16467b97STreehugger Robot if ( ![[anAdaptor getText:t1] isEqualTo:[anAdaptor getText:t2]] ) { 615*16467b97STreehugger Robot return NO; 616*16467b97STreehugger Robot } 617*16467b97STreehugger Robot // check children 618*16467b97STreehugger Robot NSInteger n1 = [anAdaptor getChildCount:t1]; 619*16467b97STreehugger Robot NSInteger n2 = [anAdaptor getChildCount:t2]; 620*16467b97STreehugger Robot if ( n1 != n2 ) { 621*16467b97STreehugger Robot return NO; 622*16467b97STreehugger Robot } 623*16467b97STreehugger Robot for (int i=0; i<n1; i++) { 624*16467b97STreehugger Robot CommonTree * child1 = [anAdaptor getChild:t1 At:i]; 625*16467b97STreehugger Robot CommonTree * child2 = [anAdaptor getChild:t2 At:i]; 626*16467b97STreehugger Robot if ( ![self _equals:child1 O2:child2 Adaptor:anAdaptor] ) { 627*16467b97STreehugger Robot return NO; 628*16467b97STreehugger Robot } 629*16467b97STreehugger Robot } 630*16467b97STreehugger Robot return YES; 631*16467b97STreehugger Robot} 632*16467b97STreehugger Robot 633*16467b97STreehugger Robot// TODO: next stuff taken from CommonTreeNodeStream 634*16467b97STreehugger Robot 635*16467b97STreehugger Robot/** Given a node, add this to the reverse index tokenTypeToStreamIndexesMap. 636*16467b97STreehugger Robot * You can override this method to alter how indexing occurs. The 637*16467b97STreehugger Robot * default is to create a 638*16467b97STreehugger Robot * 639*16467b97STreehugger Robot * Map<Integer token type,ArrayList<Integer stream index>> 640*16467b97STreehugger Robot * 641*16467b97STreehugger Robot * This data structure allows you to find all nodes with type INT in order. 642*16467b97STreehugger Robot * 643*16467b97STreehugger Robot * If you really need to find a node of type, say, FUNC quickly then perhaps 644*16467b97STreehugger Robot * 645*16467b97STreehugger Robot * Map<Integertoken type, Map<Object tree node, Integer stream index>> 646*16467b97STreehugger Robot * 647*16467b97STreehugger Robot * would be better for you. The interior maps map a tree node to 648*16467b97STreehugger Robot * the index so you don't have to search linearly for a specific node. 649*16467b97STreehugger Robot * 650*16467b97STreehugger Robot * If you change this method, you will likely need to change 651*16467b97STreehugger Robot * getNodeIndex(), which extracts information. 652*16467b97STreehugger Robot- (void)fillReverseIndex:(CommonTree *)node Index:(NSInteger)streamIndex 653*16467b97STreehugger Robot{ 654*16467b97STreehugger Robot //System.out.println("revIndex "+node+"@"+streamIndex); 655*16467b97STreehugger Robot if ( tokenTypesToReverseIndex == nil ) { 656*16467b97STreehugger Robot return; // no indexing if this is empty (nothing of interest) 657*16467b97STreehugger Robot } 658*16467b97STreehugger Robot if ( tokenTypeToStreamIndexesMap == nil ) { 659*16467b97STreehugger Robot tokenTypeToStreamIndexesMap = [Map newMap]; // first indexing op 660*16467b97STreehugger Robot } 661*16467b97STreehugger Robot int tokenType = [adaptor getType:node]; 662*16467b97STreehugger Robot Integer tokenTypeI = new Integer(tokenType); 663*16467b97STreehugger Robot if ( !(tokenTypesToReverseIndex == INDEX_ALL || 664*16467b97STreehugger Robot [tokenTypesToReverseIndex contains:tokenTypeI]) ) { 665*16467b97STreehugger Robot return; // tokenType not of interest 666*16467b97STreehugger Robot } 667*16467b97STreehugger Robot NSInteger streamIndexI = streamIndex; 668*16467b97STreehugger Robot AMutableArray *indexes = (AMutableArray *)[tokenTypeToStreamIndexesMap objectAtIndex:tokenTypeI]; 669*16467b97STreehugger Robot if ( indexes==nil ) { 670*16467b97STreehugger Robot indexes = [AMutableArray arrayWithCapacity:100]; // no list yet for this token type 671*16467b97STreehugger Robot indexes.add(streamIndexI); // not there yet, add 672*16467b97STreehugger Robot [tokenTypeToStreamIndexesMap put:tokenTypeI Idexes:indexes]; 673*16467b97STreehugger Robot } 674*16467b97STreehugger Robot else { 675*16467b97STreehugger Robot if ( ![indexes contains:streamIndexI] ) { 676*16467b97STreehugger Robot [indexes add:streamIndexI]; // not there yet, add 677*16467b97STreehugger Robot } 678*16467b97STreehugger Robot } 679*16467b97STreehugger Robot} 680*16467b97STreehugger Robot 681*16467b97STreehugger Robot ** Track the indicated token type in the reverse index. Call this 682*16467b97STreehugger Robot * repeatedly for each type or use variant with Set argument to 683*16467b97STreehugger Robot * set all at once. 684*16467b97STreehugger Robot * @param tokenType 685*16467b97STreehugger Robotpublic void reverseIndex:(NSInteger)tokenType 686*16467b97STreehugger Robot{ 687*16467b97STreehugger Robot if ( tokenTypesToReverseIndex == nil ) { 688*16467b97STreehugger Robot tokenTypesToReverseIndex = [Map newMap]; 689*16467b97STreehugger Robot } 690*16467b97STreehugger Robot else if ( tokenTypesToReverseIndex == INDEX_ALL ) { 691*16467b97STreehugger Robot return; 692*16467b97STreehugger Robot } 693*16467b97STreehugger Robot tokenTypesToReverseIndex.add(new Integer(tokenType)); 694*16467b97STreehugger Robot} 695*16467b97STreehugger Robot 696*16467b97STreehugger Robot** Track the indicated token types in the reverse index. Set 697*16467b97STreehugger Robot * to INDEX_ALL to track all token types. 698*16467b97STreehugger Robotpublic void reverseIndex(Set tokenTypes) { 699*16467b97STreehugger Robot tokenTypesToReverseIndex = tokenTypes; 700*16467b97STreehugger Robot} 701*16467b97STreehugger Robot 702*16467b97STreehugger Robot ** Given a node pointer, return its index into the node stream. 703*16467b97STreehugger Robot * This is not its Token stream index. If there is no reverse map 704*16467b97STreehugger Robot * from node to stream index or the map does not contain entries 705*16467b97STreehugger Robot * for node's token type, a linear search of entire stream is used. 706*16467b97STreehugger Robot * 707*16467b97STreehugger Robot * Return -1 if exact node pointer not in stream. 708*16467b97STreehugger Robotpublic int getNodeIndex(Object node) { 709*16467b97STreehugger Robot //System.out.println("get "+node); 710*16467b97STreehugger Robot if ( tokenTypeToStreamIndexesMap==nil ) { 711*16467b97STreehugger Robot return getNodeIndexLinearly(node); 712*16467b97STreehugger Robot } 713*16467b97STreehugger Robot int tokenType = adaptor.getType(node); 714*16467b97STreehugger Robot Integer tokenTypeI = new Integer(tokenType); 715*16467b97STreehugger Robot ArrayList indexes = (ArrayList)tokenTypeToStreamIndexesMap.get(tokenTypeI); 716*16467b97STreehugger Robot if ( indexes==nil ) { 717*16467b97STreehugger Robot //System.out.println("found linearly; stream index = "+getNodeIndexLinearly(node)); 718*16467b97STreehugger Robot return getNodeIndexLinearly(node); 719*16467b97STreehugger Robot } 720*16467b97STreehugger Robot for (int i = 0; i < indexes.size(); i++) { 721*16467b97STreehugger Robot Integer streamIndexI = (Integer)indexes.get(i); 722*16467b97STreehugger Robot Object n = get(streamIndexI.intValue()); 723*16467b97STreehugger Robot if ( n==node ) { 724*16467b97STreehugger Robot //System.out.println("found in index; stream index = "+streamIndexI); 725*16467b97STreehugger Robot return streamIndexI.intValue(); // found it! 726*16467b97STreehugger Robot } 727*16467b97STreehugger Robot } 728*16467b97STreehugger Robot return -1; 729*16467b97STreehugger Robot} 730*16467b97STreehugger Robot 731*16467b97STreehugger Robot*/ 732*16467b97STreehugger Robot 733*16467b97STreehugger Robot@synthesize adaptor; 734*16467b97STreehugger Robot@synthesize tokenNameToTypeMap; 735*16467b97STreehugger Robot@end 736