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 "ANTLRDFA.h" 28#import <ANTLRToken.h> 29#import <ANTLRNoViableAltException.h> 30 31NSInteger debug = 0; 32 33@implementation ANTLRDFA 34@synthesize recognizer; 35@synthesize decisionNumber; 36@synthesize len; 37 38- (id) initWithRecognizer:(ANTLRBaseRecognizer *) theRecognizer 39{ 40 if ((self = [super init]) != nil) { 41 recognizer = theRecognizer; 42 [recognizer retain]; 43 debug = 0; 44 } 45 return self; 46} 47 48// using the tables ANTLR generates for the DFA based prediction this method simulates the DFA 49// and returns the prediction of the alternative to be used. 50- (NSInteger) predict:(id<ANTLRIntStream>)input 51{ 52 if ( debug > 2 ) { 53 NSLog(@"Enter DFA.predict for decision %d", decisionNumber); 54 } 55 int aMark = [input mark]; 56 int s = 0; 57 @try { 58 while (YES) { 59 if ( debug > 2 ) 60 NSLog(@"DFA %d state %d LA(1)='%c'(%x)", decisionNumber, s, (unichar)[input LA:1], [input LA:1]); 61 NSInteger specialState = special[s]; 62 if (specialState >= 0) { 63 // this state is special in that it has some code associated with it. we cannot do this in a pure DFA so 64 // we signal the caller accordingly. 65 if ( debug > 2 ) { 66 NSLog(@"DFA %d state %d is special state %d", decisionNumber, s, specialState); 67 } 68 s = [self specialStateTransition:specialState Stream:input]; 69 if ( debug > 2 ) { 70 NSLog(@"DFA %d returns from special state %d to %d", decisionNumber, specialState, s); 71 } 72 if (s == -1 ) { 73 [self noViableAlt:s Stream:input]; 74 return 0; 75 } 76 [input consume]; 77 continue; 78 } 79 if (accept[s] >= 1) { // if this is an accepting state return the prediction 80 if ( debug > 2 ) NSLog(@"accept; predict %d from state %d", accept[s], s); 81 return accept[s]; 82 } 83 // based on the lookahead lookup the next transition, consume and do transition 84 // or signal that we have no viable alternative 85 int c = [input LA:1]; 86 if ( (unichar)c >= min[s] && (unichar)c <= max[s]) { 87 int snext = transition[s][c-min[s]]; 88 if (snext < 0) { 89 // was in range but not a normal transition 90 // must check EOT, which is like the else clause. 91 // eot[s]>=0 indicates that an EOT edge goes to another 92 // state. 93 if (eot[s] >= 0) { 94 if ( debug > 2 ) NSLog(@"EOT transition"); 95 s = eot[s]; 96 [input consume]; 97 // TODO: I had this as return accept[eot[s]] 98 // which assumed here that the EOT edge always 99 // went to an accept...faster to do this, but 100 // what about predicated edges coming from EOT 101 // target? 102 continue; 103 } 104 [self noViableAlt:s Stream:input]; 105 return 0; 106 } 107 s = snext; 108 [input consume]; 109 continue; 110 } 111 112 if (eot[s] >= 0) {// EOT transition? we may still accept the input in the next state 113 if ( debug > 2 ) NSLog(@"EOT transition"); 114 s = eot[s]; 115 [input consume]; 116 continue; 117 } 118 if ( c == ANTLRTokenTypeEOF && eof[s] >= 0) { // we are at EOF and may even accept the input. 119 if ( debug > 2 ) NSLog(@"accept via EOF; predict %d from %d", accept[eof[s]], eof[s]); 120 return accept[eof[s]]; 121 } 122 if ( debug > 2 ) { 123 NSLog(@"no viable alt!\n"); 124 NSLog(@"min[%d] = %d\n", s, min[s]); 125 NSLog(@"max[%d] = %d\n", s, min[s]); 126 NSLog(@"eot[%d] = %d\n", s, min[s]); 127 NSLog(@"eof[%d] = %d\n", s, min[s]); 128 for (NSInteger p = 0; p < self.len; p++) { 129 NSLog(@"%d ", transition[s][p]); 130 } 131 NSLog(@"\n"); 132 } 133 [self noViableAlt:s Stream:input]; 134 return 0; 135 } 136 } 137 @finally { 138 [input rewind:aMark]; 139 } 140 return 0; // silence warning 141} 142 143- (void) noViableAlt:(NSInteger)state Stream:(id<ANTLRIntStream>)anInput 144{ 145 if ([recognizer.state isBacktracking]) { 146 [recognizer.state setFailed:YES]; 147 return; 148 } 149 ANTLRNoViableAltException *nvae = [ANTLRNoViableAltException newException:decisionNumber state:state stream:anInput]; 150 [self error:nvae]; 151 @throw nvae; 152} 153 154- (NSInteger) specialStateTransition:(NSInteger)state Stream:(id<ANTLRIntStream>)anInput 155{ 156 @throw [ANTLRNoViableAltException newException:-1 state:state stream:anInput]; 157 return -1; 158} 159 160- (void) error:(ANTLRNoViableAltException *)nvae 161{ 162 // empty, hook for debugger support 163} 164 165- (NSString *) description 166{ 167 return @"subclass responsibility"; 168} 169 170- (BOOL) evaluateSyntacticPredicate:(SEL)synpredFragment 171{ 172 return [recognizer evaluateSyntacticPredicate:synpredFragment]; 173} 174 175+ (void) setIsEmittingDebugInfo:(BOOL) shouldEmitDebugInfo 176{ 177 debug = shouldEmitDebugInfo; 178} 179 180/** Given a String that has a run-length-encoding of some unsigned shorts 181 * like "\1\2\3\9", convert to short[] {2,9,9,9}. We do this to avoid 182 * static short[] which generates so much init code that the class won't 183 * compile. :( 184 */ 185- (short *) unpackEncodedString:(NSString *)encodedString 186{ 187 // walk first to find how big it is. 188 int size = 0; 189 for (int i=0; i < [encodedString length]; i+=2) { 190 size += [encodedString characterAtIndex:i]; 191 } 192 __strong short *data = (short *)calloc(size, sizeof(short)); 193 int di = 0; 194 for (int i=0; i < [encodedString length]; i+=2) { 195 char n = [encodedString characterAtIndex:i]; 196 char v = [encodedString characterAtIndex:i+1]; 197 // add v n times to data 198 for (int j = 0; j < n; j++) { 199 data[di++] = v; 200 } 201 } 202 return data; 203} 204 205/** Hideous duplication of code, but I need different typed arrays out :( */ 206- (char *) unpackEncodedStringToUnsignedChars:(NSString *)encodedString 207{ 208 // walk first to find how big it is. 209 int size = 0; 210 for (int i=0; i < [encodedString length]; i+=2) { 211 size += [encodedString characterAtIndex:i]; 212 } 213 __strong short *data = (short *)calloc(size, sizeof(short)); 214 int di = 0; 215 for (int i=0; i < [encodedString length]; i+=2) { 216 char n = [encodedString characterAtIndex:i]; 217 char v = [encodedString characterAtIndex:i+1]; 218 // add v n times to data 219 for (int j = 0; j < n; j++) { 220 data[di++] = v; 221 } 222 } 223 return (char *)data; 224} 225 226- (NSInteger)getDecision 227{ 228 return decisionNumber; 229} 230 231- (void)setDecision:(NSInteger)aDecison 232{ 233 decisionNumber = aDecison; 234} 235 236- (ANTLRBaseRecognizer *)getRecognizer 237{ 238 return recognizer; 239} 240 241- (void)setRecognizer:(ANTLRBaseRecognizer *)aRecognizer 242{ 243 if ( recognizer != aRecognizer ) { 244 if ( recognizer ) [recognizer release]; 245 [aRecognizer retain]; 246 } 247 recognizer = aRecognizer; 248} 249 250- (NSInteger)length 251{ 252 return len; 253} 254 255@synthesize eot; 256@synthesize eof; 257@synthesize min; 258@synthesize max; 259@synthesize accept; 260@synthesize special; 261@synthesize transition; 262@end 263