You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
7.1 KiB
250 lines
7.1 KiB
4 months ago
|
// [The "BSD licence"]
|
||
|
// Copyright (c) 2006-2007 Kay Roepke 2010 Alan Condit
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// Redistribution and use in source and binary forms, with or without
|
||
|
// modification, are permitted provided that the following conditions
|
||
|
// are met:
|
||
|
// 1. Redistributions of source code must retain the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer.
|
||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer in the
|
||
|
// documentation and/or other materials provided with the distribution.
|
||
|
// 3. The name of the author may not be used to endorse or promote products
|
||
|
// derived from this software without specific prior written permission.
|
||
|
//
|
||
|
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||
|
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||
|
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||
|
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||
|
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||
|
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
#import "CommonTreeNodeStream.h"
|
||
|
#import "TokenStream.h"
|
||
|
#import "IntStream.h"
|
||
|
#import "CharStream.h"
|
||
|
#import "AMutableArray.h"
|
||
|
#import "CommonTreeAdaptor.h"
|
||
|
|
||
|
#ifndef DEBUG_DEALLOC
|
||
|
#define DEBUG_DEALLOC
|
||
|
#endif
|
||
|
|
||
|
@implementation CommonTreeNodeStream
|
||
|
|
||
|
@synthesize root;
|
||
|
@synthesize tokens;
|
||
|
@synthesize adaptor;
|
||
|
@synthesize level;
|
||
|
|
||
|
+ (CommonTreeNodeStream *) newCommonTreeNodeStream:(CommonTree *)theTree
|
||
|
{
|
||
|
return [[CommonTreeNodeStream alloc] initWithTree:theTree];
|
||
|
}
|
||
|
|
||
|
+ (CommonTreeNodeStream *) newCommonTreeNodeStream:(id<TreeAdaptor>)anAdaptor Tree:(CommonTree *)theTree
|
||
|
{
|
||
|
return [[CommonTreeNodeStream alloc] initWithTreeAdaptor:anAdaptor Tree:theTree];
|
||
|
}
|
||
|
|
||
|
- (id) initWithTree:(CommonTree *)theTree
|
||
|
{
|
||
|
if ((self = [super init]) != nil ) {
|
||
|
adaptor = [[CommonTreeAdaptor newTreeAdaptor] retain];
|
||
|
root = [theTree retain];
|
||
|
navigationNodeEOF = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain]; // set EOF
|
||
|
it = [[TreeIterator newANTRLTreeIteratorWithAdaptor:adaptor andTree:root] retain];
|
||
|
calls = [[IntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain];
|
||
|
/** Tree (nil A B C) trees like flat A B C streams */
|
||
|
hasNilRoot = NO;
|
||
|
level = 0;
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (id) initWithTreeAdaptor:(id<TreeAdaptor>)anAdaptor Tree:(CommonTree *)theTree
|
||
|
{
|
||
|
if ((self = [super init]) != nil ) {
|
||
|
adaptor = [anAdaptor retain];
|
||
|
root = [theTree retain];
|
||
|
navigationNodeEOF = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain]; // set EOF
|
||
|
// it = [root objectEnumerator];
|
||
|
it = [[TreeIterator newANTRLTreeIteratorWithAdaptor:adaptor andTree:root] retain];
|
||
|
calls = [[IntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain];
|
||
|
/** Tree (nil A B C) trees like flat A B C streams */
|
||
|
hasNilRoot = NO;
|
||
|
level = 0;
|
||
|
}
|
||
|
// eof = [self isEOF]; // make sure tree iterator returns the EOF we want
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (void)dealloc
|
||
|
{
|
||
|
#ifdef DEBUG_DEALLOC
|
||
|
NSLog( @"called dealloc in CommonTreeNodeStream" );
|
||
|
#endif
|
||
|
if ( root ) [root release];
|
||
|
if ( tokens ) [tokens release];
|
||
|
if ( adaptor ) [adaptor release];
|
||
|
if ( it ) [it release];
|
||
|
if ( calls ) [calls release];
|
||
|
[super dealloc];
|
||
|
}
|
||
|
|
||
|
- (void) reset
|
||
|
{
|
||
|
[super reset];
|
||
|
[it reset];
|
||
|
hasNilRoot = false;
|
||
|
level = 0;
|
||
|
if ( calls != nil )
|
||
|
[calls reset]; // [calls clear]; // in Java
|
||
|
}
|
||
|
|
||
|
/** Pull elements from tree iterator. Track tree level 0..max_level.
|
||
|
* If nil rooted tree, don't give initial nil and DOWN nor final UP.
|
||
|
*/
|
||
|
- (id) nextElement
|
||
|
{
|
||
|
id t = [it nextObject];
|
||
|
//System.out.println("pulled "+adaptor.getType(t));
|
||
|
if ( t == [it up] ) {
|
||
|
level--;
|
||
|
if ( level==0 && hasNilRoot ) return [it nextObject]; // don't give last UP; get EOF
|
||
|
}
|
||
|
else if ( t == [it down] )
|
||
|
level++;
|
||
|
if ( level == 0 && [adaptor isNil:t] ) { // if nil root, scarf nil, DOWN
|
||
|
hasNilRoot = true;
|
||
|
t = [it nextObject]; // t is now DOWN, so get first real node next
|
||
|
level++;
|
||
|
t = [it nextObject];
|
||
|
}
|
||
|
return t;
|
||
|
}
|
||
|
|
||
|
- (BOOL) isEOF:(id<BaseTree>) aTree
|
||
|
{
|
||
|
return [adaptor getType:(CommonTree *)aTree] == TokenTypeEOF;
|
||
|
}
|
||
|
|
||
|
- (void) setUniqueNavigationNodes:(BOOL) uniqueNavigationNodes
|
||
|
{
|
||
|
}
|
||
|
|
||
|
- (id) getTreeSource
|
||
|
{
|
||
|
return root;
|
||
|
}
|
||
|
|
||
|
- (NSString *) getSourceName
|
||
|
{
|
||
|
return [[self getTokenStream] getSourceName];
|
||
|
}
|
||
|
|
||
|
- (id<TokenStream>) getTokenStream
|
||
|
{
|
||
|
return tokens;
|
||
|
}
|
||
|
|
||
|
- (void) setTokenStream:(id<TokenStream>)theTokens
|
||
|
{
|
||
|
if ( tokens != theTokens ) {
|
||
|
if ( tokens ) [tokens release];
|
||
|
[theTokens retain];
|
||
|
}
|
||
|
tokens = theTokens;
|
||
|
}
|
||
|
|
||
|
- (CommonTreeAdaptor *) getTreeAdaptor
|
||
|
{
|
||
|
return adaptor;
|
||
|
}
|
||
|
|
||
|
- (void) setTreeAdaptor:(CommonTreeAdaptor *) anAdaptor
|
||
|
{
|
||
|
if ( adaptor != anAdaptor ) {
|
||
|
if ( adaptor ) [adaptor release];
|
||
|
[anAdaptor retain];
|
||
|
}
|
||
|
adaptor = anAdaptor;
|
||
|
}
|
||
|
|
||
|
- (CommonTree *)getNode:(NSInteger) i
|
||
|
{
|
||
|
@throw [RuntimeException newException:@"Absolute node indexes are meaningless in an unbuffered stream"];
|
||
|
return nil;
|
||
|
}
|
||
|
|
||
|
- (NSInteger) LA:(NSInteger) i
|
||
|
{
|
||
|
return [adaptor getType:[self LT:i]];
|
||
|
}
|
||
|
|
||
|
/** Make stream jump to a new location, saving old location.
|
||
|
* Switch back with pop().
|
||
|
*/
|
||
|
- (void) push:(NSInteger) anIndex
|
||
|
{
|
||
|
if ( calls == nil ) {
|
||
|
calls = [[IntArray newArrayWithLen:INITIAL_CALL_STACK_SIZE] retain];
|
||
|
}
|
||
|
[calls push:p]; // save current anIndex
|
||
|
[self seek:anIndex];
|
||
|
}
|
||
|
|
||
|
/** Seek back to previous anIndex saved during last push() call.
|
||
|
* Return top of stack (return anIndex).
|
||
|
*/
|
||
|
- (NSInteger) pop
|
||
|
{
|
||
|
int ret = [calls pop];
|
||
|
[self seek:ret];
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
// TREE REWRITE INTERFACE
|
||
|
|
||
|
- (void) replaceChildren:(id) parent From:(NSInteger)startChildIndex To:(NSInteger)stopChildIndex With:(id) aTree
|
||
|
{
|
||
|
if ( parent != nil ) {
|
||
|
[adaptor replaceChildren:parent From:startChildIndex To:stopChildIndex With:aTree];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (NSString *) toStringFromNode:(id<BaseTree>)startNode ToNode:(id<BaseTree>)stopNode
|
||
|
{
|
||
|
// we'll have to walk from start to stop in tree; we're not keeping
|
||
|
// a complete node stream buffer
|
||
|
return @"n/a";
|
||
|
}
|
||
|
|
||
|
/** For debugging; destructive: moves tree iterator to end. */
|
||
|
- (NSString *) toTokenTypeString
|
||
|
{
|
||
|
[self reset];
|
||
|
NSMutableString *buf = [NSMutableString stringWithCapacity:5];
|
||
|
id obj = [self LT:1];
|
||
|
NSInteger type = [adaptor getType:obj];
|
||
|
while ( type != TokenTypeEOF ) {
|
||
|
[buf appendString:@" "];
|
||
|
[buf appendString:[NSString stringWithFormat:@"%d", type]];
|
||
|
[self consume];
|
||
|
obj = [self LT:1];
|
||
|
type = [adaptor getType:obj];
|
||
|
}
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
@synthesize it;
|
||
|
@synthesize calls;
|
||
|
@synthesize hasNilRoot;
|
||
|
@end
|
||
|
|