#include "scanner.hh" #include "token.hh" #include "error_handler.hh" #include "object.hh" #include extern ErrorHandler error_handler; std::vector Scanner::scan_tokens() { while (!is_at_end()) { start = current; scan_token(); } tokens.push_back(Token(TokenType::EOFILE, "", Object{}, line)); return tokens; } bool Scanner::is_at_end() { return current >= code.size(); } void Scanner::scan_token() { char c = advance(); switch (c) { case '(': add_token(TokenType::LEFT_PAREN); break; case ')': add_token(TokenType::RIGHT_PAREN); break; case '{': add_token(TokenType::LEFT_BRACE); break; case '}': add_token(TokenType::RIGHT_BRACE); break; case ',': add_token(TokenType::COMMA); break; case '.': add_token(TokenType::DOT); break; case '-': add_token(TokenType::MINUS); break; case '+': add_token(TokenType::PLUS); break; case ';': add_token(TokenType::SEMICOLON); break; case '*': add_token(TokenType::STAR); break; case '!': add_token(match('=') ? TokenType::BANG_EQUAL : TokenType::BANG); break; case '=': add_token(match('=') ? TokenType::EQUAL_EQUAL : TokenType::EQUAL); break; case '<': add_token(match('=') ? TokenType::LESS_EQUAL : TokenType::LESS); break; case '>': add_token(match('=') ? TokenType::GREATER_EQUAL : TokenType::GREATER); break; case '/': if (match('/')) { while (peek() != '\n' && !is_at_end()) { advance(); } } else { add_token(TokenType::SLASH); } break; case ' ': case '\r': case '\t': break; case '\n': ++line; break; case '"': string(); break; default: error_handler.error(line, "Unexpected character."); break; } } char Scanner::advance() { return code.at(current++); } bool Scanner::match(char expected) { if (is_at_end() || peek() != expected) { return false; } current++; return true; } char Scanner::peek() { if (is_at_end()) { return '\0'; } return code.at(current); } void Scanner::add_token(TokenType type) { add_token(type, Object{}); } void Scanner::add_token(TokenType type, Object literal) { std::string text = code.substr(start, current - start); tokens.push_back(Token(type, text, literal, line)); } void Scanner::string() { while (peek() != '"' && !is_at_end()) { if (peek() == '\n') line++; advance(); } if (is_at_end()) { error_handler.error(line, "Unterminated string."); return; } // The closing ". advance(); // Trim the surrounding quotes. std::string value = code.substr(start + 1, current - 1); add_token(TokenType::STRING, Object(StringObjectType::LITERAL, value)); }