From b08bb0a17ed05e7febaee5c71f5cf1ff3447dea1 Mon Sep 17 00:00:00 2001 From: Mustafa Quraish Date: Sun, 30 Jan 2022 02:20:58 -0500 Subject: Put tokens in their own macro to allow looping over them --- src/lexer.c | 19 +++++-------------- src/main.c | 14 ++++++++++++-- src/tokens.c | 7 ++++--- src/tokens.h | 26 +++++++++++++++----------- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/lexer.c b/src/lexer.c index ea095ba..699e960 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -79,9 +79,6 @@ static Token Lexer_make_token(Lexer *lexer, TokenType type, int inc_amount) return token; } -#define LEX_KEYWORD(str, token_type) \ - if (Lexer_starts_with(lexer, str)) return Lexer_make_token(lexer, token_type, strlen(str)); - Token Lexer_next(Lexer *lexer) { while (lexer->pos < lexer->len) { @@ -98,6 +95,8 @@ Token Lexer_next(Lexer *lexer) case '~': return Lexer_make_token(lexer, TOKEN_TILDE, 1); case '?': return Lexer_make_token(lexer, TOKEN_QUESTION, 1); case ',': return Lexer_make_token(lexer, TOKEN_COMMA, 1); + case '*': return Lexer_make_token(lexer, TOKEN_STAR, 1); + case '%': return Lexer_make_token(lexer, TOKEN_PERCENT, 1); case '&': { if (peek(lexer, 1) == '&') @@ -162,20 +161,12 @@ Token Lexer_next(Lexer *lexer) return Lexer_make_token(lexer, TOKEN_SLASH, 1); } - case '*': return Lexer_make_token(lexer, TOKEN_STAR, 1); - case '%': return Lexer_make_token(lexer, TOKEN_PERCENT, 1); - default: { // Handle keywords explicitly - LEX_KEYWORD("fn", TOKEN_FN); - LEX_KEYWORD("if", TOKEN_IF); - LEX_KEYWORD("int", TOKEN_INT); - LEX_KEYWORD("let", TOKEN_LET); - LEX_KEYWORD("for", TOKEN_FOR); - LEX_KEYWORD("else", TOKEN_ELSE); - LEX_KEYWORD("while", TOKEN_WHILE); - LEX_KEYWORD("return", TOKEN_RETURN); + #define LEX_KEYWORD(token_type, str) if (Lexer_starts_with(lexer, str)) return Lexer_make_token(lexer, token_type, strlen(str)); + ENUM_KEYWORDS(LEX_KEYWORD) + #undef LEX_KEYWORD if (isdigit(lexer->src[lexer->pos])) { // TODO: Parse hex and octal numbers diff --git a/src/main.c b/src/main.c index 15460ff..c94f8d3 100644 --- a/src/main.c +++ b/src/main.c @@ -5,12 +5,15 @@ #include "parser.h" #include "generator.h" #include "unistd.h" +#include char *filename = NULL; char *source = NULL; i64 source_len = 0; bool dump_ast = false; +char *output_file = "build/output.nasm"; + #define MAX_STDIN_SOURCE_LEN 2048 void usage(int exit_status) @@ -19,6 +22,7 @@ void usage(int exit_status) printf("Options:\n"); printf(" -c Code to compile\n"); printf(" -h Show this help\n"); + printf(" -o Output file\n"); printf(" -d Dump AST to stdout\n"); printf("Output file will be named `output.nasm`\n"); exit(exit_status); @@ -37,6 +41,9 @@ void parse_args(int argc, char **argv) usage(0); } else if (strcmp(argv[i], "-d") == 0) { dump_ast = true; + } else if (strcmp(argv[i], "-o") == 0) { + i++; + output_file = argv[i]; } else if (filename == NULL) { if (strcmp(argv[i], "-") == 0) { filename = "stdin"; @@ -73,10 +80,13 @@ int main(int argc, char**argv) { if (dump_ast) print_ast(ast); - FILE *f = fopen("output.nasm", "w"); + FILE *f = fopen(output_file, "w"); + if (f == NULL) { + fprintf(stderr, "Could not open output file: %s\n", strerror(errno)); + exit(1); + } generate_asm(ast, f); - free(source); return 0; } diff --git a/src/tokens.c b/src/tokens.c index e562e16..2d99f71 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -47,9 +47,10 @@ char *token_type_to_str(TokenType type) // Otherwise, just print the token type switch (type) { - #define ENUM_TOKEN(name, str) case name: return str; - ENUM_TOKENS(ENUM_TOKEN) - #undef ENUM_TOKEN + #define HANDLE_ITEM(name, str) case name: return str; + ENUM_TOKENS(HANDLE_ITEM) + ENUM_KEYWORDS(HANDLE_ITEM) + #undef HANDLE_ITEM default: assert(false && "Unreachable"); } } diff --git a/src/tokens.h b/src/tokens.h index 44f5e6e..3917f0f 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -12,21 +12,15 @@ F(TOKEN_CLOSE_PAREN, ")") \ F(TOKEN_COLON, ":") \ F(TOKEN_COMMA, ",") \ - F(TOKEN_ELSE, "else") \ F(TOKEN_EOF, "EOF") \ F(TOKEN_EQ, "==") \ F(TOKEN_EXCLAMATION, "!") \ - F(TOKEN_FN, "fn") \ - F(TOKEN_FOR, "for") \ F(TOKEN_GEQ, ">=") \ F(TOKEN_GT, ">") \ F(TOKEN_IDENTIFIER, "identifier") \ - F(TOKEN_IF, "if") \ - F(TOKEN_INT, "int") \ F(TOKEN_INTLIT, "integer literal") \ F(TOKEN_LEQ, "<=") \ F(TOKEN_LSHIFT, "<<") \ - F(TOKEN_LET, "let") \ F(TOKEN_LT, "<") \ F(TOKEN_MINUS, "-") \ F(TOKEN_MINUSEQUALS, "-=") \ @@ -40,20 +34,30 @@ F(TOKEN_PLUSEQUALS, "+=") \ F(TOKEN_PLUSPLUS, "++") \ F(TOKEN_QUESTION, "?") \ - F(TOKEN_RETURN, "return") \ F(TOKEN_RSHIFT, ">>") \ F(TOKEN_SEMICOLON, ";") \ F(TOKEN_SLASH, "/") \ F(TOKEN_STAR, "*") \ F(TOKEN_STRINGLIT, "string literal") \ F(TOKEN_TILDE, "~") \ - F(TOKEN_WHILE, "while") \ F(TOKEN_XOR, "^") +#define ENUM_KEYWORDS(F) \ + F(TOKEN_ELSE, "else") \ + F(TOKEN_FN, "fn") \ + F(TOKEN_FOR, "for") \ + F(TOKEN_IF, "if") \ + F(TOKEN_INT, "int") \ + F(TOKEN_LET, "let") \ + F(TOKEN_RETURN, "return") \ + F(TOKEN_WHILE, "while") \ + + typedef enum { -#define ENUM_TOKEN(name, str) name, - ENUM_TOKENS(ENUM_TOKEN) -#undef ENUM_TOKEN +#define HANDLE_ITEM(name, str) name, + ENUM_TOKENS(HANDLE_ITEM) + ENUM_KEYWORDS(HANDLE_ITEM) +#undef HANDLE_ITEM } TokenType; typedef struct { -- cgit v1.2.3