gpt4 book ai didi

objective-c - ParseKit 的汇编程序回调如何工作?我应该在哪里存储我在其中所做的工作?

转载 作者:太空狗 更新时间:2023-10-30 03:42:23 25 4
gpt4 key购买 nike

我应该如何在 parekit 中使用回调函数?假设我有以下规则:

expr_s = expr_p '+' expr_s | expr_p ; 

我应该从生成的 PKAssembly 中弹出 3 个符号并添加第一个和最后一个数字,然后将答案推回堆栈吗?
对于上面的规则,我怎么知道是第一条规则还是第二条规则导致了匹配?
我不明白 ParseKit 调用回调函数的顺序。我真的需要一些帮助。

感谢 Todd 的回复,谨记您的指示,我为包含加法和乘法的简单数学表达式编写了以下语法和回调函数:

- (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];
}

这是我得到的输出:

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

为什么我的res是0?

最佳答案

ParseKit 的开发者|在这里。

首先,理解这个东西的最好方法是Steven Metsker's book , ParseKit 基于它。


二、结帐my answer to another question about PKAssembly's stack and target.


第三,这里是my answer to another PaseKit question about unexpected callbacks .


第四,检查TDArithmeticParser.m file在 ParseKit Tests Target 中(包含在 ParseKit Xcode 项目中。此类具有实现您似乎正在寻找的相同类型算术逻辑的回调。

另请查看 arithmetic.grammar file (也在 ParseKit 测试目标中)。这是一个如何在 ParseKit 语法中设计算术文法的示例。


最后,这里有一些针对您上面的示例的更具体的想法。

让我们稍微澄清一下您的语法,因为您提出的问题非常基础,而且我认为它不需要非常复杂的语法来解决。这是一个基本的算术语法,它使乘法和除法运算符优先于加法和减法:

@start         = expr;
expr = term (plusTerm | minusTerm)*;
term = factor (timesFactor | divFactor)*;
plusTerm = '+'! term;
minusTerm = '-'! term;
timesFactor = '*'! factor;
divFactor = '/'! factor;
factor = Number;

'+' 之后的那个 ! 告诉 ParseKit 自动丢弃这个标记。这让您在编写回调时稍微方便一些。

请注意如果您希望您的语法只有从左到右的运算符优先级(如计算器),则此语法将不起作用。如果您需要,请在 StackOverflow 上单独提出一个标记为#ParseKit 的问题,我会及时回答。

我会定义这些回调:

- (void)parser:(PKParser *)p didMatchExpr:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);

NSNumber *n = [a pop];

// the expr is complete, and its value is on the stack.
// important! wrap things up by
// storing your work in `a.target`. not in an ivar.
a.target = n;
}

- (void)parser:(PKParser *)p didMatchFactor:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);

// a number token was found. store its number value on the stack
PKToken *tok = [a pop];
[a push:[NSNumber numberWithDouble:tok.floatValue]];
}

- (void)parser:(PKParser *)p didMatchPlusTerm:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);

// a '+' expr was found. pop off the two operands and add them
// store the result on the stack temporarily
NSNumber *n2 = [a pop];
NSNumber *n1 = [a pop];
[a push:[NSNumber numberWithDouble:[n1 doubleValue] + [n2 doubleValue]]];
}

- (void)parser:(PKParser *)p didMatchMinusTerm:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);

// a '-' expr was found. pop off the two operands and subtract them
// store the result on the stack temporarily
NSNumber *n2 = [a pop];
NSNumber *n1 = [a pop];
[a push:[NSNumber numberWithDouble:[n1 doubleValue] - [n2 doubleValue]]];
}

- (void)parser:(PKParser *)p didMatchTimesFactor:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);

// a '*' expr was found. pop off the two operands and multiply them
// store the result on the stack temporarily
NSNumber *n2 = [a pop];
NSNumber *n1 = [a pop];
[a push:[NSNumber numberWithDouble:[n1 doubleValue] * [n2 doubleValue]]];
}

- (void)parser:(PKParser *)p didMatchDivideFactor:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);

// a '/' expr was found. pop off the two operands and divide them
// store the result on the stack temporarily
NSNumber *n2 = [a pop];
NSNumber *n1 = [a pop];
[a push:[NSNumber numberWithDouble:[n1 doubleValue] / [n2 doubleValue]]];
}

重要的两点

  1. 不必担心这些回调被调用了多少次。它们被调用的次数可能比您预期的要多,或者调用顺序看起来很奇怪。
  2. 不要将这些回调中完成的工作结果存储在 ivar 中。始终将您的工作存储在 a 参数的 targetstack 上。我通常将临时值存储在 stack 中,并将最终结果存储在 target 中,因为我发现这样最方便。但是你在那里有灵 active 。

我会写这个驱动程序代码:

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);

我看到这个日志输出:

-[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

希望这对您有所帮助。

关于objective-c - ParseKit 的汇编程序回调如何工作?我应该在哪里存储我在其中所做的工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10045555/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com