そのため、boost 1.59 で提供されている boost::spirit::x3 で奇妙な動作に遭遇しました。
次の方法で「動的」シンボルテーブルを定義しました。
struct instructions : x3::symbols<OpCode> {
instructions()
{
name("instructions");
}
void set_instruction_set(const std::unordered_map<std::string, OpCode>& instruction_set) {
for (const auto& var : instruction_set) {
add(var.first, var.second);
}
}
} instructions_parser;
OpCode
と定義されている
struct OpCode
{
std::string mnemonic;
std::vector<...> variants;// actual type in vector<> not important.
};
現在、必要なルールに埋め込まれた記号テーブルを使用して、次のような入力文字列を解析する場合
mov r2 r1
mov r1 @80
結果の ast には、最初のmov
オペランドのみが含まれます。2 番目の mov がありませんが、オペランドは正しく解析されています。結果の AST を出力すると、次のようになります。
mov r2 r1
r1 @80
デバッガーを使用して、symbols.hpp のエラーの原因を特定しましたsymbol_parser::parse()
。
template <typename Iterator, typename Context, typename Attribute>
bool parse(Iterator& first, Iterator const& last
, Context const& context, unused_type, Attribute& attr) const
{
x3::skip_over(first, last, context);
if (value_type* val_ptr
= lookup->find(first, last, get_case_compare<Encoding>(context)))
{
x3::traits::move_to(*val_ptr, attr); //<- the error originates from here
return true;
}
return false;
}
move_to
ビーイング
で:
template <typename T>
inline void move_to(T& src, T& dest)
{
if (boost::addressof(src) != boost::addressof(dest))
dest = std::move(src);
}
ご覧のとおりsrc
、symbol_parser に追加された OpCode インスタンスが移動されています。これは、最初の呼び出しの後に再び空になることを意味し、そのため最初の命令のみが表示されます。簡単に言えば、シンボルテーブルから移動しました。
最後に私の質問: これはバグですか、それとも間違いですか?