Skip to content

Commit

Permalink
* curly action test
Browse files Browse the repository at this point in the history
  • Loading branch information
itod committed Mar 28, 2014
1 parent f325590 commit e3e666c
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 1 deletion.
10 changes: 10 additions & 0 deletions PEGKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@
D3D48D8218E5B484001B54E9 /* TableIndexSpecParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D48D8118E5B484001B54E9 /* TableIndexSpecParserTest.m */; };
D3D48D8518E5B500001B54E9 /* TableIndexSpecParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D48D8418E5B500001B54E9 /* TableIndexSpecParser.m */; };
D3D48D8718E5BCFC001B54E9 /* curly_action.grammar in Resources */ = {isa = PBXBuildFile; fileRef = D3D48D8618E5BCFC001B54E9 /* curly_action.grammar */; };
D3D48D8A18E5BFD3001B54E9 /* CurlyActionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D48D8918E5BFD3001B54E9 /* CurlyActionParser.m */; };
D3D48D8C18E5BFFF001B54E9 /* CurlyActionParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D48D8B18E5BFFF001B54E9 /* CurlyActionParserTest.m */; };
D3E9B2CD1891714100AC0974 /* PKAST.m in Sources */ = {isa = PBXBuildFile; fileRef = D375DAC2173C645C00A5E050 /* PKAST.m */; };
D3E9B2CE1891714400AC0974 /* PKAST.h in Headers */ = {isa = PBXBuildFile; fileRef = D3A1492816F8C6BD00770DEE /* PKAST.h */; settings = {ATTRIBUTES = (Public, ); }; };
D3F8A40E175817DF00056188 /* NSArray+PEGKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = D34BAFD30FF9E95500D7773A /* NSArray+PEGKitAdditions.h */; };
Expand Down Expand Up @@ -788,6 +790,9 @@
D3D48D8318E5B500001B54E9 /* TableIndexSpecParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TableIndexSpecParser.h; path = test/TableIndexSpecParser.h; sourceTree = "<group>"; };
D3D48D8418E5B500001B54E9 /* TableIndexSpecParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TableIndexSpecParser.m; path = test/TableIndexSpecParser.m; sourceTree = "<group>"; };
D3D48D8618E5BCFC001B54E9 /* curly_action.grammar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = curly_action.grammar; path = res/curly_action.grammar; sourceTree = "<group>"; };
D3D48D8818E5BFD3001B54E9 /* CurlyActionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CurlyActionParser.h; path = test/CurlyActionParser.h; sourceTree = "<group>"; };
D3D48D8918E5BFD3001B54E9 /* CurlyActionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CurlyActionParser.m; path = test/CurlyActionParser.m; sourceTree = "<group>"; };
D3D48D8B18E5BFFF001B54E9 /* CurlyActionParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CurlyActionParserTest.m; path = test/CurlyActionParserTest.m; sourceTree = "<group>"; };
D3F0E2470FFE8EB900C9DF74 /* PKQuoteState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PKQuoteState.h; path = include/PEGKit/PKQuoteState.h; sourceTree = SOURCE_ROOT; };
D3F8A48D175817DF00056188 /* PEGKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PEGKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D3F8A4921758187300056188 /* PEGKit-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "PEGKit-Info.plist"; path = "res/PEGKit-Info.plist"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -978,6 +983,7 @@
D31BBCC618E4F1A50003FFA3 /* Tests */ = {
isa = PBXGroup;
children = (
D3D48D8B18E5BFFF001B54E9 /* CurlyActionParserTest.m */,
D31BBCBC18E4AAE20003FFA3 /* TableIndexParserTest.m */,
D3D48D8118E5B484001B54E9 /* TableIndexSpecParserTest.m */,
D31BBCAF18E4722F0003FFA3 /* CreateTableStmtParserTest.m */,
Expand Down Expand Up @@ -1309,6 +1315,8 @@
D3B22A581703D07000446945 /* Parsers */ = {
isa = PBXGroup;
children = (
D3D48D8818E5BFD3001B54E9 /* CurlyActionParser.h */,
D3D48D8918E5BFD3001B54E9 /* CurlyActionParser.m */,
D31BBCBE18E4AAFC0003FFA3 /* TableIndexParser.h */,
D31BBCBF18E4AAFC0003FFA3 /* TableIndexParser.m */,
D3D48D8318E5B500001B54E9 /* TableIndexSpecParser.h */,
Expand Down Expand Up @@ -1954,6 +1962,7 @@
D30B8F4A170CFAAD001796F4 /* NegationParserTest.m in Sources */,
D30B8F53170CFF2B001796F4 /* PEGKitParserTest.m in Sources */,
D30B8F59170CFFFE001796F4 /* DelimitedParserTest.m in Sources */,
D3D48D8C18E5BFFF001B54E9 /* CurlyActionParserTest.m in Sources */,
D30B8F5E170D001E001796F4 /* DelimitedParser.m in Sources */,
D30B8F65170D0EB0001796F4 /* PatternParserTest.m in Sources */,
D30B8F6A170D0EEB001796F4 /* PatternParser.m in Sources */,
Expand Down Expand Up @@ -1997,6 +2006,7 @@
D376F6D918D0B3990064C888 /* PGReferenceNode.m in Sources */,
D31BBCF218E4F1EF0003FFA3 /* TDTokenizerTest.m in Sources */,
D30DA1771724AD0100A1A3EC /* JSONParser.m in Sources */,
D3D48D8A18E5BFD3001B54E9 /* CurlyActionParser.m in Sources */,
D30DA17A1724ADE700A1A3EC /* JSONParserTest.m in Sources */,
D30DA18A1725B6A800A1A3EC /* RecoverySingleTokenDeletionTest.m in Sources */,
D30DA18D1725BB5700A1A3EC /* RecoverySingleTokenInsertionTest.m in Sources */,
Expand Down
3 changes: 2 additions & 1 deletion res/curly_action.grammar
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
start = Word+ {
start = Word+
{
while (!EMPTY()) {
id word = POP_STR();
LOG(word);
Expand Down
13 changes: 13 additions & 0 deletions test/CurlyActionParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#import <PEGKit/PKParser.h>

enum {
TABLEINDEX_TOKEN_KIND_BY = 14,
TABLEINDEX_TOKEN_KIND_INDEXED,
TABLEINDEX_TOKEN_KIND_NOT_UPPER,
TABLEINDEX_TOKEN_KIND_DOT,
};

@interface CurlyActionParser : PKParser

@end

193 changes: 193 additions & 0 deletions test/CurlyActionParser.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#import "CurlyActionParser.h"
#import <PEGKit/PEGKit.h>

#define LT(i) [self LT:(i)]
#define LA(i) [self LA:(i)]
#define LS(i) [self LS:(i)]
#define LF(i) [self LD:(i)]

#define POP() [self.assembly pop]
#define POP_STR() [self popString]
#define POP_TOK() [self popToken]
#define POP_BOOL() [self popBool]
#define POP_INT() [self popInteger]
#define POP_UINT() [self popUnsignedInteger]
#define POP_FLOAT() [self popFloat]
#define POP_DOUBLE() [self popDouble]

#define PUSH(obj) [self.assembly push:(id)(obj)]
#define PUSH_BOOL(yn) [self pushBool:(BOOL)(yn)]
#define PUSH_INT(i) [self pushInteger:(NSInteger)(i)]
#define PUSH_UINT(u) [self pushUnsignedInteger:(NSUInteger)(u)]
#define PUSH_FLOAT(f) [self pushFloat:(float)(f)]
#define PUSH_DOUBLE(d) [self pushDouble:(double)(d)]

#define EQ(a, b) [(a) isEqual:(b)]
#define NE(a, b) (![(a) isEqual:(b)])
#define EQ_IGNORE_CASE(a, b) (NSOrderedSame == [(a) compare:(b)])

#define MATCHES(pattern, str) ([[NSRegularExpression regularExpressionWithPattern:(pattern) options:0 error:nil] numberOfMatchesInString:(str) options:0 range:NSMakeRange(0, [(str) length])] > 0)
#define MATCHES_IGNORE_CASE(pattern, str) ([[NSRegularExpression regularExpressionWithPattern:(pattern) options:NSRegularExpressionCaseInsensitive error:nil] numberOfMatchesInString:(str) options:0 range:NSMakeRange(0, [(str) length])] > 0)

#define ABOVE(fence) [self.assembly objectsAbove:(fence)]
#define EMPTY() [self.assembly isStackEmpty]

#define LOG(obj) do { NSLog(@"%@", (obj)); } while (0);
#define PRINT(str) do { printf("%s\n", (str)); } while (0);

@interface PKParser ()
@property (nonatomic, retain) NSMutableDictionary *tokenKindTab;
@property (nonatomic, retain) NSMutableArray *tokenKindNameTab;
@property (nonatomic, retain) NSString *startRuleName;
@property (nonatomic, retain) NSString *statementTerminator;
@property (nonatomic, retain) NSString *singleLineCommentMarker;
@property (nonatomic, retain) NSString *blockStartMarker;
@property (nonatomic, retain) NSString *blockEndMarker;
@property (nonatomic, retain) NSString *braces;

- (BOOL)popBool;
- (NSInteger)popInteger;
- (double)popDouble;
- (PKToken *)popToken;
- (NSString *)popString;

- (void)pushBool:(BOOL)yn;
- (void)pushInteger:(NSInteger)i;
- (void)pushDouble:(double)d;
@end

@interface CurlyActionParser ()
@end

@implementation CurlyActionParser

- (id)initWithDelegate:(id)d {
self = [super initWithDelegate:d];
if (self) {
self.startRuleName = @"qualifiedTableName";
self.tokenKindTab[@"BY"] = @(TABLEINDEX_TOKEN_KIND_BY);
self.tokenKindTab[@"INDEXED"] = @(TABLEINDEX_TOKEN_KIND_INDEXED);
self.tokenKindTab[@"NOT"] = @(TABLEINDEX_TOKEN_KIND_NOT_UPPER);
self.tokenKindTab[@"."] = @(TABLEINDEX_TOKEN_KIND_DOT);

self.tokenKindNameTab[TABLEINDEX_TOKEN_KIND_BY] = @"BY";
self.tokenKindNameTab[TABLEINDEX_TOKEN_KIND_INDEXED] = @"INDEXED";
self.tokenKindNameTab[TABLEINDEX_TOKEN_KIND_NOT_UPPER] = @"NOT";
self.tokenKindNameTab[TABLEINDEX_TOKEN_KIND_DOT] = @".";

}
return self;
}

- (void)start {
[self qualifiedTableName_];
[self matchEOF:YES];
}

- (void)qualifiedTableName_ {

[self name_];
[self indexOpt_];
[self execute:(id)^{

// now stack contains 3 `NSString`s.
// ["mydb", "mytable", "foo"]
// NSString *indexName = POP();
// NSString *tableName = POP();
// NSString *dbName = POP();
// do stuff here

}];

[self fireDelegateSelector:@selector(parser:didMatchQualifiedTableName:)];
}

- (void)databaseName_ {

[self matchWord:NO];

[self fireDelegateSelector:@selector(parser:didMatchDatabaseName:)];
}

- (void)tableName_ {

[self matchWord:NO];

[self fireDelegateSelector:@selector(parser:didMatchTableName:)];
}

- (void)indexName_ {

[self matchQuotedString:NO];

[self fireDelegateSelector:@selector(parser:didMatchIndexName:)];
}

- (void)name_ {

if ([self speculate:^{ [self databaseName_]; [self match:TABLEINDEX_TOKEN_KIND_DOT discard:YES]; }]) {
[self databaseName_];
[self match:TABLEINDEX_TOKEN_KIND_DOT discard:YES];
}
[self tableName_];
[self execute:(id)^{

// now stack contains 2 `PKToken`s of type Word
// [<Word «mydb»>, <Word «mytable»>]
// pop their string values
NSString *tableName = POP_STR();
NSString *dbName = POP_STR();
PUSH(dbName);
PUSH(tableName);

}];

[self fireDelegateSelector:@selector(parser:didMatchName:)];
}

- (void)indexOpt_ {

if ([self predicts:TABLEINDEX_TOKEN_KIND_INDEXED, TABLEINDEX_TOKEN_KIND_NOT_UPPER, 0]) {
[self index_];
} else {
[self matchEmpty:NO];
[self execute:(id)^{
PUSH(@"");
}];
}

[self fireDelegateSelector:@selector(parser:didMatchIndexOpt:)];
}

- (void)index_ {

if ([self predicts:TABLEINDEX_TOKEN_KIND_INDEXED, 0]) {
[self match:TABLEINDEX_TOKEN_KIND_INDEXED discard:YES];
[self match:TABLEINDEX_TOKEN_KIND_BY discard:YES];
[self indexName_];
[self execute:(id)^{

// now top of stack will be a Quoted String `PKToken`
// […, <Quoted String «"foo"»>]
// pop its string value
NSString *indexName = POP_STR();
// trim quotes
indexName = [indexName substringWithRange:NSMakeRange(1, [indexName length]-2)];
// leave it on the stack for later
PUSH(indexName);

}];
} else if ([self predicts:TABLEINDEX_TOKEN_KIND_NOT_UPPER, 0]) {
[self match:TABLEINDEX_TOKEN_KIND_NOT_UPPER discard:YES];
[self match:TABLEINDEX_TOKEN_KIND_INDEXED discard:YES];
[self execute:(id)^{
PUSH(@"");
}];
} else {
[self raise:@"No viable alternative found in rule 'index'."];
}

[self fireDelegateSelector:@selector(parser:didMatchIndex:)];
}

@end
87 changes: 87 additions & 0 deletions test/CurlyActionParserTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#import "TDTestScaffold.h"
#import "PGParserFactory.h"
#import "PGParserGenVisitor.h"
#import "PGRootNode.h"
#import "CurlyActionParser.h"

@interface CurlyActionParserTest : XCTestCase
@property (nonatomic, retain) PGParserFactory *factory;
@property (nonatomic, retain) PGRootNode *root;
@property (nonatomic, retain) PGParserGenVisitor *visitor;
@property (nonatomic, retain) CurlyActionParser *parser;
@property (nonatomic, retain) id mock;
@end

@implementation CurlyActionParserTest

- (void)parser:(PKParser *)p didFailToMatch:(PKAssembly *)a {}

- (void)parser:(PKParser *)p didMatchLcurly:(PKAssembly *)a {}
- (void)parser:(PKParser *)p didMatchRcurly:(PKAssembly *)a {}
- (void)parser:(PKParser *)p didMatchName:(PKAssembly *)a {}
- (void)parser:(PKParser *)p didMatchColon:(PKAssembly *)a {}
- (void)parser:(PKParser *)p didMatchValue:(PKAssembly *)a {}
- (void)parser:(PKParser *)p didMatchComma:(PKAssembly *)a {}
- (void)parser:(PKParser *)p didMatchStructure:(PKAssembly *)a {}
- (void)parser:(PKParser *)p didMatchStructs:(PKAssembly *)a {}

- (void)dealloc {
self.factory = nil;
self.root = nil;
self.visitor = nil;
self.parser = nil;
self.mock = nil;
[super dealloc];
}


- (void)setUp {
self.factory = [PGParserFactory factory];
_factory.collectTokenKinds = YES;

NSError *err = nil;
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"curly_action" ofType:@"grammar"];
NSString *g = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];

err = nil;
self.root = (id)[_factory ASTFromGrammar:g error:&err];
_root.grammarName = @"CurlyAction";

self.visitor = [[[PGParserGenVisitor alloc] init] autorelease];
_visitor.enableMemoization = NO;

[_root visit:_visitor];

#if TD_EMIT
path = [[NSString stringWithFormat:@"%s/test/CurlyActionParser.h", getenv("PWD")] stringByExpandingTildeInPath];
err = nil;
if (![_visitor.interfaceOutputString writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&err]) {
NSLog(@"%@", err);
}

path = [[NSString stringWithFormat:@"%s/test/CurlyActionParser.m", getenv("PWD")] stringByExpandingTildeInPath];
err = nil;
if (![_visitor.implementationOutputString writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&err]) {
NSLog(@"%@", err);
}
#endif

self.parser = [[[CurlyActionParser alloc] initWithDelegate:_mock] autorelease];
}

- (void)tearDown {
self.factory = nil;
}


- (void)testFooBarBaz {
NSString *s = @"foo bar baz";

NSError *err = nil;
PKAssembly *res = [_parser parseString:s error:&err];
TDNil(err);

TDEqualObjects(TDAssembly(@"[foo, bar, baz]foo/bar/baz^"), [res description]);
}

@end

0 comments on commit e3e666c

Please sign in to comment.