Simplify Object type
This commit is contained in:
		@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,27 +1,31 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string_view>
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,53 @@
 | 
			
		||||
#include "scanner.hh"
 | 
			
		||||
#include "token.hh"
 | 
			
		||||
#include "error_handler.hh"
 | 
			
		||||
#include "object.hh"
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
extern ErrorHandler error_handler;
 | 
			
		||||
 | 
			
		||||
std::vector<Token> Scanner::scan_tokens() {
 | 
			
		||||
  return std::vector<Token>{};
 | 
			
		||||
  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));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,19 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "token.hh"
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
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<Token> 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<Token> tokens;
 | 
			
		||||
  std::size_t start, current, line;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,133 @@
 | 
			
		||||
#include "token.hh"
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user