Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added checking for tags being used in a valid way.

  • Loading branch information...
commit ccf4d1e989fed3a21a9009a3b109ecf05390339b 1 parent 74f1821
@beelsebob authored
View
4 CoreParse.xcodeproj/project.pbxproj
@@ -140,6 +140,7 @@
1FA798261567DC58003AC8AE /* CPTestMapCSSTokenisingDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FB81325132FF16E0095982D /* CPTestMapCSSTokenisingDelegate.m */; };
1FA798271567DC5C003AC8AE /* CPTestErrorHandlingDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FA68DA414DE9D3D005519B9 /* CPTestErrorHandlingDelegate.m */; };
1FA866B715DFAEBC005350EE /* CPRule+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA866B515DFAEBB005350EE /* CPRule+Internal.h */; };
+ 1FA866C015E18F68005350EE /* CPRHSItem+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA866BE15E18F67005350EE /* CPRHSItem+Private.h */; };
1FB3EB24132BA02C00ACC453 /* CPTestEvaluatorDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FB3EB22132BA02C00ACC453 /* CPTestEvaluatorDelegate.h */; };
1FB3EB25132BA02C00ACC453 /* CPTestEvaluatorDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FB3EB23132BA02C00ACC453 /* CPTestEvaluatorDelegate.m */; };
1FB3EB2C132BB2F200ACC453 /* CPLR1Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FB3EB2A132BB2E600ACC453 /* CPLR1Parser.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -274,6 +275,7 @@
1FA68DA314DE9D3D005519B9 /* CPTestErrorHandlingDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPTestErrorHandlingDelegate.h; sourceTree = "<group>"; };
1FA68DA414DE9D3D005519B9 /* CPTestErrorHandlingDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CPTestErrorHandlingDelegate.m; sourceTree = "<group>"; };
1FA866B515DFAEBB005350EE /* CPRule+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CPRule+Internal.h"; sourceTree = "<group>"; };
+ 1FA866BE15E18F67005350EE /* CPRHSItem+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CPRHSItem+Private.h"; sourceTree = "<group>"; };
1FB3EB22132BA02C00ACC453 /* CPTestEvaluatorDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPTestEvaluatorDelegate.h; sourceTree = "<group>"; };
1FB3EB23132BA02C00ACC453 /* CPTestEvaluatorDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CPTestEvaluatorDelegate.m; sourceTree = "<group>"; };
1FB3EB2A132BB2E600ACC453 /* CPLR1Parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPLR1Parser.h; sourceTree = "<group>"; };
@@ -553,6 +555,7 @@
1FA866B515DFAEBB005350EE /* CPRule+Internal.h */,
1FB3EB38132D096700ACC453 /* CPGrammarSymbol.h */,
1FB3EB39132D096800ACC453 /* CPGrammarSymbol.m */,
+ 1FA866BE15E18F67005350EE /* CPRHSItem+Private.h */,
1F9F83AA13B7CAB9006E939D /* CPRHSItem.h */,
1F9F83AB13B7CABA006E939D /* CPRHSItem.m */,
1FC00D4E14544EDC00DC8D35 /* CPRHSItemResult.h */,
@@ -653,6 +656,7 @@
1FA68DA514DE9D3D005519B9 /* CPTestErrorHandlingDelegate.h in Headers */,
1F893A2314DEF40D00316FF7 /* CPTestErrorEvaluatorDelegate.h in Headers */,
1FA866B715DFAEBC005350EE /* CPRule+Internal.h in Headers */,
+ 1FA866C015E18F68005350EE /* CPRHSItem+Private.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
1  CoreParse/Grammar/CPGrammar.h
@@ -16,6 +16,7 @@
typedef enum
{
CPErrorCodeCouldNotParseEBNF = 1,
+ CPErrorCodeDuplicateTag = 2,
} CPErrorCode;
/**
View
6 CoreParse/Grammar/CPGrammar.m
@@ -314,7 +314,11 @@ - (id)initWithStart:(NSString *)initStart backusNaurForm:(NSString *)bnf error:(
return nil;
}
- NSArray *newRules = [self tidyRightHandSides:initRules];
+ NSArray *newRules = [self tidyRightHandSides:initRules error:error];
+ if (nil == newRules)
+ {
+ return nil;
+ }
return [self initWithStart:initStart rules:newRules];
}
View
2  CoreParse/Grammar/CPGrammarInternal.h
@@ -29,7 +29,7 @@
- (NSString *)uniqueSymbolNameBasedOnName:(NSString *)name;
- (NSString *)symbolNameNotInSet:(NSSet *)symbols basedOnName:(NSString *)name;
-- (NSArray *)tidyRightHandSides:(NSArray *)oldRules;
+- (NSArray *)tidyRightHandSides:(NSArray *)oldRules error:(NSError **)error;
- (NSSet *)collectRHSElementsForNewRules:(NSArray *)rightHandSide;
- (NSDictionary *)nameNewRules:(NSSet *)rhsElements withRules:(NSArray *)oldRules;
- (NSArray *)addRHSRules:(NSDictionary *)rules toRules:(NSArray *)oldRules;
View
58 CoreParse/Grammar/CPGrammarInternal.m
@@ -15,6 +15,7 @@
#import "CPLR1Item.h"
#import "CPRHSItem.h"
+#import "CPRHSItem+Private.h"
#import "CPRHSItemResult.h"
#import "NSSetFunctional.h"
@@ -240,8 +241,15 @@ - (NSString *)symbolNameNotInSet:(NSSet *)symbols basedOnName:(NSString *)name
return testName;
}
-- (NSArray *)tidyRightHandSides:(NSArray *)oldRules
+- (NSArray *)tidyRightHandSides:(NSArray *)oldRules error:(NSError **)error
{
+ NSError *invalidRuleError = [self checkRulesForErrors:oldRules];
+ if (nil != invalidRuleError)
+ {
+ *error = invalidRuleError;
+ return nil;
+ }
+
NSMutableSet *rhsElements = [NSMutableSet set];
for (CPRule *r in oldRules)
{
@@ -253,6 +261,54 @@ - (NSArray *)tidyRightHandSides:(NSArray *)oldRules
return [self addRHSRules:names toRules:oldRules];
}
+- (NSError *)checkRulesForErrors:(NSArray *)rules
+{
+ NSError *error = nil;
+ Class itemClass = [CPRHSItem class];
+ for (CPRule *rule in rules)
+ {
+ NSArray *rightHandSide = [rule rightHandSideElements];
+ NSMutableSet *tagNames = [NSMutableSet set];
+ for (id element in rightHandSide)
+ {
+ if ([element isKindOfClass:itemClass])
+ {
+ NSSet *newTagNames = [(CPRHSItem *)element tagNamesWithError:&error];
+ if (nil != error)
+ {
+ return error;
+ }
+ NSMutableSet *duplicateTags = [[tagNames mutableCopy] autorelease];
+ [duplicateTags intersectSet:newTagNames];
+ if ([duplicateTags count] > 0)
+ {
+ return [NSError errorWithDomain:CPEBNFParserErrorDomain
+ code:CPErrorCodeDuplicateTag
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithFormat:@"Duplicate tag names %@ in same part of alternative is not allowed in \"%@\".", duplicateTags, rule], NSLocalizedDescriptionKey,
+ nil]];
+ }
+ [tagNames unionSet:newTagNames];
+ NSString *tagName = [(CPRHSItem *)element tag];
+ if (nil != tagName)
+ {
+ if ([tagNames containsObject:tagName])
+ {
+ return [NSError errorWithDomain:CPEBNFParserErrorDomain
+ code:CPErrorCodeDuplicateTag
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithFormat:@"Duplicate tag names (%@) in same part of alternative is not allowed in \"%@\".", tagName, rule], NSLocalizedDescriptionKey,
+ nil]];
+ }
+ [tagNames addObject:tagName];
+ }
+ }
+ }
+ }
+
+ return nil;
+}
+
- (NSSet *)collectRHSElementsForNewRules:(NSArray *)rightHandSide
{
NSMutableSet *ret = [NSMutableSet set];
View
15 CoreParse/Grammar/CPRHSItem+Private.h
@@ -0,0 +1,15 @@
+//
+// CPRHSItem+Private.h
+// CoreParse
+//
+// Created by Tom Davie on 19/08/2012.
+// Copyright (c) 2012 In The Beginning... All rights reserved.
+//
+
+#import "CPRHSItem.h"
+
+@interface CPRHSItem (Private)
+
+- (NSSet *)tagNamesWithError:(NSError **)err;
+
+@end
View
72 CoreParse/Grammar/CPRHSItem.m
@@ -8,6 +8,9 @@
#import "CPRHSItem.h"
+#import "CPRHSItem+Private.h"
+#import "CPGrammar.h"
+
@implementation CPRHSItem
@synthesize alternatives = _alternatives;
@@ -28,8 +31,8 @@ - (BOOL)isEqual:(id)object
[self repeats] == [object repeats] &&
[self mayNotExist] == [object mayNotExist] &&
[self shouldCollapse] == [object shouldCollapse] &&
- (([self tag] == nil && [object tag] == nil) ||
- [[self tag] isEqualToString:[object tag]]));
+ (([self tag] == nil && [(CPRHSItem *)object tag] == nil) ||
+ [[self tag] isEqualToString:[(CPRHSItem *)object tag]]));
}
- (id)copyWithZone:(NSZone *)zone
@@ -91,3 +94,68 @@ - (NSString *)description
}
@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
View
7 CoreParseTests/CoreParseTests.m
@@ -698,6 +698,13 @@ - (void)testEBNF
STAssertNotNil(err, @"Error was nil after trying to create faulty grammar.");
STAssertNil(errorTestGrammar, @"Error test grammar was not nil despite being faulty.");
+ faultyGrammar = @"A ::= b@'b' b@'a'*;";
+ errorTestGrammar = [CPGrammar grammarWithStart:@"A" backusNaurForm:taggedStarGrammarString error:&err];
+ STAssertNotNil(err, @"Error was nil after using the same tag twice in a grammar rule.");
+ faultyGrammar = @"A ::= b@'b' (a@'a')*;";
+ errorTestGrammar = [CPGrammar grammarWithStart:@"A" backusNaurForm:taggedStarGrammarString error:&err];
+ STAssertNotNil(err, @"Error was nil after using a tag within a repeating section of a grammar rule.");
+
STAssertNotNil(starTree, @"EBNF star parser produced nil result", nil);
NSArray *as = [[starTree children] objectAtIndex:1];
if (![[(CPKeywordToken *)[[starTree children] objectAtIndex:0] keyword] isEqualToString:@"b"] ||
Please sign in to comment.
Something went wrong with that request. Please try again.