Boost Spirit のセマンティックアクションは全か無か ― 2020年05月22日 12時39分08秒
言葉での説明は分かりづらいので少し簡単な例を用いて。
上の例では、数字は整数か小数のどちらかとして定義している。integer が一致したとき、または real が一致したときに、その値が number に代入される。
number = integer | real;
ここで、代入しないでデバッグの為にプリントするとしよう。
さて、このセマンティックアクションだ、どうも右辺の一つに使った他の項にも影響が出るようだ。つまり、セマンティックアクションを使うのであれば全ての式に明示的に指定する必要がある。
上の数字の例で示す。integer の一致のみをプリントしてみたいと思い以下のようにする。
number = real[ std::cout << _1 << ];
これで、real に一致した場合は number に代入ではなく stdout に出力される。この括弧の中に明示的に指定した動作がセマンティックアクションだ。
どうも、real も integer のセマンティックアクションに引っ張られるようで、デフォルトアクションが呼ばれなくなるようだ。real にもセマンティックアクションを指定したら、期待通りの代入が起きるようになった。
number = integer[ std::cout << _1 << ] | real;
もう一つの対応策は項を分けること。
number = integer[ std::cout << _1 << ] | real[ _val = _1 ];
print_integer = integer[ std::cout << _1 << ];
number = print_integer | real;
Boost Qi でセマンティックアクションを用いる場合は、しっかりと全てを明示するか項を分ける。デフォルトアクションで期待通りの動作だったら良いが、一部だけ変更するのは無理みたいだ。実はこの動作の確証は掴んでいない。しかしSpirit パーサはセマンティックアクションで何が起きているのかを追うのはとても難しい。セマンティックアクションを入れ始めて動作が変わってしまった時はここを点検。
最近のコメント