ParseKit не соответствует моим символам EOL: что я делаю неправильно?

Приключения с ParseKit продолжаются... и мое следующее препятствие - попытаться распознать символы новой строки.

Вот моя грамматика:

@symbolState = '\n';
@start = textline*;
textline = Any* eol;
eol = '\n';

Вот мой тестовый текст:

1
2
3
4
5

Текст читается из текстового файла UTF-8 с окончаниями строк в формате Unix (LF). Я проверил этот формат как в Xcode (инспектор файлов -> Настройки текста), так и извне, с помощью TextWrangler.

И вот соответствующий код:

#import "FileImporterThing.h"
#import <ParseKit/ParseKit.h>

@interface FileImporterThing ()
@property (nonatomic, retain)PKParser* parser;
- (void)parser:(PKParser *)p didMatchTextline:(PKAssembly *)a;
- (void)parser:(PKParser *)p didMatchEol:(PKAssembly *)a;
@end


@implementation FileImporterThing

@synthesize parser = _parser;

-(id)init
{
    if (!(self = [super init])) return nil;

    // Have also tried "textline = Any* '\n';"
    NSString *g = @"@symbolState = '\n'; @start = textline*; textline = Any* eol; eol = '\n';";
    self.parser = [[PKParserFactory factory] parserFromGrammar:g assembler:self];

    return self;
}

- (void)testParse
{
    // read string from UTF-8 file Unix (LF) line endings 
    // (this verified in project->file inspector->Text Settings and externally with TextWrangler)
    NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"LF-test" ofType:@"parsetext"];
/* file contains text:
1
2
3
4
5

*/
    NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

    [self.parser parse:s];
}

- (void)parser:(PKParser *)p didMatchEol:(PKAssembly *)a
{
    NSLog(@"eol found");// stack = %@", [a stack]);
}

- (void)parser:(PKParser *)p didMatchTextline:(PKAssembly *)a
{
    NSLog(@"textline matched");
}

@end

Но я боюсь, что краска просто не высыхает! Перепробовал всевозможные вариации вышеперечисленного. Я не могу на всю жизнь заставить синтаксический анализатор распознавать новую строку. Вероятно, я могу обойти это, читая файл-буфер построчно (что в любом случае может быть более производительным?), но все же было бы неплохо иметь возможность сопоставления '\n'.


person Rich    schedule 12.03.2012    source источник


Ответы (1)


Разработчик ParseKit здесь. Две вещи, которые я могу внести:


1.

Я попробовал ваш пример, используя текстовый файл, созданный в TextMate или TextWrangler (сохраненный как файл .txt), и все, казалось, работало нормально. Мои обратные вызовы -parser:didMatchEol: и -parser:didMatchTexline: были вызваны, как и ожидалось.

Если это не работает для вас, возможно, попробуйте начать с ввода строки в памяти, чтобы увидеть, будет ли работать хотя бы это:

NSString *s = @"foo bar\nbaz bat\n";
[parser parse:s];

Во всяком случае, вот мой код из DebugAppDelegate.m, который у меня работает либо с вводом в память, либо с вводом на диск:

- (void)doTestGrammar {
    NSString *g = @"@symbolState = '\n'; @start = textline*; textline = Any* eol; eol = '\n';";
    PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
    //NSString *s = @"foo bar\nbaz bat\n";
    NSString *path = [@"~/Desktop/text.txt" stringByExpandingTildeInPath];
    NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    [p parse:s];
}

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

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

2.

На самом деле я был немного удивлен, что ваш пример сработал, поскольку я думал, что ваше использование продукции Any* будет жадно потреблять токены \n в конце строки, таким образом не оставляя ничего для соответствия продукции eol.

Однако, как я уже упоминал, это не было проблемой, когда я запускал ваш пример (против ParseKit HEAD of trunk).

Тем не менее, на всякий случай я бы, вероятно, порекомендовал изменить ваше производство textline на это:

textline = ~eol* eol;

определение этого производства следует читать как:

ноль или более токенов, НЕ совпадающих с eol, за которыми следует один токен, совпадающий с eol

~ — это логический оператор отрицания в синтаксисе грамматики ParseKit.

После внесения этого изменения в мой пример кода все по-прежнему работало, как и ожидалось.


Если вы все еще не можете заставить его работать после этих двух советов, дайте мне знать.

person Todd Ditchendorf    schedule 12.03.2012
comment
Спасибо за немедленный ответ, Тодд! Конечно, вы правы, моя ошибка, извините, оказалась глупой проблемой с учетом регистра, из-за которой мой тестовый файл не был найден. Но потом я был озадачен тем, почему мой настоящий код не работает. Получается, что жесткое кодирование грамматики работает, а чтение из файла — нет: кажется, что '\n' интерпретируется по-другому, как литерал? Трудно даже выразить мою точную проблему словами, достаточно сказать, если я читаю из файла, а затем передаю строку в NSLog, я вижу, что каждый «/ n» напечатан полностью. Но жестко закодированная строка отправляет на консоль настоящие новые строки. Какие-нибудь советы? - person Rich; 14.03.2012
comment
Если это было не очень понятно, то просто попробуйте адаптировать небольшой пример выше, чтобы также прочитать грамматику из файла. Это работает для вас? - person Rich; 14.03.2012
comment
Ах я вижу. Хм, да, это сложно. Может быть, попробовать использовать '\\n' в файловой версии грамматики? Я постараюсь найти немного времени, чтобы изучить это позже сегодня. Может быть ошибка в ParseKit, но я не уверен. - person Todd Ditchendorf; 14.03.2012
comment
Я тоже думал о '\\n', но не работает :( Что работает, так это физическая новая строка внутри одинарных кавычек. Не слишком элегантно, но, по крайней мере, заставляет меня двигаться :) - person Rich; 15.03.2012
comment
@Todd Есть ли место, где я могу найти список синтаксиса ParseKit? Кажется, я занимаюсь поиском синтаксиса ParseKit, читая каждое сообщение на форуме ParseKit в Интернете. Спасибо. - person Xander Dunn; 17.04.2013
comment
Обнаружение Ричем того, что совпадения '\n' у него не работают, является важным моментом. Я полагаю, что это связано с тем, что Cocoa интерпретирует символ '\n' в литерале NSString иначе, чем новую строку в файле, который импортируется с использованием stringWithContentsOfFile. Это возможно, потому что есть несколько символов Юникода, которые могут представлять новую строку. См. документацию Apple для kCFCharacterSetNewline. Нам нужно сопоставить определенный символ новой строки Unicode в файле грамматики с конкретным символом новой строки Unicode в строке, которую мы анализируем. - person Xander Dunn; 18.04.2013