【问题标题】:parsekit gives unexpected calls to selectorsparsekit 对选择器进行了意外调用
【发布时间】:2011-06-04 14:05:21
【问题描述】:

我有以下非常简单的(测试)语法文件

@start = expression+;
expression = keyword | otherWord;
otherWord = Word;
keyword = a | the;
a = 'a';
the = 'the';

然后我运行以下代码:

// Grammar contains the contents of the above grammar file.
PKParser *parser = [[PKParserFactory factory] parserFromGrammar:grammar assembler:self];
NSString *s = @"The parrot";
[parser parse:s];
PKReleaseSubparserTree(parser);

还有以下方法:

- (void)didMatchA:(PKAssembly *)a{
    [self log:a type:@"didMatchA          "];
}
- (void)didMatchThe:(PKAssembly *)a{
    [self log:a type:@"didMatchThe        "];
}
- (void)didMatchKeyword:(PKAssembly *)a{
    [self log:a type:@"didMatchKeyword    "];
}
- (void)didMatchExpression:(PKAssembly *)a{
    [self log:a type:@"didMatchExpression "];
}
- (void)didMatchOtherWord:(PKAssembly *)a{
    [self log:a type:@"didMatchOtherWord  "];
}

-(void) log:(PKAssembly *) assembly type:(NSString *) type{
    PKToken * token = [assembly top];
    NSLog(@"Method: [%@], token: %@, assembly: %@", type, token, assembly);
}

最后我在日志中得到了这些消息:

[1] Method: [didMatchThe        ], token: The, assembly: [The]The^parrot
[2] Method: [didMatchKeyword    ], token: The, assembly: [The]The^parrot
[3] Method: [didMatchOtherWord  ], token: The, assembly: [The]The^parrot
[4] Method: [didMatchExpression ], token: The, assembly: [The]The^parrot
[5] Method: [didMatchExpression ], token: The, assembly: [The]The^parrot
[6] Method: [didMatchOtherWord  ], token: parrot, assembly: [The, parrot]The/parrot^
[7] Method: [didMatchExpression ], token: parrot, assembly: [The, parrot]The/parrot^

这种说法是有道理的,但我不明白为什么会出现 %5。我真的很希望能够删除双重匹配,以便诸如“The”之类的关键字仅触发didMatchThe 而不是didMatchKeyword

不幸的是,parsekit 上的 doco 在其语法语法以及它决定触发方法的方式上似乎不存在。是的,我也浏览了源代码 :-)

有没有人有使用 parsekit 的经验并且可以对此有所了解?

【问题讨论】:

    标签: objective-c parsekit


    【解决方案1】:

    我是 ParseKit 的开发者,这实际上是正确的行为。这里有一些项目可以帮助解决这个问题:

    1. 了解 ParseKit 工作原理的最佳方式是购买 Steven John Metsker 的 "Building Parsers with Java"。 ParseKit 几乎完全基于那里的设计。

    2. ParseKit 的解析器组件具有极高的动态性,并具有无限前瞻功能。这使其非常适合快速开发或轻松解析小输入,但这也意味着 ParseKit 在解析大型文档时表现出极差的性能。

    3. 由于 ParseKit 的无限前瞻,您实现的汇编方法将被多次调用。实际上,正如您在上面描述的那样,它们会被调用太多次。这很正常。 ParseKit 会随时探索所有可用的解析路径,因此您会收到“太多”的回调。

    4. 答案是永远不要在汇编回调方法中处理 ivars。在您的 Assembler 方法中,您应该始终在当前 PKAssemblytarget ivar 中保留您正在处理的状态。

      a.target

    当前的PKAssembly 是传递给你的回调方法的那个。

    希望对您有所帮助。

    【讨论】:

    • 感谢托德这么快回来。幸运的是,我要解析的文档非常小。在 parsekit 测试代码中,我注意到堆栈上有很多弹出和推送,但我不明白为什么。保持状态是指将目标设置为各种回调的 wat,以告诉对方它们已经发生。 IE。 didMatchWord 和 didMatch 都检查目标以查看另一个是否已经填充并采取相应措施?
    • 附言。有没有办法优化这个语法,减少回调?我宁愿不买书来实现看似简单的事情。虽然这本书读起来会很有趣,但我现在不想把精力花在这上面。我希望通过一些工作,我可以将 parsekit 注入应用程序。 :-)
    • 一直在玩这个。我一直在尝试使用您编写的测试代码作为模型。所以我一直在弹出和推动价值观。此外,我一直使用目标作为跟踪状态并知道何时调用其他方法的一种手段。这似乎工作。在这个阶段不确定这是怎么回事。
    • 嗨,Derek,很高兴有帮助。 1. 不,您实际上无法调整语法以强制减少回调。这只是 ParseKit 必须接受的一个权衡:极端的活力但性能不佳。 :( 2. 我的意思是您应该将正在构建/处理的数据实际存储为程序集的目标。
    猜你喜欢
    • 2017-11-02
    • 2017-08-30
    • 2017-06-03
    • 2019-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    • 1970-01-01
    相关资源
    最近更新 更多