aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorc2024-02-03 17:34:25 -0500
committerc2024-02-03 17:34:25 -0500
commit7dbec8d29413d62967ed7eb5854dd56b1a2814ab (patch)
treeafc43e283ded4d99a1d1050617e3e0ecdf68e3ee
parent0b84414bdde53b367bc28563a6936513c4d3b50c (diff)
Parser now parses blocks and simple calls.
-rw-r--r--Makefile22
-rw-r--r--src/include/parser.h2
-rw-r--r--src/include/util.h72
-rw-r--r--src/lexer.c4
-rw-r--r--src/main.c12
-rw-r--r--src/parser.c61
-rw-r--r--src/pp.c8
-rw-r--r--src/source.c13
-rw-r--r--src/stack.c4
-rw-r--r--src/token.c2
-rw-r--r--src/tree.c12
-rw-r--r--src/util.c97
-rw-r--r--test/include/test.h12
-rw-r--r--test/parser.c464
14 files changed, 603 insertions, 182 deletions
diff --git a/Makefile b/Makefile
index 391d5d0..6c8bc12 100644
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,8 @@ CC := gcc
REG_CFLAGS := -std=c99 -O3 -s
DBG_CFLAGS := -std=c99 -Og -ggdb -pedantic
DBG_CFLAGS += -Wall -Wextra -Wformat -Wpedantic
-DBG_CFLAGS += -fsanitize=leak,address,undefined -fno-omit-frame-pointer
-CFLAGS := $(REG_CFLAGS)
+DBG_CFLAGS += -fsanitize=address -fno-omit-frame-pointer
+CFLAGS := none
SRCS := $(wildcard src/*.c)
SRCS := $(filter-out %doer.c,$(SRCS)) # Filter out incomplete doer for now.
OBJS := $(SRCS:.c=.o)
@@ -16,25 +16,21 @@ TEST_OUTS := $(TEST_SRCS:.c=.out)
all: halk
-reg_options:
+options:
@echo "HALK build options:"
@echo "CC: $(CC)"
- @echo "CFLAGS: $(REG_CFLAGS)"
+ @echo "CFLAGS: $(CFLAGS)"
@echo
-dbg_options:
- @echo "HALK build options (dbg):"
- @echo "CC: $(CC)"
- @echo "CFLAGS: $(DBG_CFLAGS)"
- @echo
-
-halk: reg_options $(OBJS)
+halk: CFLAGS := $(REG_CFLAGS)
+halk: options $(OBJS)
$(CC) $(OBJS) $(REG_CFLAGS) -o $(BIN).out
dbg: CFLAGS := $(DBG_CFLAGS)
-dbg: clean dbg_options $(OBJS)
+dbg: clean options $(OBJS)
$(CC) $(OBJS) $(DBG_CFLAGS) -o $(BIN).out
+test: CFLAGS := $(REG_CFLAGS)
test: $(TEST_OUTS)
set -e
for f in $(TEST_OUTS); do ./$$f; done
@@ -43,7 +39,7 @@ test: $(TEST_OUTS)
$(CC) -c $< -o $@ $(CFLAGS)
%.out: %.c
- $(CC) $< $(filter-out %main.o,$(OBJS)) -o $@ $(CFLAGS)
+ $(CC) $< $(filter-out %main.o,$(OBJS)) -o $@ $(DBG_CFLAGS)
install: all
mkdir -p $(PREFIX)
diff --git a/src/include/parser.h b/src/include/parser.h
index a442d60..257189d 100644
--- a/src/include/parser.h
+++ b/src/include/parser.h
@@ -47,6 +47,8 @@ tree_t* parser_parse_init(parser_t* parser);
/* Get tree for a block. */
tree_t* parser_parse_block(parser_t* parser);
+tree_t* parser_parse_kwd(parser_t* parser);
+
/* Get tree for an expression.*/
tree_t* parser_parse_expr(parser_t* parser);
diff --git a/src/include/util.h b/src/include/util.h
index 567916c..08654fd 100644
--- a/src/include/util.h
+++ b/src/include/util.h
@@ -6,7 +6,7 @@
#include <string.h>
#include <stdio.h>
-/* Welcome to macro hell. */
+/* Welcome to macro Hell. */
#define HIDE(x) do {x} while (0)
@@ -18,62 +18,94 @@
fprintf(stderr, "%s:%s:%d: ", __FILE__, __func__, __LINE__); \
)
+/* Call `f` on `x` if `x` exists. */
+#define EDO(f, x) HIDE(if (x) {f(x);})
+
/* Log some debug information. */
-void log_dbg(const char*, ...);
-#define LOG_DBG(fmt, ...) HIDE( \
+#define LOG_DBGF(fmt, ...) HIDE( \
fprintf(stderr, "\x1b[37m[\x1b[95;1m==\x1b[0m\x1b[37m]\x1b[0m\x1b[35m "); \
LOG_FINF; \
fprintf(stderr, fmt, ##__VA_ARGS__); \
fprintf(stderr, "\x1b[0m\n"); \
)
+#define LOG_DBG(body) HIDE( \
+ fprintf(stderr, "\x1b[37m[\x1b[95;1m==\x1b[0m\x1b[37m]\x1b[0m\x1b[35m "); \
+ LOG_FINF; \
+ fprintf(stderr, body); \
+ fprintf(stderr, "\x1b[0m\n"); \
+)
+
/* c: */
-void log_yay(const char*, ...);
-#define LOG_YAY(fmt, ...) HIDE( \
+#define LOG_YAYF(fmt, ...) HIDE( \
fprintf(stderr, "\x1b[37m[\x1b[92;1m==\x1b[0m\x1b[37m]\x1b[32m "); \
LOG_FINF; \
fprintf(stderr, fmt, ##__VA_ARGS__); \
fprintf(stderr, "\x1b[0m\n"); \
)
+#define LOG_YAY(body) HIDE( \
+ fprintf(stderr, "\x1b[37m[\x1b[92;1m==\x1b[0m\x1b[37m]\x1b[32m "); \
+ LOG_FINF; \
+ fprintf(stderr, body); \
+ fprintf(stderr, "\x1b[0m\n"); \
+)
+
/* Log some information. */
-void log_inf(const char*, ...);
-#define LOG_INF(fmt, ...) HIDE( \
+#define LOG_INFF(fmt, ...) HIDE( \
fprintf(stderr, "\x1b[37m[\x1b[94;1m==\x1b[0m\x1b[37m]\x1b[0m "); \
fprintf(stderr, fmt, ##__VA_ARGS__); \
fprintf(stderr, "\x1b[0m\n"); \
)
+#define LOG_INF(body) HIDE( \
+ fprintf(stderr, "\x1b[37m[\x1b[94;1m==\x1b[0m\x1b[37m]\x1b[0m "); \
+ fprintf(stderr, body); \
+ fprintf(stderr, "\x1b[0m\n"); \
+)
+
/* Log something with no formatting. */
-void log_raw(const char*, ...);
-#define LOG_RAW(fmt, ...) HIDE( \
+#define LOG_RAWF(fmt, ...) HIDE( \
fprintf(stderr, fmt, ##__VA_ARGS__); \
)
+#define LOG_RAW(body) HIDE( \
+ fprintf(stderr, body); \
+)
+
/* Log a warning. */
-void log_war(const char*, ...);
-#define LOG_WAR(fmt, ...) HIDE( \
+#define LOG_WARF(fmt, ...) HIDE( \
fprintf(stderr, "\x1b[37m[\x1b[93;1m==\x1b[0m\x1b[37m]\x1b[93;1m WARNING:\x1b[0m\x1b[33m "); \
LOG_FINF; \
fprintf(stderr, fmt, ##__VA_ARGS__); \
fprintf(stderr, "\x1b[0m\n"); \
)
+#define LOG_WAR(body) HIDE( \
+ fprintf(stderr, "\x1b[37m[\x1b[93;1m==\x1b[0m\x1b[37m]\x1b[93;1m WARNING:\x1b[0m\x1b[33m "); \
+ LOG_FINF; \
+ fprintf(stderr, body); \
+ fprintf(stderr, "\x1b[0m\n"); \
+)
+
/* Log an error. */
-void log_err(const char*, ...);
-#define LOG_ERR(fmt, ...) HIDE( \
+#define LOG_ERRF(fmt, ...) HIDE( \
fprintf(stderr, "\x1b[37m[\x1b[91;1m==\x1b[0m\x1b[37m]\x1b[91;1m ERROR:\x1b[0m\x1b[31m "); \
LOG_FINF; \
fprintf(stderr, fmt, ##__VA_ARGS__); \
fprintf(stderr, "\x1b[0m\n"); \
)
-/* Warn of soon™-to-be-removed functions. */
-#define WFDEPRECATED LOG_WAR("Use of this function is deprecated.")
+#define LOG_ERR(body) HIDE( \
+ fprintf(stderr, "\x1b[37m[\x1b[91;1m==\x1b[0m\x1b[37m]\x1b[91;1m ERROR:\x1b[0m\x1b[31m "); \
+ LOG_FINF; \
+ fprintf(stderr, body); \
+ fprintf(stderr, "\x1b[0m\n"); \
+)
/* Die and leave message. */
void die(const char*, ...);
-#define DIE(fmt, ...) HIDE( \
+#define DIEF(fmt, ...) HIDE( \
fprintf(stderr, "\x1b[37m[\x1b[91;1m==\x1b[0m\x1b[37m]\x1b[91;1m CAUSE OF DEATH:\x1b[0m\x1b[31m "); \
fprintf(stderr, fmt, ##__VA_ARGS__); \
fprintf(stderr, "\x1b[0m\n"); \
@@ -81,6 +113,14 @@ void die(const char*, ...);
exit(1); \
)
+#define DIE(body) HIDE( \
+ fprintf(stderr, "\x1b[37m[\x1b[91;1m==\x1b[0m\x1b[37m]\x1b[91;1m CAUSE OF DEATH:\x1b[0m\x1b[31m "); \
+ fprintf(stderr, body); \
+ fprintf(stderr, "\x1b[0m\n"); \
+ fprintf(stderr, "\x1b[37m[\x1b[91;1m==\x1b[0m\x1b[37m]\x1b[91;1m Exiting...\x1b[0m\n"); \
+ exit(1); \
+)
+
/* If `calloc()` returns null, die. */
void* ecalloc(size_t, size_t);
/* If `malloc()` returns null, die. */
diff --git a/src/lexer.c b/src/lexer.c
index a93828a..5094b00 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -144,7 +144,7 @@ void lexer_do_int(lexer_t* lexer) {
lexer_add_current_char_to_last_token(lexer, TOKEN_TYPE_INT);
! isdigit(*(lexer->src + 1)) && ( lexer->state = LEXER_STATE_REG );
} else {
- log_err("int state at non-int token");
+ LOG_ERR("int state at non-int token");
}
}
@@ -154,7 +154,7 @@ void lexer_do_kwd(lexer_t* lexer) {
! strchr(SYNTAX_KWD_CHARS, *(lexer->src + 1)) &&
( lexer->state = LEXER_STATE_REG );
} else {
- log_err("keyword state at non-keyword token");
+ LOG_ERR("keyword state at non-keyword token");
}
}
diff --git a/src/main.c b/src/main.c
index 4a00951..2537233 100644
--- a/src/main.c
+++ b/src/main.c
@@ -10,28 +10,28 @@ int main(int argc, char* argv[]) {
/* Get source. */
src = source_get(argv[1]);
- log_inf("Source: %s", src);
+ LOG_INFF("Source: %s", src);
/* Create pre-processor. */
pp = pp_init(src);
- log_dbg("Preprocessor created.");
+ LOG_DBG("Preprocessor created.");
/* Pre-process source. */
pp_run(pp);
free(src);
src = pp->psrc;
- log_inf("pre-processed source: %s", pp->psrc);
+ LOG_INFF("pre-processed source: %s", pp->psrc);
/* destroy pre-processor */
pp_destroy(pp);
- log_dbg("preprocessor ran");
+ LOG_DBG("preprocessor ran");
/* create lexer */
lexer = lexer_init(src);
- log_dbg("lexer created");
+ LOG_DBG("lexer created");
/* run lexer */
lexer_run(lexer);
- log_dbg("lexer ran");
+ LOG_DBG("lexer ran");
/* Print the lexer's tokens. */
token_print(lexer->tokenl);
diff --git a/src/parser.c b/src/parser.c
index 9da3da0..f7ababe 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -28,9 +28,10 @@ int parser_nxt_token(parser_t* parser) {
tree_t* parser_parse_init(parser_t* parser) {
/* There is nothing to do. */
- if (!parser->token || parser->token->type == TOKEN_TYPE_RBLOCK) {
+ if (!parser->token) {
return NULL;
}
+
tree_t* block;
block = tree_init(TREE_TYPE_BLOCK);
@@ -46,14 +47,13 @@ tree_t* parser_parse_block(parser_t* parser) {
(void) parser_nxt_token(parser); /* Skip over closing bracket. */
return NULL;
}
+
tree_t* block;
block = tree_init(TREE_TYPE_BLOCK);
block->data.block.val = parser_parse_expr(parser);
block->data.block.nxt = parser_parse_block(parser);
- parser_nxt_token(parser); /* Skip over semicolon. */
-
return block;
}
@@ -68,20 +68,53 @@ tree_t* parser_parse_expr(parser_t* parser) {
expr = parser_parse_lstr(parser);
break;
case TOKEN_TYPE_LBLOCK:
+ /* TODO: Move this into parser_parse_block, parser_parse_init exists now. */
parser_nxt_token(parser); /* Skip over opening curly bracket. */
expr = parser_parse_block(parser);
break;
+ case TOKEN_TYPE_KWD:
+ expr = parser_parse_kwd(parser);
+ break;
default:
- log_war("%s: Unknown token type: %d", __func__, parser->token->type);
+ LOG_WARF("%s: Unknown token type: %d", __func__, parser->token->type);
parser_nxt_token(parser);
}
return expr;
}
+tree_t* parser_parse_carg(parser_t* parser) {
+ tree_t* carg;
+
+ carg = tree_init(TREE_TYPE_CARG);
+
+ carg->data.carg.val = parser_parse_expr(parser);
+
+ carg->data.carg.nxt = NULL;
+
+ return carg;
+}
+
+tree_t* parser_parse_kwd(parser_t* parser) {
+ tree_t* call;
+
+ call = tree_init(TREE_TYPE_CALL);
+
+ call->data.call.target = parser->token->val;
+ parser->token->val = NULL;
+
+ if (parser_nxt_token_match(parser, TOKEN_TYPE_APPLY)) {
+ call->data.call.arg = parser_parse_carg(parser);
+ } else {
+ call->data.call.arg = NULL;
+ }
+
+ return call;
+}
+
/* I don't know if these need to exist. Guess I'll wait and see… */
int parser_match(parser_t* parser, token_type_t type) {
- return parser->token->type == type;
+ return parser->token ? parser->token->type == type : 0;
}
int parser_nxt_token_match(parser_t* parser, token_type_t type) {
@@ -140,7 +173,7 @@ tree_t* parser_parse_darg(parser_t* parser) {
darg->data.darg.tag = parser_parse_tag(parser);
- log_war("%d", parser->token->type);
+ LOG_WARF("%d", parser->token->type);
if (parser->token->type != TOKEN_TYPE_LIST_DELIM) {
darg->data.darg.nxt = NULL;
@@ -169,22 +202,6 @@ tree_t* parser_parse_def(parser_t* parser) {
return def;
}
-tree_t* parser_parse_carg(parser_t* parser) {
- tree_t* carg;
-
- carg = tree_init(TREE_TYPE_CARG);
-
- carg->data.carg.val = parser_parse_expr(parser);
- carg->data.carg.nxt = (
- parser_nxt_token_match(parser, TOKEN_TYPE_LIST_DELIM) &&
- parser_nxt_token(parser)
- ) ?
- parser_parse_carg(parser) :
- NULL;
-
- return carg;
-}
-
tree_t* parser_parse_call(parser_t* parser) {
tree_t* call;
diff --git a/src/pp.c b/src/pp.c
index db37118..bb77e0f 100644
--- a/src/pp.c
+++ b/src/pp.c
@@ -19,11 +19,11 @@ void pp_destroy(pp_t* pp) {
}
void pp_cpy_char(pp_t* pp) {
- int plen = strlen(pp->psrc);
- pp->psrc = erealloc(pp->psrc, (plen + 2) * sizeof(char));
+ int psize = strlen(pp->psrc);
+ pp->psrc = erealloc(pp->psrc, (psize + 2) * sizeof(char));
- pp->psrc[plen] = *pp->src;
- pp->psrc[plen + 1] = '\0';
+ pp->psrc[psize] = *pp->src;
+ pp->psrc[psize + 1] = '\0';
}
void pp_do_reg(pp_t* pp) {
diff --git a/src/source.c b/src/source.c
index 813e9f5..bf6655c 100644
--- a/src/source.c
+++ b/src/source.c
@@ -12,7 +12,7 @@ char* source_get_from_fpath(char* path) {
char* src;
f = fopen(path, "rb");
- if (!f) { die("source file not found: %s", path); }
+ if (!f) { DIEF("source file not found: %s", path); }
fseek(f, 0L, SEEK_END);
f_size = ftell(f);
@@ -23,7 +23,7 @@ char* source_get_from_fpath(char* path) {
if ((fread(src, f_size, 1, f) != 1) || !src) {
fclose(f);
free(src);
- die("could not read source file: %s", path);
+ DIEF("could not read source file: %s", path);
}
return src;
@@ -34,16 +34,21 @@ char* source_get_from_stdin() {
char* src;
size_t l;
+#if 0
l = 0;
src = ecalloc(16, sizeof(char));
while ((s = fgets(src + l, 20, stdin))) {
- l = MIN(16, l + strlen(src + l));
+ l = MIN(15, l + strlen(src + l));
}
/* This works, I guess. */
s && src[l - 1] == '\n' && (src[l - 1] = '\0');
+#endif
- return src;
+ src = ecalloc(256, sizeof(char));
+ fgets(src, 256, stdin);
+
+ return src;
}
diff --git a/src/stack.c b/src/stack.c
index 5c4d0ca..1d8a6fa 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -31,8 +31,8 @@ size_t stack_len(stack_t* stack) {
}
void stack_print(stack_t* stack) {
- log_inf("stack_print(): %p", stack);
+ LOG_INFF("stack_print(): %p", stack);
for (int i = stack_len(stack) - 1; i >= 0; --i) {
- log_inf("%d: %p", i, stack[i]);
+ LOG_INFF("%d: %p", i, stack[i]);
}
}
diff --git a/src/token.c b/src/token.c
index 3479a86..6ae0eae 100644
--- a/src/token.c
+++ b/src/token.c
@@ -49,7 +49,7 @@ void token_add_char(token_t* token, char c) {
void token_print(token_t* token) {
if (!token) { return; }
- log_dbg("token/t=%d\t/v=%s", token->type, token->val);
+ LOG_DBGF("token/t=%d\t/v=%s", token->type, token->val);
if (token->nxt) {
token_print(token->nxt);
}
diff --git a/src/tree.c b/src/tree.c
index 8398598..58fba36 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -131,7 +131,7 @@ int tree_cmp(tree_t* tree_0, tree_t* tree_1) {
tree_cmp(tree_0->data.call.arg, tree_1->data.call.arg);
break;
default:
- log_war("Unknown tree type.");
+ LOG_WAR("Unknown tree type.");
}
return 0;
@@ -152,13 +152,13 @@ void tree_print(tree_t* tree, int nest) {
;bc=malloc(11*sizeof(char));sprintf(c,
"\x1b[%dm",nc);sprintf(bc,"\x1b[%d;1m"
,nc);NULL;NULL;0x0;0;0;0;0;NULL;0x0;0;
- #define NEST0(T)log_raw("%s%s"T"\x1b"\
+ #define NEST0(T)LOG_RAWF("%s%s"T"\x1b"\
"""""""""""""""""""""""""[0m\n",bc,sp)
- #define NEST1(T)log_raw("%s%s"T"\x1b"\
+ #define NEST1(T)LOG_RAWF("%s%s"T"\x1b"\
"""""""""""""""""""""""""[0m\n",c,sp);
- #define NEST2(T)log_raw("%s \x1b[39;"\
+ #define NEST2(T)LOG_RAWF("%s \x1b[39;"\
"""""""""""""""49;4m%s\x1b[0m\n",sp,T)
- #define NEST3(T)log_raw("%s \x1b[39;"\
+ #define NEST3(T)LOG_RAWF("%s \x1b[39;"\
"""""""""""""""49;4m%d\x1b[0m\n",sp,T)
if (!tree) { NEST2("NULL"); goto end;}
switch (tree->type) {
@@ -224,7 +224,7 @@ void tree_print(tree_t* tree, int nest) {
tree_print(tree->data.darg.nxt, nest + 1);
break;
default:
- log_err("%d", __LINE__);
+ LOG_ERRF("%d", __LINE__);
}
end:
diff --git a/src/util.c b/src/util.c
index b2a8b07..33554a9 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,100 +1,9 @@
#include "include/util.h"
-void log_dbg(const char* fmt, ...) {
- WFDEPRECATED;
- va_list ap;
-
- fprintf(stdout, "");
- fprintf(stderr, "\x1b[37m[\x1b[95;1m==\x1b[0m\x1b[37m]\x1b[0m\x1b[35m ");
-
- va_start(ap, fmt);
- vfprintf(stdout, fmt, ap);
- va_end(ap);
-
- fprintf(stdout, "\e[0m\n");
-}
-
-void log_yay(const char* fmt, ...) {
- WFDEPRECATED;
- va_list ap;
-
- fprintf(stdout, "\x1b[37m[\x1b[92;1m==\x1b[0m\x1b[37m]\x1b[32m ");
-
- va_start(ap, fmt);
- vfprintf(stdout, fmt, ap);
- va_end(ap);
-
- fprintf(stdout, "\x1b[0m\n");
-}
-
-void log_inf(const char* fmt, ...) {
- WFDEPRECATED;
- va_list ap;
-
- fprintf(stderr, "\x1b[37m[\x1b[94;1m==\x1b[0m\x1b[37m]\x1b[0m ");
-
- va_start(ap, fmt);
- vfprintf(stdout, fmt, ap);
- va_end(ap);
-
- fprintf(stdout, "\n");
-}
-
-void log_raw(const char* fmt, ...) {
- WFDEPRECATED;
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stdout, fmt, ap);
- va_end(ap);
-}
-
-void log_war(const char* fmt, ...) {
- WFDEPRECATED;
- va_list ap;
-
- fprintf(stderr, "\x1b[37m[\x1b[93;1m==\x1b[0m\x1b[37m]\x1b[93;1m WARNING:\x1b[0m\x1b[33m ");
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fprintf(stderr, "\n");
-}
-
-void log_err(const char* fmt, ...) {
- WFDEPRECATED;
- va_list ap;
-
- fprintf(stderr, "\x1b[37m[\x1b[91;1m==\x1b[0m\x1b[37m]\x1b[91;1m ERROR:\x1b[0m\x1b[31m ");
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fprintf(stderr, "\x1b[0m\n");
-}
-
-void die(const char* fmt, ...) {
- WFDEPRECATED;
- va_list ap;
-
- fprintf(stderr, "\x1b[37m[\x1b[91;1m==\x1b[0m\x1b[37m]\x1b[91;1m CAUSE OF DEATH:\x1b[0m\x1b[31m ");
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr, "\x1b[0m\n");
-
- fprintf(stderr, "\x1b[37m[\x1b[91;1m==\x1b[0m\x1b[37m]\x1b[91;1m Exiting...\x1b[0m\n");
-
- exit(1);
-}
-
void* ecalloc(size_t nmemb, size_t size) {
void* p;
- if (! (p = calloc(nmemb, size))) { die("failed to calloc:"); }
+ if (! (p = calloc(nmemb, size))) { DIE("Failed to calloc:"); }
return p;
}
@@ -102,7 +11,7 @@ void* ecalloc(size_t nmemb, size_t size) {
void* emalloc(size_t size) {
void* p;
- if (! (p = malloc(size))) { die("failed to malloc:"); }
+ if (! (p = malloc(size))) { DIE("Failed to malloc:"); }
return p;
}
@@ -110,7 +19,7 @@ void* emalloc(size_t size) {
void* erealloc(void* dest, size_t size) {
void* p;
- if (! (p = realloc(dest, size))) { die("failed to realloc:"); }
+ if (! (p = realloc(dest, size))) { DIE("Failed to realloc:"); }
return p;
}
diff --git a/test/include/test.h b/test/include/test.h
index 7366aa2..74642b7 100644
--- a/test/include/test.h
+++ b/test/include/test.h
@@ -12,23 +12,19 @@ extern unsigned int TESTS_PASSED;
#define TEST_INIT unsigned int TESTS_RUN = 0, TESTS_PASSED = 0;
-#ifndef __func__
-#define __func__ ""
-#endif
-
#define ASSERT(EXPR) \
TESTS_RUN++; \
if (EXPR && ++TESTS_PASSED) { \
- LOG_INF("%s:%s:%d: Assertion passed!", __FILE__, __func__, __LINE__); \
+ LOG_INFF("%s:%s:%d: Assertion passed!", __FILE__, __func__, __LINE__); \
} else { \
- LOG_ERR("%s:%s:%d: Assertion failed:\n\t%s", __FILE__, __func__, __LINE__, #EXPR); \
+ LOG_ERRF("Assertion failed:\n\t%s", #EXPR); \
}
#define TEST_REPORT \
if (TESTS_RUN == TESTS_PASSED) { \
- LOG_YAY("%s: All %d tests passed!", __FILE__, TESTS_RUN); \
+ LOG_YAYF("%s: All %d tests passed!", __FILE__, TESTS_RUN); \
} else { \
- LOG_ERR("%d/%d tests failed.", TESTS_RUN - TESTS_PASSED, TESTS_RUN); \
+ LOG_ERRF("%d/%d tests failed.", TESTS_RUN - TESTS_PASSED, TESTS_RUN); \
}
#endif
diff --git a/test/parser.c b/test/parser.c
index f2fe908..3bceab1 100644
--- a/test/parser.c
+++ b/test/parser.c
@@ -39,9 +39,11 @@ void empty() {
/* Probably not cleaning up fully here. Whatever. */
token_destroy(lexer->tokenl);
lexer_destroy(lexer);
+ free(pp->psrc);
pp_destroy(pp);
tree_destroy(parser->tree);
parser_destroy(parser);
+ tree_destroy(tree);
}
void single_lint() {
@@ -82,9 +84,11 @@ void single_lint() {
token_destroy(lexer->tokenl);
lexer_destroy(lexer);
+ free(pp->psrc);
pp_destroy(pp);
tree_destroy(parser->tree);
parser_destroy(parser);
+ tree_destroy(tree);
}
void double_lint() {
@@ -134,9 +138,11 @@ void double_lint() {
token_destroy(lexer->tokenl);
lexer_destroy(lexer);
+ free(pp->psrc);
pp_destroy(pp);
tree_destroy(parser->tree);
parser_destroy(parser);
+ tree_destroy(tree);
}
void single_lstr() {
@@ -163,7 +169,8 @@ void single_lstr() {
tree = tree_init(TREE_TYPE_BLOCK);
tree_t* tree0lstr = tree->data.block.val = tree_init(TREE_TYPE_LSTR);
- tree0lstr->data.lstr.val = "Hello, World.";
+ char* str0 = tree0lstr->data.lstr.val = ecalloc(14, sizeof(char));
+ strcpy(str0, "Hello, World.");
tree0lstr->data.lstr.len = 13;
tree->data.block.nxt = NULL;
@@ -180,9 +187,11 @@ void single_lstr() {
token_destroy(lexer->tokenl);
lexer_destroy(lexer);
+ free(pp->psrc);
pp_destroy(pp);
tree_destroy(parser->tree);
parser_destroy(parser);
+ tree_destroy(tree);
}
void double_lstr() {
@@ -217,11 +226,13 @@ void double_lstr() {
tree = tree_init(TREE_TYPE_BLOCK);
tree_t* tree0lstr = tree->data.block.val = tree_init(TREE_TYPE_LSTR);
- tree0lstr->data.lstr.val = "foo";
+ char* str0 = tree0lstr->data.lstr.val = ecalloc(4, sizeof(char));
+ strcpy(str0, "foo");
tree0lstr->data.lstr.len = 3;
tree_t* tree0block = tree->data.block.nxt = tree_init(TREE_TYPE_BLOCK);
tree_t* tree1lstr = tree0block->data.block.val = tree_init(TREE_TYPE_LSTR);
- tree1lstr->data.lstr.val = "bar";
+ char* str1 = tree1lstr->data.lstr.val = ecalloc(4, sizeof(char));
+ strcpy(str1, "bar");
tree1lstr->data.lstr.len = 3;
tree0block->data.block.nxt = NULL;
@@ -238,9 +249,11 @@ void double_lstr() {
token_destroy(lexer->tokenl);
lexer_destroy(lexer);
+ free(pp->psrc);
pp_destroy(pp);
tree_destroy(parser->tree);
parser_destroy(parser);
+ tree_destroy(tree);
}
void single_block() {
@@ -288,9 +301,11 @@ void single_block() {
token_destroy(lexer->tokenl);
lexer_destroy(lexer);
+ free(pp->psrc);
pp_destroy(pp);
tree_destroy(parser->tree);
parser_destroy(parser);
+ tree_destroy(tree);
}
void lint_and_block() {
@@ -299,7 +314,7 @@ void lint_and_block() {
lexer_t* lexer;
parser_t* parser;
- char src[] = "1;{1}";
+ char src[] = "1{1}";
/*
@@ -346,9 +361,443 @@ void lint_and_block() {
token_destroy(lexer->tokenl);
lexer_destroy(lexer);
+ free(pp->psrc);
pp_destroy(pp);
tree_destroy(parser->tree);
parser_destroy(parser);
+ tree_destroy(tree);
+}
+
+void double_block() {
+ tree_t* tree;
+ pp_t* pp;
+ lexer_t* lexer;
+ parser_t* parser;
+
+ char src[] = "{1}{2}";
+
+ /*
+
+ [block]
+ val:
+ [block]
+ val:
+ [lint]
+ val:
+ 1
+ nxt:
+ NULL
+ nxt:
+ [block]
+ val:
+ [block]
+ val:
+ [lint]
+ val:
+ 2
+ nxt:
+ NULL
+ nxt:
+ NULL
+
+ */
+
+ tree = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0block = tree->data.block.val = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0lint = tree0block->data.block.val = tree_init(TREE_TYPE_LINT);
+ tree0lint->data.lint.val = 1;
+ tree0block->data.block.nxt = NULL;
+ tree_t* tree1block = tree->data.block.nxt = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree2block = tree1block->data.block.val = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree1lint = tree2block->data.block.val = tree_init(TREE_TYPE_LINT);
+ tree1lint->data.lint.val = 2;
+ tree2block->data.block.nxt = NULL;
+ tree1block->data.block.nxt = NULL;
+
+
+ pp = pp_init(src);
+ pp_run(pp);
+
+ lexer = lexer_init(pp->psrc);
+ lexer_run(lexer);
+
+ parser = parser_init(lexer->tokenl);
+ parser_run(parser);
+
+ ASSERT(tree_cmp(parser->tree, tree) == 1);
+
+ token_destroy(lexer->tokenl);
+ lexer_destroy(lexer);
+ free(pp->psrc);
+ pp_destroy(pp);
+ tree_destroy(parser->tree);
+ parser_destroy(parser);
+ tree_destroy(tree);
+}
+
+void nested_block() {
+ tree_t* tree;
+ pp_t* pp;
+ lexer_t* lexer;
+ parser_t* parser;
+
+ char src[] = "{1;2}";
+
+ /*
+
+ [block]
+ val:
+ [block]
+ val:
+ [lint]
+ val:
+ 1
+ nxt:
+ [block]
+ val:
+ [lint]
+ val:
+ 2
+ nxt:
+ NULL
+ nxt:
+ NULL
+
+ */
+
+ tree = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0block = tree->data.block.val = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0lint = tree0block->data.block.val = tree_init(TREE_TYPE_LINT);
+ tree0lint->data.lint.val = 1;
+ tree_t* tree1block = tree0block->data.block.nxt = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree1lint = tree1block->data.block.val = tree_init(TREE_TYPE_LINT);
+ tree1lint->data.lint.val = 2;
+ tree1block->data.block.nxt = NULL;
+ tree->data.block.nxt = NULL;
+
+
+ pp = pp_init(src);
+ pp_run(pp);
+
+ lexer = lexer_init(pp->psrc);
+ lexer_run(lexer);
+
+ parser = parser_init(lexer->tokenl);
+ parser_run(parser);
+
+ ASSERT(tree_cmp(parser->tree, tree) == 1);
+
+ token_destroy(lexer->tokenl);
+ lexer_destroy(lexer);
+ free(pp->psrc);
+ pp_destroy(pp);
+ tree_destroy(parser->tree);
+ parser_destroy(parser);
+ tree_destroy(tree);
+}
+
+void superfluous_semicolons() {
+ tree_t* tree;
+ pp_t* pp;
+ lexer_t* lexer;
+ parser_t* parser;
+
+ char src[] = "{;;;;;\"Hello\";;;;;;;;;;;};;;\"World\";;;;;;;;";
+
+ /*
+
+ [block]
+ val:
+ [block]
+ val:
+ [lstr]
+ val:
+ Hello
+ len:
+ 5
+ nxt:
+ NULL
+ nxt:
+ [block]
+ val:
+ [lstr]
+ val:
+ World
+ len:
+ 5
+ nxt:
+ NULL
+
+ */
+
+ tree = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0block = tree->data.block.val = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0lstr = tree0block->data.block.val = tree_init(TREE_TYPE_LSTR);
+ char* str0 = tree0lstr->data.lstr.val = ecalloc(6, sizeof(char));
+ strcpy(str0, "Hello");
+ tree0lstr->data.lstr.len = 5;
+ tree_t* tree1block = tree->data.block.nxt = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree1lstr = tree1block->data.block.val = tree_init(TREE_TYPE_LSTR);
+ char* str1 = tree1lstr->data.lstr.val = ecalloc(6, sizeof(char));
+ strcpy(str1, "World");
+ tree1lstr->data.lstr.len = 5;
+ tree1block->data.block.nxt = NULL;
+
+
+ pp = pp_init(src);
+ pp_run(pp);
+
+ lexer = lexer_init(pp->psrc);
+ lexer_run(lexer);
+
+ parser = parser_init(lexer->tokenl);
+ parser_run(parser);
+
+ ASSERT(tree_cmp(parser->tree, tree) == 1);
+
+ token_destroy(lexer->tokenl);
+ lexer_destroy(lexer);
+ free(pp->psrc);
+ pp_destroy(pp);
+ tree_destroy(parser->tree);
+ parser_destroy(parser);
+ tree_destroy(tree);
+}
+
+void bare_call() {
+ tree_t* tree;
+ pp_t* pp;
+ lexer_t* lexer;
+ parser_t* parser;
+
+ char src[] = "f";
+
+ /*
+
+ [block]
+ val:
+ [call]
+ target:
+ f
+ arg:
+ NULL
+ nxt:
+ NULL
+
+ */
+
+ tree = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0call = tree->data.block.val = tree_init(TREE_TYPE_CALL);
+ char* target0 = tree0call->data.call.target = ecalloc(2, sizeof(char));
+ strcpy(target0, "f");
+ tree0call->data.call.arg = NULL;
+ tree->data.block.nxt = NULL;
+
+
+ pp = pp_init(src);
+ pp_run(pp);
+
+ lexer = lexer_init(pp->psrc);
+ lexer_run(lexer);
+
+ parser = parser_init(lexer->tokenl);
+ parser_run(parser);
+
+ ASSERT(tree_cmp(parser->tree, tree) == 1);
+
+ token_destroy(lexer->tokenl);
+ lexer_destroy(lexer);
+ free(pp->psrc);
+ pp_destroy(pp);
+ tree_destroy(parser->tree);
+ parser_destroy(parser);
+ tree_destroy(tree);
+}
+
+void double_bare_call() {
+ tree_t* tree;
+ pp_t* pp;
+ lexer_t* lexer;
+ parser_t* parser;
+
+ char src[] = "f;g";
+
+ /*
+
+ [block]
+ val:
+ [call]
+ target:
+ f
+ arg:
+ NULL
+ nxt:
+ [block]
+ val:
+ [call]
+ target:
+ g
+ arg:
+ NULL
+ nxt:
+ NULL
+
+ */
+
+ tree = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0call = tree->data.block.val = tree_init(TREE_TYPE_CALL);
+ char* target0 = tree0call->data.call.target = ecalloc(2, sizeof(char));
+ strcpy(target0, "f");
+ tree0call->data.call.arg = NULL;
+ tree_t* tree1block = tree->data.block.nxt = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree1call = tree1block->data.block.val = tree_init(TREE_TYPE_CALL);
+ char* target1 = tree1call->data.call.target = ecalloc(2, sizeof(char));
+ strcpy(target1, "g");
+ tree1call->data.call.arg = NULL;
+ tree1block->data.block.nxt = NULL;
+
+
+ pp = pp_init(src);
+ pp_run(pp);
+
+ lexer = lexer_init(pp->psrc);
+ lexer_run(lexer);
+
+ parser = parser_init(lexer->tokenl);
+ parser_run(parser);
+
+ ASSERT(tree_cmp(parser->tree, tree) == 1);
+
+ token_destroy(lexer->tokenl);
+ lexer_destroy(lexer);
+ free(pp->psrc);
+ pp_destroy(pp);
+ tree_destroy(parser->tree);
+ parser_destroy(parser);
+ tree_destroy(tree);
+}
+
+void cargumented_call_of_call() {
+ tree_t* tree;
+ pp_t* pp;
+ lexer_t* lexer;
+ parser_t* parser;
+
+ char src[] = "f.x";
+
+ /*
+
+ [block]
+ val:
+ [call]
+ target:
+ f
+ arg:
+ [carg]
+ val:
+ [call]
+ target:
+ x
+ arg:
+ NULL
+ nxt:
+ NULL
+ nxt:
+ NULL
+
+ */
+
+ tree = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0call = tree->data.block.val = tree_init(TREE_TYPE_CALL);
+ char* target0 = tree0call->data.call.target = ecalloc(2, sizeof(char));
+ strcpy(target0, "f");
+ tree_t* tree0carg = tree0call->data.call.arg = tree_init(TREE_TYPE_CARG);
+ tree_t* tree1call = tree0carg->data.carg.val = tree_init(TREE_TYPE_CALL);
+ char* target1 = tree1call->data.call.target = ecalloc(2, sizeof(char));
+ strcpy(target1, "x");
+ tree1call->data.call.arg = NULL;
+ tree0call->data.carg.nxt = NULL;
+ tree->data.block.nxt = NULL;
+
+ pp = pp_init(src);
+ pp_run(pp);
+
+ lexer = lexer_init(pp->psrc);
+ lexer_run(lexer);
+
+ parser = parser_init(lexer->tokenl);
+ parser_run(parser);
+
+ ASSERT(tree_cmp(parser->tree, tree) == 1);
+
+ tree_print(tree, 0);
+ tree_print(parser->tree, 0);
+
+ token_destroy(lexer->tokenl);
+ lexer_destroy(lexer);
+ free(pp->psrc);
+ pp_destroy(pp);
+ tree_destroy(parser->tree);
+ parser_destroy(parser);
+ tree_destroy(tree);
+}
+
+void cargumented_call_of_lint() {
+ tree_t* tree;
+ pp_t* pp;
+ lexer_t* lexer;
+ parser_t* parser;
+
+ char src[] = "f.5";
+
+ /*
+
+ [block]
+ val:
+ [call]
+ target:
+ f
+ arg:
+ [carg]
+ val:
+ [lint]
+ val:
+ 5
+ nxt:
+ NULL
+ nxt:
+ NULL
+
+ */
+
+ tree = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree0call = tree->data.block.val = tree_init(TREE_TYPE_CALL);
+ char* target0 = tree0call->data.call.target = ecalloc(2, sizeof(char));
+ strcpy(target0, "f");
+ tree_t* tree0carg = tree0call->data.call.arg = tree_init(TREE_TYPE_CARG);
+ tree_t* tree0lint = tree0carg->data.carg.val = tree_init(TREE_TYPE_LINT);
+ tree0lint->data.lint.val = 5;
+ tree0carg->data.carg.nxt = NULL;
+ tree->data.block.nxt = NULL;
+
+ pp = pp_init(src);
+ pp_run(pp);
+
+ lexer = lexer_init(pp->psrc);
+ lexer_run(lexer);
+
+ parser = parser_init(lexer->tokenl);
+ parser_run(parser);
+
+ ASSERT(tree_cmp(parser->tree, tree) == 1);
+
+ token_destroy(lexer->tokenl);
+ lexer_destroy(lexer);
+ free(pp->psrc);
+ pp_destroy(pp);
+ tree_destroy(parser->tree);
+ parser_destroy(parser);
+ tree_destroy(tree);
}
int main() {
@@ -359,6 +808,13 @@ int main() {
double_lstr();
single_block();
lint_and_block();
+ double_block();
+ nested_block();
+ superfluous_semicolons();
+ bare_call();
+ double_bare_call();
+ cargumented_call_of_call();
+ cargumented_call_of_lint();
TEST_REPORT;