Permalink
Browse files

Added the ability to ask the parser not to recover from an error.

  • Loading branch information...
1 parent 882d13d commit 068cce66931c47c770bb89bce200bc37a7c83092 @beelsebob beelsebob committed Mar 3, 2012
@@ -73,7 +73,7 @@
1F530B921322814000F52EB5 /* CPRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F530B901322813F00F52EB5 /* CPRule.m */; };
1F6D44901348CC9500E982C7 /* CPLALR1Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F6D448E1348CC9500E982C7 /* CPLALR1Parser.h */; settings = {ATTRIBUTES = (Public, ); }; };
1F6D44911348CC9600E982C7 /* CPLALR1Parser.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F6D448F1348CC9500E982C7 /* CPLALR1Parser.m */; };
- 1F893A1F14DEEBFC00316FF7 /* CPRecoveryAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F893A1D14DEEBFC00316FF7 /* CPRecoveryAction.h */; };
+ 1F893A1F14DEEBFC00316FF7 /* CPRecoveryAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F893A1D14DEEBFC00316FF7 /* CPRecoveryAction.h */; settings = {ATTRIBUTES = (Public, ); }; };
1F893A2014DEEBFC00316FF7 /* CPRecoveryAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F893A1E14DEEBFC00316FF7 /* CPRecoveryAction.m */; };
1F893A2314DEF40D00316FF7 /* CPTestErrorEvaluatorDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F893A2114DEF40D00316FF7 /* CPTestErrorEvaluatorDelegate.h */; };
1F893A2414DEF40D00316FF7 /* CPTestErrorEvaluatorDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F893A2214DEF40D00316FF7 /* CPTestErrorEvaluatorDelegate.m */; };
@@ -129,7 +129,7 @@
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 */; };
- 1FA68DA014DE98C4005519B9 /* CPErrorToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA68D9E14DE98C4005519B9 /* CPErrorToken.h */; };
+ 1FA68DA014DE98C4005519B9 /* CPErrorToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA68D9E14DE98C4005519B9 /* CPErrorToken.h */; settings = {ATTRIBUTES = (Public, ); }; };
1FA68DA114DE98C4005519B9 /* CPErrorToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FA68D9F14DE98C4005519B9 /* CPErrorToken.m */; };
1FA68DA514DE9D3D005519B9 /* CPTestErrorHandlingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA68DA314DE9D3D005519B9 /* CPTestErrorHandlingDelegate.h */; };
1FA68DA614DE9D3D005519B9 /* CPTestErrorHandlingDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FA68DA414DE9D3D005519B9 /* CPTestErrorHandlingDelegate.m */; };
@@ -614,6 +614,8 @@
1FB3EB3A132D096900ACC453 /* CPGrammarSymbol.h in Headers */,
1F45A2E413422E1300092D78 /* CPJSONParser.h in Headers */,
1F3881DC1322ACE7000C8876 /* CPShiftReduceParser.h in Headers */,
+ 1FA68DA014DE98C4005519B9 /* CPErrorToken.h in Headers */,
+ 1F893A1F14DEEBFC00316FF7 /* CPRecoveryAction.h in Headers */,
1F3881E11322ADC9000C8876 /* CPShiftReduceAction.h in Headers */,
1F3881E51322AEE8000C8876 /* CPShiftReduceState.h in Headers */,
1F3881ED1322B66B000C8876 /* CPShiftReduceActionTable.h in Headers */,
@@ -631,9 +633,7 @@
1F9F83A613B732AC006E939D /* Term.h in Headers */,
1F9F83AC13B7CABA006E939D /* CPRHSItem.h in Headers */,
1FC00D5014544EDC00DC8D35 /* CPRHSItemResult.h in Headers */,
- 1FA68DA014DE98C4005519B9 /* CPErrorToken.h in Headers */,
1FA68DA514DE9D3D005519B9 /* CPTestErrorHandlingDelegate.h in Headers */,
- 1F893A1F14DEEBFC00316FF7 /* CPRecoveryAction.h in Headers */,
1F893A2314DEF40D00316FF7 /* CPTestErrorEvaluatorDelegate.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -87,108 +87,124 @@ - (BOOL)constructShiftReduceTables
return NO;
}
+#define kCPStopParsingException @"CPStopParsingException"
+
- (id)parse:(CPTokenStream *)tokenStream
{
- NSMutableArray *stateStack = [NSMutableArray arrayWithObject:[CPShiftReduceState shiftReduceStateWithObject:nil state:0]];
- CPToken *nextToken = [[tokenStream peekToken] retain];
- BOOL hasErrorToken = NO;
- while (1)
+ @try
{
- @autoreleasepool
+ NSMutableArray *stateStack = [NSMutableArray arrayWithObject:[CPShiftReduceState shiftReduceStateWithObject:nil state:0]];
+ CPToken *nextToken = [[tokenStream peekToken] retain];
+ BOOL hasErrorToken = NO;
+ while (1)
{
- CPShiftReduceAction *action = [self actionForState:[(CPShiftReduceState *)[stateStack lastObject] state] token:nextToken];
-
- if ([action isShiftAction])
+ @autoreleasepool
{
- [stateStack addObject:[CPShiftReduceState shiftReduceStateWithObject:nextToken state:[action newState]]];
- if (!hasErrorToken)
- {
- [tokenStream popToken];
- }
- [nextToken release];
- nextToken = [[tokenStream peekToken] retain];
- hasErrorToken = NO;
- }
- else if ([action isReduceAction])
- {
- CPRule *reductionRule = [action reductionRule];
- NSUInteger numElements = [[reductionRule rightHandSideElements] count];
- NSMutableArray *components = [NSMutableArray arrayWithCapacity:numElements];
- NSRange stateStackRange = NSMakeRange([stateStack count] - numElements, numElements);
- [stateStack enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:stateStackRange]
- options:NSEnumerationReverse
- usingBlock:^(CPShiftReduceState *state, NSUInteger idx, BOOL *stop)
- {
- 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;
+ CPShiftReduceAction *action = [self actionForState:[(CPShiftReduceState *)[stateStack lastObject] state] token:nextToken];
- Class c = [reductionRule representitiveClass];
- if (nil != c)
+ if ([action isShiftAction])
{
- result = [(id<CPParseResult>)[c alloc] initWithSyntaxTree:tree];
- }
-
- if (nil == result)
- {
- result = tree;
- if ([[self delegate] respondsToSelector:@selector(parser:didProduceSyntaxTree:)])
+ [stateStack addObject:[CPShiftReduceState shiftReduceStateWithObject:nextToken state:[action newState]]];
+ if (!hasErrorToken)
{
- result = [[self delegate] parser:self didProduceSyntaxTree:tree];
+ [tokenStream popToken];
}
+ [nextToken release];
+ nextToken = [[tokenStream peekToken] retain];
+ hasErrorToken = NO;
}
-
- NSUInteger newState = [self gotoForState:[(CPShiftReduceState *)[stateStack lastObject] state] rule:reductionRule];
- [stateStack addObject:[CPShiftReduceState shiftReduceStateWithObject:result state:newState]];
- }
- else if ([action isAccept])
- {
- return [(CPShiftReduceState *)[stateStack lastObject] object];
- }
- else
- {
- CPRecoveryAction *recoveryAction = [self error:tokenStream expecting:[self acceptableTokenNamesForState:[(CPShiftReduceState *)[stateStack lastObject] state]]];
- if (nil == recoveryAction)
+ else if ([action isReduceAction])
{
- if ([nextToken isKindOfClass:[CPErrorToken class]] && [stateStack count] > 0)
+ CPRule *reductionRule = [action reductionRule];
+ NSUInteger numElements = [[reductionRule rightHandSideElements] count];
+ NSMutableArray *components = [NSMutableArray arrayWithCapacity:numElements];
+ NSRange stateStackRange = NSMakeRange([stateStack count] - numElements, numElements);
+ [stateStack enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:stateStackRange]
+ options:NSEnumerationReverse
+ usingBlock:^(CPShiftReduceState *state, NSUInteger idx, BOOL *stop)
+ {
+ 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;
+
+ Class c = [reductionRule representitiveClass];
+ if (nil != c)
{
- [stateStack removeLastObject];
+ result = [(id<CPParseResult>)[c alloc] initWithSyntaxTree:tree];
}
- else
+
+ if (nil == result)
{
- return nil;
+ result = tree;
+ if ([[self delegate] respondsToSelector:@selector(parser:didProduceSyntaxTree:)])
+ {
+ result = [[self delegate] parser:self didProduceSyntaxTree:tree];
+ }
}
+
+ NSUInteger newState = [self gotoForState:[(CPShiftReduceState *)[stateStack lastObject] state] rule:reductionRule];
+ [stateStack addObject:[CPShiftReduceState shiftReduceStateWithObject:result state:newState]];
+ }
+ else if ([action isAccept])
+ {
+ return [(CPShiftReduceState *)[stateStack lastObject] object];
}
else
{
- switch ([recoveryAction recoveryType])
+ CPRecoveryAction *recoveryAction = [self error:tokenStream expecting:[self acceptableTokenNamesForState:[(CPShiftReduceState *)[stateStack lastObject] state]]];
+ if (nil == recoveryAction)
{
- case CPRecoveryTypeAddToken:
- [nextToken release];
- nextToken = [[recoveryAction additionalToken] retain];
- hasErrorToken = YES;
- break;
- case CPRecoveryTypeRemoveToken:
- [tokenStream popToken];
- [nextToken release];
- nextToken = [[tokenStream peekToken] retain];
- hasErrorToken = NO;
- break;
- default:
- break;
+ if ([nextToken isKindOfClass:[CPErrorToken class]] && [stateStack count] > 0)
+ {
+ [stateStack removeLastObject];
+ }
+ else
+ {
+ return nil;
+ }
+ }
+ else
+ {
+ switch ([recoveryAction recoveryType])
+ {
+ case CPRecoveryTypeAddToken:
+ [nextToken release];
+ nextToken = [[recoveryAction additionalToken] retain];
+ hasErrorToken = YES;
+ break;
+ case CPRecoveryTypeRemoveToken:
+ [tokenStream popToken];
+ [nextToken release];
+ nextToken = [[tokenStream peekToken] retain];
+ hasErrorToken = NO;
+ break;
+ case CPRecoveryTypeBail:
+ [NSException raise:kCPStopParsingException format:@""];
+ break;
+ default:
+ break;
+ }
}
}
}
}
}
+ @catch (NSException *e)
+ {
+ if (![[e name] isEqualToString:kCPStopParsingException])
+ {
+ [e raise];
+ }
+ return nil;
+ }
}
- (CPRecoveryAction *)error:(CPTokenStream *)tokenStream expecting:(NSSet *)acceptableTokens
@@ -13,7 +13,8 @@
typedef enum
{
CPRecoveryTypeAddToken = 0,
- CPRecoveryTypeRemoveToken
+ CPRecoveryTypeRemoveToken ,
+ CPRecoveryTypeBail
} CPRecoveryType;
/**
@@ -47,6 +48,11 @@ typedef enum
+ (id)recoveryActionDeletingCurrentToken;
/**
+ * Allocates and initialise a new CPRecovery action asking the parser to stop immediately.
+ */
++ (id)recoveryActionStop;
+
+/**
* Initialises a CPRecoveryAction asking the parser to add a new token to the token stream.
*
* @param token The token to add to the stream.
@@ -61,4 +67,9 @@ typedef enum
*/
- (id)initWithDeleteAction;
+/**
+ * Initialises a CPRecoveryAction asking the parser to stop immediately.
+ */
+- (id)initWithStopAction;
+
@end
@@ -23,6 +23,11 @@ + (id)recoveryActionDeletingCurrentToken
return [[[self alloc] initWithDeleteAction] autorelease];
}
++ (id)recoveryActionStop
+{
+ return [[[self alloc] initWithStopAction] autorelease];
+}
+
- (id)initWithAdditionalToken:(CPToken *)token
{
self = [super init];
@@ -48,4 +53,16 @@ - (id)initWithDeleteAction
return self;
}
+- (id)initWithStopAction
+{
+ self = [super init];
+
+ if (nil != self)
+ {
+ [self setRecoveryType:CPRecoveryTypeBail];
+ }
+
+ return self;
+}
+
@end

0 comments on commit 068cce6

Please sign in to comment.