ParseKit não corresponde aos meus símbolos EOL:O que estou fazendo de errado?
-
12-12-2019 - |
Pergunta
A aventura do ParseKit continua...e meu próximo obstáculo é tentar fazer com que os símbolos de nova linha sejam reconhecidos.
Aqui está minha gramática:
@symbolState = '\n';
@start = textline*;
textline = Any* eol;
eol = '\n';
Aqui está meu texto de teste:
1
2
3
4
5
O texto está sendo lido de um arquivo de texto UTF-8 com finais de linha no formato Unix (LF).Verifiquei esse formato tanto no Xcode (inspetor de arquivos -> Configurações de texto) quanto externamente, com TextWrangler.
E aqui está o código relevante:
#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
Mas temo que a tinta simplesmente não esteja secando!Tentei todos os tipos de variações acima.Não consigo fazer com que o analisador reconheça uma nova linha.Provavelmente posso contornar isso lendo o buffer de arquivo linha por linha (o que pode ter melhor desempenho, de qualquer maneira?), Mas ainda seria bom ter a opção de combinar ' '.
Solução
Desenvolvedor de Kit de análise aqui.Duas coisas que posso contribuir:
1.
Tentei seu exemplo usando um arquivo de texto criado no TextMate ou no TextWrangler (salvo como um arquivo .txt) e tudo pareceu funcionar bem.Meu -parser:didMatchEol:
e -parser:didMatchTexline:
retornos de chamada foram chamados conforme o esperado.
Se isso não estiver funcionando para você, tente começar com a entrada de string na memória para ver se pelo menos isso funcionará:
NSString *s = @"foo bar\nbaz bat\n";
[parser parse:s];
De qualquer forma, aqui está o meu código de DebugAppDelegate.m
que está funcionando para mim com entrada na memória ou entrada no disco:
- (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.
Na verdade, fiquei um pouco surpreso que seu exemplo tenha funcionado, pois pensei que seu uso do Any*
a produção consumiria avidamente o \n
tokens no final da linha, não deixando nada para o eol
produção a combinar.
Porém, como mencionei, isso não foi um problema quando executei seu exemplo (no ParseKit HEAD do tronco).
Ainda assim, para garantir, eu provavelmente recomendaria alterar seu textline
produção para isso:
textline = ~eol* eol;
a definição desta produção deve ser lida como:
zero ou mais tokens NÃO correspondidos por eol
, seguido por um token correspondido por eol
~
é o operador de negação booleano na sintaxe gramatical do ParseKit.
Depois de fazer essa alteração no meu código de exemplo, tudo ainda funcionou conforme o esperado.
Se você ainda não conseguir fazer funcionar depois dessas duas dicas, me avise.