#ifndef GOOSE_PARSE_RESOLVER_H #define GOOSE_PARSE_RESOLVER_H namespace goose::parse { class Resolver { public: Resolver( const ptr< lex::TokenProvider >& tokProv, const sema::Context& c ) : m_tokProvider( tokProv ), m_context( c ), m_valueStoreVersion( c.env()->valueStoreVersion() ) {} Resolver( const Resolver& r, const sema::Context& c ) : m_tokProvider( r.m_tokProvider ), m_context( c ), m_valueStoreVersion( c.env()->valueStoreVersion() ) {} const auto& context() const { return m_context; } auto& context() { return m_context; } bool eos() const; auto currentLocation() { return m_tokProvider->currentLocation(); } // Consume the next token. Bound identifiers are resolved. optional< TermLoc > consume(); // Consume the next token. No resolution is performed on identifiers. optional< TermLoc > consumeUnresolved(); optional< TermLoc > lookAhead( size_t distance = 0 ); optional< TermLoc > lookAheadUnresolved( size_t distance = 0 ); // Consume the next unit from the provider and yield each token that it contains. // An unit is: // - any brace, paren or bracket block and every unit they contain // - any other token Generator< TermLoc > consumeUnit(); void clearLookAheadCache() const; private: TermLoc resolve( const TermLoc& t ) const; void clearCacheIfNeeded() const { if( m_context.env()->valueStoreVersion() == m_valueStoreVersion ) return; clearLookAheadCache(); } Generator< TermLoc > consumeBlock( Delimiter end ); ptr< lex::TokenProvider > m_tokProvider; sema::Context m_context; mutable deque< TermLoc > m_lookAheadCache; mutable uint64_t m_valueStoreVersion = 0; }; } #endif