2

So, I ran into strange behaviour with boost::spirit::x3 as supplied in boost 1.59:

I defined a 'dynamic' symbol table via:

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;

OpCodeis defined as

struct OpCode
{
    std::string mnemonic;
    std::vector<...> variants;// actual type in vector<> not important.
};

now, with the symbol table embedded in the neccessary rules, when parsing an input string like

mov r2  r1
mov r1  @80

the resulting ast only contains the first mov with its operands. The second mov is missing but the operands are correctly parsed. This may look as followed, when printing the resulting AST:

mov r2 r1 
    r1 @80

With the debugger I located the source of the error in symbols.hpp in 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;
    }

with move_to beeing:

template <typename T>
inline void move_to(T& src, T& dest)
{
    if (boost::addressof(src) != boost::addressof(dest))
        dest = std::move(src);
}

As you can see, the src which is my OpCode instance added in the symbol_parser is moved. This means after the first call its empty again and that's why only the first instructions appears. It's, simply put, moved out of the symbol table.

Now finally my question: Is this a bug or am I making a mistake?

sehe
  • 374,641
  • 47
  • 450
  • 633
UsYer
  • 173
  • 1
  • 8
  • 1
    [Seems to be a bug](http://melpon.org/wandbox/permlink/XxPCnmWExNkmsmP2). – llonesmiz Feb 22 '16 at 05:09
  • 1
    Thanks for providing the example. That is exactly the behaviour I experienced. I found a temporary workaround: By declaring the template parameter as const one can suppress move semantics. The copy-ctor is then called. I.E.: x3::symbols – UsYer Feb 22 '16 at 19:34
  • Could you please file the workaround as an answer and a bug at Boost Trac/a PR at github? Splendid observation! – sehe Feb 23 '16 at 06:52
  • Thanks for your response @sehe. I filed a bug in boost trac at https://svn.boost.org/trac/boost/ticket/12016 I'm not sure if I can file a PR. I'll have to investigate a proper fix. – UsYer Feb 23 '16 at 21:54

1 Answers1

3

As suggested by sehe my workaround as an answer:

I found a temporary workaround: By declaring the template parameter as const one can suppress move semantics. The copy-ctor is then called.

I.E.: x3::symbols<const std::string>

UsYer
  • 173
  • 1
  • 8