2012-04-03 7 views
4

構文エラーが発生する前にPKParserが解析したアセンブリまでの距離を返す方法があるかどうかは疑問でした。ParseKitフレームワークで解析エラーを見つける方法

参照:http://parsekit.com/

私は基本的にプレフィックス表記式言語を記述する文法を使用しています。私は[(、+、A]ここで一致したことを取得したいのですが - "(BC +))" ので、私あなたの標準プレフィックス表記の式の文法や文字列を与えられた

:たとえば

ユーザーにエラーを修正する場所を知らせることができますが、completeMatchForとbestMatchForはこの情報を見つけるために使用できるものを返しません。

理想的には、私は '期待していますが、私が使っているものと同じくらい単純な文法のために必要ではありません。

ユーザーマニュアルに記載されている本から、このためにカスタムパーサを作成する必要がある場合は、フレームワークで何かを逃してしまったのかもしれないと思っていました。

思考?

答えて

3

デベロッパーParseKitここに。

ParseKitには、入力時に解析エラーが発生したことをユーザーが理解できるようにするためのヒントが2つあります。

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

あなたが-bestMatchFor:方法を知っているように、あなたがこのような場合には期待して何をしていない場合でも聞こえます。

私はPKTrackクラスがここでもっと役立つと思います。 Metsker's bookに記載されているように、PKTrackはサブパーザが必要であることを除いて全く同じようにPKSequenceとなり、サブパラザがすべて一致しないとエラーが表示されます。

は、だからここにあなたの例の入力のための文法です:

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

連続的に記載されている任意の作品は、シーケンスです - 代わりにトラックである可能性があります。

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

現在、問題は、PKParserFactoryがトラックを使用してパーサーを作成したことがないことです。代わりに、常にSequencesを使用します。

だから、私はに追加しました。トランクの頭に新しいオプションが追加されました。Google Code(あなたはうつ病にする必要があります)。

PKParserFactory.m 

#define USE_TRACK 0 

これは、デフォルトで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 : - 

希望したがって、上記の文法や、このような不正な入力与えられましたそれは助ける。

3

私もこの問題に取り組んでいます。 -bestMatchFor:がエラー状態を特定するのに有用であるためには、パースされるトークン/文字がもっとあるかどうかを示すPKAssemblyの公開インタフェースのメソッドが存在するはずです。 -completeMatchFor:は、プライベート-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に認識されないトークンの場所が含まれます。

関連する問題