Compare commits

..

No commits in common. "8e8b6233d69298202ee9e22b15df378d78cde097" and "77f40cf3c59a735ac7a8157cf33df6cb803b42ad" have entirely different histories.

16 changed files with 76 additions and 184 deletions

1
.gitignore vendored
View File

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

View File

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

View File

@ -1,3 +1,3 @@
# SCL: Simple Calculator Language # SCL: Simple Calculator Language
A spiritual successor to halk. A rewrite of halk.

View File

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

View File

@ -1,27 +0,0 @@
#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);
}

View File

@ -1,21 +0,0 @@
#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,10 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include "util.h"
#include "token.h" #include "token.h"
#define TOKENS_MAX 32 #define TOKENS_MAX 32
@ -55,4 +52,9 @@ void lexer_inc(Lexer* lexer);
// Add a token to the lexer. // Add a token to the lexer.
void lexer_add_token(Lexer* lexer, Token* token); 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 #endif

View File

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

View File

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

View File

@ -1,5 +1,9 @@
#include "include/lexer.h" #include "include/lexer.h"
#include "include/util.h" #include "include/token.h"
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
Lexer* lexer_init(char* src) { Lexer* lexer_init(char* src) {
Lexer* lexer = malloc(sizeof(Lexer)); Lexer* lexer = malloc(sizeof(Lexer));
@ -8,7 +12,7 @@ Lexer* lexer_init(char* src) {
lexer->srcl = strlen(src); lexer->srcl = strlen(src);
lexer->cchar = lexer->src; lexer->cchar = lexer->src;
lexer->tokens = calloc(TOKENS_MAX, sizeof(Token*)); lexer->tokens = calloc(TOKENS_MAX, sizeof(Token));
lexer->ntokens = 0; lexer->ntokens = 0;
lexer->state = LEXER_STATE_CONFUSED; lexer->state = LEXER_STATE_CONFUSED;
@ -18,7 +22,7 @@ Lexer* lexer_init(char* src) {
void lexer_destroy(Lexer* lexer) { void lexer_destroy(Lexer* lexer) {
free(lexer->src); free(lexer->src);
for (int i = 0; i < lexer->ntokens; i++) token_destroy(lexer->tokens[i]); for (int i = 0; i < lexer->ntokens; token_destroy(lexer->tokens[i++]));
} }
void lexer_lex(Lexer* lexer) { void lexer_lex(Lexer* lexer) {
@ -33,13 +37,11 @@ void lexer_lex(Lexer* lexer) {
} }
void lexer_do_confused(Lexer* lexer) { void lexer_do_confused(Lexer* lexer) {
log_dbg("entered confused mode");
if (isdigit(*lexer->cchar)) lexer_do_number(lexer); if (isdigit(*lexer->cchar)) lexer_do_number(lexer);
else lexer_do_call(lexer); else lexer_do_call(lexer);
} }
void lexer_do_number(Lexer* lexer) { void lexer_do_number(Lexer* lexer) {
log_dbg("entered number mode");
// Size of the number string. // Size of the number string.
size_t numsz; size_t numsz;
@ -57,7 +59,6 @@ void lexer_do_number(Lexer* lexer) {
} }
void lexer_do_call(Lexer* lexer) { void lexer_do_call(Lexer* lexer) {
log_dbg("entered call mode");
// Size of the call string. // Size of the call string.
size_t callsz; size_t callsz;
@ -70,8 +71,6 @@ void lexer_do_call(Lexer* lexer) {
char* call = malloc(callsz + 1); char* call = malloc(callsz + 1);
memcpy(call, start, callsz); memcpy(call, start, callsz);
call[callsz] = '\0'; call[callsz] = '\0';
lexer_add_token(lexer, token_init(TOKEN_TYPE_CALL, call));
} }
void lexer_inc(Lexer* lexer) { void lexer_inc(Lexer* lexer) {
@ -82,8 +81,29 @@ void lexer_add_token(Lexer* lexer, Token* token) {
assert(lexer->ntokens < TOKENS_MAX); assert(lexer->ntokens < TOKENS_MAX);
if (lexer->ntokens < TOKENS_MAX - 1) { if (lexer->ntokens < TOKENS_MAX - 1) {
lexer->tokens[lexer->ntokens] = token; lexer->tokens[lexer->ntokens - 1] = token;
lexer->ntokens++; 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,17 +1,14 @@
#include <stdio.h> #include <stdio.h>
#include "include/token.h"
#include "include/util.h" #include "include/util.h"
#include "include/lexer.h" #include "include/lexer.h"
int main(int argc, char** argv) { int main(int argc, char** argv) {
char* text = malloc(5); char* text = malloc(5);
text = "aa11"; text = "a1b2";
Lexer* lexer = lexer_init(text); Lexer* lexer = lexer_init(text);
lexer_print(lexer);
lexer_lex(lexer); lexer_lex(lexer);
lexer_print(lexer);
printf("%s\n", token_to_str(lexer->tokens[0], 0));
lexer_destroy(lexer);
} }

View File

@ -1,5 +1,4 @@
#include "include/token.h" #include "include/token.h"
#include <stdio.h>
Token* token_init(TokenType type, char* val) { Token* token_init(TokenType type, char* val) {
Token* t = malloc(sizeof(Token)); Token* t = malloc(sizeof(Token));
@ -15,8 +14,17 @@ void token_destroy(Token* t) {
free(t); free(t);
} }
char* token_to_str(Token* token, unsigned int indent) { void token_print(Token* token) {
char* title = malloc(sizeof("Token @ 0x000000000000\n")); printf("Token @%p:\n", token);
sprintf(title, "Token @%p\n", token); printf("\ttype: %s\n", token_type_str(token));
return title; 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 "???";
}
} }

View File

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

View File

@ -1,37 +0,0 @@
#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);
}

View File

@ -1,52 +0,0 @@
#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 Normal file
View File

@ -0,0 +1,18 @@
#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);
}