Я пытаюсь использовать перегрузку операторов '&' и '|'и операторы '| =' в C ++ для создания BNF (Backus Naur Form), встроенной в C ++.Два существенных класса в этом встроенном BNF - это класс Terminal и класс NonTerminal.
В качестве примера Snippet рассмотрим описание BNF списка символов «a» или «b»:
Terminal _a('a'), _b('b');
NonTerminal list, token;
token |= _a | _b;
list |= token | token & list;
// Parse a string of 'a's and 'b's
if(list.match("baabaabaa"))
cout << "matched!!!";
else
cout << "failed!!!";
// Test the token nonterminal
token.match("a");
Определения классов следующие: они ничего не делаютна данный момент, но служат проверкой логики.
using namespace std;
class Sequence;
class Production;
class Base {
Base() {}
virtual ~Base() {}
friend Sequence operator & (const Base& lhs, const Base& rhs);
friend Production operator | (const Base& lhs, const Base& rhs);
virtual bool match(string) const { return false; }
};
class Terminal : public Base {
char token;
public:
Terminal(char c) : token(c) {}
virtual ~Terminal() {}
virtual bool match(string s) const { return true; }
};
class Sequence : public Base {
const Base& lhs;
const Base& rhs;
public:
Sequence(const Base& lhs, const Base& rhs) : lhs(lhs), rhs(rhs) {}
virtual ~Sequence() {}
virtual bool match(string s) const { return lhs.match(s) && rhs.match(s); }
};
class Production: public Base {
const Base& lhs;
const Base& rhs;
public:
Production(const Base& lhs, const Base& rhs) : lhs(lhs), rhs(rhs) {}
virtual ~Production() {}
virtual bool match(std::string s) const { return lhs.match(s) || rhs.match(s); }
};
Последнее определение класса, NonTerminal, - это то, где у меня возникают проблемы.И проблема заключается в семантике перемещения C + 11.
class NonTerminal : Base {
Base dummy; // Needed to make initialization work.
Base& ref; // Or maybe Base&& ref or possibly Base ref or could it be Base* ref?
NonTerminal() : ref(dummy) {}
virtual ~NonTerminal() {}
// Used when rhs is of type Sequence or Production
void operator |= (Base&& rhs) {
// The desired action is to capture rhs and keep it in memory.
ref = move(rhs);
}
// Used when rhs is of type Terminal
void operator |= (const Base& rhs) {
// The desired action is to reference rhs.
ref = rhs;
}
virtual bool match(string s) { return ref.match(s); }
};
Код, основанный на приведенном выше примере, основан на компиляции, но когда вызывается метод list.match (), он вызывает метод Base :: match (), а не Production :: match (), что является ожидаемым поведением.Таким же образом, вызов token.match () также вызывает метод Base :: match (), а не Terminal :: match ().Итак, как мне вызвать правильные перезаписанные методы сопоставления и сделать это правильно для значения r, полученного в первом операторе | = метод?
Спасибо