Creator of ParseKit here. A few items:
ParseKit deprecation:
Just this week, I have forked ParseKit to a cleaner/smaller/faster library called PEGKit. ParseKit should be considered deprecated, and PEGKit should be used for all new development. Please move to PEGKit.
PEGKit is nearly identical to the grammar and code-gen features of ParseKit, and your ParseKit grammars are usable with PEGKit with a few small changes. In fact, all of the examples in your question here are usable with no changes in PEGKit.
See the Deprecation Notice in the ParseKit README.
And this tutorial on PEGKit.
Syntax errors in your grammar:
I spot 3 syntax errors in your grammar samples above (this applies equally to both ParseKit and PEGKit).
This line:
createTableStmt ='CREATE' ('TEMP'| 'TEMPORARY')? 'TABLE' 'IF NOT EXISTS'? databaseName;
Should be:
createTableStmt ='CREATE' ('TEMP'| 'TEMPORARY')? 'TABLE' ('IF' 'NOT' 'EXISTS')? databaseName;
Notice the break up of the invalid
'IF NOT EXISTS'
construct into individual literal tokens. This is not only necessary, but also desireable so that variable whitespace between the words is allowed.The
POP()
macro should be all upper case.Your
createTableStmt
rule is missing a semicolon at the very end (after the action's closing}
).
Before Answering:
Make sure you are using v0.3.1 PEGKit or later (HEAD of master). I fixed an important bug while finding the answer to your question, and my solutions below require this fix.
Answer to your first question:
My question is how can I see if it matched ('TEMP' | 'TEMPORARY') so I can set the value?
Good question! You basically have the right idea in your further comments above.
Specficially, I would probably break up the createTableStmt
rule into 4 rules like this:
createTableStmt = 'CREATE'! tempOpt 'TABLE'! existsOpt databaseName ';'!;
databaseName = QuotedString;
tempOpt
= ('TEMP'! | 'TEMPORARY'!)
| Empty
;
existsOpt
= ('IF'! 'NOT'! 'EXISTS'!)
| Empty
;
Notice all of the vital
!
discard directives for discarding unneeded literal tokens.Also Notice that I've changed the last two rules to use
| Empty
rather than?
. This is so I can add Actions to the Empty alternatives (you'll see that in a sec).
Then you can either add Actions to your grammar, or use ObjC parser delegate callbacks if you prefer to work in pure code.
If you use Actions in your grammar, something like the following will work:
createTableStmt = 'CREATE'! tempOpt 'TABLE'! existsOpt databaseName ';'!
{
NSString *dbName = POP();
BOOL ifNotExists = POP_BOOL();
BOOL isTemp = POP_BOOL();
NSLog(@"create table: %@, %d, %d", dbName, ifNotExists, isTemp);
// go to town
// myCreateTable(dbName, ifNotExists, isTemp);
};
databaseName = QuotedString
{
// pop the string value of the `PKToken` on the top of the stack
NSString *dbName = POP_STR();
// trim quotes
dbName = [dbName substringWithRange:NSMakeRange(1, [dbName length]-2)];
// leave it on the stack for later
PUSH(dbName);
};
tempOpt
= ('TEMP'! | 'TEMPORARY'!) { PUSH(@YES); }
| Empty { PUSH(@NO); }
;
existsOpt
= ('IF'! 'NOT'! 'EXISTS'!) { PUSH(@YES); }
| Empty { PUSH(@NO); }
;
I've added this Grammar and a test case to the PEGKit project.
As for your second question, please break it out as a new SO question, and tag it ParseKit
and PEGKit
and I will get to it ASAP.