-
Notifications
You must be signed in to change notification settings - Fork 49
/
CPRHSItem.m
161 lines (142 loc) · 5.34 KB
/
CPRHSItem.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//
// CPRHSItem.m
// CoreParse
//
// Created by Thomas Davie on 26/06/2011.
// Copyright 2011 In The Beginning... All rights reserved.
//
#import "CPRHSItem.h"
#import "CPRHSItem+Private.h"
#import "CPGrammar.h"
@implementation CPRHSItem
@synthesize alternatives = _alternatives;
@synthesize repeats = _repeats;
@synthesize mayNotExist = _mayNotExist;
@synthesize tag = _tag;
@synthesize shouldCollapse = _shouldCollapse;
- (NSUInteger)hash
{
return [[self alternatives] hash] << 2 + ([self repeats] ? 0x2 : 0x0) + ([self mayNotExist] ? 0x1 : 0x0);
}
- (BOOL)isEqual:(id)object
{
return ([object isKindOfClass:[CPRHSItem class]] &&
[[self alternatives] isEqualToArray:[object alternatives]] &&
[self repeats] == [object repeats] &&
[self mayNotExist] == [object mayNotExist] &&
[self shouldCollapse] == [object shouldCollapse] &&
(([self tag] == nil && [(CPRHSItem *)object tag] == nil) ||
[[self tag] isEqualToString:[(CPRHSItem *)object tag]]));
}
- (id)copyWithZone:(NSZone *)zone
{
CPRHSItem *other = [[CPRHSItem allocWithZone:zone] init];
[other setAlternatives:[self alternatives]];
[other setRepeats:[self repeats]];
[other setMayNotExist:[self mayNotExist]];
[other setTag:[self tag]];
[other setShouldCollapse:[self shouldCollapse]];
return other;
}
- (void)dealloc
{
[_alternatives release];
[_tag release];
[super dealloc];
}
- (NSString *)description
{
NSMutableString *desc = [NSMutableString string];
if ([[self alternatives] count] != 1 || [[[self alternatives] objectAtIndex:0] count] != 1)
{
[desc appendString:@"("];
}
NSUInteger i = 0;
for (NSArray *components in [self alternatives])
{
i++;
NSUInteger j = 0;
for (id comp in components)
{
j++;
if (j != [components count])
{
[desc appendFormat:@"%@ ", comp];
}
else
{
[desc appendFormat:@"%@", comp];
}
}
if (i != [[self alternatives] count])
{
[desc appendString:@"| "];
}
}
if ([[self alternatives] count] != 1 || [[[self alternatives] objectAtIndex:0] count] != 1)
{
[desc appendString:@")"];
}
[desc appendString:[self repeats] ? ([self mayNotExist] ? @"*" : @"+") : ([self mayNotExist] ? @"?" : @"")];
return desc;
}
@end
@implementation CPRHSItem (Private)
- (NSSet *)tagNamesWithError:(NSError **)err
{
Class itemClass = [CPRHSItem class];
NSMutableSet *tagNames = [NSMutableSet set];
for (NSArray *components in [self alternatives])
{
NSMutableSet *tagNamesInAlternative = [NSMutableSet set];
for (id comp in components)
{
if ([comp isKindOfClass:itemClass])
{
NSSet *newTagNames = [(CPRHSItem *)comp tagNamesWithError:err];
if (nil != *err)
{
return nil;
}
NSMutableSet *duplicateTags = [[tagNamesInAlternative mutableCopy] autorelease];
[duplicateTags intersectSet:newTagNames];
if ([duplicateTags count] > 0)
{
*err = [NSError errorWithDomain:CPEBNFParserErrorDomain
code:CPErrorCodeDuplicateTag
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:@"Duplicate tag names %@ in same part of alternative is not allowed in \"%@\".", duplicateTags, self], NSLocalizedDescriptionKey,
nil]];
return nil;
}
[tagNamesInAlternative unionSet:newTagNames];
NSString *tagName = [(CPRHSItem *)comp tag];
if (nil != tagName)
{
if ([tagNamesInAlternative containsObject:tagName])
{
*err = [NSError errorWithDomain:CPEBNFParserErrorDomain
code:CPErrorCodeDuplicateTag
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:@"Duplicate tag names (%@) in same part of alternative is not allowed in \"%@\".", tagName, self], NSLocalizedDescriptionKey,
nil]];
return nil;
}
[tagNamesInAlternative addObject:tagName];
}
}
}
[tagNames unionSet:tagNamesInAlternative];
}
if ([tagNames count] > 0 && [self repeats])
{
*err = [NSError errorWithDomain:CPEBNFParserErrorDomain
code:CPErrorCodeDuplicateTag
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:@"Tag names are not allowed within repeating section of rule \"%@\".", self], NSLocalizedDescriptionKey,
nil]];
return nil;
}
return tagNames;
}
@end