in lang/c++/impl/parsing/Symbol.hh [408:484]
Symbol::Kind advance(Symbol::Kind k) {
for (;;) {
Symbol &s = parsingStack.top();
// std::cout << "advance: " << Symbol::toString(s.kind())
// << " looking for " << Symbol::toString(k) << '\n';
if (s.kind() == k) {
parsingStack.pop();
return k;
} else if (s.isTerminal()) {
throwMismatch(k, s.kind());
} else {
switch (s.kind()) {
case Symbol::Kind::Root:
append(std::get<0>(*s.extrap<RootInfo>()));
continue;
case Symbol::Kind::Indirect: {
ProductionPtr pp =
s.extra<ProductionPtr>();
parsingStack.pop();
append(pp);
}
continue;
case Symbol::Kind::Symbolic: {
ProductionPtr pp(
s.extra<std::weak_ptr<Production>>());
parsingStack.pop();
append(pp);
}
continue;
case Symbol::Kind::Repeater: {
auto *p = s.extrap<RepeaterInfo>();
std::stack<ssize_t> &ns = std::get<0>(*p);
if (ns.empty()) {
throw Exception(
"Empty item count stack in repeater advance");
}
if (ns.top() == 0) {
throw Exception(
"Zero item count in repeater advance");
}
--ns.top();
append(std::get<2>(*p));
}
continue;
case Symbol::Kind::Error:
throw Exception(s.extra<std::string>());
case Symbol::Kind::Resolve: {
const std::pair<Symbol::Kind, Symbol::Kind> *p =
s.extrap<std::pair<Symbol::Kind, Symbol::Kind>>();
assertMatch(p->second, k);
Symbol::Kind result = p->first;
parsingStack.pop();
return result;
}
case Symbol::Kind::SkipStart:
parsingStack.pop();
skip(*decoder_);
break;
default:
if (s.isImplicitAction()) {
size_t n = handler_.handle(s);
if (s.kind() == Symbol::Kind::WriterUnion) {
parsingStack.pop();
selectBranch(n);
} else {
parsingStack.pop();
}
} else {
std::ostringstream oss;
oss << "Encountered " << Symbol::toString(s.kind())
<< " while looking for " << Symbol::toString(k);
throw Exception(oss.str());
}
}
}
}
}