21

このプレゼンテーションを読んで見る : http://boost-spirit.com/home/2011/06/12/ast-construction-with-the-universal-tree/
セマンティック アクションを使用します。

私はすでにそのようなことを感じたことを認めなければなりません: セマンティックアクションを伴う文法は実際にはちょっと醜く見えます. そして、それらを拡張/変更する必要があるときは、セマンティックアクションを正確に使用した多くの「マイクロ管理」が必要でした. プレゼンテーションで示されている属性文法を使用したアプローチは、はるかにエレガントで有望なようです。

そこでお聞きしたいのですが、これは「公式」ポイントですか?属性文法の扱い方や、セマンティック アクションを避ける方法をもっと詳しく学ぶ必要がありますか? もしそうなら -- 私は = そのようなアプローチを示すいくつかの基本的な (おそらく些細な) 例を求めたいです -- LISP インタプリタは複雑すぎて私には理解できません...

4

1 に答える 1

28

きっとハルトムートがすぐに答えてくれるでしょう。それまでは、これが私の見解です:

いいえ、それは公式のポイントではありません。

セマンティック アクションにはいくつかの欠点があります

  • セマンティック アクションの最も単純な欠点は、関心の分離というスタイル上の概念です。ある場所で構文を表現し、別の場所でセマンティクスを表現したい。これは保守性に役立ちます (特に、Spirit Grammar をコンパイルするための長いコンパイル時間に関して)

  • 副作用がある場合は、より複雑な意味になります (これはよくあることです)。セマンティック アクションに副作用がある場合に、解析されたノードからバックトラックすることを想像してみてください。パーサーの状態は元に戻されますが、外部効果は元に戻りません。

    ある意味では、属性のみを使用することは、関数型プログラムで決定論的で純粋な関数を使用するようなものです。純粋な関数のみで構成されている場合、プログラム (または、この場合は文法状態マシン)の正確性について推論する方が簡単です。

  • セマンティック アクションには、値によってより多くのコピーを導入する傾向があります (必ずしもそうとは限りません)。これは、大量のバックトラッキングと組み合わせて、パフォーマンスを低下させる可能性があります。もちろん、セマンティック アクションが「重い」場合、これ自体が解析のパフォーマンスを妨げることになります。


セマンティック アクションは、さまざまな目的に適しています。実際、重要な文法を文脈依存で解析する必要がある場合、それらをエスケープすることはできません。

  1. qi::locals<>および継承された属性(Mini XML - ASTs!サンプルのコード)の使用を検討してください。これらにはセマンティック アクションが含まれます。

    xml =
            start_tag                   [at_c<0>(_val) = _1]
        >>  *node                      
        >>  end_tag(at_c<0>(_val)) // passing the name from the 
                                   // ... start_tag as inherited attribute
    ;
    

    またはqi::locals を使用するもの:

    rule<char const*, locals<char> > rl;
    rl = alpha[_a = _1] >> char_(_a); // get two identical characters
    test_parser("aa", rl); // pass
    test_parser("ax", rl); // fail
    

    IMO、これらのセマンティック アクションは、バックトラックされたときに、次に実行が (同じ) セマンティック アクションを通過したときに、ローカルが新しい正しい値によって上書きされるため、通常はあまり問題になりません。

  2. また、一部のジョブは本当に「手早く」、utreeや手作業で作成された AST タイプの使用を保証しません。

     qi::phrase_parse(first, last, // imagine qi::istream_iterator... 
         intesting_string_pattern  // we want to match certain patterns on the fly
                [ log_interesting_strings ], // and pass them to our logger
         noise_skipper             // but we skip all noise
     );
    

    ここで、セマンティック アクションはパーサー関数の中核です。セマンティックアクションを持つノードのレベルではバックトラッキングが関与しないため、機能します。

  3. セマンティック アクションは、Spirit Karma のセマンティック アクションの鏡像であり、Qi よりも問題が少ないのが普通です。したがって、インターフェース/API の一貫性のためだけであっても、セマンティック アクションは「良いこと」であり、Boost Spirit 全体の使いやすさを高めます。

于 2011-11-24T15:48:38.847 に答える