210 Token(TokenType type, std::string lexeme, Location location)
211 : tok_type(type), lexeme(std::move(lexeme)), location(location) {}
212 bool is_comparison()
const {
213 return tok_type == TokLESS || tok_type == TokGreaterEqual ||
214 tok_type == TokLessEqual || tok_type == TokGREATER ||
215 tok_type == TokEQUAL || tok_type == TokNOTEqual;
217 bool is_assign()
const {
return tok_type == TokASSIGN; }
218 bool is_logical()
const {
return tok_type == TokOR || tok_type == TokAND; }
219 bool is_bitwise()
const {
220 return tok_type == TokAndLogical || tok_type == TokORLogical ||
221 tok_type == TokXOR || tok_type == TokSHL || tok_type == TokSHR;
223 Location get_location()
const {
return this->location; }
231 using TokenList = std::list<std::shared_ptr<Token>>;
232 using Iterator = TokenList::iterator;
236 Iterator rollback_cursor;
238 std::function<void()> tokenProducer;
242 std::shared_ptr<Token> original;
244 std::vector<SplitRecord> pending_splits;
245 size_t splits_at_mark = 0;
248 while (cursor == TokStream.end() && tokenProducer)
253 std::vector<std::shared_ptr<Token>> ErrStream;
256 : cursor(TokStream.end()), rollback_cursor(TokStream.end()),
259 void setTokenProducer(std::function<
void()> producer) {
260 tokenProducer = std::move(producer);
263 void push_back(
const std::shared_ptr<Token> &token) {
264 if (token->tok_type == TokINVALID) {
266 ErrStream.push_back(token);
269 bool was_at_end = (cursor == TokStream.end());
270 TokStream.push_back(token);
272 cursor = std::prev(TokStream.end());
275 bool hasErrors()
const {
return error; }
277 void push_back(
const Token &token) {
278 this->push_back(std::make_shared<Token>(token));
281 void mark_rollback() {
282 rollback_cursor = cursor;
283 splits_at_mark = pending_splits.size();
287 while (pending_splits.size() > splits_at_mark) {
288 auto &r = pending_splits.back();
289 *std::prev(r.inserted) = r.original;
290 TokStream.erase(r.inserted);
291 pending_splits.pop_back();
293 cursor = rollback_cursor;
296 void rollback(
size_t rollback_count) {
297 for (
size_t i = 0; i < rollback_count; ++i) {
298 assert(cursor != TokStream.begin() &&
299 "Cannot rollback past the beginning");
304 std::shared_ptr<Token> &exhaust_until(TokenType tokType) {
305 if (tokType == TokenType::TokEOF) {
306 while (tokenProducer) {
307 if (!TokStream.empty() && TokStream.back()->tok_type == TokEOF)
311 cursor = std::prev(TokStream.end());
312 return TokStream.back();
316 if ((*cursor)->tok_type == tokType) {
324 return TokStream.back();
329 return cursor != TokStream.end() && (*cursor)->tok_type == TokEOF;
332 std::shared_ptr<Token> peek() {
337 std::shared_ptr<Token> consume() {
339 auto token = *cursor;
340 if (token->tok_type != TokEOF)
347 if (!TokStream.empty())
348 return (*cursor)->get_location();
352 void split_current(TokenType first_type,
const std::string &first_lex,
353 TokenType second_type,
const std::string &second_lex) {
355 auto original = *cursor;
356 auto loc = original->location;
357 *cursor = std::make_shared<Token>(first_type, first_lex, loc);
358 auto inserted = TokStream.insert(
360 std::make_shared<Token>(second_type, second_lex, loc));
361 pending_splits.push_back({inserted, original});