diff options
Diffstat (limited to 'antlr-3.4/runtime/ObjC/Framework/ANTLRDFA.m')
-rw-r--r-- | antlr-3.4/runtime/ObjC/Framework/ANTLRDFA.m | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/antlr-3.4/runtime/ObjC/Framework/ANTLRDFA.m b/antlr-3.4/runtime/ObjC/Framework/ANTLRDFA.m new file mode 100644 index 0000000..b42daf5 --- /dev/null +++ b/antlr-3.4/runtime/ObjC/Framework/ANTLRDFA.m @@ -0,0 +1,262 @@ +// [The "BSD licence"] +// Copyright (c) 2006-2007 Kay Roepke 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 "ANTLRDFA.h" +#import <ANTLRToken.h> +#import <ANTLRNoViableAltException.h> + +NSInteger debug = 0; + +@implementation ANTLRDFA +@synthesize recognizer; +@synthesize decisionNumber; +@synthesize len; + +- (id) initWithRecognizer:(ANTLRBaseRecognizer *) theRecognizer +{ + if ((self = [super init]) != nil) { + recognizer = theRecognizer; + [recognizer retain]; + debug = 0; + } + return self; +} + +// using the tables ANTLR generates for the DFA based prediction this method simulates the DFA +// and returns the prediction of the alternative to be used. +- (NSInteger) predict:(id<ANTLRIntStream>)input +{ + if ( debug > 2 ) { + NSLog(@"Enter DFA.predict for decision %d", decisionNumber); + } + int aMark = [input mark]; + int s = 0; + @try { + while (YES) { + if ( debug > 2 ) + NSLog(@"DFA %d state %d LA(1)='%c'(%x)", decisionNumber, s, (unichar)[input LA:1], [input LA:1]); + NSInteger specialState = special[s]; + if (specialState >= 0) { + // this state is special in that it has some code associated with it. we cannot do this in a pure DFA so + // we signal the caller accordingly. + if ( debug > 2 ) { + NSLog(@"DFA %d state %d is special state %d", decisionNumber, s, specialState); + } + s = [self specialStateTransition:specialState Stream:input]; + if ( debug > 2 ) { + NSLog(@"DFA %d returns from special state %d to %d", decisionNumber, specialState, s); + } + if (s == -1 ) { + [self noViableAlt:s Stream:input]; + return 0; + } + [input consume]; + continue; + } + if (accept[s] >= 1) { // if this is an accepting state return the prediction + if ( debug > 2 ) NSLog(@"accept; predict %d from state %d", accept[s], s); + return accept[s]; + } + // based on the lookahead lookup the next transition, consume and do transition + // or signal that we have no viable alternative + int c = [input LA:1]; + if ( (unichar)c >= min[s] && (unichar)c <= max[s]) { + int snext = transition[s][c-min[s]]; + if (snext < 0) { + // was in range but not a normal transition + // must check EOT, which is like the else clause. + // eot[s]>=0 indicates that an EOT edge goes to another + // state. + if (eot[s] >= 0) { + if ( debug > 2 ) NSLog(@"EOT transition"); + s = eot[s]; + [input consume]; + // TODO: I had this as return accept[eot[s]] + // which assumed here that the EOT edge always + // went to an accept...faster to do this, but + // what about predicated edges coming from EOT + // target? + continue; + } + [self noViableAlt:s Stream:input]; + return 0; + } + s = snext; + [input consume]; + continue; + } + + if (eot[s] >= 0) {// EOT transition? we may still accept the input in the next state + if ( debug > 2 ) NSLog(@"EOT transition"); + s = eot[s]; + [input consume]; + continue; + } + if ( c == ANTLRTokenTypeEOF && eof[s] >= 0) { // we are at EOF and may even accept the input. + if ( debug > 2 ) NSLog(@"accept via EOF; predict %d from %d", accept[eof[s]], eof[s]); + return accept[eof[s]]; + } + if ( debug > 2 ) { + NSLog(@"no viable alt!\n"); + NSLog(@"min[%d] = %d\n", s, min[s]); + NSLog(@"max[%d] = %d\n", s, min[s]); + NSLog(@"eot[%d] = %d\n", s, min[s]); + NSLog(@"eof[%d] = %d\n", s, min[s]); + for (NSInteger p = 0; p < self.len; p++) { + NSLog(@"%d ", transition[s][p]); + } + NSLog(@"\n"); + } + [self noViableAlt:s Stream:input]; + return 0; + } + } + @finally { + [input rewind:aMark]; + } + return 0; // silence warning +} + +- (void) noViableAlt:(NSInteger)state Stream:(id<ANTLRIntStream>)anInput +{ + if ([recognizer.state isBacktracking]) { + [recognizer.state setFailed:YES]; + return; + } + ANTLRNoViableAltException *nvae = [ANTLRNoViableAltException newException:decisionNumber state:state stream:anInput]; + [self error:nvae]; + @throw nvae; +} + +- (NSInteger) specialStateTransition:(NSInteger)state Stream:(id<ANTLRIntStream>)anInput +{ + @throw [ANTLRNoViableAltException newException:-1 state:state stream:anInput]; + return -1; +} + +- (void) error:(ANTLRNoViableAltException *)nvae +{ + // empty, hook for debugger support +} + +- (NSString *) description +{ + return @"subclass responsibility"; +} + +- (BOOL) evaluateSyntacticPredicate:(SEL)synpredFragment +{ + return [recognizer evaluateSyntacticPredicate:synpredFragment]; +} + ++ (void) setIsEmittingDebugInfo:(BOOL) shouldEmitDebugInfo +{ + debug = shouldEmitDebugInfo; +} + +/** Given a String that has a run-length-encoding of some unsigned shorts + * like "\1\2\3\9", convert to short[] {2,9,9,9}. We do this to avoid + * static short[] which generates so much init code that the class won't + * compile. :( + */ +- (short *) unpackEncodedString:(NSString *)encodedString +{ + // walk first to find how big it is. + int size = 0; + for (int i=0; i < [encodedString length]; i+=2) { + size += [encodedString characterAtIndex:i]; + } + __strong short *data = (short *)calloc(size, sizeof(short)); + int di = 0; + for (int i=0; i < [encodedString length]; i+=2) { + char n = [encodedString characterAtIndex:i]; + char v = [encodedString characterAtIndex:i+1]; + // add v n times to data + for (int j = 0; j < n; j++) { + data[di++] = v; + } + } + return data; +} + +/** Hideous duplication of code, but I need different typed arrays out :( */ +- (char *) unpackEncodedStringToUnsignedChars:(NSString *)encodedString +{ + // walk first to find how big it is. + int size = 0; + for (int i=0; i < [encodedString length]; i+=2) { + size += [encodedString characterAtIndex:i]; + } + __strong short *data = (short *)calloc(size, sizeof(short)); + int di = 0; + for (int i=0; i < [encodedString length]; i+=2) { + char n = [encodedString characterAtIndex:i]; + char v = [encodedString characterAtIndex:i+1]; + // add v n times to data + for (int j = 0; j < n; j++) { + data[di++] = v; + } + } + return (char *)data; +} + +- (NSInteger)getDecision +{ + return decisionNumber; +} + +- (void)setDecision:(NSInteger)aDecison +{ + decisionNumber = aDecison; +} + +- (ANTLRBaseRecognizer *)getRecognizer +{ + return recognizer; +} + +- (void)setRecognizer:(ANTLRBaseRecognizer *)aRecognizer +{ + if ( recognizer != aRecognizer ) { + if ( recognizer ) [recognizer release]; + [aRecognizer retain]; + } + recognizer = aRecognizer; +} + +- (NSInteger)length +{ + return len; +} + +@synthesize eot; +@synthesize eof; +@synthesize min; +@synthesize max; +@synthesize accept; +@synthesize special; +@synthesize transition; +@end |