4

構文エラーが発生する前に、PKParserが解析したアセンブリのどこまで戻るかを考えていました。

参照: http: //parsekit.com/

基本的に接頭記法の表現言語を記述する文法を使用しています。

例えば:

標準のプレフィックス表記式の文法と文字列"(+ a --bc))"が与えられた場合、一致する場所でその[(、+、a]を取得したいので、修正する場所をユーザーに示すことができます。エラーが発生しましたが、completeMatchForとbestMatchForは、この情報を見つけるために使用できるものを返しません。

理想的には、「(」が期待されていたと言いたいのですが、私が使用しているものほど単純な文法では必要ありません。

ユーザーマニュアルとして言及されている本からは、このためのカスタムパーサーを作成する必要があるように見えましたが、フレームワークで何かを見逃してしまったのではないかと期待していました。

考え?

4

2 に答える 2

3

ここでParseKitの開発者。

ParseKitには2つの機能があり、入力で発生した解析エラーを説明するユーザーが読み取り可能なヒントを提供するために使用できます。

  1. -[PKParser bestMatchFor:]
  2. PKTrackクラス_

-bestMatchFor:この場合、期待どおりに機能していなくても、メソッドを認識しているようです。

PKTrackここでは授業がもっと役立つと思います。Metskerの本で説明されているように、は、サブパーサーが必要であり、すべてのサブパーサーが一致しない場合にエラーがスローされる(有用なエラーメッセージが表示される)ことを除いて、PKTrackまったく同じです。PKSequence

したがって、入力例の文法は次のとおりです。

@start         = '(' expr ')' | expr;
expr           = ('+' | '-') term term;
term           = '(' expr ')' | Word;

連続してリストされているプロダクションはすべてシーケンスですが、代わりにトラックである可能性があります。

これらのシーケンスをトラックに変更する利点はNSException、入力が一致しない場合に、人間が読める形式の解析エラーメッセージとともにスローされることです。欠点は、これらのTrack例外をキャッチするために、工場で生成されたパーサーのすべての使用法をtry/catchブロックでラップする必要があることです。

現在(または少なくとも今まで)の問題は、PKParserFactoryTracksを使用してパーサーを作成したことがないことです。代わりに、常にシーケンスを使用します。

そこで、 Google Codeのトランクの先頭に新しいオプションを追加しました更新する必要があります)。

#define USE_TRACK 0

PKParserFactory.m

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 : -

お役に立てば幸いです。

于 2012-04-04T05:51:21.510 に答える
3

私もこの問題に取り組んでいます。-bestMatchFor:エラー状態の識別に役立つためにPKAssemblyは、解析するトークン/文字がさらにあるかどうかを示すメソッドがパブリックインターフェイスにある必要があります。プライベートメソッド-completeMatchFor:にアクセスできるため、エラー状態を判別できます。-hasMoreおそらく、PKAssembly-hasMoreメソッドは公開する必要があります。

私は見ましPKTrackたが、プログラムでエラーを処理したいので、それは私には役に立ちませんでした。

私の結論は、独自のカスタムTrackパーサーを作成するか、フレームワークを変更して公開すること-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認識されないトークンの場所が含まれます。

于 2012-07-07T13:23:41.813 に答える