きっとハルトムートがすぐに答えてくれるでしょう。それまでは、これが私の見解です:
いいえ、それは公式のポイントではありません。
セマンティック アクションにはいくつかの欠点があります
セマンティック アクションの最も単純な欠点は、関心の分離というスタイル上の概念です。ある場所で構文を表現し、別の場所でセマンティクスを表現したい。これは保守性に役立ちます (特に、Spirit Grammar をコンパイルするための長いコンパイル時間に関して)
副作用がある場合は、より複雑な意味になります (これはよくあることです)。セマンティック アクションに副作用がある場合に、解析されたノードからバックトラックすることを想像してみてください。パーサーの状態は元に戻されますが、外部効果は元に戻りません。
ある意味では、属性のみを使用することは、関数型プログラムで決定論的で純粋な関数を使用するようなものです。純粋な関数のみで構成されている場合、プログラム (または、この場合は文法状態マシン)の正確性について推論する方が簡単です。
セマンティック アクションには、値によってより多くのコピーを導入する傾向があります (必ずしもそうとは限りません)。これは、大量のバックトラッキングと組み合わせて、パフォーマンスを低下させる可能性があります。もちろん、セマンティック アクションが「重い」場合、これ自体が解析のパフォーマンスを妨げることになります。
セマンティック アクションは、さまざまな目的に適しています。実際、重要な文法を文脈依存で解析する必要がある場合、それらをエスケープすることはできません。
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、これらのセマンティック アクションは、バックトラックされたときに、次に実行が (同じ) セマンティック アクションを通過したときに、ローカルが新しい正しい値によって上書きされるため、通常はあまり問題になりません。
また、一部のジョブは本当に「手早く」、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
);
ここで、セマンティック アクションはパーサー関数の中核です。セマンティックアクションを持つノードのレベルではバックトラッキングが関与しないため、機能します。
セマンティック アクションは、Spirit Karma のセマンティック アクションの鏡像であり、Qi よりも問題が少ないのが普通です。したがって、インターフェース/API の一貫性のためだけであっても、セマンティック アクションは「良いこと」であり、Boost Spirit 全体の使いやすさを高めます。