1//
2//  ANTLRCommonErrorNode.m
3//  ANTLR
4//
5// [The "BSD licence"]
6// Copyright (c) 2010 Alan Condit
7// All rights reserved.
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions
11// are met:
12// 1. Redistributions of source code must retain the above copyright
13//    notice, this list of conditions and the following disclaimer.
14// 2. Redistributions in binary form must reproduce the above copyright
15//    notice, this list of conditions and the following disclaimer in the
16//    documentation and/or other materials provided with the distribution.
17// 3. The name of the author may not be used to endorse or promote products
18//    derived from this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#import "ANTLRCommonErrorNode.h"
32#import "ANTLRMissingTokenException.h"
33#import "ANTLRNoViableAltException.h"
34#import "ANTLRTreeNodeStream.h"
35#import "ANTLRUnwantedTokenException.h"
36
37@implementation ANTLRCommonErrorNode
38
39+ (id) newANTLRCommonErrorNode:(id<ANTLRTokenStream>)anInput
40                          From:(id<ANTLRToken>)aStartToken
41                            To:(id<ANTLRToken>)aStopToken
42                     Exception:(ANTLRRecognitionException *) e
43{
44    return [[ANTLRCommonErrorNode alloc] initWithInput:anInput From:aStartToken To:aStopToken Exception:e];
45}
46
47- (id) init
48{
49    self = [super init];
50    if ( self != nil ) {
51    }
52    return self;
53}
54
55- (id) initWithInput:(id<ANTLRTokenStream>)anInput
56                From:(id<ANTLRToken>)aStartToken
57                  To:(id<ANTLRToken>)aStopToken
58           Exception:(ANTLRRecognitionException *) e
59{
60    self = [super init];
61    if ( self != nil ) {
62        //System.out.println("aStartToken: "+aStartToken+", aStopToken: "+aStopToken);
63        if ( aStopToken == nil ||
64            ([aStopToken getTokenIndex] < [aStartToken getTokenIndex] &&
65             aStopToken.type != ANTLRTokenTypeEOF) )
66        {
67            // sometimes resync does not consume a token (when LT(1) is
68            // in follow set.  So, aStopToken will be 1 to left to aStartToken. adjust.
69            // Also handle case where aStartToken is the first token and no token
70            // is consumed during recovery; LT(-1) will return null.
71            aStopToken = aStartToken;
72        }
73        input = anInput;
74        if ( input ) [input retain];
75        startToken = aStartToken;
76        if ( startToken ) [startToken retain];
77        stopToken = aStopToken;
78        if ( stopToken ) [stopToken retain];
79        trappedException = e;
80        if ( trappedException ) [trappedException retain];
81    }
82    return self;
83}
84
85- (void)dealloc
86{
87#ifdef DEBUG_DEALLOC
88    NSLog( @"called dealloc in ANTLRCommonErrorNode" );
89#endif
90    if ( input ) [input release];
91    if ( startToken ) [startToken release];
92    if ( stopToken ) [stopToken release];
93    if ( trappedException ) [trappedException release];
94	[super dealloc];
95}
96
97- (BOOL) isNil
98{
99    return NO;
100}
101
102- (NSInteger)type
103{
104    return ANTLRTokenTypeInvalid;
105}
106
107- (NSString *)text
108{
109    NSString *badText = nil;
110    if ( [startToken isKindOfClass:[self class]] ) {
111        int i = [(id<ANTLRToken>)startToken getTokenIndex];
112        int j = [(id<ANTLRToken>)stopToken getTokenIndex];
113        if ( stopToken.type == ANTLRTokenTypeEOF ) {
114            j = [(id<ANTLRTokenStream>)input size];
115        }
116        badText = [(id<ANTLRTokenStream>)input toStringFromStart:i ToEnd:j];
117    }
118    else if ( [startToken isKindOfClass:[self class]] ) {
119        badText = [(id<ANTLRTreeNodeStream>)input toStringFromNode:startToken ToNode:stopToken];
120    }
121    else {
122        // people should subclass if they alter the tree type so this
123        // next one is for sure correct.
124        badText = @"<unknown>";
125    }
126    return badText;
127}
128
129- (NSString *)toString
130{
131    NSString *aString;
132    if ( [trappedException isKindOfClass:[ANTLRMissingTokenException class]] ) {
133        aString = [NSString stringWithFormat:@"<missing type: %@ >",
134        [(ANTLRMissingTokenException *)trappedException getMissingType]];
135        return aString;
136    }
137    else if ( [trappedException isKindOfClass:[ANTLRUnwantedTokenException class]] ) {
138        aString = [NSString stringWithFormat:@"<extraneous: %@, resync=%@>",
139        [trappedException getUnexpectedToken],
140        [self text]];
141        return aString;
142    }
143    else if ( [trappedException isKindOfClass:[ANTLRMismatchedTokenException class]] ) {
144        aString = [NSString stringWithFormat:@"<mismatched token: %@, resync=%@>", trappedException.token, [self text]];
145        return aString;
146    }
147    else if ( [trappedException isKindOfClass:[ANTLRNoViableAltException class]] ) {
148        aString = [NSString stringWithFormat:@"<unexpected:  %@, resync=%@>", trappedException.token, [self text]];
149        return aString;
150    }
151    aString = [NSString stringWithFormat:@"<error: %@>",[self text]];
152    return aString;
153}
154
155@synthesize input;
156@synthesize startToken;
157@synthesize stopToken;
158@synthesize trappedException;
159@end
160