aboutsummaryrefslogtreecommitdiff
path: root/antlr-3.4/runtime/ObjC/Framework/ANTLRDFA.m
diff options
context:
space:
mode:
Diffstat (limited to 'antlr-3.4/runtime/ObjC/Framework/ANTLRDFA.m')
-rw-r--r--antlr-3.4/runtime/ObjC/Framework/ANTLRDFA.m262
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