ここでParseKitの開発者。私はあなたの両方の質問に答えます:
1)あなたは正しいアプローチを取っていますが、これはトリッキーなケースです。いくつかの小さな落とし穴があり、文法を少し変更する必要があります。
私は私のために働いている文法を開発しました:
// Tokenizer Directives
@symbolState = '"' "'"; // effectively tells the tokenizer to turn off QuoteState.
// Otherwise, variables enclosed in quotes would not be found (they'd be embedded in quoted strings).
// now single- & double-quotes will be recognized as individual symbols, not start- & end-markers for quoted strings
@symbols = '${'; // declare '${' as a multi-char symbol
@reportsWhitespaceTokens = YES; // tell the tokenizer to preserve/report whitespace
// Grammar
@start = content*;
content = passthru | variable;
passthru = /[^$].*/;
variable = start name end;
start = '${';
end = '}';
name = Word;
次に、次の2つのコールバックをアセンブラーに実装します。
- (void)parser:(PKParser *)p didMatchName:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);
PKToken *tok = [a pop];
NSString *name = tok.stringValue;
// do something with name
}
- (void)parser:(PKParser *)p didMatchPassthru:(PKAssembly *)a {
NSLog(@"%s %@", __PRETTY_FUNCTION__, a);
PKToken *tok = [a pop];
NSMutableString *s = a.target;
if (!s) {
s = [NSMutableString string];
}
[s appendString:tok.stringValue];
a.target = s;
}
そして、クライアント/ドライバーのコードは次のようになります。
NSString *g = // fetch grammar
PKParser *p = [[PKParserFactory factory] parserFromGrammar:g assembler:self];
NSString *s = @"<img src=\"${image}\" />";
[p parse:s];
NSString *result = [p parse:s];
NSLog(@"result %@", result);
これは印刷されます:
result: <img src="" />
2)はい、この比較的単純なケースでは、Tokenizerを直接使用する方が間違いなくはるかに良いと思います。パフォーマンスが大幅に向上します。Tokenizerを使用してタスクにアプローチする方法は次のとおりです。
PKTokenizer *t = [PKTokenizer tokenizerWithString:s];
[t setTokenizerState:t.symbolState from:'"' to:'"'];
[t setTokenizerState:t.symbolState from:'\'' to:'\''];
[t.symbolState add:@"${"];
t.whitespaceState.reportsWhitespaceTokens = YES;
NSMutableString *result = [NSMutableString string];
PKToken *eof = [PKToken EOFToken];
PKToken *tok = nil;
while (eof != (tok = [t nextToken])) {
if ([@"${" isEqualToString:tok.stringValue]) {
tok = [t nextToken];
NSString *varName = tok.stringValue;
// do something with variable
} else if ([@"}" isEqualToString:tok.stringValue]) {
// do nothing
} else {
[result appendString:tok.stringValue];
}
}