diff options
-rwxr-xr-x | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | src/include/lexer.h | 2 | ||||
-rw-r--r-- | src/include/parser.h | 17 | ||||
-rw-r--r-- | src/include/pp.h | 2 | ||||
-rw-r--r-- | src/include/tree.h | 2 | ||||
-rw-r--r-- | src/parser.c | 86 | ||||
-rw-r--r-- | test/include/test.h | 4 | ||||
-rw-r--r-- | test/parser.c | 70 | ||||
-rw-r--r-- | test/tree.c | 4 |
10 files changed, 143 insertions, 51 deletions
@@ -4,6 +4,7 @@ tags *.out *.tmp.* +coredump *.notes.md [._]sw[a-p] [._]*.sw[a-p] @@ -1,8 +1,8 @@ BIN := halk PREFIX := /usr/local/bin CC := gcc -REG_CFLAGS := -ansi -O3 -s -DBG_CFLAGS := -ansi -Og -ggdb -pedantic +REG_CFLAGS := -std=c99 -O3 -s +DBG_CFLAGS := -std=c99 -Og -ggdb -pedantic DBG_CFLAGS += -Wall -Wextra -Wformat -Werror -Wpedantic DBG_CFLAGS += -fsanitize=leak,address,undefined -fno-omit-frame-pointer CFLAGS := $(REG_CFLAGS) @@ -35,7 +35,7 @@ dbg: CFLAGS := $(DBG_CFLAGS) dbg: dbg_options $(OBJS) $(CC) $(OBJS) $(DBG_CFLAGS) -o $(BIN).out -test: dbg $(TEST_OUTS) +test: clean dbg $(TEST_OUTS) set -e for f in $(TEST_OUTS); do ./$$f; done diff --git a/src/include/lexer.h b/src/include/lexer.h index 02275cb..5235f3b 100644 --- a/src/include/lexer.h +++ b/src/include/lexer.h @@ -23,7 +23,7 @@ typedef struct LEXER_STRUC { /* Integer. */ LEXER_STATE_INT, /* Keyword. */ - LEXER_STATE_KWD, + LEXER_STATE_KWD } state; /* The linked list of tokens generated. */ diff --git a/src/include/parser.h b/src/include/parser.h index eae09d4..a442d60 100644 --- a/src/include/parser.h +++ b/src/include/parser.h @@ -14,7 +14,7 @@ typedef enum PARSER_STATE { PARSER_STATE_DARG, PARSER_STATE_CARG, PARSER_STATE_DEF, - PARSER_STATE_CALL, + PARSER_STATE_CALL } parser_state_t; typedef struct PARSER { @@ -41,6 +41,15 @@ void parser_destroy(parser_t* parser); /* Step the parser forward by 1 token. */ int parser_nxt_token(parser_t* parser); +/* Get tree for first (implied) block. */ +tree_t* parser_parse_init(parser_t* parser); + +/* Get tree for a block. */ +tree_t* parser_parse_block(parser_t* parser); + +/* Get tree for an expression.*/ +tree_t* parser_parse_expr(parser_t* parser); + /* Check whether the current token matches the given type. - If it doesn't, return 0 and throw error. @@ -56,12 +65,6 @@ tree_t* parser_parse_lint(parser_t* parser); /* Return the tree for a string. */ tree_t* parser_parse_lstr(parser_t* parser); -/* Return the tree for an expression.*/ -tree_t* parser_parse_expr(parser_t* parser); - -/* Return the tree for an block. */ -tree_t* parser_parse_block(parser_t* parser); - /* Return the tree for a definition's arguments. */ tree_t* parser_parse_darg(parser_t* parser); diff --git a/src/include/pp.h b/src/include/pp.h index 4186ef3..bbb901c 100644 --- a/src/include/pp.h +++ b/src/include/pp.h @@ -27,7 +27,7 @@ typedef struct PP_STRUC { PP_STATE_REG, /* Regular. */ PP_STATE_STR, /* String. */ PP_STATE_COM, /* Comment. */ - PP_STATE_ESC, /* Escaped character in string. */ + PP_STATE_ESC /* Escaped character in string. */ /* PP_STATE_MCO, */ /* Macro. */ } state; } pp_t; diff --git a/src/include/tree.h b/src/include/tree.h index 31b8f3f..2a62f26 100644 --- a/src/include/tree.h +++ b/src/include/tree.h @@ -12,7 +12,7 @@ typedef enum TREE_TYPE { TREE_TYPE_DARG, TREE_TYPE_CARG, TREE_TYPE_DEF, - TREE_TYPE_CALL, + TREE_TYPE_CALL } tree_type_t; /* The Abstract Syntax Tree (AST) structure. */ diff --git a/src/parser.c b/src/parser.c index 2cf9b2c..f94fe53 100644 --- a/src/parser.c +++ b/src/parser.c @@ -18,6 +18,7 @@ void parser_destroy(parser_t* parser) { /* TODO: What if the program begins with a ";"? */ int parser_nxt_token(parser_t* parser) { /* Preserve original token list, to be cleaned up by lexer. */ + if (!parser->token) { return 0; } parser->token = parser->token->nxt; if (parser->token && parser->token->type == TOKEN_TYPE_EXPR_END) { return parser_nxt_token(parser); @@ -25,6 +26,59 @@ int parser_nxt_token(parser_t* parser) { return parser->token ? 1 : 0; } +tree_t* parser_parse_init(parser_t* parser) { + /* There is nothing to do. */ + if (!parser->token || parser->token->type == TOKEN_TYPE_RBLOCK) { + 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); + + return block; +} + +tree_t* parser_parse_block(parser_t* parser) { + /* There is nothing to do. */ + if (!parser->token || parser->token->type == TOKEN_TYPE_RBLOCK) { + 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; +} + +tree_t* parser_parse_expr(parser_t* parser) { + tree_t* expr = NULL; + + switch (parser->token->type) { + case TOKEN_TYPE_INT: + expr = parser_parse_lint(parser); + break; + case TOKEN_TYPE_STR: + expr = parser_parse_lstr(parser); + break; + case TOKEN_TYPE_LBLOCK: + parser_nxt_token(parser); /* Skip over opening curly bracket. */ + expr = parser_parse_block(parser); + break; + default: + log_war("%s: Unknown token type: %d", __func__, parser->token->type); + parser_nxt_token(parser); + } + + return expr; +} + /* 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; @@ -59,38 +113,6 @@ tree_t* parser_parse_lstr(parser_t* parser) { return lstr; } -tree_t* parser_parse_expr(parser_t* parser) { - tree_t* expr = NULL; - - switch (parser->token->type) { - case TOKEN_TYPE_INT: - expr = parser_parse_lint(parser); - break; - case TOKEN_TYPE_STR: - expr = parser_parse_lstr(parser); - break; - default: - log_war("%s: Unknown token type: %d", __func__, parser->token->type); - parser_nxt_token(parser); - } - - return expr; -} - -tree_t* parser_parse_block(parser_t* parser) { - /* There is nothing to do. */ - if (!parser->token || parser->token->type == TOKEN_TYPE_RBLOCK) { - 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); - - return block; -} - tree_t* parser_parse_tag(parser_t* parser) { if (parser->token->type != TOKEN_TYPE_TAG) { return NULL; } diff --git a/test/include/test.h b/test/include/test.h index 3193c52..8cde34d 100644 --- a/test/include/test.h +++ b/test/include/test.h @@ -12,6 +12,10 @@ 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++; \ (EXPR && ++TESTS_PASSED) ? \ diff --git a/test/parser.c b/test/parser.c index feb9c70..f2fe908 100644 --- a/test/parser.c +++ b/test/parser.c @@ -249,7 +249,7 @@ void single_block() { lexer_t* lexer; parser_t* parser; - char src[] = "{}"; + char src[] = "{1}"; /* @@ -257,7 +257,9 @@ void single_block() { val: [block] val: - NULL + [lint] + val: + 1 nxt: NULL nxt: @@ -267,7 +269,8 @@ void single_block() { tree = tree_init(TREE_TYPE_BLOCK); tree_t* tree0block = tree->data.block.val = tree_init(TREE_TYPE_BLOCK); - tree0block->data.block.val = NULL; + tree_t* tree0lint = tree0block->data.block.val = tree_init(TREE_TYPE_LINT); + tree0lint->data.lint.val = 1; tree0block->data.block.nxt = NULL; tree->data.block.nxt = NULL; @@ -290,13 +293,72 @@ void single_block() { parser_destroy(parser); } -int main(int argc, char** argv) { +void lint_and_block() { + tree_t* tree; + pp_t* pp; + lexer_t* lexer; + parser_t* parser; + + char src[] = "1;{1}"; + + /* + + [block] + val: + [lint] + val: + 1 + nxt: + [block] + val: + [block] + val: + [lint] + val: + 1 + nxt: + NULL + nxt: + NULL + + */ + + tree = tree_init(TREE_TYPE_BLOCK); + tree_t* tree0lint = tree->data.block.val = tree_init(TREE_TYPE_LINT); + tree0lint->data.lint.val = 1; + tree_t* tree0block = tree->data.block.nxt = tree_init(TREE_TYPE_BLOCK); + tree_t* tree1block = tree0block->data.block.val = tree_init(TREE_TYPE_BLOCK); + tree_t* tree1lint = tree1block->data.block.val = tree_init(TREE_TYPE_LINT); + tree1lint->data.lint.val = 1; + tree1block->data.block.nxt = NULL; + tree0block->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); + pp_destroy(pp); + tree_destroy(parser->tree); + parser_destroy(parser); +} + +int main() { empty(); single_lint(); double_lint(); single_lstr(); double_lstr(); single_block(); + lint_and_block(); TEST_REPORT; diff --git a/test/tree.c b/test/tree.c index b9ef210..567daae 100644 --- a/test/tree.c +++ b/test/tree.c @@ -20,8 +20,6 @@ void test_things() { tree_t* tree_lstr_1; tree_t* tree_tag_0; tree_t* tree_tag_1; - tree_t* tree_def_0; - tree_t* tree_def_1; tree_t* tree_carg_0; tree_t* tree_carg_1; tree_t* tree_call_0; @@ -245,6 +243,8 @@ void test_things() { ASSERT(tree_cmp(tree_block_0, tree_block_0) == 1); ASSERT(tree_cmp(tree_block_0, tree_block_1) == 0); + + /* *Definitely* not cleaning up fully here. Oh, well. */ } int main() { |