Added dynamic strings. They do not yet work.
This commit is contained in:
parent
89e8674ced
commit
8e8b6233d6
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
*.o
|
||||
*.so
|
||||
tags
|
||||
*.out
|
||||
.cache
|
||||
compile_commands.json
|
||||
|
11
Makefile
11
Makefile
@ -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
1
examples/test.scl
Normal file
@ -0,0 +1 @@
|
||||
1 + 1
|
27
src/dstr.c
Normal file
27
src/dstr.c
Normal 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
21
src/include/dstr.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
38
src/lexer.c
38
src/lexer.c
@ -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 "???";
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
18
src/token.c
18
src/token.c
@ -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;
|
||||
}
|
||||
|
@ -1,3 +1 @@
|
||||
#include "include/util.h"
|
||||
|
||||
int is_even(int n) { return !(n % 2); }
|
||||
|
37
test/dstr.c
Normal file
37
test/dstr.c
Normal 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
52
test/lexer.c
Normal 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);
|
||||
}
|
18
test/util.c
18
test/util.c
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user