From 6e84fea3d171de29290318ddc273969cc460b6f1 Mon Sep 17 00:00:00 2001 From: Shautvast Date: Sat, 12 Oct 2024 17:09:42 +0200 Subject: [PATCH] more smaller sources, another page in the book --- makefile | 11 ++++- src/lox.c | 103 ++++++----------------------------------- src/scanner.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/scanner.h | 14 ++++++ src/utils.c | 19 ++++++++ src/utils.h | 6 +++ 6 files changed, 185 insertions(+), 92 deletions(-) create mode 100644 src/scanner.c create mode 100644 src/scanner.h create mode 100644 src/utils.c create mode 100644 src/utils.h diff --git a/makefile b/makefile index 0523659..ea8c010 100644 --- a/makefile +++ b/makefile @@ -5,12 +5,19 @@ 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)/tokens.c.o - clang $(TARGET)/lox.c.o -L$(TARGET) -ltokens.c.o -o $(TARGET)/lox +$(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)/utils.c.o: $(SRC)/utils.c + $(CC) $< -o $@ $(TARGET)/tokens.c.o: $(SRC)/tokens.c $(CC) $< -o $@ +$(TARGET)/scanner.c.o: $(SRC)/scanner.c + $(CC) $< -o $@ + + $(TARGET)/lox.c.o: $(SRC)/lox.c $(TARGET) $(CC) $< -o $@ diff --git a/src/lox.c b/src/lox.c index 8636516..66283b5 100644 --- a/src/lox.c +++ b/src/lox.c @@ -2,18 +2,13 @@ #include #include #include +#include "scanner.h" #include "tokens.h" +#include "utils.h" int run_file(char* file); void run_prompt(void); -void run(char* source); -void scan_tokens(char* source); -void scan_token(char* source, int line, int start, int* current_pos, TokenList* token_list); -void error(int line, char* nessage); -void report(int line, char* where, char* message); -char* substring(char* string, int position, int length); - -static bool had_error = false; +ScanResult run(char* source); int main(int argc, char* argv[]){ if (argc>2){ @@ -27,8 +22,8 @@ int main(int argc, char* argv[]){ return EXIT_SUCCESS; } - int run_file(char* filename){ + FILE* file = fopen(filename, "r"); if (file == NULL){ printf("unable to open file '%s'\n", filename); @@ -54,15 +49,17 @@ int run_file(char* filename){ fclose(file); - run(content); + ScanResult scan_result = run(content); // FREE UP free(content); - if (had_error){ + if (scan_result.had_error){ return 65; } + tokenlist_print(&scan_result.token_list); + return EXIT_SUCCESS; } @@ -78,86 +75,12 @@ void run_prompt(void){ } int len =(int)strlen(line); - run(substring(line, 1, len-1)); - had_error = false; + ScanResult scan_result = run(substring(line, 1, len-1)); + + tokenlist_print(&scan_result.token_list); } } -void run(char* source){ - scan_tokens(source); -} - -void scan_tokens(char* source){ - int current = 0; - int start = 0; - int line = 1; - - TokenList token_list; - tokenlist_init(&token_list); - int len = (int)strlen(source); - - while (current < len) { - start = current; - scan_token(source, line, start, ¤t, &token_list); - } - tokenlist_print(&token_list); -} - -void add_token(char* source, int line, TokenList* token_list, enum TokenType type, int start, int current_pos){ - Token token; - token.type = type; - token.lexeme = substring(source, start, current_pos); - token.literal = NULL; - token.line = line; - - tokenlist_add(token_list, token); -} - -char advance(char * source, int* pos){ - char c = source[*pos]; - (*pos) +=1; - return c; -} - -void scan_token(char* source, int line, int start, int* current_pos, TokenList* token_list){ - char c = advance(source, current_pos); - - switch (c){ - case '(': add_token(source, line, token_list, LEFT_PAREN, start, *current_pos); break; - case ')': add_token(source, line, token_list, RIGHT_PAREN, start, *current_pos); break; - case '{': add_token(source, line, token_list, LEFT_BRACE, start, *current_pos); break; - case '}': add_token(source, line, token_list, RIGHT_BRACE, start, *current_pos); break; - case ',': add_token(source, line, token_list, COMMA, start, *current_pos); break; - case '.': add_token(source, line, token_list, DOT, start, *current_pos); break; - case '+': add_token(source, line, token_list, PLUS, start, *current_pos); break; - case '-': add_token(source, line, token_list, MINUS, start, *current_pos); break; - - default: error(line, "Unexpected character."); break; - } -} - -void error(int line, char* message){ - report(line, "", message); -} - -void report(int line, char* where, char* message){ - printf("*[Line %i] Error %s : %s\n", line, where, message); - had_error = true; -} - -char* substring(char* string, int position, int length){ - char* ptr = malloc(length+1); - if (ptr == NULL) { - printf("out of memory"); - exit(EXIT_FAILURE); - } - - int c; - for (c=0; c < length; c+=1){ - *(ptr+c) = *(string+position-1); - string += sizeof(char); - } - *(ptr+c) = '\0'; - - return ptr; +ScanResult run(char* source){ + return scan_tokens(source); } diff --git a/src/scanner.c b/src/scanner.c new file mode 100644 index 0000000..7a0b7b0 --- /dev/null +++ b/src/scanner.c @@ -0,0 +1,124 @@ +#include "scanner.h" +#include "tokens.h" +#include "utils.h" +#include +#include +#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); + +bool had_error = false; +int current_pos = -1; +int start = -1; +int current_line = -1; +char *source; +TokenList token_list; + +ScanResult scan_tokens(char *src) { + current_pos = 0; + start = 0; + current_line = 1; + source = src; + + tokenlist_init(&token_list); + int len = (int)strlen(source); + + while (current_pos < len) { + start = current_pos; + scan_token(); + } + + ScanResult scan_result; + scan_result.token_list = token_list; + scan_result.had_error = had_error; + + // tokenlist_print(&scan_result.token_list); + + return scan_result; +} + +void add_token(enum TokenType type) { + Token token; + token.type = type; + token.lexeme = substring(source, start, current_pos); + token.literal = NULL; + token.line = current_line; + + tokenlist_add(&token_list, token); +} + +char advance(void) { + char c = source[current_pos++]; + return c; +} + +void scan_token(void) { + char c = advance(); + + switch (c) { + case '(': + add_token(LEFT_PAREN); + break; + case ')': + add_token(RIGHT_PAREN); + break; + case '{': + add_token(LEFT_BRACE); + break; + case '}': + add_token(RIGHT_BRACE); + break; + case ',': + add_token(COMMA); + break; + case '.': + add_token(DOT); + break; + case '+': + add_token(PLUS); + break; + case '-': + add_token(MINUS); + break; + case '!': + add_token(match('=') ? BANG_EQUAL : BANG); + break; + case '=': + add_token(match('=') ? EQUAL_EQUAL : EQUAL); + break; + case '>': + add_token(match('=') ? GREATER_EQUAL : GREATER); + break; + case '<': + add_token(match('=') ? LESS_EQUAL : LESS); + break; + default: + error("Unexpected character."); + break; + } +} + +bool match(char expected) { + if (is_at_end()) { + return false; + } + if (expected != source[current_pos]) { + return false; + } + current_pos += 1; + return true; +} + +bool is_at_end(void) { return current_pos >= (int)strlen(source); } + +void error(char *message) { report("", message); } + +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 new file mode 100644 index 0000000..a506133 --- /dev/null +++ b/src/scanner.h @@ -0,0 +1,14 @@ +#ifndef SCANNER_H +#define SCANNER_H + +#include +#include "tokens.h" + +typedef struct { + bool had_error; + TokenList token_list; +} ScanResult; + +ScanResult scan_tokens(char* source); + +#endif diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..7a00364 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,19 @@ +#include +#include + +char* substring(char* string, int position, int length){ + char* ptr = malloc(length+1); + if (ptr == NULL) { + printf("out of memory"); + exit(EXIT_FAILURE); + } + + int c; + for (c=0; c < length; c+=1){ + *(ptr+c) = *(string+position-1); + string += sizeof(char); + } + *(ptr+c) = '\0'; + + return ptr; +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..7356eb3 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,6 @@ +#ifndef UTILS_H +#define UTILS_H + +char* substring(char* string, int position, int length); + +#endif