1*16467b97STreehugger Robot// [The "BSD licence"] 2*16467b97STreehugger Robot// Copyright (c) 2006-2007 Kay Roepke 2010 Alan Condit 3*16467b97STreehugger Robot// All rights reserved. 4*16467b97STreehugger Robot// 5*16467b97STreehugger Robot// Redistribution and use in source and binary forms, with or without 6*16467b97STreehugger Robot// modification, are permitted provided that the following conditions 7*16467b97STreehugger Robot// are met: 8*16467b97STreehugger Robot// 1. Redistributions of source code must retain the above copyright 9*16467b97STreehugger Robot// notice, this list of conditions and the following disclaimer. 10*16467b97STreehugger Robot// 2. Redistributions in binary form must reproduce the above copyright 11*16467b97STreehugger Robot// notice, this list of conditions and the following disclaimer in the 12*16467b97STreehugger Robot// documentation and/or other materials provided with the distribution. 13*16467b97STreehugger Robot// 3. The name of the author may not be used to endorse or promote products 14*16467b97STreehugger Robot// derived from this software without specific prior written permission. 15*16467b97STreehugger Robot// 16*16467b97STreehugger Robot// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17*16467b97STreehugger Robot// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18*16467b97STreehugger Robot// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19*16467b97STreehugger Robot// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20*16467b97STreehugger Robot// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21*16467b97STreehugger Robot// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22*16467b97STreehugger Robot// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23*16467b97STreehugger Robot// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24*16467b97STreehugger Robot// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25*16467b97STreehugger Robot// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*16467b97STreehugger Robot 27*16467b97STreehugger Robot#import <ANTLR/antlr.h> 28*16467b97STreehugger Robot#import "Lexer.h" 29*16467b97STreehugger Robot 30*16467b97STreehugger Robot@implementation Lexer 31*16467b97STreehugger Robot 32*16467b97STreehugger Robot@synthesize input; 33*16467b97STreehugger Robot@synthesize ruleNestingLevel; 34*16467b97STreehugger Robot#pragma mark Initializer 35*16467b97STreehugger Robot 36*16467b97STreehugger Robot- (id) initWithCharStream:(id<CharStream>)anInput 37*16467b97STreehugger Robot{ 38*16467b97STreehugger Robot self = [super initWithState:[[RecognizerSharedState alloc] init]]; 39*16467b97STreehugger Robot if ( self != nil ) { 40*16467b97STreehugger Robot input = [anInput retain]; 41*16467b97STreehugger Robot if (state.token != nil) 42*16467b97STreehugger Robot [((CommonToken *)state.token) setInput:anInput]; 43*16467b97STreehugger Robot ruleNestingLevel = 0; 44*16467b97STreehugger Robot } 45*16467b97STreehugger Robot return self; 46*16467b97STreehugger Robot} 47*16467b97STreehugger Robot 48*16467b97STreehugger Robot- (id) initWithCharStream:(id<CharStream>)anInput State:(RecognizerSharedState *)aState 49*16467b97STreehugger Robot{ 50*16467b97STreehugger Robot self = [super initWithState:aState]; 51*16467b97STreehugger Robot if ( self != nil ) { 52*16467b97STreehugger Robot input = [anInput retain]; 53*16467b97STreehugger Robot if (state.token != nil) 54*16467b97STreehugger Robot [((CommonToken *)state.token) setInput:anInput]; 55*16467b97STreehugger Robot ruleNestingLevel = 0; 56*16467b97STreehugger Robot } 57*16467b97STreehugger Robot return self; 58*16467b97STreehugger Robot} 59*16467b97STreehugger Robot 60*16467b97STreehugger Robot- (void) dealloc 61*16467b97STreehugger Robot{ 62*16467b97STreehugger Robot if ( input ) [input release]; 63*16467b97STreehugger Robot [super dealloc]; 64*16467b97STreehugger Robot} 65*16467b97STreehugger Robot 66*16467b97STreehugger Robot- (id) copyWithZone:(NSZone *)aZone 67*16467b97STreehugger Robot{ 68*16467b97STreehugger Robot Lexer *copy; 69*16467b97STreehugger Robot 70*16467b97STreehugger Robot copy = [[[self class] allocWithZone:aZone] init]; 71*16467b97STreehugger Robot // copy = [super copyWithZone:aZone]; // allocation occurs here 72*16467b97STreehugger Robot if ( input != nil ) 73*16467b97STreehugger Robot copy.input = input; 74*16467b97STreehugger Robot copy.ruleNestingLevel = ruleNestingLevel; 75*16467b97STreehugger Robot return copy; 76*16467b97STreehugger Robot} 77*16467b97STreehugger Robot 78*16467b97STreehugger Robot- (void) reset 79*16467b97STreehugger Robot{ 80*16467b97STreehugger Robot [super reset]; // reset all recognizer state variables 81*16467b97STreehugger Robot // wack Lexer state variables 82*16467b97STreehugger Robot if ( input != nil ) { 83*16467b97STreehugger Robot [input seek:0]; // rewind the input 84*16467b97STreehugger Robot } 85*16467b97STreehugger Robot if ( state == nil ) { 86*16467b97STreehugger Robot return; // no shared state work to do 87*16467b97STreehugger Robot } 88*16467b97STreehugger Robot state.token = nil; 89*16467b97STreehugger Robot state.type = CommonToken.INVALID_TOKEN_TYPE; 90*16467b97STreehugger Robot state.channel = CommonToken.DEFAULT_CHANNEL; 91*16467b97STreehugger Robot state.tokenStartCharIndex = -1; 92*16467b97STreehugger Robot state.tokenStartCharPositionInLine = -1; 93*16467b97STreehugger Robot state.tokenStartLine = -1; 94*16467b97STreehugger Robot state.text = nil; 95*16467b97STreehugger Robot} 96*16467b97STreehugger Robot 97*16467b97STreehugger Robot// token stuff 98*16467b97STreehugger Robot#pragma mark Tokens 99*16467b97STreehugger Robot 100*16467b97STreehugger Robot- (id<Token>)getToken 101*16467b97STreehugger Robot{ 102*16467b97STreehugger Robot return [state getToken]; 103*16467b97STreehugger Robot} 104*16467b97STreehugger Robot 105*16467b97STreehugger Robot- (void) setToken: (id<Token>) aToken 106*16467b97STreehugger Robot{ 107*16467b97STreehugger Robot if (state.token != aToken) { 108*16467b97STreehugger Robot [aToken retain]; 109*16467b97STreehugger Robot state.token = aToken; 110*16467b97STreehugger Robot } 111*16467b97STreehugger Robot} 112*16467b97STreehugger Robot 113*16467b97STreehugger Robot 114*16467b97STreehugger Robot// this method may be overridden in the generated lexer if we generate a filtering lexer. 115*16467b97STreehugger Robot- (id<Token>) nextToken 116*16467b97STreehugger Robot{ 117*16467b97STreehugger Robot while (YES) { 118*16467b97STreehugger Robot [self setToken:nil]; 119*16467b97STreehugger Robot state.channel = CommonToken.DEFAULT_CHANNEL; 120*16467b97STreehugger Robot state.tokenStartCharIndex = input.index; 121*16467b97STreehugger Robot state.tokenStartCharPositionInLine = input.getCharPositionInLine; 122*16467b97STreehugger Robot state.tokenStartLine = input.getLine; 123*16467b97STreehugger Robot state.text = nil; 124*16467b97STreehugger Robot 125*16467b97STreehugger Robot // [self setText:[self text]]; 126*16467b97STreehugger Robot if ([input LA:1] == CharStreamEOF) { 127*16467b97STreehugger Robot CommonToken *eof = [CommonToken newToken:input 128*16467b97STreehugger Robot Type:TokenTypeEOF 129*16467b97STreehugger Robot Channel:CommonToken.DEFAULT_CHANNEL 130*16467b97STreehugger Robot Start:input.index 131*16467b97STreehugger Robot Stop:input.index]; 132*16467b97STreehugger Robot [eof setLine:input.getLine]; 133*16467b97STreehugger Robot [eof setCharPositionInLine:input.getCharPositionInLine]; 134*16467b97STreehugger Robot return eof; 135*16467b97STreehugger Robot } 136*16467b97STreehugger Robot @try { 137*16467b97STreehugger Robot [self mTokens]; 138*16467b97STreehugger Robot // SEL aMethod = @selector(mTokens); 139*16467b97STreehugger Robot // [[self class] instancesRespondToSelector:aMethod]; 140*16467b97STreehugger Robot if ( state.token == nil) 141*16467b97STreehugger Robot [self emit]; 142*16467b97STreehugger Robot else if ( state.token == [CommonToken skipToken] ) { 143*16467b97STreehugger Robot continue; 144*16467b97STreehugger Robot } 145*16467b97STreehugger Robot return state.token; 146*16467b97STreehugger Robot } 147*16467b97STreehugger Robot @catch (MismatchedRangeException *re) { 148*16467b97STreehugger Robot [self reportError:re]; 149*16467b97STreehugger Robot // [self recover:re]; 150*16467b97STreehugger Robot } 151*16467b97STreehugger Robot @catch (MismatchedTokenException *re) { 152*16467b97STreehugger Robot [self reportError:re]; 153*16467b97STreehugger Robot // [self recover:re]; 154*16467b97STreehugger Robot } 155*16467b97STreehugger Robot @catch (RecognitionException *re) { 156*16467b97STreehugger Robot [self reportError:re]; 157*16467b97STreehugger Robot [self recover:re]; 158*16467b97STreehugger Robot } 159*16467b97STreehugger Robot } 160*16467b97STreehugger Robot} 161*16467b97STreehugger Robot 162*16467b97STreehugger Robot- (void) mTokens 163*16467b97STreehugger Robot{ // abstract, defined in generated source as a starting point for matching 164*16467b97STreehugger Robot [self doesNotRecognizeSelector:_cmd]; 165*16467b97STreehugger Robot} 166*16467b97STreehugger Robot 167*16467b97STreehugger Robot- (void) skip 168*16467b97STreehugger Robot{ 169*16467b97STreehugger Robot state.token = [CommonToken skipToken]; 170*16467b97STreehugger Robot} 171*16467b97STreehugger Robot 172*16467b97STreehugger Robot- (id<CharStream>) input 173*16467b97STreehugger Robot{ 174*16467b97STreehugger Robot return input; 175*16467b97STreehugger Robot} 176*16467b97STreehugger Robot 177*16467b97STreehugger Robot- (void) setInput:(id<CharStream>) anInput 178*16467b97STreehugger Robot{ 179*16467b97STreehugger Robot if ( anInput != input ) { 180*16467b97STreehugger Robot if ( input ) [input release]; 181*16467b97STreehugger Robot } 182*16467b97STreehugger Robot input = nil; 183*16467b97STreehugger Robot [self reset]; 184*16467b97STreehugger Robot input = anInput; 185*16467b97STreehugger Robot [input retain]; 186*16467b97STreehugger Robot} 187*16467b97STreehugger Robot 188*16467b97STreehugger Robot/** Currently does not support multiple emits per nextToken invocation 189*16467b97STreehugger Robot * for efficiency reasons. Subclass and override this method and 190*16467b97STreehugger Robot * nextToken (to push tokens into a list and pull from that list rather 191*16467b97STreehugger Robot * than a single variable as this implementation does). 192*16467b97STreehugger Robot */ 193*16467b97STreehugger Robot- (void) emit:(id<Token>)aToken 194*16467b97STreehugger Robot{ 195*16467b97STreehugger Robot state.token = aToken; 196*16467b97STreehugger Robot} 197*16467b97STreehugger Robot 198*16467b97STreehugger Robot/** The standard method called to automatically emit a token at the 199*16467b97STreehugger Robot * outermost lexical rule. The token object should point into the 200*16467b97STreehugger Robot * char buffer start..stop. If there is a text override in 'text', 201*16467b97STreehugger Robot * use that to set the token's text. Override this method to emit 202*16467b97STreehugger Robot * custom Token objects. 203*16467b97STreehugger Robot * 204*16467b97STreehugger Robot * If you are building trees, then you should also override 205*16467b97STreehugger Robot * Parser or TreeParser.getMissingSymbol(). 206*16467b97STreehugger Robot */ 207*16467b97STreehugger Robot- (void) emit 208*16467b97STreehugger Robot{ 209*16467b97STreehugger Robot id<Token> aToken = [CommonToken newToken:input 210*16467b97STreehugger Robot Type:state.type 211*16467b97STreehugger Robot Channel:state.channel 212*16467b97STreehugger Robot Start:state.tokenStartCharIndex 213*16467b97STreehugger Robot Stop:input.index-1]; 214*16467b97STreehugger Robot aToken.text = [self text]; 215*16467b97STreehugger Robot [aToken setCharPositionInLine:state.tokenStartCharPositionInLine]; 216*16467b97STreehugger Robot [aToken setLine:state.tokenStartLine]; 217*16467b97STreehugger Robot [aToken retain]; 218*16467b97STreehugger Robot [self emit:aToken]; 219*16467b97STreehugger Robot // [aToken release]; 220*16467b97STreehugger Robot} 221*16467b97STreehugger Robot 222*16467b97STreehugger Robot// matching 223*16467b97STreehugger Robot#pragma mark Matching 224*16467b97STreehugger Robot- (void) matchString:(NSString *)aString 225*16467b97STreehugger Robot{ 226*16467b97STreehugger Robot unichar c; 227*16467b97STreehugger Robot unsigned int i = 0; 228*16467b97STreehugger Robot unsigned int stringLength = [aString length]; 229*16467b97STreehugger Robot while ( i < stringLength ) { 230*16467b97STreehugger Robot c = [input LA:1]; 231*16467b97STreehugger Robot if ( c != [aString characterAtIndex:i] ) { 232*16467b97STreehugger Robot if ([state getBacktracking] > 0) { 233*16467b97STreehugger Robot state.failed = YES; 234*16467b97STreehugger Robot return; 235*16467b97STreehugger Robot } 236*16467b97STreehugger Robot MismatchedTokenException *mte = [MismatchedTokenException newExceptionChar:[aString characterAtIndex:i] Stream:input]; 237*16467b97STreehugger Robot mte.c = c; 238*16467b97STreehugger Robot [self recover:mte]; 239*16467b97STreehugger Robot @throw mte; 240*16467b97STreehugger Robot } 241*16467b97STreehugger Robot i++; 242*16467b97STreehugger Robot [input consume]; 243*16467b97STreehugger Robot state.failed = NO; 244*16467b97STreehugger Robot } 245*16467b97STreehugger Robot} 246*16467b97STreehugger Robot 247*16467b97STreehugger Robot- (void) matchAny 248*16467b97STreehugger Robot{ 249*16467b97STreehugger Robot [input consume]; 250*16467b97STreehugger Robot} 251*16467b97STreehugger Robot 252*16467b97STreehugger Robot- (void) matchChar:(unichar) aChar 253*16467b97STreehugger Robot{ 254*16467b97STreehugger Robot // TODO: -LA: is returning an int because it sometimes is used in the generated parser to compare lookahead with a tokentype. 255*16467b97STreehugger Robot // try to change all those occurrences to -LT: if possible (i.e. if ANTLR can be made to generate LA only for lexer code) 256*16467b97STreehugger Robot unichar charLA; 257*16467b97STreehugger Robot charLA = [input LA:1]; 258*16467b97STreehugger Robot if ( charLA != aChar) { 259*16467b97STreehugger Robot if ([state getBacktracking] > 0) { 260*16467b97STreehugger Robot state.failed = YES; 261*16467b97STreehugger Robot return; 262*16467b97STreehugger Robot } 263*16467b97STreehugger Robot MismatchedTokenException *mte = [MismatchedTokenException newExceptionChar:aChar Stream:input]; 264*16467b97STreehugger Robot mte.c = charLA; 265*16467b97STreehugger Robot [self recover:mte]; 266*16467b97STreehugger Robot @throw mte; 267*16467b97STreehugger Robot } 268*16467b97STreehugger Robot [input consume]; 269*16467b97STreehugger Robot state.failed = NO; 270*16467b97STreehugger Robot} 271*16467b97STreehugger Robot 272*16467b97STreehugger Robot- (void) matchRangeFromChar:(unichar)fromChar to:(unichar)toChar 273*16467b97STreehugger Robot{ 274*16467b97STreehugger Robot unichar charLA = (unichar)[input LA:1]; 275*16467b97STreehugger Robot if ( charLA < fromChar || charLA > toChar ) { 276*16467b97STreehugger Robot if ([state getBacktracking] > 0) { 277*16467b97STreehugger Robot state.failed = YES; 278*16467b97STreehugger Robot return; 279*16467b97STreehugger Robot } 280*16467b97STreehugger Robot MismatchedRangeException *mre = [MismatchedRangeException 281*16467b97STreehugger Robot newException:NSMakeRange((NSUInteger)fromChar,(NSUInteger)toChar) 282*16467b97STreehugger Robot stream:input]; 283*16467b97STreehugger Robot mre.c = charLA; 284*16467b97STreehugger Robot [self recover:mre]; 285*16467b97STreehugger Robot @throw mre; 286*16467b97STreehugger Robot } 287*16467b97STreehugger Robot [input consume]; 288*16467b97STreehugger Robot state.failed = NO; 289*16467b97STreehugger Robot} 290*16467b97STreehugger Robot 291*16467b97STreehugger Robot // info 292*16467b97STreehugger Robot#pragma mark Informational 293*16467b97STreehugger Robot 294*16467b97STreehugger Robot- (NSUInteger) line 295*16467b97STreehugger Robot{ 296*16467b97STreehugger Robot return input.getLine; 297*16467b97STreehugger Robot} 298*16467b97STreehugger Robot 299*16467b97STreehugger Robot- (NSUInteger) charPositionInLine 300*16467b97STreehugger Robot{ 301*16467b97STreehugger Robot return input.getCharPositionInLine; 302*16467b97STreehugger Robot} 303*16467b97STreehugger Robot 304*16467b97STreehugger Robot- (NSInteger) index 305*16467b97STreehugger Robot{ 306*16467b97STreehugger Robot return 0; 307*16467b97STreehugger Robot} 308*16467b97STreehugger Robot 309*16467b97STreehugger Robot- (NSString *) text 310*16467b97STreehugger Robot{ 311*16467b97STreehugger Robot if (state.text != nil) { 312*16467b97STreehugger Robot return state.text; 313*16467b97STreehugger Robot } 314*16467b97STreehugger Robot return [input substringWithRange:NSMakeRange(state.tokenStartCharIndex, input.index-state.tokenStartCharIndex)]; 315*16467b97STreehugger Robot} 316*16467b97STreehugger Robot 317*16467b97STreehugger Robot- (void) setText:(NSString *) theText 318*16467b97STreehugger Robot{ 319*16467b97STreehugger Robot state.text = theText; 320*16467b97STreehugger Robot} 321*16467b97STreehugger Robot 322*16467b97STreehugger Robot // error handling 323*16467b97STreehugger Robot- (void) reportError:(RecognitionException *)e 324*16467b97STreehugger Robot{ 325*16467b97STreehugger Robot /** TODO: not thought about recovery in lexer yet. 326*16467b97STreehugger Robot * 327*16467b97STreehugger Robot // if we've already reported an error and have not matched a token 328*16467b97STreehugger Robot // yet successfully, don't report any errors. 329*16467b97STreehugger Robot if ( errorRecovery ) { 330*16467b97STreehugger Robot //System.err.print("[SPURIOUS] "); 331*16467b97STreehugger Robot return; 332*16467b97STreehugger Robot } 333*16467b97STreehugger Robot errorRecovery = true; 334*16467b97STreehugger Robot */ 335*16467b97STreehugger Robot 336*16467b97STreehugger Robot [self displayRecognitionError:[self getTokenNames] Exception:e]; 337*16467b97STreehugger Robot} 338*16467b97STreehugger Robot 339*16467b97STreehugger Robot- (NSString *)getErrorMessage:(RecognitionException *)e TokenNames:(AMutableArray *)tokenNames 340*16467b97STreehugger Robot{ 341*16467b97STreehugger Robot/* NSString *msg = [NSString stringWithFormat:@"Gotta fix getErrorMessage in Lexer.m--%@\n", 342*16467b97STreehugger Robot e.name]; 343*16467b97STreehugger Robot */ 344*16467b97STreehugger Robot NSString *msg = nil; 345*16467b97STreehugger Robot if ( [e isKindOfClass:[MismatchedTokenException class]] ) { 346*16467b97STreehugger Robot MismatchedTokenException *mte = (MismatchedTokenException *)e; 347*16467b97STreehugger Robot msg = [NSString stringWithFormat:@"mismatched character \"%@\" expecting \"%@\"", 348*16467b97STreehugger Robot [self getCharErrorDisplay:mte.c], [self getCharErrorDisplay:mte.expectingChar]]; 349*16467b97STreehugger Robot } 350*16467b97STreehugger Robot else if ( [e isKindOfClass:[NoViableAltException class]] ) { 351*16467b97STreehugger Robot NoViableAltException *nvae = (NoViableAltException *)e; 352*16467b97STreehugger Robot // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>" 353*16467b97STreehugger Robot // and "(decision="+nvae.decisionNumber+") and 354*16467b97STreehugger Robot // "state "+nvae.stateNumber 355*16467b97STreehugger Robot msg = [NSString stringWithFormat:@"no viable alternative decision:%d state:%d at character \"%@\"", 356*16467b97STreehugger Robot nvae.decisionNumber, nvae.stateNumber, [self getCharErrorDisplay:(nvae.c)]]; 357*16467b97STreehugger Robot } 358*16467b97STreehugger Robot else if ( [e isKindOfClass:[EarlyExitException class]] ) { 359*16467b97STreehugger Robot EarlyExitException *eee = (EarlyExitException *)e; 360*16467b97STreehugger Robot // for development, can add "(decision="+eee.decisionNumber+")" 361*16467b97STreehugger Robot msg = [NSString stringWithFormat:@"required (...)+ loop did not match anything at character \"%@\"", 362*16467b97STreehugger Robot [self getCharErrorDisplay:(eee.c)]]; 363*16467b97STreehugger Robot } 364*16467b97STreehugger Robot else if ( [e isKindOfClass:[MismatchedNotSetException class]] ) { 365*16467b97STreehugger Robot MismatchedNotSetException *mse = (MismatchedNotSetException *)e; 366*16467b97STreehugger Robot msg = [NSString stringWithFormat:@"mismatched character \"%@\" expecting set \"%@\"", 367*16467b97STreehugger Robot [self getCharErrorDisplay:(mse.c)], mse.expecting]; 368*16467b97STreehugger Robot } 369*16467b97STreehugger Robot else if ( [e isKindOfClass:[MismatchedSetException class]] ) { 370*16467b97STreehugger Robot MismatchedSetException *mse = (MismatchedSetException *)e; 371*16467b97STreehugger Robot msg = [NSString stringWithFormat:@"mismatched character \"%@\" expecting set \"%@\"", 372*16467b97STreehugger Robot [self getCharErrorDisplay:(mse.c)], mse.expecting]; 373*16467b97STreehugger Robot } 374*16467b97STreehugger Robot else if ( [e isKindOfClass:[MismatchedRangeException class]] ) { 375*16467b97STreehugger Robot MismatchedRangeException *mre = (MismatchedRangeException *)e; 376*16467b97STreehugger Robot msg = [NSString stringWithFormat:@"mismatched character \"%@\" \"%@..%@\"", 377*16467b97STreehugger Robot [self getCharErrorDisplay:(mre.c)], [self getCharErrorDisplay:(mre.range.location)], 378*16467b97STreehugger Robot [self getCharErrorDisplay:(mre.range.location+mre.range.length-1)]]; 379*16467b97STreehugger Robot } 380*16467b97STreehugger Robot else { 381*16467b97STreehugger Robot msg = [super getErrorMessage:e TokenNames:[self getTokenNames]]; 382*16467b97STreehugger Robot } 383*16467b97STreehugger Robot return msg; 384*16467b97STreehugger Robot} 385*16467b97STreehugger Robot 386*16467b97STreehugger Robot- (NSString *)getCharErrorDisplay:(NSInteger)c 387*16467b97STreehugger Robot{ 388*16467b97STreehugger Robot NSString *s; 389*16467b97STreehugger Robot switch ( c ) { 390*16467b97STreehugger Robot case 0: 391*16467b97STreehugger Robot s = @"char=<nil>"; 392*16467b97STreehugger Robot break; 393*16467b97STreehugger Robot case TokenTypeEOF : 394*16467b97STreehugger Robot case 65535: 395*16467b97STreehugger Robot s = @"<EOF>"; 396*16467b97STreehugger Robot break; 397*16467b97STreehugger Robot case '\n' : 398*16467b97STreehugger Robot s = @"\\n"; 399*16467b97STreehugger Robot break; 400*16467b97STreehugger Robot case '\t' : 401*16467b97STreehugger Robot s = @"\\t"; 402*16467b97STreehugger Robot break; 403*16467b97STreehugger Robot case '\r' : 404*16467b97STreehugger Robot s = @"\\r"; 405*16467b97STreehugger Robot break; 406*16467b97STreehugger Robot default: 407*16467b97STreehugger Robot s = [NSString stringWithFormat:@"%c", (char)c]; 408*16467b97STreehugger Robot break; 409*16467b97STreehugger Robot } 410*16467b97STreehugger Robot return s; 411*16467b97STreehugger Robot} 412*16467b97STreehugger Robot 413*16467b97STreehugger Robot/** Lexers can normally match any char in it's vocabulary after matching 414*16467b97STreehugger Robot * a token, so do the easy thing and just kill a character and hope 415*16467b97STreehugger Robot * it all works out. You can instead use the rule invocation stack 416*16467b97STreehugger Robot * to do sophisticated error recovery if you are in a fragment rule. 417*16467b97STreehugger Robot */ 418*16467b97STreehugger Robot- (void)recover:(RecognitionException *)re 419*16467b97STreehugger Robot{ 420*16467b97STreehugger Robot //System.out.println("consuming char "+(char)input.LA(1)+" during recovery"); 421*16467b97STreehugger Robot //re.printStackTrace(); 422*16467b97STreehugger Robot [input consume]; 423*16467b97STreehugger Robot} 424*16467b97STreehugger Robot 425*16467b97STreehugger Robot- (void)traceIn:(NSString *)ruleName Index:(NSInteger)ruleIndex 426*16467b97STreehugger Robot{ 427*16467b97STreehugger Robot NSString *inputSymbol = [NSString stringWithFormat:@"%c line=%d:%d\n", [input LT:1], input.getLine, input.getCharPositionInLine]; 428*16467b97STreehugger Robot [super traceIn:ruleName Index:ruleIndex Object:inputSymbol]; 429*16467b97STreehugger Robot} 430*16467b97STreehugger Robot 431*16467b97STreehugger Robot- (void)traceOut:(NSString *)ruleName Index:(NSInteger)ruleIndex 432*16467b97STreehugger Robot{ 433*16467b97STreehugger Robot NSString *inputSymbol = [NSString stringWithFormat:@"%c line=%d:%d\n", [input LT:1], input.getLine, input.getCharPositionInLine]; 434*16467b97STreehugger Robot [super traceOut:ruleName Index:ruleIndex Object:inputSymbol]; 435*16467b97STreehugger Robot} 436*16467b97STreehugger Robot 437*16467b97STreehugger Robot@end 438