more idiomatic, I think

This commit is contained in:
Shautvast 2024-10-15 16:41:40 +02:00
parent 07cec15696
commit f07ac236bc
8 changed files with 193 additions and 109 deletions

2
.gitignore vendored
View file

@ -1 +1,3 @@
target/ target/
.idea
.cache

70
compile_commands.json Normal file
View file

@ -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"
}
]

View file

@ -5,10 +5,10 @@ CC := clang++ -c -std=c++17 -Wall -Wextra -pedantic -Werror
SRCS := $(shell find $(SRC) -name '*.c') SRCS := $(shell find $(SRC) -name '*.c')
OBJS := $(SRCS:%=$(TARGET)/%.o) OBJS := $(SRCS:%=$(TARGET)/%.o)
$(TARGET)/lox: $(TARGET)/lox.cpp.o $(TARGET)/parser.cpp.o $(TARGET)/scanner.cpp.o $(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 -o $(TARGET)/lox 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 $@ $(CC) $< -o $@
$(TARGET)/scanner.cpp.o: $(SRC)/scanner.cpp $(TARGET)/scanner.cpp.o: $(SRC)/scanner.cpp

View file

@ -59,12 +59,7 @@ ScanResult run(std::string source) {
void print_tokens(std::list<Token> *list) { void print_tokens(std::list<Token> *list) {
for (std::list<Token>::iterator token = list->begin(); token != list->end(); for (std::list<Token>::iterator token = list->begin(); token != list->end();
++token) { ++token) {
std::cout << token->to_string() << "(" << token->get_literal() << "), ";
if (token->literal != NULL) {
std::cout << token_name(token->type) << "(" << token->literal << "), ";
} else {
std::cout << token_name(token->type) << ", ";
}
} }
std::cout << "\n"; std::cout << "\n";

View file

@ -22,23 +22,15 @@ ScanResult Scanner::scan_tokens() {
return scan_result; return scan_result;
} }
void Scanner::add_token(TokenType type) { void Scanner::add_token(Token::Type type) {
Token token; Token token =
token.type = type; Token(type, source.substr(start, current_pos), "", current_line);
token.lexeme = source.substr(start, current_pos);
token.literal = NULL;
token.line = current_line;
token_list.push_front(token); token_list.push_front(token);
} }
void Scanner::add_token_with_literal(TokenType type, std::string literal) { void Scanner::add_token_with_literal(Token::Type type, std::string literal) {
Token token; Token token =
token.type = type; Token(type, source.substr(start, current_pos), literal, current_line);
token.lexeme = source.substr(start, current_pos);
token.literal = static_cast<void *>(&literal);
token.line = current_line;
token_list.push_front(token); token_list.push_front(token);
} }
@ -52,40 +44,40 @@ void Scanner::scan_token() {
switch (c) { switch (c) {
case '(': case '(':
add_token(LEFT_PAREN); add_token(Token::Type::LEFT_PAREN);
break; break;
case ')': case ')':
add_token(RIGHT_PAREN); add_token(Token::Type::RIGHT_PAREN);
break; break;
case '{': case '{':
add_token(LEFT_BRACE); add_token(Token::Type::LEFT_BRACE);
break; break;
case '}': case '}':
add_token(RIGHT_BRACE); add_token(Token::Type::RIGHT_BRACE);
break; break;
case ',': case ',':
add_token(COMMA); add_token(Token::Type::COMMA);
break; break;
case '.': case '.':
add_token(DOT); add_token(Token::Type::DOT);
break; break;
case '+': case '+':
add_token(PLUS); add_token(Token::Type::PLUS);
break; break;
case '-': case '-':
add_token(MINUS); add_token(Token::Type::MINUS);
break; break;
case '!': case '!':
add_token(match('=') ? BANG_EQUAL : BANG); add_token(match('=') ? Token::Type::BANG_EQUAL : Token::Type::BANG);
break; break;
case '=': case '=':
add_token(match('=') ? EQUAL_EQUAL : EQUAL); add_token(match('=') ? Token::Type::EQUAL_EQUAL : Token::Type::EQUAL);
break; break;
case '>': case '>':
add_token(match('=') ? GREATER_EQUAL : GREATER); add_token(match('=') ? Token::Type::GREATER_EQUAL : Token::Type::GREATER);
break; break;
case '<': case '<':
add_token(match('=') ? LESS_EQUAL : LESS); add_token(match('=') ? Token::Type::LESS_EQUAL : Token::Type::LESS);
break; break;
case '/': case '/':
if (match('/')) { if (match('/')) {
@ -93,7 +85,7 @@ void Scanner::scan_token() {
advance(); advance();
} }
} else { } else {
add_token(SLASH); add_token(Token::Type::SLASH);
} }
break; break;
case ' ': case ' ':
@ -125,9 +117,9 @@ void Scanner::identifier() {
std::string text = source.substr(start + 1, current_pos - start); 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) { if (tokentype == NULL) {
add_token(IDENTIFIER); add_token(Token::Type::IDENTIFIER);
} else { } else {
add_token(*tokentype); add_token(*tokentype);
} }
@ -140,7 +132,8 @@ void Scanner::number() {
advance(); advance();
while (is_digit(peek())) while (is_digit(peek()))
advance(); 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'; } bool Scanner::is_digit(char c) { return c >= '0' && c <= '9'; }
@ -159,8 +152,8 @@ void Scanner::string() {
advance(); advance();
std::string string = source.substr(start + 2, current_pos - start - 2); std::string string = source.substr(start + 1, current_pos - start - 2);
add_token_with_literal(STRING, string); add_token_with_literal(Token::Type::STRING, string);
} }
bool Scanner::match(char expected) { bool Scanner::match(char expected) {

View file

@ -22,8 +22,8 @@ private:
public: public:
Scanner(std::string s); Scanner(std::string s);
ScanResult scan_tokens(); ScanResult scan_tokens();
void add_token(TokenType type); void add_token(Token::Type type);
void add_token_with_literal(TokenType type, std::string literal); void add_token_with_literal(Token::Type type, std::string literal);
char advance(); char advance();
void scan_token(); void scan_token();
void identifier(); void identifier();
@ -42,16 +42,20 @@ public:
typedef struct { typedef struct {
const std::string key; const std::string key;
const TokenType value; const Token::Type value;
} Item; } Item;
static const Item keywords[] = { static const Item keywords[] = {
{"and", AND}, {"class", CLASS}, {"else", ELSE}, {"false", FALSE}, {"and", Token::Type::AND}, {"class", Token::Type::CLASS},
{"for", FOR}, {"fun", FUN}, {"if", IF}, {"nil", NIL}, {"else", Token::Type::ELSE}, {"false", Token::Type::FALSE},
{"or", OR}, {"print", PRINT}, {"return", RETURN}, {"super", SUPER}, {"for", Token::Type::FOR}, {"fun", Token::Type::FUN},
{"this", THIS}, {"true", TRUE}, {"var", VAR}, {"while", WHILE}}; {"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 low = 0;
int high = sizeof(keywords) / sizeof(Item); int high = sizeof(keywords) / sizeof(Item);

25
src/tokens.cpp Normal file
View file

@ -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; }

View file

@ -2,65 +2,60 @@
#include <string> #include <string>
typedef enum { class Token {
LEFT_PAREN, private:
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;
std::string lexeme; std::string lexeme;
void *literal; std::string literal;
int line; 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);
};