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.
239 lines
6.1 KiB
239 lines
6.1 KiB
// [The "BSD licence"]
|
|
// Copyright (c) 2006-2007 Kay Roepke
|
|
// 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 "TreeAdaptor.h"
|
|
#import "TreeException.h"
|
|
#import "BaseTree.h"
|
|
|
|
@implementation TreeAdaptor
|
|
|
|
|
|
+ (id) newEmptyTree
|
|
{
|
|
return [TreeAdaptor newTreeWithToken:nil];
|
|
}
|
|
|
|
+ (id) newAdaptor
|
|
{
|
|
return [[TreeAdaptor alloc] init];
|
|
}
|
|
|
|
- (id) init
|
|
{
|
|
self = [super init];
|
|
return self;
|
|
}
|
|
|
|
- (id) initWithPayload:(id<Token>)payload
|
|
{
|
|
self = [super init];
|
|
return self;
|
|
}
|
|
|
|
#pragma mark Rewrite Rules
|
|
|
|
/** Create a tree node from Token object; for CommonTree type trees,
|
|
* then the token just becomes the payload. This is the most
|
|
* common create call.
|
|
*
|
|
* Override if you want another kind of node to be built.
|
|
*/
|
|
- (id) create:(id<Token>) payload
|
|
{
|
|
return nil;
|
|
}
|
|
|
|
/** Create a new node derived from a token, with a new token type.
|
|
* This is invoked from an imaginary node ref on right side of a
|
|
* rewrite rule as IMAG[$tokenLabel].
|
|
*
|
|
* This should invoke createToken(Token).
|
|
*/
|
|
- (id) createTree:(NSInteger)tokenType fromToken:(id<Token>)fromToken
|
|
{
|
|
id<Token> newToken = [self createToken:fromToken];
|
|
[newToken setType:tokenType];
|
|
|
|
id newTree = [self create:newToken];
|
|
[newToken release];
|
|
return newTree;
|
|
}
|
|
|
|
/** Create a new node derived from a token, with a new token type.
|
|
* This is invoked from an imaginary node ref on right side of a
|
|
* rewrite rule as IMAG[$tokenLabel].
|
|
*
|
|
* This should invoke createToken(Token).
|
|
*/
|
|
- (id) createTree:(NSInteger)tokenType fromToken:(id<Token>)fromToken text:(NSString *)tokenText
|
|
{
|
|
id<Token> newToken = [self createToken:fromToken];
|
|
[newToken setText:tokenText];
|
|
|
|
id newTree = [self create:newToken];
|
|
[newToken release];
|
|
return newTree;
|
|
}
|
|
|
|
/** Create a new node derived from a token, with a new token type.
|
|
* This is invoked from an imaginary node ref on right side of a
|
|
* rewrite rule as IMAG["IMAG"].
|
|
*
|
|
* This should invoke createToken(int,String).
|
|
*/
|
|
- (id) createTree:(NSInteger)tokenType text:(NSString *)tokenText
|
|
{
|
|
id<Token> newToken = [self createToken:tokenType text:tokenText];
|
|
|
|
id newTree = [self create:newToken];
|
|
[newToken release];
|
|
return newTree;
|
|
}
|
|
|
|
- (id) copyNode:(id)aNode
|
|
{
|
|
return [aNode copyWithZone:nil]; // not -copy: to silence warnings
|
|
}
|
|
|
|
- (id) copyTree:(id)aTree
|
|
{
|
|
return [aTree deepCopy];
|
|
}
|
|
|
|
|
|
- (void) addChild:(id)child toTree:(id)aTree
|
|
{
|
|
[aTree addChild:child];
|
|
}
|
|
|
|
- (id) makeNode:(id)newRoot parentOf:(id)oldRoot
|
|
{
|
|
id newRootNode = newRoot;
|
|
|
|
if (oldRoot == nil)
|
|
return newRootNode;
|
|
// handles ^(nil real-node) case
|
|
if ([newRootNode isNil]) {
|
|
if ([newRootNode getChildCount] > 1) {
|
|
#warning TODO: Find a way to the current input stream here!
|
|
@throw [TreeException exceptionWithOldRoot:oldRoot newRoot:newRootNode stream:nil];
|
|
}
|
|
#warning TODO: double check memory management with respect to code generation
|
|
// remove the empty node, placing its sole child in its role.
|
|
id tmpRootNode = [[newRootNode childAtIndex:0] retain];
|
|
[newRootNode release];
|
|
newRootNode = tmpRootNode;
|
|
}
|
|
// the handling of an empty node at the root of oldRoot happens in addChild:
|
|
[newRootNode addChild:oldRoot];
|
|
// this release relies on the fact that the ANTLR code generator always assigns the return value of this method
|
|
// to the variable originally holding oldRoot. If we don't release we leak the reference.
|
|
// FIXME: this is totally non-obvious. maybe do it in calling code by comparing pointers and conditionally releasing
|
|
// the old object
|
|
[oldRoot release];
|
|
|
|
// what happens to newRootNode's retain count? Should we be autoreleasing this one? Probably.
|
|
return [newRootNode retain];
|
|
}
|
|
|
|
|
|
- (id) postProcessTree:(id)aTree
|
|
{
|
|
id processedNode = aTree;
|
|
if (aTree != nil && [aTree isNil] != NO && [aTree getChildCount] == 1) {
|
|
processedNode = [aTree childAtIndex:0];
|
|
}
|
|
return processedNode;
|
|
}
|
|
|
|
|
|
- (NSUInteger) uniqueIdForTree:(id)aNode
|
|
{
|
|
// TODO: is hash appropriate here?
|
|
return [aNode hash];
|
|
}
|
|
|
|
|
|
#pragma mark Content
|
|
|
|
- (NSInteger) tokenTypeForNode:(id)aNode
|
|
{
|
|
return [aNode getType];
|
|
}
|
|
|
|
- (void) setTokenType:(NSInteger)tokenType forNode:(id)aNode
|
|
{
|
|
// currently unimplemented
|
|
}
|
|
|
|
|
|
- (NSString *) textForNode:(id)aNode
|
|
{
|
|
return [aNode getText];
|
|
}
|
|
|
|
- (void) setText:(NSString *)tokenText forNode:(id)aNode
|
|
{
|
|
// currently unimplemented
|
|
}
|
|
|
|
|
|
#pragma mark Navigation / Tree Parsing
|
|
|
|
- (id) childForNode:(id) aNode atIndex:(NSInteger) i
|
|
{
|
|
// currently unimplemented
|
|
return nil;
|
|
}
|
|
|
|
- (NSInteger) childCountForTree:(id) aTree
|
|
{
|
|
// currently unimplemented
|
|
return 0;
|
|
}
|
|
|
|
#pragma mark Subclass Responsibilties
|
|
|
|
- (void) setBoundariesForTree:(id)aTree fromToken:(id<Token>)startToken toToken:(id<Token>)stopToken
|
|
{
|
|
// subclass responsibility
|
|
}
|
|
|
|
- (NSInteger) tokenStartIndexForTree:(id)aTree
|
|
{
|
|
// subclass responsibility
|
|
return 0;
|
|
}
|
|
|
|
- (NSInteger) tokenStopIndexForTree:(id)aTree
|
|
{
|
|
// subclass responsibility
|
|
return 0;
|
|
}
|
|
|
|
|
|
@end
|