more idiomatic, I think
This commit is contained in:
parent
07cec15696
commit
f07ac236bc
8 changed files with 193 additions and 109 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1 +1,3 @@
|
|||
target/
|
||||
.idea
|
||||
.cache
|
||||
|
|
|
|||
70
compile_commands.json
Normal file
70
compile_commands.json
Normal 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"
|
||||
}
|
||||
]
|
||||
6
makefile
6
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
|
||||
|
|
|
|||
|
|
@ -59,12 +59,7 @@ ScanResult run(std::string source) {
|
|||
void print_tokens(std::list<Token> *list) {
|
||||
for (std::list<Token>::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";
|
||||
|
|
|
|||
|
|
@ -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<void *>(&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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
25
src/tokens.cpp
Normal file
25
src/tokens.cpp
Normal 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; }
|
||||
115
src/tokens.hpp
115
src/tokens.hpp
|
|
@ -2,65 +2,60 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
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);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue