diff options
-rw-r--r-- | Makefile | 22 | ||||
-rw-r--r-- | src/include/parser.h | 2 | ||||
-rw-r--r-- | src/include/util.h | 72 | ||||
-rw-r--r-- | src/lexer.c | 4 | ||||
-rw-r--r-- | src/main.c | 12 | ||||
-rw-r--r-- | src/parser.c | 61 | ||||
-rw-r--r-- | src/pp.c | 8 | ||||
-rw-r--r-- | src/source.c | 13 | ||||
-rw-r--r-- | src/stack.c | 4 | ||||
-rw-r--r-- | src/token.c | 2 | ||||
-rw-r--r-- | src/tree.c | 12 | ||||
-rw-r--r-- | src/util.c | 97 | ||||
-rw-r--r-- | test/include/test.h | 12 | ||||
-rw-r--r-- | test/parser.c | 464 |
14 files changed, 603 insertions, 182 deletions
@@ -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"); } } @@ -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; @@ -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); } @@ -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: @@ -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; |