// // TreePatternParser.m // ANTLR // // Created by Alan Condit on 6/18/10. // [The "BSD licence"] // Copyright (c) 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 "TreePatternParser.h" #import "TreePatternLexer.h" @implementation TreePatternParser + (TreePatternParser *)newTreePatternParser:(TreePatternLexer *)aTokenizer Wizard:(TreeWizard *)aWizard Adaptor:(id)anAdaptor { return [[TreePatternParser alloc] initWithTokenizer:aTokenizer Wizard:aWizard Adaptor:anAdaptor]; } - (id) init { if ((self = [super init]) != nil) { //tokenizer = aTokenizer; //wizard = aWizard; //adaptor = anAdaptor; //ttype = [tokenizer nextToken]; // kickstart } return self; } - (id) initWithTokenizer:(TreePatternLexer *)aTokenizer Wizard:(TreeWizard *)aWizard Adaptor:(id)anAdaptor { if ((self = [super init]) != nil) { adaptor = anAdaptor; if ( adaptor ) [adaptor retain]; tokenizer = aTokenizer; if ( tokenizer ) [tokenizer retain]; wizard = aWizard; if ( wizard ) [wizard retain]; ttype = [aTokenizer nextToken]; // kickstart } return self; } - (void) dealloc { #ifdef DEBUG_DEALLOC NSLog( @"called dealloc in TreePatternParser" ); #endif if ( adaptor ) [adaptor release]; if ( tokenizer ) [tokenizer release]; if ( wizard ) [wizard release]; [super dealloc]; } - (id)pattern { if ( ttype==LexerTokenTypeBEGIN ) { return [self parseTree]; } else if ( ttype==LexerTokenTypeID ) { id node = [self parseNode]; if ( ttype==LexerTokenTypeEOF ) { return node; } return nil; // extra junk on end } return nil; } - (id) parseTree { if ( ttype != LexerTokenTypeBEGIN ) { @throw [RuntimeException newException:@"no BEGIN"]; } ttype = [tokenizer nextToken]; id root = [self parseNode]; if ( root==nil ) { return nil; } while ( ttype==LexerTokenTypeBEGIN || ttype==LexerTokenTypeID || ttype==LexerTokenTypePERCENT || ttype==LexerTokenTypeDOT ) { if ( ttype==LexerTokenTypeBEGIN ) { id subtree = [self parseTree]; [adaptor addChild:subtree toTree:root]; } else { id child = [self parseNode]; if ( child == nil ) { return nil; } [adaptor addChild:child toTree:root]; } } if ( ttype != LexerTokenTypeEND ) { @throw [RuntimeException newException:@"no END"]; } ttype = [tokenizer nextToken]; return root; } - (id) parseNode { // "%label:" prefix NSString *label = nil; TreePattern *node; if ( ttype == LexerTokenTypePERCENT ) { ttype = [tokenizer nextToken]; if ( ttype != LexerTokenTypeID ) { return nil; } label = [tokenizer toString]; ttype = [tokenizer nextToken]; if ( ttype != LexerTokenTypeCOLON ) { return nil; } ttype = [tokenizer nextToken]; // move to ID following colon } // Wildcard? if ( ttype == LexerTokenTypeDOT ) { ttype = [tokenizer nextToken]; id wildcardPayload = [CommonToken newToken:0 Text:@"."]; node = [ANTLRWildcardTreePattern newANTLRWildcardTreePattern:wildcardPayload]; if ( label != nil ) { node.label = label; } return node; } // "ID" or "ID[arg]" if ( ttype != LexerTokenTypeID ) { return nil; } NSString *tokenName = [tokenizer toString]; ttype = [tokenizer nextToken]; if ( [tokenName isEqualToString:@"nil"] ) { return [adaptor emptyNode]; } NSString *text = tokenName; // check for arg NSString *arg = nil; if ( ttype == LexerTokenTypeARG ) { arg = [tokenizer toString]; text = arg; ttype = [tokenizer nextToken]; } // create node int treeNodeType = [wizard getTokenType:tokenName]; if ( treeNodeType==TokenTypeInvalid ) { return nil; } node = [adaptor createTree:treeNodeType Text:text]; if ( label!=nil && [node class] == [TreePattern class] ) { ((TreePattern *)node).label = label; } if ( arg!=nil && [node class] == [TreePattern class] ) { ((TreePattern *)node).hasTextArg = YES; } return node; } @synthesize tokenizer; @synthesize ttype; @synthesize wizard; @synthesize adaptor; @end