1 // [The "BSD licence"] 2 // Copyright (c) 2006-2007 Kay Roepke 2010 Alan Condit 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. The name of the author may not be used to endorse or promote products 14 // derived from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #import "Foundation/NSObjCRuntime.h" 28 #import "RecognitionException.h" 29 #import "TokenStream.h" 30 #import "TreeNodeStream.h" 31 #import "BufferedTokenStream.h" 32 33 @implementation RecognitionException 34 35 @synthesize input; 36 @synthesize index; 37 @synthesize token; 38 @synthesize node; 39 @synthesize c; 40 @synthesize line; 41 @synthesize charPositionInLine; 42 @synthesize approximateLineInfo; 43 44 + (id) newException 45 { 46 return [[RecognitionException alloc] init]; 47 } 48 49 + (id) newException:(id<IntStream>) anInputStream 50 { 51 return [[RecognitionException alloc] initWithStream:anInputStream]; 52 } 53 54 + (id) newException:(id<IntStream>) anInputStream reason:(NSString *)aReason 55 { 56 return [[RecognitionException alloc] initWithStream:anInputStream reason:aReason]; 57 } 58 59 - (id) init 60 { 61 self = [super initWithName:@"Recognition Exception" reason:@"Recognition Exception" userInfo:nil]; 62 if ( self != nil ) { 63 } 64 return self; 65 } 66 67 - (id) initWithStream:(id<IntStream>)anInputStream reason:(NSString *)aReason 68 { 69 self = [super initWithName:NSStringFromClass([self class]) reason:aReason userInfo:nil]; 70 if ( self != nil ) { 71 [self setStream:anInputStream]; 72 index = input.index; 73 74 Class inputClass = [input class]; 75 if ([inputClass conformsToProtocol:@protocol(TokenStream)]) { 76 [self setToken:[(id<TokenStream>)input LT:1]]; 77 line = token.line; 78 charPositionInLine = token.charPositionInLine; 79 } else if ([inputClass conformsToProtocol:@protocol(CharStream)]) { 80 c = (unichar)[input LA:1]; 81 line = ((id<CharStream>)input).getLine; 82 charPositionInLine = ((id<CharStream>)input).getCharPositionInLine; 83 } else if ([inputClass conformsToProtocol:@protocol(TreeNodeStream)]) { 84 [self setNode:[(id<TreeNodeStream>)input LT:1]]; 85 line = [node line]; 86 charPositionInLine = [node charPositionInLine]; 87 } else { 88 c = (unichar)[input LA:1]; 89 } 90 } 91 return self; 92 } 93 94 - (id) initWithStream:(id<IntStream>)anInputStream 95 { 96 self = [super initWithName:NSStringFromClass([self class]) reason:@"Runtime Exception" userInfo:nil]; 97 if ( self != nil ) { 98 self.input = anInputStream; 99 self.index = input.index; 100 if ( [anInputStream isKindOfClass:[BufferedTokenStream class]] ) { 101 self.token = [(id<TokenStream>)anInputStream LT:1]; 102 self.line = [token line]; 103 self.charPositionInLine = [token charPositionInLine]; 104 if ( [input conformsToProtocol:objc_getProtocol("TreeNodeStream")] ) { 105 [self extractInformationFromTreeNodeStream:anInputStream]; 106 } 107 else if ( [[anInputStream class] instancesRespondToSelector:@selector(LA1:)] ) { 108 c = [anInputStream LA:1]; 109 if ( [[anInputStream class] instancesRespondToSelector:@selector(getLine)] ) 110 line = [anInputStream getLine]; 111 if ( [[anInputStream class] instancesRespondToSelector:@selector(getCharPositionInLine)] ) 112 charPositionInLine = [anInputStream getCharPositionInLine]; 113 } 114 else { 115 c = [anInputStream LA:1]; 116 } 117 } 118 } 119 return self; 120 } 121 122 - (id) initWithName:(NSString *)aName reason:(NSString *)aReason userInfo:(NSDictionary *)aUserInfo 123 { 124 self = [super initWithName:aName reason:aReason userInfo:aUserInfo]; 125 if ( self != nil ) { 126 } 127 return self; 128 } 129 130 - (void) dealloc 131 { 132 #ifdef DEBUG_DEALLOC 133 NSLog( @"called dealloc in RecognitionException" ); 134 #endif 135 if ( input ) [input release]; 136 if ( token ) [token release]; 137 if ( node ) [node release]; 138 [super dealloc]; 139 } 140 141 - (void) extractInformationFromTreeNodeStream:(id<TreeNodeStream>)anInput 142 { 143 id<TreeNodeStream> nodes = anInput; 144 node = [nodes LT:1]; 145 id<TreeAdaptor> adaptor = [nodes getTreeAdaptor]; 146 id<Token> payload = [adaptor getToken:node]; 147 if ( payload != nil ) { 148 token = payload; 149 if ( payload.line <= 0 ) { 150 // imaginary node; no line/pos info; scan backwards 151 int i = -1; 152 id priorNode = [nodes LT:i]; 153 while ( priorNode != nil ) { 154 id<Token> priorPayload = [adaptor getToken:priorNode]; 155 if ( priorPayload!=nil && priorPayload.line > 0 ) { 156 // we found the most recent real line / pos info 157 line = priorPayload.line; 158 charPositionInLine = priorPayload.charPositionInLine; 159 approximateLineInfo = YES; 160 break; 161 } 162 --i; 163 priorNode = [nodes LT:i]; 164 } 165 } 166 else { // node created from real token 167 line = payload.line; 168 charPositionInLine = payload.charPositionInLine; 169 } 170 } 171 else if ( [self.node isKindOfClass:[CommonTree class]] ) { 172 line = ((id<Tree>)node).line; 173 charPositionInLine = ((id<Tree>)node).charPositionInLine; 174 if ( [node isMemberOfClass:[CommonTree class]]) { 175 token = ((CommonTree *)node).token; 176 } 177 } 178 else { 179 NSInteger type = [adaptor getType:node]; 180 NSString *text = [adaptor getText:node]; 181 self.token = [CommonToken newToken:type Text:text]; 182 } 183 } 184 185 - (NSInteger) unexpectedType 186 { 187 if (token) { 188 return token.type; 189 } else if (node) { 190 return [node type]; 191 } else { 192 return c; 193 } 194 } 195 196 - (id<Token>)getUnexpectedToken 197 { 198 return token; 199 } 200 201 - (NSString *) description 202 { 203 //NSMutableString *desc = [[NSMutableString alloc] initWithString:NSStringFromClass([self class])]; 204 NSMutableString *desc = [NSMutableString stringWithString:[self className]]; 205 if (token) { 206 [desc appendFormat:@" token:%@", token]; 207 } else if (node) { 208 [desc appendFormat:@" node:%@", node]; 209 } else { 210 [desc appendFormat:@" char:%c", c]; 211 } 212 [desc appendFormat:@" line:%d position:%d", line, charPositionInLine]; 213 return desc; 214 } 215 216 //---------------------------------------------------------- 217 // input 218 //---------------------------------------------------------- 219 - (id<IntStream>) getStream 220 { 221 return input; 222 } 223 224 - (void) setStream: (id<IntStream>) aStream 225 { 226 if ( input != aStream ) { 227 if ( input ) [input release]; 228 if ( aStream ) [aStream retain]; 229 input = aStream; 230 } 231 } 232 233 //---------------------------------------------------------- 234 // token 235 //---------------------------------------------------------- 236 - (id<Token>) getToken 237 { 238 return token; 239 } 240 241 - (void) setToken: (id<Token>) aToken 242 { 243 if (token != aToken) { 244 if ( token ) [token release]; 245 if ( aToken ) [aToken retain]; 246 token = aToken; 247 } 248 } 249 250 //---------------------------------------------------------- 251 // node 252 //---------------------------------------------------------- 253 - (id<BaseTree>) getNode 254 { 255 return node; 256 } 257 258 - (void) setNode: (id<BaseTree>) aNode 259 { 260 if (node != aNode) { 261 if ( node ) [node release]; 262 if ( aNode ) [aNode retain]; 263 node = aNode; 264 } 265 } 266 267 - (NSString *)getMessage 268 { 269 return @"Fix getMessage in RecognitionException"; 270 } 271 272 - (NSUInteger)charPositionInLine 273 { 274 return charPositionInLine; 275 } 276 277 - (void)setCharPositionInLine:(NSUInteger)aPos 278 { 279 charPositionInLine = aPos; 280 } 281 282 @end 283