added parser file

This commit is contained in:
Shautvast 2024-10-14 10:51:33 +02:00
parent 8663a3c993
commit e079f63d27
7 changed files with 154 additions and 134 deletions

View file

@ -5,8 +5,8 @@ CC := clang -c -std=c17 -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.c.o $(TARGET)/scanner.c.o $(TARGET)/tokens.c.o $(TARGET)/utils.c.o $(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) -ltokens.c.o -lscanner.c.o -lutils.c.o -o $(TARGET)/lox 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 $(TARGET)/utils.c.o: $(SRC)/utils.c
$(CC) $< -o $@ $(CC) $< -o $@
@ -17,6 +17,8 @@ $(TARGET)/tokens.c.o: $(SRC)/tokens.c
$(TARGET)/scanner.c.o: $(SRC)/scanner.c $(TARGET)/scanner.c.o: $(SRC)/scanner.c
$(CC) $< -o $@ $(CC) $< -o $@
$(TARGET)/parser.c.o: $(SRC)/parser.c
$(CC) $< -o $@
$(TARGET)/lox.c.o: $(SRC)/lox.c $(TARGET) $(TARGET)/lox.c.o: $(SRC)/lox.c $(TARGET)
$(CC) $< -o $@ $(CC) $< -o $@

View file

@ -1,20 +1,20 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "scanner.h" #include "scanner.h"
#include "tokens.h" #include "tokens.h"
#include "utils.h" #include "utils.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int run_file(char* file); int run_file(char *file);
void run_prompt(void); void run_prompt(void);
ScanResult run(char* source); ScanResult run(char *source);
int main(int argc, char* argv[]){ int main(int argc, char *argv[]) {
if (argc>2){ if (argc > 2) {
puts("Usage: lox [script]"); puts("Usage: lox [script]");
return EXIT_FAILURE; return EXIT_FAILURE;
} else if (argc == 2){ } else if (argc == 2) {
return run_file(argv[1]); return run_file(argv[1]);
} else { } else {
run_prompt(); run_prompt();
@ -22,26 +22,25 @@ int main(int argc, char* argv[]){
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
int run_file(char* filename){ int run_file(char *filename) {
FILE* file = fopen(filename, "r"); FILE *file = fopen(filename, "r");
if (file == NULL){ if (file == NULL) {
printf("unable to open file '%s'\n", filename); printf("unable to open file '%s'\n", filename);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
char line[255]; char line[255];
char* content = malloc(1); char *content = malloc(1);
if (content == NULL){ if (content == NULL) {
puts("Out of memory"); puts("Out of memory");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
content[0] = '\0'; content[0] = '\0';
while (fgets(line, sizeof(line), file)) {
while (fgets(line, sizeof(line), file)){ content = realloc(content, strlen(content) + strlen(line) + 1);
content = realloc(content, strlen(content) + strlen(line) + 1 ); if (content == NULL) {
if (content == NULL){
return EXIT_FAILURE; return EXIT_FAILURE;
} }
strcat(content, line); strcat(content, line);
@ -54,7 +53,7 @@ int run_file(char* filename){
// FREE UP // FREE UP
free(content); free(content);
if (scan_result.had_error){ if (scan_result.had_error) {
return 65; return 65;
} }
@ -63,24 +62,22 @@ int run_file(char* filename){
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void run_prompt(void){ void run_prompt(void) {
char line[255]; char line[255];
for (;;){ for (;;) {
printf(">"); printf(">");
char* r = fgets(line, 255, stdin); char *r = fgets(line, 255, stdin);
if (r == NULL){ if (r == NULL) {
break; break;
} }
int len =(int)strlen(line); int len = (int)strlen(line);
ScanResult scan_result = run(substring(line, 1, len-1)); ScanResult scan_result = run(substring(line, 1, len - 1));
tokenlist_print(&scan_result.token_list); tokenlist_print(&scan_result.token_list);
} }
} }
ScanResult run(char* source){ ScanResult run(char *source) { return scan_tokens(source); }
return scan_tokens(source);
}

21
src/parser.c Normal file
View file

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

1
src/parser.h Normal file
View file

@ -0,0 +1 @@
typedef struct Binary Binary;

View file

@ -6,46 +6,26 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
void scan_token(void); static void scan_token(void);
void error(char *message); static void error(char *message);
void report(char *where, char *message); static void report(char *where, char *message);
bool is_at_end(void); static bool is_at_end(void);
bool match(char expected); static bool match(char expected);
char peek(void); static char peek(void);
char peek_next(void); static char peek_next(void);
void string(void); static void string(void);
bool is_digit(char c); static bool is_digit(char c);
void number(void); static void number(void);
bool is_alpha(char c); static bool is_alpha(char c);
bool is_alphanumeric(char c); static bool is_alphanumeric(char c);
void identifier(void); static void identifier(void);
bool had_error = false; static bool had_error = false;
int current_pos = -1; static int current_pos = -1;
int start = -1; static int start = -1;
int current_line = -1; static int current_line = -1;
char *source; static char *source;
TokenList token_list; static 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;
}
ScanResult scan_tokens(char *src) { ScanResult scan_tokens(char *src) {
current_pos = 0; current_pos = 0;
@ -70,7 +50,7 @@ ScanResult scan_tokens(char *src) {
return scan_result; return scan_result;
} }
void add_token(enum TokenType type) { static void add_token(TokenType type) {
Token token; Token token;
token.type = type; token.type = type;
token.lexeme = substring(source, start, current_pos); token.lexeme = substring(source, start, current_pos);
@ -80,7 +60,7 @@ void add_token(enum TokenType type) {
tokenlist_add(&token_list, token); 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 token;
token.type = type; token.type = type;
token.lexeme = substring(source, start, current_pos); 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); tokenlist_add(&token_list, token);
} }
char advance(void) { static char advance(void) {
char c = source[current_pos++]; char c = source[current_pos++];
return c; return c;
} }
void scan_token(void) { static void scan_token(void) {
char c = advance(); char c = advance();
switch (c) { switch (c) {
@ -166,14 +146,14 @@ void scan_token(void) {
} }
} }
void identifier(void) { static void identifier(void) {
while (is_alphanumeric(peek())) { while (is_alphanumeric(peek())) {
advance(); advance();
} }
char *text = substring(source, start + 1, current_pos - start); 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) { if (tokentype == NULL) {
add_token(IDENTIFIER); add_token(IDENTIFIER);
} else { } else {
@ -181,7 +161,7 @@ void identifier(void) {
} }
} }
void number(void) { static void number(void) {
while (is_digit(peek())) while (is_digit(peek()))
advance(); advance();
if (peek() == '.' && is_digit((peek_next()))) if (peek() == '.' && is_digit((peek_next())))
@ -212,7 +192,7 @@ void string(void) {
add_token_with_literal(STRING, string); add_token_with_literal(STRING, string);
} }
bool match(char expected) { static bool match(char expected) {
if (is_at_end()) { if (is_at_end()) {
return false; return false;
} }
@ -223,30 +203,30 @@ bool match(char expected) {
return true; return true;
} }
char peek_next(void) { static char peek_next(void) {
if (current_pos + 1 >= (int)strlen(source)) { if (current_pos + 1 >= (int)strlen(source)) {
return '\0'; return '\0';
} }
return source[current_pos + 1]; return source[current_pos + 1];
} }
char peek(void) { static char peek(void) {
if (is_at_end()) { if (is_at_end()) {
return '\0'; return '\0';
} }
return source[current_pos]; 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 == '_'); 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); printf("*[Line %i] Error %s : %s\n", current_line, where, message);
had_error = true; had_error = true;
} }

View file

@ -14,7 +14,7 @@ ScanResult scan_tokens(char *source);
typedef struct { typedef struct {
const char *key; const char *key;
const enum TokenType value; const TokenType value;
} Item; } Item;
static const Item keywords[] = { static const Item keywords[] = {
@ -23,4 +23,23 @@ static const Item keywords[] = {
{"or", OR}, {"print", PRINT}, {"return", RETURN}, {"super", SUPER}, {"or", OR}, {"print", PRINT}, {"return", RETURN}, {"super", SUPER},
{"this", THIS}, {"true", TRUE}, {"var", VAR}, {"while", WHILE}}; {"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 #endif

View file

@ -1,7 +1,7 @@
#ifndef TOKENS_H #ifndef TOKENS_H
#define TOKENS_H #define TOKENS_H
enum TokenType { typedef enum {
LEFT_PAREN, LEFT_PAREN,
RIGHT_PAREN, RIGHT_PAREN,
LEFT_BRACE, LEFT_BRACE,
@ -41,16 +41,9 @@ enum TokenType {
VAR, VAR,
WHILE, WHILE,
END_OF_FILE END_OF_FILE
}; } TokenType;
typedef struct { static inline const char *token_name(TokenType type) {
enum TokenType type;
char *lexeme;
void *literal;
int line;
} Token;
static inline const char *token_name(enum TokenType type) {
static const char *tokens[] = { static const char *tokens[] = {
"LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", "RIGHT_BRACE", "COMMA", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", "RIGHT_BRACE", "COMMA",
"DOT", "MINUS", "PLUS", "SEMICOLON", "SLASH", "DOT", "MINUS", "PLUS", "SEMICOLON", "SLASH",
@ -65,6 +58,13 @@ static inline const char *token_name(enum TokenType type) {
} }
typedef struct { typedef struct {
TokenType type;
char *lexeme;
void *literal;
int line;
} Token;
typedef struct TokenList {
Token *tokens; Token *tokens;
int size; int size;
int capacity; int capacity;