Symbol::Kind advance()

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());
                        }
                }
            }
        }
    }