Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added support for EBNF grammars.

  • Loading branch information...
commit a73a8f68a12cc60635188edaf63d5b8d54ed2153 1 parent 773a846
Tom Davie beelsebob authored
17 CoreParse.xcodeproj/project.pbxproj
View
@@ -77,6 +77,8 @@
1F9F83A213B731F3006E939D /* Expression.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9F83A013B731F3006E939D /* Expression.m */; };
1F9F83A613B732AC006E939D /* Term.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F9F83A413B732AC006E939D /* Term.h */; };
1F9F83A713B732AC006E939D /* Term.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9F83A513B732AC006E939D /* Term.m */; };
+ 1F9F83AC13B7CABA006E939D /* CPRHSItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F9F83AA13B7CAB9006E939D /* CPRHSItem.h */; };
+ 1F9F83AD13B7CABA006E939D /* CPRHSItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F9F83AB13B7CABA006E939D /* CPRHSItem.m */; };
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, ); }; };
@@ -89,6 +91,8 @@
1FB81323132FEDAF0095982D /* CPTestWhiteSpaceIgnoringDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FB81321132FEDAF0095982D /* CPTestWhiteSpaceIgnoringDelegate.m */; };
1FB81326132FF16E0095982D /* CPTestMapCSSTokenisingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FB81324132FF16E0095982D /* CPTestMapCSSTokenisingDelegate.h */; };
1FB81327132FF16E0095982D /* CPTestMapCSSTokenisingDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FB81325132FF16E0095982D /* CPTestMapCSSTokenisingDelegate.m */; };
+ 1FC00D5014544EDC00DC8D35 /* CPRHSItemResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC00D4E14544EDC00DC8D35 /* CPRHSItemResult.h */; };
+ 1FC00D5114544EDC00DC8D35 /* CPRHSItemResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FC00D4F14544EDC00DC8D35 /* CPRHSItemResult.m */; };
1FC1827D139ADC800027F597 /* CPGrammarPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC1827B139ADC800027F597 /* CPGrammarPrivate.h */; };
1FC1827E139ADC800027F597 /* CPGrammarPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FC1827C139ADC800027F597 /* CPGrammarPrivate.m */; };
1FC18282139AE3810027F597 /* CPGrammarInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC18280139AE3800027F597 /* CPGrammarInternal.h */; };
@@ -184,6 +188,8 @@
1F9F83A013B731F3006E939D /* Expression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Expression.m; sourceTree = "<group>"; };
1F9F83A413B732AC006E939D /* Term.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Term.h; sourceTree = "<group>"; };
1F9F83A513B732AC006E939D /* Term.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Term.m; sourceTree = "<group>"; };
+ 1F9F83AA13B7CAB9006E939D /* CPRHSItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPRHSItem.h; sourceTree = "<group>"; };
+ 1F9F83AB13B7CABA006E939D /* CPRHSItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CPRHSItem.m; 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>"; };
@@ -196,6 +202,8 @@
1FB81321132FEDAF0095982D /* CPTestWhiteSpaceIgnoringDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CPTestWhiteSpaceIgnoringDelegate.m; sourceTree = "<group>"; };
1FB81324132FF16E0095982D /* CPTestMapCSSTokenisingDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPTestMapCSSTokenisingDelegate.h; sourceTree = "<group>"; };
1FB81325132FF16E0095982D /* CPTestMapCSSTokenisingDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CPTestMapCSSTokenisingDelegate.m; sourceTree = "<group>"; };
+ 1FC00D4E14544EDC00DC8D35 /* CPRHSItemResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPRHSItemResult.h; sourceTree = "<group>"; };
+ 1FC00D4F14544EDC00DC8D35 /* CPRHSItemResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CPRHSItemResult.m; sourceTree = "<group>"; };
1FC1827B139ADC800027F597 /* CPGrammarPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPGrammarPrivate.h; sourceTree = "<group>"; };
1FC1827C139ADC800027F597 /* CPGrammarPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CPGrammarPrivate.m; sourceTree = "<group>"; };
1FC18280139AE3800027F597 /* CPGrammarInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPGrammarInternal.h; sourceTree = "<group>"; };
@@ -425,6 +433,10 @@
1F530B901322813F00F52EB5 /* CPRule.m */,
1FB3EB38132D096700ACC453 /* CPGrammarSymbol.h */,
1FB3EB39132D096800ACC453 /* CPGrammarSymbol.m */,
+ 1F9F83AA13B7CAB9006E939D /* CPRHSItem.h */,
+ 1F9F83AB13B7CABA006E939D /* CPRHSItem.m */,
+ 1FC00D4E14544EDC00DC8D35 /* CPRHSItemResult.h */,
+ 1FC00D4F14544EDC00DC8D35 /* CPRHSItemResult.m */,
);
path = Grammar;
sourceTree = "<group>";
@@ -504,6 +516,8 @@
1FC18282139AE3810027F597 /* CPGrammarInternal.h in Headers */,
1F9F83A113B731F3006E939D /* Expression.h in Headers */,
1F9F83A613B732AC006E939D /* Term.h in Headers */,
+ 1F9F83AC13B7CABA006E939D /* CPRHSItem.h in Headers */,
+ 1FC00D5014544EDC00DC8D35 /* CPRHSItemResult.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -568,6 +582,7 @@
1F0E88EC130462F300537D04 /* Project object */ = {
isa = PBXProject;
attributes = {
+ LastUpgradeCheck = 0420;
ORGANIZATIONNAME = "In The Beginning...";
};
buildConfigurationList = 1F0E88EF130462F300537D04 /* Build configuration list for PBXProject "CoreParse" */;
@@ -683,6 +698,8 @@
1FC18283139AE3810027F597 /* CPGrammarInternal.m in Sources */,
1F9F83A213B731F3006E939D /* Expression.m in Sources */,
1F9F83A713B732AC006E939D /* Term.m in Sources */,
+ 1F9F83AD13B7CABA006E939D /* CPRHSItem.m in Sources */,
+ 1FC00D5114544EDC00DC8D35 /* CPRHSItemResult.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
83 CoreParse/Grammar/CPGrammar.m
View
@@ -8,6 +8,7 @@
#import "CPGrammar.h"
#import "CPGrammarPrivate.h"
+#import "CPGrammarInternal.h"
#import "CPTokeniser.h"
#import "CPTokenStream.h"
@@ -17,7 +18,7 @@
#import "CPWhiteSpaceToken.h"
#import "CPQuotedRecogniser.h"
#import "CPIdentifierRecogniser.h"
-#import "CPSLRParser.h"
+#import "CPLALR1Parser.h"
#import "CPIdentifierToken.h"
#import "CPQuotedToken.h"
#import "CPNumberToken.h"
@@ -25,6 +26,8 @@
#import "CPItem.h"
#import "CPLR1Item.h"
+#import "CPRHSItem.h"
+
#import "NSSetFunctional.h"
#import <objc/runtime.h>
@@ -94,11 +97,49 @@ - (id)parser:(CPParser *)parser didProduceSyntaxTree:(CPSyntaxTree *)syntaxTree
case 9:
return [NSMutableArray arrayWithObject:[children objectAtIndex:0]];
case 10:
- case 11:
return [children objectAtIndex:0];
+ case 11:
+ {
+ CPRHSItem *i = [[[CPRHSItem alloc] init] autorelease];
+ [i setContents:[NSArray arrayWithObject:[children objectAtIndex:0]]];
+ NSString *symbol = [(CPKeywordToken *)[children objectAtIndex:1] keyword];
+ if ([symbol isEqualToString:@"*"])
+ {
+ [i setRepeats:YES];
+ [i setMayNotExist:YES];
+ }
+ else if ([symbol isEqualToString:@"+"])
+ {
+ [i setRepeats:YES];
+ [i setMayNotExist:NO];
+ }
+ else
+ {
+ [i setRepeats:NO];
+ [i setMayNotExist:YES];
+ }
+ return i;
+ }
case 12:
- return [CPGrammarSymbol nonTerminalWithName:[(CPIdentifierToken *)[children objectAtIndex:1] identifier]];
+ return [children objectAtIndex:0];
case 13:
+ {
+ CPRHSItem *i = [[[CPRHSItem alloc] init] autorelease];
+ [i setContents:[children objectAtIndex:1]];
+ [i setRepeats:NO];
+ [i setMayNotExist:NO];
+ return i;
+ }
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ return [children objectAtIndex:0];
+ return [children objectAtIndex:0];
+ case 19:
+ return [CPGrammarSymbol nonTerminalWithName:[(CPIdentifierToken *)[children objectAtIndex:1] identifier]];
+ case 20:
return [CPGrammarSymbol terminalWithName:[(CPQuotedToken *)[children objectAtIndex:0] content]];
default:
return syntaxTree;
@@ -156,6 +197,11 @@ - (id)initWithStart:(NSString *)initStart backusNaurForm:(NSString *)bnf
[tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"::="]];
[tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"<"]];
[tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@">"]];
+ [tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"("]];
+ [tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@")"]];
+ [tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"*"]];
+ [tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"+"]];
+ [tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"?"]];
[tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"|"]];
[tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@";"]];
[tokeniser addTokenRecogniser:[CPNumberRecogniser integerRecogniser]];
@@ -177,22 +223,33 @@ - (id)initWithStart:(NSString *)initStart backusNaurForm:(NSString *)bnf
CPRule *rightHandSide2 = [CPRule ruleWithName:@"rightHandSide" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"rightHandSide"], [CPGrammarSymbol terminalWithName:@"|"], nil] tag:6];
CPRule *rightHandSide3 = [CPRule ruleWithName:@"rightHandSide" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"sumset"], nil] tag:7];
- CPRule *sumset1 = [CPRule ruleWithName:@"sumset" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"sumset"], [CPGrammarSymbol nonTerminalWithName:@"grammarSymbol"], nil] tag:8];
- CPRule *sumset2 = [CPRule ruleWithName:@"sumset" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"grammarSymbol"], nil] tag:9];
+ CPRule *sumset1 = [CPRule ruleWithName:@"sumset" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"sumset"], [CPGrammarSymbol nonTerminalWithName:@"rightHandSideItem"], nil] tag:8];
+ CPRule *sumset2 = [CPRule ruleWithName:@"sumset" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"rightHandSideItem"], nil] tag:9];
+
+ CPRule *rightHandSideItem1 = [CPRule ruleWithName:@"rightHandSideItem" rightHandSideElements:[NSArray arrayWithObject:[CPGrammarSymbol nonTerminalWithName:@"unit"]] tag:10];
+ CPRule *rightHandSideItem2 = [CPRule ruleWithName:@"rightHandSideItem" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"unit"], [CPGrammarSymbol nonTerminalWithName:@"repeatSymbol"], nil] tag:11];
+
+ CPRule *unit1 = [CPRule ruleWithName:@"unit" rightHandSideElements:[NSArray arrayWithObject:[CPGrammarSymbol nonTerminalWithName:@"grammarSymbol"]] tag:12];
+ CPRule *unit2 = [CPRule ruleWithName:@"unit" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol terminalWithName:@"("], [CPGrammarSymbol nonTerminalWithName:@"sumset"], [CPGrammarSymbol terminalWithName:@")"], nil] tag:13];
+
+ CPRule *repeatSymbol1 = [CPRule ruleWithName:@"repeatSymbol" rightHandSideElements:[NSArray arrayWithObject:[CPGrammarSymbol terminalWithName:@"*"]] tag:14];
+ CPRule *repeatSymbol2 = [CPRule ruleWithName:@"repeatSymbol" rightHandSideElements:[NSArray arrayWithObject:[CPGrammarSymbol terminalWithName:@"+"]] tag:15];
+ CPRule *repeatSymbol3 = [CPRule ruleWithName:@"repeatSymbol" rightHandSideElements:[NSArray arrayWithObject:[CPGrammarSymbol terminalWithName:@"?"]] tag:16];
- CPRule *grammarSymbol1 = [CPRule ruleWithName:@"grammarSymbol" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"nonterminal"], nil] tag:10];
- CPRule *grammarSymbol2 = [CPRule ruleWithName:@"grammarSymbol" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"terminal"], nil] tag:11];
+ CPRule *grammarSymbol1 = [CPRule ruleWithName:@"grammarSymbol" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"nonterminal"], nil] tag:17];
+ CPRule *grammarSymbol2 = [CPRule ruleWithName:@"grammarSymbol" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol nonTerminalWithName:@"terminal"], nil] tag:18];
- CPRule *nonterminal = [CPRule ruleWithName:@"nonterminal" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol terminalWithName:@"<"], [CPGrammarSymbol terminalWithName:@"Identifier"], [CPGrammarSymbol terminalWithName:@">"], nil] tag:12];
+ CPRule *nonterminal = [CPRule ruleWithName:@"nonterminal" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol terminalWithName:@"<"], [CPGrammarSymbol terminalWithName:@"Identifier"], [CPGrammarSymbol terminalWithName:@">"], nil] tag:19];
- CPRule *terminal = [CPRule ruleWithName:@"terminal" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol terminalWithName:@"String"], nil] tag:13];
+ CPRule *terminal = [CPRule ruleWithName:@"terminal" rightHandSideElements:[NSArray arrayWithObjects:[CPGrammarSymbol terminalWithName:@"String"], nil] tag:20];
- CPGrammar *bnfGrammar = [CPGrammar grammarWithStart:@"ruleset" rules:[NSArray arrayWithObjects:ruleset1, ruleset2, rule1, rule2, unNumbered, rightHandSide1, rightHandSide2, rightHandSide3, sumset1, sumset2, grammarSymbol1, grammarSymbol2, nonterminal, terminal, nil]];
- CPParser *parser = [CPSLRParser parserWithGrammar:bnfGrammar];
+ CPGrammar *bnfGrammar = [CPGrammar grammarWithStart:@"ruleset" rules:[NSArray arrayWithObjects:ruleset1, ruleset2, rule1, rule2, unNumbered, rightHandSide1, rightHandSide2, rightHandSide3, sumset1, sumset2, rightHandSideItem1, rightHandSideItem2, unit1, unit2, repeatSymbol1, repeatSymbol2, repeatSymbol3, grammarSymbol1, grammarSymbol2, nonterminal, terminal, nil]];
+ CPParser *parser = [CPLALR1Parser parserWithGrammar:bnfGrammar];
[parser setDelegate:del];
- NSArray *initRules = [parser parse:tokenStream];
- return [self initWithStart:initStart rules:initRules];
+ NSMutableArray *initRules = [parser parse:tokenStream];
+
+ return [self initWithStart:initStart rules:[self tidyRightHandSides:initRules]];
}
- (id)init
6 CoreParse/Grammar/CPGrammarInternal.h
View
@@ -27,5 +27,11 @@
- (NSSet *)first:(NSArray *)obj;
- (NSString *)uniqueSymbolNameBasedOnName:(NSString *)name;
+- (NSString *)symbolNameNotInSet:(NSSet *)symbols basedOnName:(NSString *)name;
+
+- (NSArray *)tidyRightHandSides:(NSArray *)oldRules;
+- (NSSet *)collectRHSElementsForNewRules:(NSArray *)rightHandSide;
+- (NSDictionary *)nameNewRules:(NSSet *)rhsElements withRules:(NSArray *)oldRules;
+- (NSArray *)addRHSRules:(NSDictionary *)rules toRules:(NSArray *)oldRules;
@end
119 CoreParse/Grammar/CPGrammarInternal.m
View
@@ -12,6 +12,9 @@
#import "CPItem.h"
#import "CPLR1Item.h"
+#import "CPRHSItem.h"
+#import "CPRHSItemResult.h"
+
#import "NSSetFunctional.h"
@implementation CPGrammar (CPGrammarInternal)
@@ -221,9 +224,13 @@ - (NSSet *)first:(NSArray *)symbols
- (NSString *)uniqueSymbolNameBasedOnName:(NSString *)name
{
+ return [self symbolNameNotInSet:[self allSymbolNames] basedOnName:name];
+}
+
+- (NSString *)symbolNameNotInSet:(NSSet *)symbols basedOnName:(NSString *)name
+{
NSString *testName = [[name copy] autorelease];
- NSSet *allSymbols = [self allSymbolNames];
- while ([allSymbols containsObject:testName])
+ while ([symbols containsObject:testName])
{
testName = [NSString stringWithFormat:@"_%@", testName];
}
@@ -231,4 +238,112 @@ - (NSString *)uniqueSymbolNameBasedOnName:(NSString *)name
return testName;
}
+- (NSArray *)tidyRightHandSides:(NSArray *)oldRules
+{
+ NSMutableSet *rhsElements = [NSMutableSet set];
+ for (CPRule *r in oldRules)
+ {
+ [rhsElements unionSet:[self collectRHSElementsForNewRules:[r rightHandSideElements]]];
+ }
+
+ NSDictionary *names = [self nameNewRules:rhsElements withRules:oldRules];
+
+ return [self addRHSRules:names toRules:oldRules];
+}
+
+- (NSSet *)collectRHSElementsForNewRules:(NSArray *)rightHandSide
+{
+ NSMutableSet *ret = [NSMutableSet set];
+ Class itemClass = [CPRHSItem class];
+ for (id element in rightHandSide)
+ {
+ if ([element isKindOfClass:itemClass])
+ {
+ [ret addObject:element];
+ [ret unionSet:[self collectRHSElementsForNewRules:[(CPRHSItem *)element contents]]];
+ }
+ }
+ return ret;
+}
+
+- (NSDictionary *)nameNewRules:(NSSet *)rhsElements withRules:(NSArray *)oldRules
+{
+ NSSet *symbolNames = [self symbolNamesInRules:oldRules];
+ NSUInteger name = 0;
+ NSMutableDictionary *namedRules = [NSMutableDictionary dictionaryWithCapacity:[rhsElements count]];
+ for (CPRHSItem *item in rhsElements)
+ {
+ [namedRules setObject:[self symbolNameNotInSet:symbolNames basedOnName:[NSString stringWithFormat:@"RHS%d", name]] forKey:item];
+ name++;
+ }
+ return namedRules;
+}
+
+- (NSArray *)addRHSRules:(NSDictionary *)newRules toRules:(NSArray *)oldRules
+{
+ NSMutableArray *rules = [[NSMutableArray alloc] initWithArray:oldRules];
+
+ Class rhsItemClass = [CPRHSItemResult class];
+ for (CPRHSItem *item in newRules)
+ {
+ NSString *ruleName = [newRules objectForKey:item];
+ CPRule *rule;
+ if ([item mayNotExist])
+ {
+ rule = [[[CPRule alloc] initWithName:ruleName rightHandSideElements:[NSArray array]] autorelease];
+ [rule setTag:0];
+ }
+ else
+ {
+ rule = [[[CPRule alloc] initWithName:ruleName rightHandSideElements:[item contents]] autorelease];
+ [rule setTag:1];
+ }
+ [rule setRepresentitiveClass:rhsItemClass];
+ [rules addObject:rule];
+
+ if ([item repeats])
+ {
+ rule = [[[CPRule alloc] initWithName:ruleName rightHandSideElements:[[item contents] arrayByAddingObject:[CPGrammarSymbol nonTerminalWithName:ruleName]]] autorelease];
+ [rule setTag:2];
+ }
+ else if ([item mayNotExist])
+ {
+ rule = [[[CPRule alloc] initWithName:ruleName rightHandSideElements:[item contents]] autorelease];
+ [rule setTag:1];
+ }
+ else
+ {
+ rule = nil;
+ }
+
+ if (nil != rule)
+ {
+ [rule setRepresentitiveClass:rhsItemClass];
+ [rules addObject:rule];
+ }
+ }
+
+ Class itemClass = [CPRHSItem class];
+ for (CPRule *rule in rules)
+ {
+ NSArray *rhsElements = [rule rightHandSideElements];
+ NSMutableArray *newRightHandSideElements = [NSMutableArray arrayWithCapacity:[rhsElements count]];
+ for (id element in rhsElements)
+ {
+ if ([element isKindOfClass:itemClass])
+ {
+ [newRightHandSideElements addObject:[CPGrammarSymbol nonTerminalWithName:[newRules objectForKey:element]]];
+ }
+ else
+ {
+ [newRightHandSideElements addObject:element];
+ }
+ }
+ [rule setRightHandSideElements:newRightHandSideElements];
+ }
+
+ return rules;
+}
+
+
@end
1  CoreParse/Grammar/CPGrammarPrivate.h
View
@@ -20,6 +20,7 @@
- (NSArray *)orderedRules;
- (NSSet *)allSymbolNames;
+- (NSSet *)symbolNamesInRules:(NSArray *)rules;
- (NSSet *)firstSymbol:(CPGrammarSymbol *)obj;
@end
15 CoreParse/Grammar/CPGrammarPrivate.m
View
@@ -117,14 +117,23 @@ - (NSSet *)firstSymbol:(CPGrammarSymbol *)sym
- (NSSet *)allSymbolNames
{
+ return [self symbolNamesInRules:[self rules]];
+}
+
+- (NSSet *)symbolNamesInRules:(NSArray *)rules
+{
NSMutableSet *symbols = [NSMutableSet set];
- for (CPRule *rule in [self rules])
+ Class grammarSymbolClass = [CPGrammarSymbol class];
+ for (CPRule *rule in rules)
{
[symbols addObject:[rule name]];
- for (CPGrammarSymbol *sym in [rule rightHandSideElements])
+ for (id sym in [rule rightHandSideElements])
{
- [symbols addObject:[sym name]];
+ if ([sym isKindOfClass:grammarSymbolClass])
+ {
+ [symbols addObject:[sym name]];
+ }
}
}
18 CoreParse/Grammar/CPRHSItem.h
View
@@ -0,0 +1,18 @@
+//
+// CPRHSItem.h
+// CoreParse
+//
+// Created by Thomas Davie on 26/06/2011.
+// Copyright 2011 In The Beginning... All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface CPRHSItem : NSObject <NSCopying>
+
+@property (readwrite,copy) NSArray *contents;
+
+@property (readwrite,assign) BOOL repeats;
+@property (readwrite,assign) BOOL mayNotExist;
+
+@end
41 CoreParse/Grammar/CPRHSItem.m
View
@@ -0,0 +1,41 @@
+//
+// CPRHSItem.m
+// CoreParse
+//
+// Created by Thomas Davie on 26/06/2011.
+// Copyright 2011 In The Beginning... All rights reserved.
+//
+
+#import "CPRHSItem.h"
+
+@implementation CPRHSItem
+
+@synthesize contents;
+@synthesize repeats;
+@synthesize mayNotExist;
+
+- (NSUInteger)hash
+{
+ return [[self contents] hash] << 2 + ([self repeats] ? 0x2 : 0x0) + ([self mayNotExist] ? 0x1 : 0x0);
+}
+
+- (BOOL)isEqual:(id)object
+{
+ if ([object isKindOfClass:[CPRHSItem class]])
+ {
+ CPRHSItem *i = (CPRHSItem *)object;
+ return [[self contents] isEqualToArray:[i contents]] && [self repeats] == [i repeats] && [self mayNotExist] == [i mayNotExist];
+ }
+ return NO;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ CPRHSItem *other = [[CPRHSItem allocWithZone:zone] init];
+ [other setContents:[self contents]];
+ [other setRepeats:[self repeats]];
+ [other setMayNotExist:[self mayNotExist]];
+ return other;
+}
+
+@end
17 CoreParse/Grammar/CPRHSItemResult.h
View
@@ -0,0 +1,17 @@
+//
+// CPRHSItemResult.h
+// CoreParse
+//
+// Created by Thomas Davie on 23/10/2011.
+// Copyright (c) 2011 In The Beginning... All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "CPParser.h"
+
+@interface CPRHSItemResult : NSObject <CPParseResult>
+
+@property (readwrite, retain) NSMutableArray *contents;
+
+@end
59 CoreParse/Grammar/CPRHSItemResult.m
View
@@ -0,0 +1,59 @@
+//
+// CPRHSItemResult.m
+// CoreParse
+//
+// Created by Thomas Davie on 23/10/2011.
+// Copyright (c) 2011 In The Beginning... All rights reserved.
+//
+
+#import "CPRHSItemResult.h"
+
+@implementation CPRHSItemResult
+
+@synthesize contents;
+
+- (id)initWithSyntaxTree:(CPSyntaxTree *)syntaxTree
+{
+ self = [super init];
+
+ if (nil != self)
+ {
+ NSArray *children = [syntaxTree children];
+
+ switch ([[syntaxTree rule] tag])
+ {
+ case 0:
+ [self setContents:[NSMutableArray array]];
+ break;
+ case 1:
+ [self setContents:[[children mutableCopy] autorelease]];
+ break;
+ case 2:
+ {
+ NSMutableArray *nextContents = (NSMutableArray *)[children lastObject];
+ NSUInteger i = 0;
+ for (id newContent in [children subarrayWithRange:NSMakeRange(0, [children count] - 1)])
+ {
+ [nextContents insertObject:newContent atIndex:i];
+ i++;
+ }
+ [self setContents:nextContents];
+ break;
+ }
+ default:
+ [self release];
+ self = nil;
+ break;
+ }
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [contents release];
+ [super dealloc];
+}
+
+@end
13 CoreParse/Parsers/CPShiftReduceParser.m
View
@@ -13,6 +13,8 @@
#import "CPGrammarSymbol.h"
+#import "CPRHSItemResult.h"
+
@interface CPShiftReduceParser ()
- (CPShiftReduceAction *)actionForState:(NSUInteger)state token:(CPToken *)token;
@@ -78,13 +80,18 @@ - (id)parse:(CPTokenStream *)tokenStream
NSMutableArray *components = [NSMutableArray arrayWithCapacity:numElements];
NSRange stateStackRange = NSMakeRange([stateStack count] - numElements, numElements);
[stateStack enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:stateStackRange]
- options:NSEnumerationConcurrent | NSEnumerationReverse
+ options:NSEnumerationReverse
usingBlock:^(CPShiftReduceState *state, NSUInteger idx, BOOL *stop)
{
- [components insertObject:[state object] atIndex:0];
+ id o = [state object];
+ if ([o isKindOfClass:[CPRHSItemResult class]])
+ {
+ o = [(CPRHSItemResult *)o contents];
+ }
+ [components insertObject:o atIndex:0];
}];
[stateStack removeObjectsInRange:stateStackRange];
-
+
CPSyntaxTree *tree = [CPSyntaxTree syntaxTreeWithRule:reductionRule children:components];
id result = nil;
69 CoreParseTests/CoreParseTests.m
View
@@ -557,6 +557,7 @@ - (void)testBNFGrammarGeneration
if (![grammar isEqual:grammar1])
{
+
STFail(@"Crating grammar from BNF failed", nil);
}
@@ -643,5 +644,73 @@ - (void)testJSONParsing
STFail(@"Failed to parse JSON", nil);
}
}
+
+- (void)testEBNF
+{
+ CPTokeniser *tokeniser = [[[CPTokeniser alloc] init] autorelease];
+ [tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"a"]];
+ [tokeniser addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"b"]];
+ CPTokenStream *tokenStream = [tokeniser tokenise:@"baaa"];
+ NSString *starGrammarString = @"A ::= \"b\"\"a\"*;";
+ CPGrammar *starGrammar = [CPGrammar grammarWithStart:@"A" backusNaurForm:starGrammarString];
+ CPParser *starParser = [CPLALR1Parser parserWithGrammar:starGrammar];
+ CPSyntaxTree *starTree = [starParser parse:tokenStream];
+ tokenStream = [tokeniser tokenise:@"baaa"];
+ NSString *plusGrammarString = @"A ::= \"b\"\"a\"+;";
+ CPGrammar *plusGrammar = [CPGrammar grammarWithStart:@"A" backusNaurForm:plusGrammarString];
+ CPParser *plusParser = [CPLALR1Parser parserWithGrammar:plusGrammar];
+ CPSyntaxTree *plusTree = [plusParser parse:tokenStream];
+ tokenStream = [tokeniser tokenise:@"baaa"];
+ NSString *queryGrammarString = @"A ::= \"b\"\"a\"\"a\"\"a\"\"a\"?;";
+ CPGrammar *queryGrammar = [CPGrammar grammarWithStart:@"A" backusNaurForm:queryGrammarString];
+ CPParser *queryParser = [CPLALR1Parser parserWithGrammar:queryGrammar];
+ CPSyntaxTree *queryTree = [queryParser parse:tokenStream];
+ tokenStream = [tokeniser tokenise:@"baaab"];
+ NSString *parenGrammarString = @"A ::= \"b\"(\"a\")*\"b\";";
+ CPGrammar *parenGrammar = [CPGrammar grammarWithStart:@"A" backusNaurForm:parenGrammarString];
+ CPParser *parenParser = [CPLALR1Parser parserWithGrammar:parenGrammar];
+ CPSyntaxTree *parenTree = [parenParser parse:tokenStream];
+
+ STAssertNotNil(starTree, @"EBNF star parser produced nil result", nil);
+ NSArray *as = [[starTree children] objectAtIndex:1];
+ if (![[(CPKeywordToken *)[[starTree children] objectAtIndex:0] keyword] isEqualToString:@"b"] ||
+ [as count] != 3 ||
+ ![[(CPKeywordToken *)[as objectAtIndex:0] keyword] isEqualToString:@"a"] ||
+ ![[(CPKeywordToken *)[as objectAtIndex:1] keyword] isEqualToString:@"a"] ||
+ ![[(CPKeywordToken *)[as objectAtIndex:2] keyword] isEqualToString:@"a"])
+ {
+ STFail(@"EBNF star parser did not correctly parse its result", nil);
+ }
+ STAssertNotNil(plusTree, @"EBNF plus parser produced nil result", nil);
+ as = [[plusTree children] objectAtIndex:1];
+ if (![[(CPKeywordToken *)[[plusTree children] objectAtIndex:0] keyword] isEqualToString:@"b"] ||
+ [as count] != 3 ||
+ ![[(CPKeywordToken *)[as objectAtIndex:0] keyword] isEqualToString:@"a"] ||
+ ![[(CPKeywordToken *)[as objectAtIndex:1] keyword] isEqualToString:@"a"] ||
+ ![[(CPKeywordToken *)[as objectAtIndex:2] keyword] isEqualToString:@"a"])
+ {
+ STFail(@"EBNF plus parser did not correctly parse its result", nil);
+ }
+ STAssertNotNil(queryTree, @"EBNF query parser produced nil result", nil);
+ as = [[queryTree children] objectAtIndex:4];
+ if (![[(CPKeywordToken *)[[queryTree children] objectAtIndex:0] keyword] isEqualToString:@"b"] ||
+ ![[(CPKeywordToken *)[[queryTree children] objectAtIndex:1] keyword] isEqualToString:@"a"] ||
+ ![[(CPKeywordToken *)[[queryTree children] objectAtIndex:2] keyword] isEqualToString:@"a"] ||
+ ![[(CPKeywordToken *)[[queryTree children] objectAtIndex:3] keyword] isEqualToString:@"a"] ||
+ [as count] != 0)
+ {
+ STFail(@"EBNF query parser did not correctly parse its result", nil);
+ }
+ STAssertNotNil(parenTree, @"EBNF paren parser produced nil result", nil);
+ as = [[parenTree children] objectAtIndex:1];
+ if (![[(CPKeywordToken *)[[parenTree children] objectAtIndex:0] keyword] isEqualToString:@"b"] ||
+ [as count] != 3 ||
+ ![[(CPKeywordToken *)[(NSArray *)[as objectAtIndex:0] objectAtIndex:0] keyword] isEqualToString:@"a"] ||
+ ![[(CPKeywordToken *)[(NSArray *)[as objectAtIndex:1] objectAtIndex:0] keyword] isEqualToString:@"a"] ||
+ ![[(CPKeywordToken *)[(NSArray *)[as objectAtIndex:2] objectAtIndex:0] keyword] isEqualToString:@"a"])
+ {
+ STFail(@"EBNF paren parser did not correctly parse its result", nil);
+ }
+}
@end
Please sign in to comment.
Something went wrong with that request. Please try again.