diff --git a/.gitignore b/.gitignore index 2f7896d..a47c673 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ target/ +.idea +.cache diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..91b8f36 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,70 @@ +[ + { + "arguments": [ + "/usr/bin/clang++", + "-c", + "-std=c++17", + "-Wall", + "-Wextra", + "-pedantic", + "-Werror", + "-o", + "target/lox.cpp.o", + "src/lox.cpp" + ], + "directory": "/Users/Shautvast/dev/clox", + "file": "/Users/Shautvast/dev/clox/src/lox.cpp", + "output": "/Users/Shautvast/dev/clox/target/lox.cpp.o" + }, + { + "arguments": [ + "/usr/bin/clang++", + "-c", + "-std=c++17", + "-Wall", + "-Wextra", + "-pedantic", + "-Werror", + "-o", + "target/parser.cpp.o", + "src/parser.cpp" + ], + "directory": "/Users/Shautvast/dev/clox", + "file": "/Users/Shautvast/dev/clox/src/parser.cpp", + "output": "/Users/Shautvast/dev/clox/target/parser.cpp.o" + }, + { + "arguments": [ + "/usr/bin/clang++", + "-c", + "-std=c++17", + "-Wall", + "-Wextra", + "-pedantic", + "-Werror", + "-o", + "target/scanner.cpp.o", + "src/scanner.cpp" + ], + "directory": "/Users/Shautvast/dev/clox", + "file": "/Users/Shautvast/dev/clox/src/scanner.cpp", + "output": "/Users/Shautvast/dev/clox/target/scanner.cpp.o" + }, + { + "arguments": [ + "/usr/bin/clang++", + "-c", + "-std=c++17", + "-Wall", + "-Wextra", + "-pedantic", + "-Werror", + "-o", + "target/tokens.cpp.o", + "src/tokens.cpp" + ], + "directory": "/Users/Shautvast/dev/clox", + "file": "/Users/Shautvast/dev/clox/src/tokens.cpp", + "output": "/Users/Shautvast/dev/clox/target/tokens.cpp.o" + } +] diff --git a/makefile b/makefile index f4ecb09..3a8d74f 100644 --- a/makefile +++ b/makefile @@ -5,10 +5,10 @@ CC := clang++ -c -std=c++17 -Wall -Wextra -pedantic -Werror SRCS := $(shell find $(SRC) -name '*.c') OBJS := $(SRCS:%=$(TARGET)/%.o) -$(TARGET)/lox: $(TARGET)/lox.cpp.o $(TARGET)/parser.cpp.o $(TARGET)/scanner.cpp.o - clang++ $(TARGET)/lox.cpp.o -L$(TARGET) -lscanner.cpp.o -o $(TARGET)/lox +$(TARGET)/lox: $(TARGET)/lox.cpp.o $(TARGET)/parser.cpp.o $(TARGET)/scanner.cpp.o $(TARGET)/tokens.cpp.o + clang++ $(TARGET)/lox.cpp.o -L$(TARGET) -lscanner.cpp.o -ltokens.cpp.o -o $(TARGET)/lox -$(TARGET)/utils.cpp.o: $(SRC)/utils.cpp +$(TARGET)/tokens.cpp.o: $(SRC)/tokens.cpp $(CC) $< -o $@ $(TARGET)/scanner.cpp.o: $(SRC)/scanner.cpp diff --git a/src/lox.cpp b/src/lox.cpp index 5affe10..8e0c7ab 100644 --- a/src/lox.cpp +++ b/src/lox.cpp @@ -59,12 +59,7 @@ ScanResult run(std::string source) { void print_tokens(std::list *list) { for (std::list::iterator token = list->begin(); token != list->end(); ++token) { - - if (token->literal != NULL) { - std::cout << token_name(token->type) << "(" << token->literal << "), "; - } else { - std::cout << token_name(token->type) << ", "; - } + std::cout << token->to_string() << "(" << token->get_literal() << "), "; } std::cout << "\n"; diff --git a/src/scanner.cpp b/src/scanner.cpp index da2116f..2cd497d 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -22,23 +22,15 @@ ScanResult Scanner::scan_tokens() { return scan_result; } -void Scanner::add_token(TokenType type) { - Token token; - token.type = type; - token.lexeme = source.substr(start, current_pos); - token.literal = NULL; - token.line = current_line; - +void Scanner::add_token(Token::Type type) { + Token token = + Token(type, source.substr(start, current_pos), "", current_line); token_list.push_front(token); } -void Scanner::add_token_with_literal(TokenType type, std::string literal) { - Token token; - token.type = type; - token.lexeme = source.substr(start, current_pos); - token.literal = static_cast(&literal); - token.line = current_line; - +void Scanner::add_token_with_literal(Token::Type type, std::string literal) { + Token token = + Token(type, source.substr(start, current_pos), literal, current_line); token_list.push_front(token); } @@ -52,40 +44,40 @@ void Scanner::scan_token() { switch (c) { case '(': - add_token(LEFT_PAREN); + add_token(Token::Type::LEFT_PAREN); break; case ')': - add_token(RIGHT_PAREN); + add_token(Token::Type::RIGHT_PAREN); break; case '{': - add_token(LEFT_BRACE); + add_token(Token::Type::LEFT_BRACE); break; case '}': - add_token(RIGHT_BRACE); + add_token(Token::Type::RIGHT_BRACE); break; case ',': - add_token(COMMA); + add_token(Token::Type::COMMA); break; case '.': - add_token(DOT); + add_token(Token::Type::DOT); break; case '+': - add_token(PLUS); + add_token(Token::Type::PLUS); break; case '-': - add_token(MINUS); + add_token(Token::Type::MINUS); break; case '!': - add_token(match('=') ? BANG_EQUAL : BANG); + add_token(match('=') ? Token::Type::BANG_EQUAL : Token::Type::BANG); break; case '=': - add_token(match('=') ? EQUAL_EQUAL : EQUAL); + add_token(match('=') ? Token::Type::EQUAL_EQUAL : Token::Type::EQUAL); break; case '>': - add_token(match('=') ? GREATER_EQUAL : GREATER); + add_token(match('=') ? Token::Type::GREATER_EQUAL : Token::Type::GREATER); break; case '<': - add_token(match('=') ? LESS_EQUAL : LESS); + add_token(match('=') ? Token::Type::LESS_EQUAL : Token::Type::LESS); break; case '/': if (match('/')) { @@ -93,7 +85,7 @@ void Scanner::scan_token() { advance(); } } else { - add_token(SLASH); + add_token(Token::Type::SLASH); } break; case ' ': @@ -125,9 +117,9 @@ void Scanner::identifier() { std::string text = source.substr(start + 1, current_pos - start); - const TokenType *tokentype = get_keyword_token(text); + const Token::Type *tokentype = get_keyword_token(text); if (tokentype == NULL) { - add_token(IDENTIFIER); + add_token(Token::Type::IDENTIFIER); } else { add_token(*tokentype); } @@ -140,7 +132,8 @@ void Scanner::number() { advance(); while (is_digit(peek())) advance(); - add_token_with_literal(NUMBER, source.substr(start + 1, current_pos - start)); + add_token_with_literal(Token::Type::NUMBER, + source.substr(start + 1, current_pos - start)); } bool Scanner::is_digit(char c) { return c >= '0' && c <= '9'; } @@ -159,8 +152,8 @@ void Scanner::string() { advance(); - std::string string = source.substr(start + 2, current_pos - start - 2); - add_token_with_literal(STRING, string); + std::string string = source.substr(start + 1, current_pos - start - 2); + add_token_with_literal(Token::Type::STRING, string); } bool Scanner::match(char expected) { diff --git a/src/scanner.hpp b/src/scanner.hpp index d1c5693..f4d27a8 100644 --- a/src/scanner.hpp +++ b/src/scanner.hpp @@ -22,8 +22,8 @@ private: public: Scanner(std::string s); ScanResult scan_tokens(); - void add_token(TokenType type); - void add_token_with_literal(TokenType type, std::string literal); + void add_token(Token::Type type); + void add_token_with_literal(Token::Type type, std::string literal); char advance(); void scan_token(); void identifier(); @@ -42,16 +42,20 @@ public: typedef struct { const std::string key; - const TokenType value; + const Token::Type value; } Item; static const Item keywords[] = { - {"and", AND}, {"class", CLASS}, {"else", ELSE}, {"false", FALSE}, - {"for", FOR}, {"fun", FUN}, {"if", IF}, {"nil", NIL}, - {"or", OR}, {"print", PRINT}, {"return", RETURN}, {"super", SUPER}, - {"this", THIS}, {"true", TRUE}, {"var", VAR}, {"while", WHILE}}; + {"and", Token::Type::AND}, {"class", Token::Type::CLASS}, + {"else", Token::Type::ELSE}, {"false", Token::Type::FALSE}, + {"for", Token::Type::FOR}, {"fun", Token::Type::FUN}, + {"if", Token::Type::IF}, {"nil", Token::Type::NIL}, + {"or", Token::Type::OR}, {"print", Token::Type::PRINT}, + {"return", Token::Type::RETURN}, {"super", Token::Type::SUPER}, + {"this", Token::Type::THIS}, {"true", Token::Type::TRUE}, + {"var", Token::Type::VAR}, {"while", Token::Type::WHILE}}; -inline static const TokenType *get_keyword_token(std::string key) { +inline static const Token::Type *get_keyword_token(std::string key) { int low = 0; int high = sizeof(keywords) / sizeof(Item); diff --git a/src/tokens.cpp b/src/tokens.cpp new file mode 100644 index 0000000..5546f1e --- /dev/null +++ b/src/tokens.cpp @@ -0,0 +1,25 @@ +#include "tokens.hpp" + +Token::Token(Token::Type _tokentype, std::string _lexeme, std::string _literal, + int _line) + : lexeme(_lexeme), literal(_literal), line(_line), tokentype(_tokentype) {} + +std::string Token::to_string() { + static const std::string tokens[] = { + "END_OF_FILE", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", "RIGHT_BRACE", + "COMMA", "DOT", "MINUS", "PLUS", "SEMICOLON", + "SLASH", "STAR", "BANG", "BANG_EQUAL", "EQUAL", + "EQUAL_EQUAL", "GREATER", "GREATER_EQUAL", "LESS", "LESS_EQUAL", + "IDENTIFIER", "STRING", "NUMBER", "AND", "CLASS", + "ELSE", "FALSE", "FUN", "FOR", "IF", + "NIL", "OR", "PRINT", "RETURN", "SUPER", + "THIS", "TRUE", "VAR", "WHILE"}; + + return tokens[(int)tokentype]; // TODO shift the enum int values +} + +std::string Token::get_lexeme() { return lexeme; } + +std::string Token::get_literal() { return literal; } + +int Token::get_line() { return line; } diff --git a/src/tokens.hpp b/src/tokens.hpp index 8cb977a..a7c27b6 100644 --- a/src/tokens.hpp +++ b/src/tokens.hpp @@ -2,65 +2,60 @@ #include -typedef enum { - LEFT_PAREN, - RIGHT_PAREN, - LEFT_BRACE, - RIGHT_BRACE, - COMMA, - DOT, - MINUS, - PLUS, - SEMICOLON, - SLASH, - STAR, - BANG, - BANG_EQUAL, - EQUAL, - EQUAL_EQUAL, - GREATER, - GREATER_EQUAL, - LESS, - LESS_EQUAL, - IDENTIFIER, - STRING, - NUMBER, - AND, - CLASS, - ELSE, - FALSE, - FUN, - FOR, - IF, - NIL, - OR, - PRINT, - RETURN, - SUPER, - THIS, - TRUE, - VAR, - WHILE, - END_OF_FILE -} TokenType; - -static inline const char *token_name(TokenType type) { - static const char *tokens[] = { - "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", "RIGHT_BRACE", "COMMA", - "DOT", "MINUS", "PLUS", "SEMICOLON", "SLASH", - "STAR", "BANG", "BANG_EQUAL", "EQUAL", "EQUAL_EQUAL", - "GREATER", "GREATER_EQUAL", "LESS", "LESS_EQUAL", "IDENTIFIER", - "STRING", "NUMBER", "AND", "CLASS", "ELSE", - "FALSE", "FUN", "FOR", "IF", "NIL", - "OR", "PRINT", "RETURN", "SUPER", "THIS", - "TRUE", "VAR", "WHILE", "END_OF_FILE"}; - - return tokens[type]; -} - -typedef struct { - TokenType type; +class Token { +private: std::string lexeme; - void *literal; + std::string literal; int line; -} Token; + +public: + enum Type { + END_OF_FILE = 0, + LEFT_PAREN = 1, + RIGHT_PAREN = 2, + LEFT_BRACE = 3, + RIGHT_BRACE = 4, + COMMA = 5, + DOT = 6, + MINUS = 7, + PLUS = 8, + SEMICOLON = 9, + SLASH = 10, + STAR = 11, + BANG = 12, + BANG_EQUAL = 13, + EQUAL = 14, + EQUAL_EQUAL = 15, + GREATER = 16, + GREATER_EQUAL = 17, + LESS = 18, + LESS_EQUAL = 19, + IDENTIFIER = 20, + STRING = 21, + NUMBER = 22, + AND = 23, + CLASS = 24, + ELSE = 25, + FALSE = 26, + FUN = 27, + FOR = 28, + IF = 29, + NIL = 30, + OR = 31, + PRINT = 32, + RETURN = 33, + SUPER = 34, + THIS = 35, + TRUE = 36, + VAR = 37, + WHILE = 38, + } tokentype; + + std::string get_lexeme(); + std::string get_literal(); + int get_line(); + std::string to_string(); + + Token(Token::Type _tokentype, std::string _lexeme, std::string _literal, + int line); +};