How should I use callback functions in parsekit? suppose I have the following rule:
expr_s = expr_p '+' expr_s | expr_p ;
should I pop 3 symbols from the resulting PKAssembly and add first and last numbers and then push the answer back to the stack?
And for the above rule how should I know it is the first or the second rule that caused a match?
I don’t understand the order in which ParseKit calls callback functions. I could really use some help.
Thanks Todd for your response, keeping in mind your instructions I wrote the following grammar and callback functions for a simple mathematics expression that includes addition and multiplication:
- (IBAction)press_equals:(id)sender {
NSString *g = @"@start = expr_s; expr_s = expr_p ('+'! expr_p)+ ; expr_p = Number ('*'! Number)+ ;";
PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
NSString *s = @"3*4+4*8";
[p parse:s];
PKAssembly *res = [p parse:s];
NSLog(@"res %@", res);
}
- (void)parser:(PKParser *)p didMatchExpr_s:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);
NSArray *toks = [a objectsAbove:nil];
double total = 0.0;
for (PKToken *tok in toks) {
total += tok.floatValue;
}
a.target = [NSNumber numberWithDouble:total];
}
- (void)parser:(PKParser *)p didMatchExpr_p:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);
NSArray *toks = [a objectsAbove:nil];
double total = 1.0;
for (PKToken *tok in toks) {
total *= tok.floatValue;
}
a.target = [NSNumber numberWithDouble:total];
}
and here is the output I get:
2012-04-06 22:54:31.975 Calculator[1070:207] -[CalculatorViewController parser:didMatchExpr_p:] [3, 4]3/*/4^+/4/*/8
2012-04-06 22:54:31.976 Calculator[1070:207] -[CalculatorViewController parser:didMatchExpr_p:] [4, 8]3/*/4/+/4/*/8^
2012-04-06 22:54:31.977 Calculator[1070:207] -[CalculatorViewController parser:didMatchExpr_s:] []3/*/4/+/4/*/8^
2012-04-06 22:54:31.977 Calculator[1070:207] -[CalculatorViewController parser:didMatchExpr_p:] [3, 4]3/*/4^+/4/*/8
2012-04-06 22:54:31.978 Calculator[1070:207] -[CalculatorViewController parser:didMatchExpr_p:] [4, 8]3/*/4/+/4/*/8^
2012-04-06 22:54:31.978 Calculator[1070:207] -[CalculatorViewController parser:didMatchExpr_s:] []3/*/4/+/4/*/8^
2012-04-06 22:54:31.979 Calculator[1070:207] res 0
Why is my res 0?
Developer of ParseKit here.
First, the best way to understand this stuff is Steven Metsker’s book, upon which ParseKit is based.
Second, checkout my answer to another question about
PKAssembly‘sstackandtarget.Third, here’s my answer to another PaseKit question about unexpected callbacks.
Fourth, checkout the
TDArithmeticParser.mfile in the the ParseKit Tests Target (included in the ParseKit Xcode project. This class has callbacks which implement the same kind of arithmetic logic you seem to be looking for.Also checkout the
arithmetic.grammarfile (also in the ParseKit Tests Target). This is an example of how to design an arithmetic grammar in ParseKit syntax.Finally, here’s some thoughts more specific to your example above.
Let’s clarify your grammar a bit, as the question you’re asking is pretty basic, and I don’t think it requires a very complex grammar to tackle. Here’s a basic arithmetic grammar which gives multiplication and division operators precedence over addition and subtraction:
That
!after the'+'tells ParseKit to discard this token automatically. This makes things slightly more convenient for you when writing your callbacks.Note that if you want your grammar to have only left-to-right operator precedence (like a calculator), this grammar will not work. If you need that, please ask a separate question tagged #ParseKit here on StackOverflow, and I will answer it promptly.
I would define these callbacks:
Two important points are
aargument’stargetorstack. I usually store temporary values on thestack, and the ultimate result on thetarget, as I find that most convenient. But you have flexibility there.I would write this driver code:
I see this log output:
Hope this helps.