From e079f63d274602b8d820c0f062e3f2846e1d5eba Mon Sep 17 00:00:00 2001 From: Shautvast Date: Mon, 14 Oct 2024 10:51:33 +0200 Subject: [PATCH] added parser file --- makefile | 6 ++- src/lox.c | 131 ++++++++++++++++++++++++-------------------------- src/parser.c | 21 ++++++++ src/parser.h | 1 + src/scanner.c | 88 +++++++++++++-------------------- src/scanner.h | 21 +++++++- src/tokens.h | 20 ++++---- 7 files changed, 154 insertions(+), 134 deletions(-) create mode 100644 src/parser.c create mode 100644 src/parser.h diff --git a/makefile b/makefile index ea8c010..333b974 100644 --- a/makefile +++ b/makefile @@ -5,8 +5,8 @@ CC := clang -c -std=c17 -Wall -Wextra -pedantic -Werror SRCS := $(shell find $(SRC) -name '*.c') OBJS := $(SRCS:%=$(TARGET)/%.o) -$(TARGET)/lox: $(TARGET)/lox.c.o $(TARGET)/scanner.c.o $(TARGET)/tokens.c.o $(TARGET)/utils.c.o - clang $(TARGET)/lox.c.o -L$(TARGET) -ltokens.c.o -lscanner.c.o -lutils.c.o -o $(TARGET)/lox +$(TARGET)/lox: $(TARGET)/lox.c.o $(TARGET)/parser.c.o $(TARGET)/scanner.c.o $(TARGET)/tokens.c.o $(TARGET)/utils.c.o + clang $(TARGET)/lox.c.o -L$(TARGET) -lparser.c.o -ltokens.c.o -lscanner.c.o -lutils.c.o -o $(TARGET)/lox $(TARGET)/utils.c.o: $(SRC)/utils.c $(CC) $< -o $@ @@ -17,6 +17,8 @@ $(TARGET)/tokens.c.o: $(SRC)/tokens.c $(TARGET)/scanner.c.o: $(SRC)/scanner.c $(CC) $< -o $@ +$(TARGET)/parser.c.o: $(SRC)/parser.c + $(CC) $< -o $@ $(TARGET)/lox.c.o: $(SRC)/lox.c $(TARGET) $(CC) $< -o $@ diff --git a/src/lox.c b/src/lox.c index 66283b5..65f4870 100644 --- a/src/lox.c +++ b/src/lox.c @@ -1,86 +1,83 @@ -#include -#include -#include -#include #include "scanner.h" #include "tokens.h" #include "utils.h" +#include +#include +#include +#include -int run_file(char* file); +int run_file(char *file); void run_prompt(void); -ScanResult run(char* source); +ScanResult run(char *source); -int main(int argc, char* argv[]){ - if (argc>2){ - puts("Usage: lox [script]"); - return EXIT_FAILURE; - } else if (argc == 2){ - return run_file(argv[1]); - } else { - run_prompt(); - } - return EXIT_SUCCESS; +int main(int argc, char *argv[]) { + if (argc > 2) { + puts("Usage: lox [script]"); + return EXIT_FAILURE; + } else if (argc == 2) { + return run_file(argv[1]); + } else { + run_prompt(); + } + return EXIT_SUCCESS; } -int run_file(char* filename){ +int run_file(char *filename) { - FILE* file = fopen(filename, "r"); - if (file == NULL){ - printf("unable to open file '%s'\n", filename); - return EXIT_FAILURE; + FILE *file = fopen(filename, "r"); + if (file == NULL) { + printf("unable to open file '%s'\n", filename); + return EXIT_FAILURE; + } + char line[255]; + + char *content = malloc(1); + if (content == NULL) { + puts("Out of memory"); + return EXIT_FAILURE; + } + content[0] = '\0'; + + while (fgets(line, sizeof(line), file)) { + content = realloc(content, strlen(content) + strlen(line) + 1); + if (content == NULL) { + return EXIT_FAILURE; } - char line[255]; + strcat(content, line); + } - char* content = malloc(1); - if (content == NULL){ - puts("Out of memory"); - return EXIT_FAILURE; - } - content[0] = '\0'; + fclose(file); + ScanResult scan_result = run(content); - while (fgets(line, sizeof(line), file)){ - content = realloc(content, strlen(content) + strlen(line) + 1 ); - if (content == NULL){ - return EXIT_FAILURE; - } - strcat(content, line); + // FREE UP + free(content); + + if (scan_result.had_error) { + return 65; + } + + tokenlist_print(&scan_result.token_list); + + return EXIT_SUCCESS; +} + +void run_prompt(void) { + char line[255]; + + for (;;) { + printf(">"); + char *r = fgets(line, 255, stdin); + + if (r == NULL) { + break; } - fclose(file); - - ScanResult scan_result = run(content); - - // FREE UP - free(content); - - if (scan_result.had_error){ - return 65; - } + int len = (int)strlen(line); + ScanResult scan_result = run(substring(line, 1, len - 1)); tokenlist_print(&scan_result.token_list); - - return EXIT_SUCCESS; + } } -void run_prompt(void){ - char line[255]; - - for (;;){ - printf(">"); - char* r = fgets(line, 255, stdin); - - if (r == NULL){ - break; - } - - int len =(int)strlen(line); - ScanResult scan_result = run(substring(line, 1, len-1)); - - tokenlist_print(&scan_result.token_list); - } -} - -ScanResult run(char* source){ - return scan_tokens(source); -} +ScanResult run(char *source) { return scan_tokens(source); } diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..8c10e2e --- /dev/null +++ b/src/parser.c @@ -0,0 +1,21 @@ +#include "parser.h" +#include "tokens.h" + +enum ExprType { + Bin, +}; + +struct Binary { + Binary *left; + Token operator; + Binary *right; +}; + +union Expr { + Binary binary; +}; + +struct Expression { + enum ExprType type; + union Expr expr; +}; diff --git a/src/parser.h b/src/parser.h new file mode 100644 index 0000000..8b87c9f --- /dev/null +++ b/src/parser.h @@ -0,0 +1 @@ +typedef struct Binary Binary; diff --git a/src/scanner.c b/src/scanner.c index 8d13968..71bd493 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -6,46 +6,26 @@ #include #include -void scan_token(void); -void error(char *message); -void report(char *where, char *message); -bool is_at_end(void); -bool match(char expected); -char peek(void); -char peek_next(void); -void string(void); -bool is_digit(char c); -void number(void); -bool is_alpha(char c); -bool is_alphanumeric(char c); -void identifier(void); +static void scan_token(void); +static void error(char *message); +static void report(char *where, char *message); +static bool is_at_end(void); +static bool match(char expected); +static char peek(void); +static char peek_next(void); +static void string(void); +static bool is_digit(char c); +static void number(void); +static bool is_alpha(char c); +static bool is_alphanumeric(char c); +static void identifier(void); -bool had_error = false; -int current_pos = -1; -int start = -1; -int current_line = -1; -char *source; -TokenList token_list; - -static const enum TokenType *get_token(char *key) { - int low = 0; - int high = sizeof(keywords) / sizeof(Item); - - while (low < high) { - int mid = (low + high) / 2; - - int c = strcmp(keywords[mid].key, key); - if (c == 0) { - return &keywords[mid].value; - } - if (c < 0) { - low = mid + 1; - } else { - high = mid; - } - } - return NULL; -} +static bool had_error = false; +static int current_pos = -1; +static int start = -1; +static int current_line = -1; +static char *source; +static TokenList token_list; ScanResult scan_tokens(char *src) { current_pos = 0; @@ -70,7 +50,7 @@ ScanResult scan_tokens(char *src) { return scan_result; } -void add_token(enum TokenType type) { +static void add_token(TokenType type) { Token token; token.type = type; token.lexeme = substring(source, start, current_pos); @@ -80,7 +60,7 @@ void add_token(enum TokenType type) { tokenlist_add(&token_list, token); } -void add_token_with_literal(enum TokenType type, char *literal) { +static void add_token_with_literal(TokenType type, char *literal) { Token token; token.type = type; token.lexeme = substring(source, start, current_pos); @@ -90,12 +70,12 @@ void add_token_with_literal(enum TokenType type, char *literal) { tokenlist_add(&token_list, token); } -char advance(void) { +static char advance(void) { char c = source[current_pos++]; return c; } -void scan_token(void) { +static void scan_token(void) { char c = advance(); switch (c) { @@ -166,14 +146,14 @@ void scan_token(void) { } } -void identifier(void) { +static void identifier(void) { while (is_alphanumeric(peek())) { advance(); } char *text = substring(source, start + 1, current_pos - start); - const enum TokenType *tokentype = get_token(text); + const TokenType *tokentype = get_keyword_token(text); if (tokentype == NULL) { add_token(IDENTIFIER); } else { @@ -181,7 +161,7 @@ void identifier(void) { } } -void number(void) { +static void number(void) { while (is_digit(peek())) advance(); if (peek() == '.' && is_digit((peek_next()))) @@ -212,7 +192,7 @@ void string(void) { add_token_with_literal(STRING, string); } -bool match(char expected) { +static bool match(char expected) { if (is_at_end()) { return false; } @@ -223,30 +203,30 @@ bool match(char expected) { return true; } -char peek_next(void) { +static char peek_next(void) { if (current_pos + 1 >= (int)strlen(source)) { return '\0'; } return source[current_pos + 1]; } -char peek(void) { +static char peek(void) { if (is_at_end()) { return '\0'; } return source[current_pos]; } -bool is_alpha(char c) { +static bool is_alpha(char c) { return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'); } -bool is_alphanumeric(char c) { return is_alpha(c) || is_digit(c); } +static bool is_alphanumeric(char c) { return is_alpha(c) || is_digit(c); } -bool is_at_end(void) { return current_pos >= (int)strlen(source); } +static bool is_at_end(void) { return current_pos >= (int)strlen(source); } -void error(char *message) { report("", message); } +static void error(char *message) { report("", message); } -void report(char *where, char *message) { +static void report(char *where, char *message) { printf("*[Line %i] Error %s : %s\n", current_line, where, message); had_error = true; } diff --git a/src/scanner.h b/src/scanner.h index 00f939d..8bba336 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -14,7 +14,7 @@ ScanResult scan_tokens(char *source); typedef struct { const char *key; - const enum TokenType value; + const TokenType value; } Item; static const Item keywords[] = { @@ -23,4 +23,23 @@ static const Item keywords[] = { {"or", OR}, {"print", PRINT}, {"return", RETURN}, {"super", SUPER}, {"this", THIS}, {"true", TRUE}, {"var", VAR}, {"while", WHILE}}; +inline static const TokenType *get_keyword_token(char *key) { + int low = 0; + int high = sizeof(keywords) / sizeof(Item); + + while (low < high) { + int mid = (low + high) / 2; + + int c = strcmp(keywords[mid].key, key); + if (c == 0) { + return &keywords[mid].value; + } + if (c < 0) { + low = mid + 1; + } else { + high = mid; + } + } + return NULL; +} #endif diff --git a/src/tokens.h b/src/tokens.h index 900986f..8ad66eb 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -1,7 +1,7 @@ #ifndef TOKENS_H #define TOKENS_H -enum TokenType { +typedef enum { LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, @@ -41,16 +41,9 @@ enum TokenType { VAR, WHILE, END_OF_FILE -}; +} TokenType; -typedef struct { - enum TokenType type; - char *lexeme; - void *literal; - int line; -} Token; - -static inline const char *token_name(enum TokenType type) { +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", @@ -65,6 +58,13 @@ static inline const char *token_name(enum TokenType type) { } typedef struct { + TokenType type; + char *lexeme; + void *literal; + int line; +} Token; + +typedef struct TokenList { Token *tokens; int size; int capacity;