From 2300bc89b5fd49ded5fbfcc77b042f00a9619adb Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sun, 21 Dec 2014 22:42:30 -0800 Subject: [PATCH] Implement PKParser.isEmptyOK. This can be set so that the parser will accept empty input. The parse* methods will return PEGKitSuccessfulEmptyParse in that case. Note that we need to check that we're actually at the end of the stream, otherwise we're going to accept every bad parse as an empty one. --- include/PEGKit/PKParser.h | 12 ++++++++++++ res/PGClassImplementationTemplate.txt | 12 ++++++++++++ src/PKParser.m | 1 + 3 files changed, 25 insertions(+) diff --git a/include/PEGKit/PKParser.h b/include/PEGKit/PKParser.h index 1b84a9f..fdf80fa 100644 --- a/include/PEGKit/PKParser.h +++ b/include/PEGKit/PKParser.h @@ -33,6 +33,11 @@ extern NSInteger PEGKitRecognitionErrorCode; extern NSString * const PEGKitRecognitionTokenMatchFailed; extern NSString * const PEGKitRecognitionPredicateFailed; +/** + * Returned by the parse* methods if isEmptyOK is set and the input is empty. + */ +extern NSString * const PEGKitSuccessfulEmptyParse; + typedef void (^PKSActionBlock) (void); typedef void (^PKSSpeculateBlock)(void); typedef BOOL (^PKSPredicateBlock)(void); @@ -72,4 +77,11 @@ enum { @property (nonatomic, assign) BOOL enableActions; // default YES @property (nonatomic, assign) BOOL enableAutomaticErrorRecovery; // default NO @property (nonatomic, assign) BOOL enableVerboseErrorReporting; // default NO + +/** + * Set this if you want to accept empty input. + * The parse* methods will return PEGKitSuccessfulEmptyParse in this case. + */ +@property (nonatomic) BOOL isEmptyOK; + @end diff --git a/res/PGClassImplementationTemplate.txt b/res/PGClassImplementationTemplate.txt index 9e5a3fd..f5c1bf4 100644 --- a/res/PGClassImplementationTemplate.txt +++ b/res/PGClassImplementationTemplate.txt @@ -37,6 +37,18 @@ {%/for%}} {%/if%} - (void)start { + if (!self.isEmptyOK || [self speculate:^{ + [self startSpeculate]; + }]) { + [self startSpeculate]; + } + else { + [self matchEOF:YES]; + PUSH(PEGKitSuccessfulEmptyParse); + } +} + +- (void)startSpeculate { {{beforeAction}} {{startMethodBody}} {{afterAction}}} diff --git a/src/PKParser.m b/src/PKParser.m index 8b0b410..dd3f6e9 100644 --- a/src/PKParser.m +++ b/src/PKParser.m @@ -39,6 +39,7 @@ NSInteger PEGKitRecognitionErrorCode = 1; NSString * const PEGKitRecognitionTokenMatchFailed = @"Failed to match next input token"; NSString * const PEGKitRecognitionPredicateFailed = @"Predicate failed"; +NSString * const PEGKitSuccessfulEmptyParse = @"PEGKitSuccessfulEmptyParse"; @interface NSObject () - (void)parser:(PKParser *)p didFailToMatch:(PKAssembly *)a;