diff --git a/cclox_src/object.cc b/cclox_src/object.cc index 32560a6..db516e6 100644 --- a/cclox_src/object.cc +++ b/cclox_src/object.cc @@ -1,18 +1,28 @@ #include "object.hh" -void Identifier::write(std::ostream &os) const { - os << identifier; -}; - -void StringLit::write(std::ostream &os) const { - os << literal; -}; - -void Number::write(std::ostream &os) const { - os << number; -}; +Object::Object(StringObjectType string_type, const std::string &value) : str{value} { + switch (string_type) { + case StringObjectType::IDENTIFIER: + type = ObjectType::IDENTIFIER; + break; + case StringObjectType::LITERAL: + type = ObjectType::STRING_LIT; + break; + } +} std::ostream &operator<<(std::ostream &os, const Object &obj) { - obj.write(os); + switch (obj.type) { + case ObjectType::NIL: + break; + case ObjectType::IDENTIFIER: + case ObjectType::STRING_LIT: + os << obj.str; + break; + case ObjectType::NUMBER: + os << obj.number; + break; + } + return os; } diff --git a/cclox_src/object.hh b/cclox_src/object.hh index fd59666..6dfdca1 100644 --- a/cclox_src/object.hh +++ b/cclox_src/object.hh @@ -1,27 +1,31 @@ #pragma once -#include +#include #include +#include + +enum class StringObjectType : uint8_t { + IDENTIFIER, + LITERAL, +}; + +enum class ObjectType : uint8_t { + NIL, + IDENTIFIER, + STRING_LIT, + NUMBER, +}; struct Object { - Object() = delete; - virtual ~Object() = default; - virtual void write(std::ostream &os) const = 0; -}; + Object() : type{ObjectType::NIL} {}; + Object(double number) : type{ObjectType::NUMBER}, number{number} {}; + Object(StringObjectType string_type, const std::string &value); -struct Identifier : public Object { - virtual void write(std::ostream &os) const final; - std::string identifier; -}; - -struct StringLit : public Object { - virtual void write(std::ostream &os) const final; - std::string literal; -}; - -struct Number : public Object { - virtual void write(std::ostream &os) const final; - double number; + ObjectType type; + union { + std::string_view str; + double number; + }; }; std::ostream &operator<<(std::ostream &os, const Object &obj); diff --git a/cclox_src/scanner.cc b/cclox_src/scanner.cc index 68259aa..dc62654 100644 --- a/cclox_src/scanner.cc +++ b/cclox_src/scanner.cc @@ -1,7 +1,53 @@ #include "scanner.hh" #include "token.hh" +#include "error_handler.hh" +#include "object.hh" #include +extern ErrorHandler error_handler; + std::vector Scanner::scan_tokens() { - return std::vector{}; + 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; + default: + error_handler.error(line, "Unexpected character."); + break; + } +} + +char Scanner::advance() { + 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)); } diff --git a/cclox_src/scanner.hh b/cclox_src/scanner.hh index ae24ce1..5931a4f 100644 --- a/cclox_src/scanner.hh +++ b/cclox_src/scanner.hh @@ -1,11 +1,19 @@ #pragma once #include "token.hh" +#include #include struct Scanner { - Scanner(const std::string &code) : code{code} {}; + Scanner(const std::string &code) : code{code}, tokens{}, start{0}, current{0}, line{1} {}; std::vector scan_tokens(); + bool is_at_end(); + void scan_token(); + char advance(); + void add_token(TokenType type); + void add_token(TokenType type, Object literal); std::string code; + std::vector tokens; + std::size_t start, current, line; }; diff --git a/cclox_src/token.cc b/cclox_src/token.cc index a60b490..8c92041 100644 --- a/cclox_src/token.cc +++ b/cclox_src/token.cc @@ -1,5 +1,133 @@ #include "token.hh" +#include + +std::ostream &operator<<(std::ostream &os, const TokenType &type) { + switch (type) { + case TokenType::LEFT_PAREN: + os << "TokenType::LEFT_PAREN"; + break; + case TokenType::RIGHT_PAREN: + os << "TokenType::RIGHT_PAREN"; + break; + case TokenType::LEFT_BRACE: + os << "TokenType::LEFT_BRACE"; + break; + case TokenType::RIGHT_BRACE: + os << "TokenType::RIGHT_BRACE"; + break; + case TokenType::COMMA: + os << "TokenType::COMMA"; + break; + case TokenType::DOT: + os << "TokenType::DOT"; + break; + case TokenType::MINUS: + os << "TokenType::MINUS"; + break; + case TokenType::PLUS: + os << "TokenType::PLUS"; + break; + case TokenType::SEMICOLON: + os << "TokenType::SEMICOLON"; + break; + case TokenType::SLASH: + os << "TokenType::SLASH"; + break; + case TokenType::STAR: + os << "TokenType::STAR"; + break; + case TokenType::BANG: + os << "TokenType::BANG"; + break; + case TokenType::BANG_EQUAL: + os << "TokenType::BANG_EQUAL"; + break; + case TokenType::EQUAL: + os << "TokenType::EQUAL"; + break; + case TokenType::EQUAL_EQUAL: + os << "TokenType::EQUAL_EQUAL"; + break; + case TokenType::GREATER: + os << "TokenType::GREATER"; + break; + case TokenType::GREATER_EQUAL: + os << "TokenType::GREATER_EQUAL"; + break; + case TokenType::LESS: + os << "TokenType::LESS"; + break; + case TokenType::LESS_EQUAL: + os << "TokenType::LESS_EQUAL"; + break; + case TokenType::IDENTIFIER: + os << "TokenType::IDENTIFIER"; + break; + case TokenType::STRING: + os << "TokenType::STRING"; + break; + case TokenType::NUMBER: + os << "TokenType::NUMBER"; + break; + case TokenType::AND: + os << "TokenType::AND"; + break; + case TokenType::CLASS: + os << "TokenType::CLASS"; + break; + case TokenType::ELSE: + os << "TokenType::ELSE"; + break; + case TokenType::FALSE: + os << "TokenType::FALSE"; + break; + case TokenType::FUN: + os << "TokenType::FUN"; + break; + case TokenType::FOR: + os << "TokenType::FOR"; + break; + case TokenType::IF: + os << "TokenType::IF"; + break; + case TokenType::NIL: + os << "TokenType::NIL"; + break; + case TokenType::OR: + os << "TokenType::OR"; + break; + case TokenType::PRINT: + os << "TokenType::PRINT"; + break; + case TokenType::RETURN: + os << "TokenType::RETURN"; + break; + case TokenType::SUPER: + os << "TokenType::SUPER"; + break; + case TokenType::THIS: + os << "TokenType::THIS"; + break; + case TokenType::TRUE: + os << "TokenType::TRUE"; + break; + case TokenType::VAR: + os << "TokenType::VAR"; + break; + case TokenType::WHILE: + os << "TokenType::WHILE"; + break; + case TokenType::EOFILE: + os << "TokenType::EOFILE"; + break; + } + + return os; +} std::ostream &operator<<(std::ostream &os, const Token &token) { - return os << uint8_t(token.type) << ' ' << token.lexeme << ' ' << token.literal; + os << token.type << ' '; + os << token.lexeme << ' '; + os << token.literal; + return os; } diff --git a/cclox_src/token.hh b/cclox_src/token.hh index 4f3e88e..16d86d2 100644 --- a/cclox_src/token.hh +++ b/cclox_src/token.hh @@ -26,14 +26,15 @@ enum class TokenType : uint8_t { }; struct Token { - Token(TokenType type, const std::string &lexeme, Object &literal, int line) + Token(TokenType type, const std::string &lexeme, Object literal, int line) : type{type}, lexeme{lexeme}, literal{literal}, line{line} {}; TokenType type; std::string lexeme; - Object &literal; + Object literal; int line; }; +std::ostream &operator<<(std::ostream &os, const TokenType &type); std::ostream &operator<<(std::ostream &os, const Token &token);