more smaller sources, another page in the book

This commit is contained in:
Shautvast 2024-10-12 17:09:42 +02:00
parent 7f670a5301
commit 6e84fea3d1
6 changed files with 185 additions and 92 deletions

View file

@ -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 $@

103
src/lox.c
View file

@ -2,18 +2,13 @@
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#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, &current, &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);
}

124
src/scanner.c Normal file
View file

@ -0,0 +1,124 @@
#include "scanner.h"
#include "tokens.h"
#include "utils.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}

14
src/scanner.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef SCANNER_H
#define SCANNER_H
#include <stdbool.h>
#include "tokens.h"
typedef struct {
bool had_error;
TokenList token_list;
} ScanResult;
ScanResult scan_tokens(char* source);
#endif

19
src/utils.c Normal file
View file

@ -0,0 +1,19 @@
#include <stdlib.h>
#include <stdio.h>
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;
}

6
src/utils.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef UTILS_H
#define UTILS_H
char* substring(char* string, int position, int length);
#endif