Added dynamic strings. They do not yet work.

This commit is contained in:
Jacob Signorovitch 2024-10-10 16:09:25 -04:00
parent 89e8674ced
commit 8e8b6233d6
15 changed files with 183 additions and 75 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
*.o
*.so
tags
*.out
.cache
compile_commands.json

View File

@ -11,7 +11,7 @@ TEST_OBJ_DIR = $(TEST_BUILD_DIR)/obj
CC = clang
LINK = clang
CFLAGS = -Wall
CFLAGS = -Wall -DDBG -ggdb
LDFLAGS =
SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
@ -28,6 +28,10 @@ WHITE_BOLD = $(RESETCOLOR)\x1b[37;1m
all: $(TARGET)
release: clean
release: CFLAGS = -Wall -O2
release: $(TARGET)
# Link to final binary.
$(TARGET): $(OBJ_FILES)
@ echo -e "$(WHITE_BOLD)Linking $(WHITE)$(TARGET)$(WHITE_BOLD)...$(RESETCOLOR) $(CC) -o $(TARGET) $(OBJ_FILES) $(LDFLAGS)"
@ -56,5 +60,8 @@ clean:
@ echo -e "$(WHITE_BOLD)Cleaning up...$(WHITE) $(OBJ_DIR)/*.o $(TEST_OBJ_DIR)/*.o $(TEST_BUILD_DIR)/test.out $(TARGET)$(RESETCOLOR)"
@ rm -rf $(OBJ_DIR)/*.o $(TEST_OBJ_DIR)/*.o $(TEST_BUILD_DIR)/test.out $(TARGET)
.PHONY: all clean test nocolor
run:
./$(TARGET)
.PHONY: all clean test nocolor release

1
examples/test.scl Normal file
View File

@ -0,0 +1 @@
1 + 1

27
src/dstr.c Normal file
View File

@ -0,0 +1,27 @@
#include "include/dstr.h"
#include <string.h>
Dstr* dstr_init(void) {
Dstr* dstr = malloc(sizeof(Dstr));
dstr->bufsz = DSTR_INITSZ;
dstr->buf = malloc(DSTR_INITSZ);
dstr->ln = 0;
return dstr;
}
void dstr_destroy(Dstr* dstr) {
free(dstr->buf);
free(dstr);
}
void dstr_append(Dstr* dest, size_t ln, char* src) {
if (dest->ln + ln > dest->bufsz) {
// Double the buffer size when overflown.
dest->bufsz *= dest->bufsz;
dest->buf = realloc(dest->buf, dest->bufsz);
}
strcat(dest->buf + ln, src);
}

21
src/include/dstr.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef DSTR_H
#define DSTR_H
#include <stdlib.h>
#include <string.h>
#define DSTR_INITSZ 128
typedef struct {
char* buf; // The buffer containing the string.
size_t bufsz; // The size of the buffer.
size_t ln; // The number of characters in the buffer.
} Dstr;
Dstr* dstr_init(void);
void dstr_destroy(Dstr* dstr);
// Append ln characters of src to dest.
void dstr_append(Dstr* dest, size_t ln, char* src);
#endif

View File

@ -4,7 +4,10 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include "util.h"
#include "token.h"
#define TOKENS_MAX 32
@ -52,9 +55,4 @@ void lexer_inc(Lexer* lexer);
// Add a token to the lexer.
void lexer_add_token(Lexer* lexer, Token* token);
// Print the contents of a lexer.
void lexer_print(Lexer* lexer);
static char* lexer_state_str(Lexer* lexer);
#endif

View File

@ -19,7 +19,10 @@ typedef struct {
Token* token_init(TokenType type, char* val);
void token_destroy(Token* token);
void token_print(Token* token);
static char* token_type_str(Token* token);
// Returns a string representation of the Token.
char* token_to_str(Token* token, unsigned int indent);
// Returns a string representation of the TokenType.
char* token_type_to_str(TokenType t);
#endif

View File

@ -1,6 +1,12 @@
#ifndef UTIL_H
#define UTIL_H
int is_even(int n);
#ifdef DBG
#define log_dbg(msg) \
printf("[dbg:%s:%s:%d] %s\n", __FILE__, __func__, __LINE__, msg); \
fflush(stdout);
#else
#define log_dbg(msg)
#endif
#endif

View File

@ -1,9 +1,5 @@
#include "include/lexer.h"
#include "include/token.h"
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "include/util.h"
Lexer* lexer_init(char* src) {
Lexer* lexer = malloc(sizeof(Lexer));
@ -12,7 +8,7 @@ Lexer* lexer_init(char* src) {
lexer->srcl = strlen(src);
lexer->cchar = lexer->src;
lexer->tokens = calloc(TOKENS_MAX, sizeof(Token));
lexer->tokens = calloc(TOKENS_MAX, sizeof(Token*));
lexer->ntokens = 0;
lexer->state = LEXER_STATE_CONFUSED;
@ -22,7 +18,7 @@ Lexer* lexer_init(char* src) {
void lexer_destroy(Lexer* lexer) {
free(lexer->src);
for (int i = 0; i < lexer->ntokens; token_destroy(lexer->tokens[i++]));
for (int i = 0; i < lexer->ntokens; i++) token_destroy(lexer->tokens[i]);
}
void lexer_lex(Lexer* lexer) {
@ -37,11 +33,13 @@ void lexer_lex(Lexer* lexer) {
}
void lexer_do_confused(Lexer* lexer) {
log_dbg("entered confused mode");
if (isdigit(*lexer->cchar)) lexer_do_number(lexer);
else lexer_do_call(lexer);
}
void lexer_do_number(Lexer* lexer) {
log_dbg("entered number mode");
// Size of the number string.
size_t numsz;
@ -59,6 +57,7 @@ void lexer_do_number(Lexer* lexer) {
}
void lexer_do_call(Lexer* lexer) {
log_dbg("entered call mode");
// Size of the call string.
size_t callsz;
@ -71,6 +70,8 @@ void lexer_do_call(Lexer* lexer) {
char* call = malloc(callsz + 1);
memcpy(call, start, callsz);
call[callsz] = '\0';
lexer_add_token(lexer, token_init(TOKEN_TYPE_CALL, call));
}
void lexer_inc(Lexer* lexer) {
@ -81,29 +82,8 @@ void lexer_add_token(Lexer* lexer, Token* token) {
assert(lexer->ntokens < TOKENS_MAX);
if (lexer->ntokens < TOKENS_MAX - 1) {
lexer->tokens[lexer->ntokens - 1] = token;
lexer->tokens[lexer->ntokens] = token;
lexer->ntokens++;
}
}
void lexer_print(Lexer* lexer) {
printf("Lexer @%p:\n", lexer);
printf("\tsrc: \"%s\"\n", lexer->src);
printf("\tsrcl: \"%ld\"\n", lexer->srcl);
printf("\tcchar: \"%s\"\n", lexer->cchar);
printf("\tntokens: %ld\n", lexer->ntokens);
printf("\ttokens: [START]\n");
for (int i = 0; i < lexer->ntokens; i++) token_print(lexer->tokens[i]);
printf("[END]\n");
printf("\tstate: %s\n", lexer_state_str(lexer));
}
static char* lexer_state_str(Lexer* lexer) {
switch (lexer->state) {
case LEXER_STATE_NUM: return "NUM";
case LEXER_STATE_CALL: return "CALL";
case LEXER_STATE_CONFUSED: return "CONFUSED";
default: return "???";
}
}

View File

@ -1,14 +1,17 @@
#include <stdio.h>
#include "include/token.h"
#include "include/util.h"
#include "include/lexer.h"
int main(int argc, char** argv) {
char* text = malloc(5);
text = "a1b2";
text = "aa11";
Lexer* lexer = lexer_init(text);
lexer_print(lexer);
lexer_lex(lexer);
lexer_print(lexer);
printf("%s\n", token_to_str(lexer->tokens[0], 0));
lexer_destroy(lexer);
}

View File

@ -1,4 +1,5 @@
#include "include/token.h"
#include <stdio.h>
Token* token_init(TokenType type, char* val) {
Token* t = malloc(sizeof(Token));
@ -14,17 +15,8 @@ void token_destroy(Token* t) {
free(t);
}
void token_print(Token* token) {
printf("Token @%p:\n", token);
printf("\ttype: %s\n", token_type_str(token));
printf("\tval: %s\n", token->val);
printf("\tlen: %ld\n", token->len);
}
static char* token_type_str(Token* token) {
switch (token->type) {
case TOKEN_TYPE_CALL: return "CALL";
case TOKEN_TYPE_NUMBER: return "NUMBER";
default: return "???";
}
char* token_to_str(Token* token, unsigned int indent) {
char* title = malloc(sizeof("Token @ 0x000000000000\n"));
sprintf(title, "Token @%p\n", token);
return title;
}

View File

@ -1,3 +1 @@
#include "include/util.h"
int is_even(int n) { return !(n % 2); }

37
test/dstr.c Normal file
View File

@ -0,0 +1,37 @@
#include "../src/include/dstr.h"
#include "unity/unity.h"
#include "registry.h"
void test_dstr_init() {
Dstr* dstr = dstr_init();
TEST_ASSERT_EQUAL_INT(DSTR_INITSZ, dstr->bufsz);
TEST_ASSERT_EQUAL_STRING(malloc(DSTR_INITSZ), dstr->buf);
TEST_ASSERT_EQUAL_size_t(0, dstr->ln);
}
void test_dstr_append() {
char* str1 = malloc(2);
str1 = "h";
char* str2 = malloc(DSTR_INITSZ);
str2 = "h";
Dstr* dstr = dstr_init();
dstr_append(dstr, 1, str1);
TEST_ASSERT_EQUAL_STRING(str2, dstr->buf);
}
int test_dstr() {
UNITY_BEGIN();
RUN_TEST(test_dstr_init);
RUN_TEST(test_dstr_append);
UNITY_END();
return 0;
}
__attribute__((constructor)) void register_dstr() {
register_test(test_dstr);
}

52
test/lexer.c Normal file
View File

@ -0,0 +1,52 @@
#include "../src/include/lexer.h"
#include "unity/unity.h"
#include "registry.h"
void test_lexer_init() {
char* src = malloc(sizeof("a1b2"));
src = "a1b2";
Lexer* lexer = lexer_init(src);
TEST_ASSERT_EQUAL_STRING(src, lexer->src);
TEST_ASSERT_EQUAL_INT(4, lexer->srcl);
TEST_ASSERT_EQUAL_CHAR(src[0], *lexer->cchar);
TEST_ASSERT_EQUAL_INT(LEXER_STATE_CONFUSED, lexer->state);
// Hope that token arr. is right size :).
TEST_ASSERT_EQUAL_INT(0, lexer->ntokens);
}
void test_lexer_lex_callnum() {
char* src = malloc(sizeof("a1b2"));
src = "a1b2";
Lexer* lexer = lexer_init(src);
Token* tokens[4] = {
token_init(TOKEN_TYPE_CALL, "a"),
token_init(TOKEN_TYPE_NUMBER, "1"),
token_init(TOKEN_TYPE_CALL, "b"),
token_init(TOKEN_TYPE_NUMBER, "2"),
};
lexer_lex(lexer);
TEST_ASSERT_EQUAL_INT(4, lexer->ntokens);
for (int i = 0; i < 4; i++) {
printf("h");
fflush(stdout);
TEST_ASSERT_EQUAL_INT(tokens[i]->type, lexer->tokens[i]->type);
TEST_ASSERT_EQUAL_STRING(tokens[i]->val, lexer->tokens[i]->val);
}
}
int test_lexer() {
UNITY_BEGIN();
RUN_TEST(test_lexer_init);
RUN_TEST(test_lexer_lex_callnum);
UNITY_END();
return 0;
}
__attribute__((constructor)) void register_lexer() {
register_test(test_lexer);
}

View File

@ -1,18 +0,0 @@
#include "../src/include/util.h"
#include "registry.h"
#include "unity/unity.h"
void test_is_even() {
TEST_ASSERT_EQUAL(0, is_even(1));;
TEST_ASSERT_EQUAL(1, is_even(2));
}
int test_util() {
UNITY_BEGIN();
RUN_TEST(test_is_even);
return UNITY_END();
}
__attribute__((constructor)) void register_tests_util() {
register_test(test_util);
}