// // ANTLRTreePatternParser.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 "ANTLRTreePatternParser.h" #import "ANTLRTreePatternLexer.h" @implementation ANTLRTreePatternParser + (ANTLRTreePatternParser *)newANTLRTreePatternParser:(ANTLRTreePatternLexer *)aTokenizer Wizard:(ANTLRTreeWizard *)aWizard Adaptor:(id<ANTLRTreeAdaptor>)anAdaptor { return [[ANTLRTreePatternParser 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:(ANTLRTreePatternLexer *)aTokenizer Wizard:(ANTLRTreeWizard *)aWizard Adaptor:(id<ANTLRTreeAdaptor>)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 ANTLRTreePatternParser" ); #endif if ( adaptor ) [adaptor release]; if ( tokenizer ) [tokenizer release]; if ( wizard ) [wizard release]; [super dealloc]; } - (id<ANTLRBaseTree>)pattern { if ( ttype==ANTLRLexerTokenTypeBEGIN ) { return [self parseTree]; } else if ( ttype==ANTLRLexerTokenTypeID ) { id<ANTLRBaseTree> node = [self parseNode]; if ( ttype==ANTLRLexerTokenTypeEOF ) { return node; } return nil; // extra junk on end } return nil; } - (id<ANTLRBaseTree>) parseTree { if ( ttype != ANTLRLexerTokenTypeBEGIN ) { @throw [ANTLRRuntimeException newException:@"no BEGIN"]; } ttype = [tokenizer nextToken]; id<ANTLRBaseTree> root = [self parseNode]; if ( root==nil ) { return nil; } while ( ttype==ANTLRLexerTokenTypeBEGIN || ttype==ANTLRLexerTokenTypeID || ttype==ANTLRLexerTokenTypePERCENT || ttype==ANTLRLexerTokenTypeDOT ) { if ( ttype==ANTLRLexerTokenTypeBEGIN ) { id<ANTLRBaseTree> subtree = [self parseTree]; [adaptor addChild:subtree toTree:root]; } else { id<ANTLRBaseTree> child = [self parseNode]; if ( child == nil ) { return nil; } [adaptor addChild:child toTree:root]; } } if ( ttype != ANTLRLexerTokenTypeEND ) { @throw [ANTLRRuntimeException newException:@"no END"]; } ttype = [tokenizer nextToken]; return root; } - (id<ANTLRBaseTree>) parseNode { // "%label:" prefix NSString *label = nil; ANTLRTreePattern *node; if ( ttype == ANTLRLexerTokenTypePERCENT ) { ttype = [tokenizer nextToken]; if ( ttype != ANTLRLexerTokenTypeID ) { return nil; } label = [tokenizer toString]; ttype = [tokenizer nextToken]; if ( ttype != ANTLRLexerTokenTypeCOLON ) { return nil; } ttype = [tokenizer nextToken]; // move to ID following colon } // Wildcard? if ( ttype == ANTLRLexerTokenTypeDOT ) { ttype = [tokenizer nextToken]; id<ANTLRToken> wildcardPayload = [ANTLRCommonToken newToken:0 Text:@"."]; node = [ANTLRWildcardTreePattern newANTLRWildcardTreePattern:wildcardPayload]; if ( label != nil ) { node.label = label; } return node; } // "ID" or "ID[arg]" if ( ttype != ANTLRLexerTokenTypeID ) { 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 == ANTLRLexerTokenTypeARG ) { arg = [tokenizer toString]; text = arg; ttype = [tokenizer nextToken]; } // create node int treeNodeType = [wizard getTokenType:tokenName]; if ( treeNodeType==ANTLRTokenTypeInvalid ) { return nil; } node = [adaptor createTree:treeNodeType Text:text]; if ( label!=nil && [node class] == [ANTLRTreePattern class] ) { ((ANTLRTreePattern *)node).label = label; } if ( arg!=nil && [node class] == [ANTLRTreePattern class] ) { ((ANTLRTreePattern *)node).hasTextArg = YES; } return node; } @synthesize tokenizer; @synthesize ttype; @synthesize wizard; @synthesize adaptor; @end