Objective c 如何使用ParseKit框架查找解析错误
我想知道在遇到语法错误之前,是否有办法返回PKParser解析程序集的距离 参考: 我使用的语法基本上描述了前缀符号表达式语言 例如: 给定您的标准前缀符号表达式语法和字符串“(+a-bc))” 我想在匹配的地方检索[(,+,a],这样我可以让用户知道在哪里查找以修复错误,但是completeMatchFor和bestMatchFor不会返回任何我可以用来查找此信息的内容 理想情况下,我想说的是应该有一个“(”,但对于像我所使用的那样简单的语法来说,这并不是必需的 从《用户手册》中提到的那本书来看,似乎我需要为此创建一个自定义解析器,但我希望我只是错过了框架中的一些东西 想法?这里的开发者 ParseKit中有两个特性可用于帮助提供用户可读的提示,以描述输入中遇到的解析错误Objective c 如何使用ParseKit框架查找解析错误,objective-c,parsekit,Objective C,Parsekit,我想知道在遇到语法错误之前,是否有办法返回PKParser解析程序集的距离 参考: 我使用的语法基本上描述了前缀符号表达式语言 例如: 给定您的标准前缀符号表达式语法和字符串“(+a-bc))” 我想在匹配的地方检索[(,+,a],这样我可以让用户知道在哪里查找以修复错误,但是completeMatchFor和bestMatchFor不会返回任何我可以用来查找此信息的内容 理想情况下,我想说的是应该有一个“(”,但对于像我所使用的那样简单的语法来说,这并不是必需的 从《用户手册》中提到的那本书来
-[PKParser bestMatchFor:]
PKTrack
类-bestMatchFor:
方法,即使它没有达到您在本例中预期的效果
我认为PKTrack
类在这里会更有用。如中所述,PKTrack
与PKSequence
完全相同,只是它的子parser是必需的,并且当它的所有子parser都不匹配时会抛出一个错误(带有有用的错误消息)
下面是示例输入的语法:
@start = '(' expr ')' | expr;
expr = ('+' | '-') term term;
term = '(' expr ')' | Word;
连续列出的任何作品都是一个序列,但也可以是一个曲目
将这些序列更改为轨迹的好处是,如果输入不匹配,则会抛出一条人类可读的解析错误消息。缺点是现在必须将工厂生成的解析器的所有用法包装在try/catch块中,以捕获这些轨迹异常
目前(至少在现在之前)的问题是,PKParserFactory
从未生成使用轨迹的解析器,而是始终使用序列
因此,我刚刚在(您需要进行udpate)的躯干头部添加了一个新选项
在
默认情况下为0
。如果将此定义更改为1
,则将使用曲目而不是序列。因此,考虑到上述语法和以下无效输入:
(+ a - b c))
此客户端代码:
NSString *g = // fetch grammar above
PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
NSString *s = @"(+ a - b c))";
@try {
PKAssembly *res = [p parse:s];
NSLog(@"res %@", res);
}
@catch (NSException *exception) {
NSLog(@"Parse Error:%@", exception);
}
您将得到一个很好的人类可读的错误:
Parse Error:
After : ( + a
Expected : Alternation (term)
Found : -
希望这会有所帮助。我也在努力解决这个问题。为了使
-bestMatchFor:
在识别错误条件方面有用,在PKAssembly
的公共界面中应该有方法指示是否有更多的令牌/字符需要解析。-completeMatchFor:
能够确定错误状态se它可以访问私有的-hasMore
方法。也许PKAssembly
的-hasMore
方法应该是公共的
我查看了PKTrack
,但由于我希望以编程方式处理错误,因此它对我没有用处
我的结论是,要么编写自己的自定义轨迹解析器,要么修改框架并公开-hasMore
。还有其他方法来处理错误吗
在找到更好的错误检测方法之前,我已将以下内容添加到包含自定义解析器实现的文件中:
@interface PKAssembly ()
- (BOOL)hasMore;
- (id)peek;
@end
@implementation PMParser
...
@end
在我的解析方法中:
PKAssembly* a = [PKTokenAssembly assemblyWithString:s];
PKAssembly* best = [self bestMatchFor:a];
PMParseNode* node = nil;
BOOL error = NO;
NSUInteger errorOffset = 0;
if (best == nil) // Anything recognized?
{
error = YES;
}
else
{
if ([best hasMore]) // Partial recognition?
{
PKToken* t = [best peek];
error = YES;
errorOffset = t.offset;
}
node = [best pop];
}
如果发生错误,errorOffset
将包含无法识别的令牌的位置
@interface PKAssembly ()
- (BOOL)hasMore;
- (id)peek;
@end
@implementation PMParser
...
@end
PKAssembly* a = [PKTokenAssembly assemblyWithString:s];
PKAssembly* best = [self bestMatchFor:a];
PMParseNode* node = nil;
BOOL error = NO;
NSUInteger errorOffset = 0;
if (best == nil) // Anything recognized?
{
error = YES;
}
else
{
if ([best hasMore]) // Partial recognition?
{
PKToken* t = [best peek];
error = YES;
errorOffset = t.offset;
}
node = [best pop];
}