ParseKit developer is here.
Firstly, the best way to understand this material is the book of Stephen Metsker , on which ParseKit is based.
Secondly, check out my answer to another question about the PKAssembly
stack
and target
.
Thirdly, here is my answer to another PaseKit question about unexpected callbacks .
Fourth, check the TDArithmeticParser.m
file in the ParseKit Tests Target tag (included in ParseKit Xcode This class has callbacks that implement the exact same arithmetic logic that you seem to be looking for.
Also check the arithmetic.grammar
file (also in the ParseKit Tests Target tag). This is an example of how to create arithmetic grammar in ParseKit syntax.
Finally, here are some thoughts more specific to your example above.
Explain your grammar a bit, as the question you ask is pretty simple, and I don't think it requires complicated grammar. Here's the basic arithmetic grammar, which gives the advantage of multiplying and dividing operators over additions and subtractions:
@start = expr; expr = term (plusTerm | minusTerm)*; term = factor (timesFactor | divFactor)*; plusTerm = '+'! term; minusTerm = '-'! term; timesFactor = '*'! factor; divFactor = '/'! factor; factor = Number;
What !
after '+'
tells ParseKit to automatically cancel this token . This makes things a little more convenient for you when writing callbacks.
Note If you want your grammar to have only operator priority from left to right (for example, a calculator), this grammar will not work. If you need this, please ask a separate question with the #ParseKit tag here in StackOverflow, and I will answer it quickly.
I would define these callbacks:
- (void)parser:(PKParser *)p didMatchExpr:(PKAssembly *)a { NSLog(@"%s %@", __PRETTY_FUNCTION__, a); NSNumber *n = [a pop];
Two important points :
- Don't worry about how many times these callbacks are called . They can be called more than you expect, or in a strange way.
- Do not save the results of work done on these callbacks in ivar . Always save your work with either
a
target
or stack
. I usually save temporary values ββon stack
and the final result on target
, as I find this the most convenient. But you have the flexibility.
I would write this driver code:
NSString *g = .. // fetch grammar above PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self]; NSString *s = @"3*4+4*8"; PKAssembly *res = [p parse:s]; NSLog(@"res %@", res);
I see this log output:
-[DebugAppDelegate parser:didMatchFactor:] [3]3^*/4/+/4/*/8 -[DebugAppDelegate parser:didMatchFactor:] [3, 4]3/*/4^+/4/*/8 -[DebugAppDelegate parser:didMatchTimesFactor:] [3, 4]3/*/4^+/4/*/8 -[DebugAppDelegate parser:didMatchFactor:] [12, 4]3/*/4/+/4^*/8 -[DebugAppDelegate parser:didMatchFactor:] [12, 4, 8]3/*/4/+/4/*/8^ -[DebugAppDelegate parser:didMatchTimesFactor:] [12, 4, 8]3/*/4/+/4/*/8^ -[DebugAppDelegate parser:didMatchPlusTerm:] [12, 4]3/*/4/+/4^*/8 -[DebugAppDelegate parser:didMatchPlusTerm:] [12, 32]3/*/4/+/4/*/8^ -[DebugAppDelegate parser:didMatchExpr:] [3]3^*/4/+/4/*/8 -[DebugAppDelegate parser:didMatchExpr:] [12]3/*/4^+/4/*/8 -[DebugAppDelegate parser:didMatchExpr:] [16]3/*/4/+/4^*/8 -[DebugAppDelegate parser:didMatchExpr:] [44]3/*/4/+/4/*/8^ res 44
Hope this helps.