0

ソースの位置情報を使用して AST を構築するためのパーサー コンビネーターをいくつか作成しました。プロファイリングは、少なくとも実行の 30% パーセントが不要な情報を繰り返し解析してソース ロケーション データを生成するために費やされていることを示しています。パフォーマンスを改善するための別のアプローチを見つける手助けが必要です。

問題

「A」と「B」の 2 つのトークンだけで構成される言語を解析しているとします。AST ノードを生成するために、現在、場所を抽出してノードを構築するコンビネータを定義しています。

// Parse body and build resulting node from function
// nodeFactory called with position and result from body.
var node = function(body, nodeFactory) {
    return bind(
        locParser, // get the current location in the token stream
        body,
        prevEnd, // get the previous end position in the token stream
        function(o, x, c) {
            return always(f(Location(o, c), x));
        });
};

var a = node(char('A'), buildNodeA);
var b = node(char('B'), buildNodeB);

このアプローチの問題はlocParser、本体が成功するかどうかに関係なく、常に実行されることです。

var element = either(a, b);
var program = many(element);
run(program, "AAABBA");

予想される行動

a失敗することが明らかになったらすぐにbody失敗します。

実際の動作

「B」トークンの場合、最初locParserに foraが実行され、body失敗するとlocParserforbが実行されます。ネストと分岐が増えると、これはパフォーマンスの問題になります。

エッジケース

場所には、消費される入力の全範囲が含まれます。

var c = node(next(char(' '), char('C')), buildNodeC);

「C」ノードの位置は、スペース文字の先頭から始まります。

var d = node(between(char('('), char(')'), char('D')), buildNodeD);

「D」ノードの位置は、「(」の開始点から始まり、「)」の終了点で終わります。これらのケースはどちらも、 によって正しく処理されnodeます。

質問

これらのパーサーをリファクタリングして、すぐに失敗しても正しい位置データにアクセスするにはどうすればよいですか?

各パーサーを自己完結型に保ち、ロジックの繰り返しを避けることをお勧めします。さらに、構築後にノードを変更してはなりません。

4

0 に答える 0