Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions include/csquare/arena.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef _ARENA_ALLOCATOR_H
#define _ARENA_ALLOCATOR_H

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct {
uint8_t *mem;
size_t cap;
size_t offset;
} arena;

void *arena_alloc(arena *a, size_t size);
void arena_free(arena *a);

#endif
43 changes: 43 additions & 0 deletions include/csquare/error.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef ERROR_H
#define ERROR_H

#include <stddef.h>

typedef enum {
ERROR_NONE,
SYNERR_UNKNOWN_CHARACTER,
SYNERR_UNTERMINATED_STRING
} error_type;

typedef enum { ERROR_LEVEL_WARNING, ERROR_LEVEL_ERROR } error_level;

typedef struct {
int line;
int col;
} file_pos;

typedef struct {
const char *ptr;
size_t len;
} text_span;

typedef struct {
const char *message;
error_type type;
error_level level;

const char *file;
file_pos pos;

text_span line;
text_span highlight;
} error_info;

error_info new_error_info(const char *msg, error_type type, error_level level,
const char *file, int line, int col,
const char *line_str, int highlight_start,
int highlight_len);

void print_error(const error_info *err);

#endif
14 changes: 11 additions & 3 deletions include/csquare/lexer/lexer.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef _LEXER_H
#define _LEXER_H

#include "csquare/error.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -93,13 +94,20 @@ struct token {
const char *start;
int length;
token_type type;

int line;
int col;
error_type errtype;
const char *errmsg;
};

typedef struct token token;

token *new_token(const char *start, int length, token_type type);
token *new_token(const char *start, int length, token_type type, int line,
int col);
void free_token(token *tk);
token *error_token(const char *msg);
token *error_token(const char *msg, const char *src, int len, int line, int col,
error_type errtype);

typedef struct {
token **tokens;
Expand All @@ -115,7 +123,7 @@ void add_token(token_list *list, token *tk);
#define isdigit(c) (c >= '0' && c <= '9')
#define isalpha(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))

#define LEX_FUNC_ARGS const char *p, int *len
#define LEX_FUNC_ARGS const char *p, int *len, int *line, int *col
token *lex_symbol(LEX_FUNC_ARGS);
token *lex_digit(LEX_FUNC_ARGS);
token *lex_string(LEX_FUNC_ARGS);
Expand Down
8 changes: 8 additions & 0 deletions include/csquare/parser/rules/literals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _RULES_LITERALS_H
#define _RULES_LITERALS_H

#include "csquare/parser/parser.h"

void parse_literal(parser *p, node *curr);

#endif
38 changes: 38 additions & 0 deletions src/csquare/arena.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "csquare/arena.h"
#include <stddef.h>
#include <stdlib.h>

#include <stdlib.h>
#include <string.h>

void *arena_alloc(arena *a, size_t size) {
size = (size + 7) & ~7; // 8-byte alignment

if (a->offset + size > a->cap) {
size_t new_cap = a->cap ? a->cap : 1024;

while (new_cap < a->offset + size) {
new_cap *= 2;
}

unsigned char *new_mem = realloc(a->mem, new_cap);
if (!new_mem) {
abort();
}

a->mem = new_mem;
a->cap = new_cap;
}

void *ptr = a->mem + a->offset;
a->offset += size;

return ptr;
}

void arena_free(arena *a) {
free(a->mem);
a->mem = NULL;
a->cap = 0;
a->offset = 0;
}
71 changes: 71 additions & 0 deletions src/csquare/error.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "csquare/error.h"
#include <stdio.h>
#include <string.h>

#include "csquare/error.h"
#include <string.h>

error_info new_error_info(const char *msg, error_type type, error_level level,
const char *file, int line, int col,
const char *line_str, int highlight_start,
int highlight_len) {
error_info e;
e.message = strdup(msg);
e.type = type;
e.level = level;
e.file = file;
e.pos = (file_pos){line, col};

e.line.ptr = line_str;

size_t line_len = 0;
while (line_str[line_len] && line_str[line_len] != '\n')
line_len++;
e.line.len = line_len;

e.highlight.ptr = line_str + highlight_start;
e.highlight.len = highlight_len;

return e;
}

#define CRED "\x1b[31m"
#define CYELLOW "\x1b[33m"
#define CCYAN "\x1b[36m"
#define CBLUE "\x1b[34m"
#define CRESET "\x1b[0m"

// static void print_span(const char *ptr, size_t len) {
// fwrite(ptr, 1, len, stdout);
// }

void print_error(const error_info *e) {
const char *level_color = (e->level == ERROR_LEVEL_ERROR) ? CRED : CYELLOW;

printf("%s%s:%s %s\n", level_color,
(e->level == ERROR_LEVEL_ERROR ? "error" : "warning"), CRESET,
e->message);
printf(" --> %s:%d:%d\n", e->file, e->pos.line, e->pos.col);
printf(" |\n");

printf("%4d | ", e->pos.line);

fwrite(e->line.ptr, 1, e->highlight.ptr - e->line.ptr, stdout);

printf(CRED);
fwrite(e->highlight.ptr, 1, e->highlight.len, stdout);
printf(CRESET);

size_t rest_len =
e->line.len - (e->highlight.ptr - e->line.ptr) - e->highlight.len;
fwrite(e->highlight.ptr + e->highlight.len, 1, rest_len, stdout);
printf("\n");

printf(" | ");
for (size_t i = 0; i < e->highlight.ptr - e->line.ptr; i++)
putchar((e->line.ptr[i] == '\t') ? '\t' : ' ');
printf(CRED);
for (size_t i = 0; i < e->highlight.len; i++)
putchar('^');
printf(CRESET "\n");
}
5 changes: 3 additions & 2 deletions src/lexer/lex_digit.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "csquare/lexer/lexer.h"
#include <stdbool.h>

token *lex_digit(const char *p, int *len) {
token *lex_digit(const char *p, int *len, int *line, int *col) {
const char *start = p;
token_type type = T_DECIMAL;
bool has_dot = false;
Expand Down Expand Up @@ -42,5 +42,6 @@ token *lex_digit(const char *p, int *len) {
}

*len = (int)(p - start);
return new_token(start, *len, type);
*col = (*col) + (*len);
return new_token(start, *len, type, *line, *col - *len);
}
5 changes: 3 additions & 2 deletions src/lexer/lex_ident.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const struct {

int keyword_count = sizeof(keyword_table) / sizeof(keyword_table[0]);

token *lex_ident(const char *p, int *len) {
token *lex_ident(const char *p, int *len, int *line, int *col) {
char buf[64];
int bufi = 0;
token_type type = T_IDENTIFIER;
Expand Down Expand Up @@ -76,5 +76,6 @@ token *lex_ident(const char *p, int *len) {

const char *start = p - bufi;
*len = bufi;
return new_token(start, bufi, type);
*col = (*col) + (*len);
return new_token(start, bufi, type, *line, *col - *len);
}
9 changes: 6 additions & 3 deletions src/lexer/lex_string.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "csquare/error.h"
#include "csquare/lexer/lexer.h"

token *lex_string(const char *p, int *len) {
token *lex_string(const char *p, int *len, int *line, int *col) {
const char *start = p;
char delim = *p;
p++;
Expand All @@ -13,16 +14,18 @@ token *lex_string(const char *p, int *len) {

if (*p != delim) {
*len = (int)(p - start);
*col = (*col) + (*len);

const char *prefix = "Unterminated string: ";
char *msg = malloc(strlen(prefix) + *len + 1);

sprintf(msg, "Unterminated string: %.*s", *len, start);
return error_token(msg);
return error_token(msg, p, *len, *line, *col, SYNERR_UNTERMINATED_STRING);
}

p++;

*len = (int)(p - start);
return new_token(start, *len, T_STRING);
*col = (*col) + (*len);
return new_token(start, *len, T_STRING, *line, *col - *len);
}
8 changes: 6 additions & 2 deletions src/lexer/lex_symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const struct {

int symbol_count = sizeof(symbol_table) / sizeof(symbol_table[0]);

token *lex_symbol(const char *p, int *len) {
token *lex_symbol(const char *p, int *len, int *line, int *col) {
int best_len = 0;
token_type best_type = T_ERROR;

Expand All @@ -33,8 +33,12 @@ token *lex_symbol(const char *p, int *len) {
if (best_len == 0) {
best_len = 1;
best_type = T_ERROR;
*len = best_len;
*col = (*col) + (*line);
return NULL;
}

*len = best_len;
return new_token(p, best_len, best_type);
*col = (*col) + (*line);
return new_token(p, best_len, best_type, *line, *col - *len);
}
Loading
Loading