Home | History | Annotate | Download | only in Framework
      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 
     31 NSInteger 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