#include #include #include #include #include typedef scc_ast_node_t *(*scc_parse_node_func)(scc_parser_t *parser); static scc_ast_node_t *process_input(const char *input, scc_parse_node_func parse_func, cbool need_sema) { int res = 0; scc_sstream_t mem_stream; res = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, 16); Assert(res == 0); scc_lexer_t lexer; scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream)); scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false); scc_parser_t parser; if (need_sema) { scc_sema_callbacks_t sema_callbacks; scc_sema_init(&sema_callbacks); scc_parser_init(&parser, tok_ring, &sema_callbacks); } else { scc_parser_init(&parser, tok_ring, null); } scc_ast_node_t *ret = parse_func(&parser); cbool not_eof = false; scc_ring_not_eof(*parser.ring, not_eof); if (not_eof == true) { // FIXME MAYBE free LOG_FATAL("Didn't consume all tokens"); return null; } scc_lexer_drop_ring(parser.ring); scc_parser_drop(&parser); scc_lexer_drop(&lexer); scc_sstream_drop(&mem_stream); return ret; } typedef void (*scc_tree_dump_output_t)(void *userdata, const char *fmt, ...); #define BUFFER_SIZE (4096) char expect_buffer[BUFFER_SIZE]; char output_buffer[BUFFER_SIZE]; static void dump2buffer(void *_buffer, const char *fmt, ...) { char *buffer = _buffer; va_list args; va_start(args, fmt); int res = scc_vsnprintf(buffer + strlen(buffer), BUFFER_SIZE - strlen(buffer) - 1, fmt, args); Assert(res > 0); va_end(args); } static void _scc_check_ast(scc_ast_node_t *expect_node_ptr, const char *str, scc_parse_node_func parse_func, cbool need_sema) { scc_ast_node_t *output_node_ptr = process_input(str, parse_func, need_sema); scc_tree_dump_ctx_t ctx; expect_buffer[0] = '\n', expect_buffer[1] = '\0'; scc_tree_dump_ctx_init(&ctx, true, dump2buffer, expect_buffer); scc_ast_dump_node(&ctx, expect_node_ptr); scc_tree_dump_ctx_drop(&ctx); output_buffer[0] = '\n', output_buffer[1] = '\0'; scc_tree_dump_ctx_init(&ctx, true, dump2buffer, output_buffer); scc_ast_dump_node(&ctx, output_node_ptr); scc_tree_dump_ctx_drop(&ctx); } #define SCC_CHECK_AST_WITH_SEMA(expect_node_ptr, str, parse_func) \ do { \ _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \ true); \ TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ TEST_MSG("Expected: %s", expect_buffer); \ TEST_MSG("Produced: %s", output_buffer); \ } while (0); #define SCC_CHECK_AST(expect_node_ptr, str, parse_func) \ do { \ _scc_check_ast(expect_node_ptr, str, (scc_parse_node_func)parse_func, \ false); \ TEST_CHECK(strcmp(output_buffer, expect_buffer) == 0); \ TEST_MSG("Expected: %s", expect_buffer); \ TEST_MSG("Produced: %s", output_buffer); \ } while (0);