aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/tree.h4
-rw-r--r--src/parser.c57
-rw-r--r--src/tree.c2
-rw-r--r--test/include/test.h4
-rw-r--r--test/parser.c66
5 files changed, 81 insertions, 52 deletions
diff --git a/src/include/tree.h b/src/include/tree.h
index 8b8e14a..31b8f3f 100644
--- a/src/include/tree.h
+++ b/src/include/tree.h
@@ -82,8 +82,8 @@ typedef struct TREE {
} tree_t;
/* Create a new AST. */
-tree_t* tree_init(int type);
-/* Destroy the AST. */
+tree_t* tree_init(tree_type_t type);
+/* Destroy the AST (if it exists). */
void tree_destroy(tree_t* tree);
/*
diff --git a/src/parser.c b/src/parser.c
index bb945db..344ca89 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,4 +1,5 @@
#include "include/parser.h"
+#include "include/token.h"
parser_t* parser_init(token_t* token) {
parser_t* parser;
@@ -11,18 +12,16 @@ parser_t* parser_init(token_t* token) {
}
void parser_destroy(parser_t* parser) {
- free(parser);
+ if (parser) { free(parser); }
}
int parser_nxt_token(parser_t* parser) {
- if (parser->token->nxt) {
- token_t* nxt = parser->token->nxt;
- free(parser->token);
- parser->token = nxt;
- return 1;
- } else {
- return 0;
+ /* Preserve original token list, to be cleaned up by lexer. */
+ parser->token = parser->token->nxt;
+ if (parser->token && parser->token->type == TOKEN_TYPE_EXPR_END) {
+ return parser_nxt_token(parser);
}
+ return parser->token ? 1 : 0;
}
int parser_match(parser_t* parser, token_type_t type) {
@@ -39,6 +38,7 @@ tree_t* parser_parse_lint(parser_t* parser) {
lint = tree_init(TREE_TYPE_LINT);
lint->data.lint.val = atoi(parser->token->val);
+ parser_nxt_token(parser);
return lint;
}
@@ -57,52 +57,33 @@ tree_t* parser_parse_lstr(parser_t* parser) {
}
tree_t* parser_parse_expr(parser_t* parser) {
- tree_t* expr;
-
- expr = tree_init(TREE_TYPE_EXPR);
+ tree_t* expr = NULL;
switch (parser->token->type) {
case TOKEN_TYPE_INT:
- expr->data.expr.val = parser_parse_lint(parser);
- break;
- case TOKEN_TYPE_STR:
- expr->data.expr.val = parser_parse_lstr(parser);
+ expr = parser_parse_lint(parser);
break;
- case TOKEN_TYPE_KWD:
- expr->data.expr.val = parser_parse_call(parser);
- break;
- case TOKEN_TYPE_TAG:
- expr->data.expr.val = parser_parse_def(parser);
- break;
- case TOKEN_TYPE_LBLOCK:
+ case TOKEN_TYPE_EXPR_END:
parser_nxt_token(parser);
- expr->data.expr.val = parser_parse_block(parser);
break;
default:
- expr->data.lstr.val = "???"; /* TODO: Add an "unknown" token type. */
- return expr;
+ 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);
- if (!parser->token) {
- block->data.block.val = NULL;
- block->data.block.nxt = NULL;
- } else {
- switch (parser->token->type) {
- case TOKEN_TYPE_INT:
- block->data.block.val = parser_parse_lint(parser);
- break;
- }
- }
-
- block->data.block.nxt = NULL;
+ block->data.block.val = parser_parse_expr(parser);
+ block->data.block.nxt = parser_parse_block(parser);
return block;
}
diff --git a/src/tree.c b/src/tree.c
index a024371..62c8218 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -1,6 +1,6 @@
#include "include/tree.h"
-tree_t* tree_init(int type) {
+tree_t* tree_init(tree_type_t type) {
tree_t* tree;
tree = emalloc(sizeof(tree_t));
diff --git a/test/include/test.h b/test/include/test.h
index c5fd97e..02c3d18 100644
--- a/test/include/test.h
+++ b/test/include/test.h
@@ -11,8 +11,8 @@ extern unsigned int TESTS_PASSED;
#define ASSERT(EXPR) \
TESTS_RUN++; \
(EXPR && ++TESTS_PASSED) ? \
- log_inf("%s:%d: Assertion passed!", __FILE__, __LINE__) : \
- log_err("%s:%d: Assertion failed:\n\t%s", __FILE__, __LINE__, #EXPR);
+ log_inf("%s:%s:%d: Assertion passed!", __func__, __FILE__, __LINE__) : \
+ log_err("%s:%s:%d: Assertion failed:\n\t%s", __func__, __FILE__, __LINE__, #EXPR);
#define TEST_REPORT \
(TESTS_RUN == TESTS_PASSED) ? \
diff --git a/test/parser.c b/test/parser.c
index db296e6..2007e93 100644
--- a/test/parser.c
+++ b/test/parser.c
@@ -16,16 +16,52 @@ void test_simple_empty() {
/*
+ NULL
+
+ */
+
+ tree = 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);
+}
+
+void test_single_lint() {
+ tree_t* tree;
+ pp_t* pp;
+ lexer_t* lexer;
+ parser_t* parser;
+
+ char src[] = "1";
+
+ /*
+
[block]
val:
- NULL
+ [lint]
+ val:
+ 1
nxt:
NULL
*/
tree = tree_init(TREE_TYPE_BLOCK);
- tree->data.block.val = NULL;
+ tree->data.block.val = tree_init(TREE_TYPE_LINT);
+ tree->data.block.val->data.lint.val = 1;
tree->data.block.nxt = NULL;
pp = pp_init(src);
@@ -39,18 +75,20 @@ void test_simple_empty() {
ASSERT(tree_cmp(parser->tree, tree) == 1);
+ token_destroy(lexer->tokenl);
+ lexer_destroy(lexer);
pp_destroy(pp);
+ tree_destroy(parser->tree);
parser_destroy(parser);
- lexer_destroy(lexer);
}
-void test_single_lint() {
+void test_double_lint() {
tree_t* tree;
pp_t* pp;
lexer_t* lexer;
parser_t* parser;
- char src[] = "1";
+ char src[] = "1;1";
/*
@@ -60,14 +98,23 @@ void test_single_lint() {
val:
1
nxt:
- NULL
+ [block]
+ val:
+ [lint]
+ val:
+ 1
+ nxt:
+ NULL
*/
tree = tree_init(TREE_TYPE_BLOCK);
- tree->data.block.val = tree_init(TREE_TYPE_LINT);
- tree->data.block.val->data.lint.val = 1;
- tree->data.block.nxt = NULL;
+ tree_t* tree0lint = tree->data.block.val = tree_init(TREE_TYPE_LINT);
+ tree0lint->data.lint.val = 1;
+ tree_t* tree1block = tree->data.block.nxt = tree_init(TREE_TYPE_BLOCK);
+ tree_t* tree2lint = tree1block->data.block.val = tree_init(TREE_TYPE_LINT);
+ tree2lint->data.lint.val = 1;
+ tree1block->data.block.nxt = NULL;
pp = pp_init(src);
pp_run(pp);
@@ -90,6 +137,7 @@ void test_single_lint() {
int main(int argc, char** argv) {
test_simple_empty();
test_single_lint();
+ test_double_lint();
TEST_REPORT;