#include #include #include static void test_parser_ok(char const* oracle, char const* source) { err_t err; err_init(&err); err.quiet = 1; lexer_t lex; lexer_init(&lex, source, &err); parser_t parser; parser_init(&parser, &lex, &err); node_t* node = parser_try_new_tree(&parser); cr_assert(NULL != node, "error -> %s", source); size_t const SZ = 256; char msg[SZ]; node_str(node, msg, SZ); cr_assert_str_eq(msg, oracle); node_free(node); free(node); parser_free(&parser); lexer_free(&lex); err_free(&err); } static void test_parser_ko(char const* source) { err_t err; err_init(&err); err.quiet = 1; lexer_t lex; lexer_init(&lex, source, &err); parser_t parser; parser_init(&parser, &lex, &err); node_t* node = parser_try_new_tree(&parser); cr_assert(NULL == node); cr_assert_gt(err.total, 0); parser_free(&parser); lexer_free(&lex); err_free(&err); } Test(parser, num) { test_parser_ok("MOD", ""); test_parser_ok("MOD(NUM[37],NUM[29])", "37 29"); test_parser_ko(" ยง "); } Test(parser, bool) { test_parser_ok("MOD(BOOL[true],BOOL[false])", "true false"); } Test(parser, str) { test_parser_ok("MOD(STR[bim bam bum])", " \"bim bam bum\""); } Test(parser, assert) { test_parser_ok("MOD(ASSERT(BOOL[false]))", " assert false "); test_parser_ok("MOD(ASSERT(BOOL[true]))", " assert true "); } Test(parser, eqne) { test_parser_ok("MOD(EQ(NUM[3],NUM[3]))", " 3 == 3 "); test_parser_ok("MOD(NE(NUM[3],NUM[3]))", " 3 != 3 "); } Test(parser, cmp) { test_parser_ok("MOD(LT(NUM[3],NUM[3]))", " 3 < 3 "); test_parser_ok("MOD(LE(NUM[3],NUM[3]))", " 3 <= 3 "); test_parser_ok("MOD(GT(NUM[3],NUM[3]))", " 3 > 3 "); test_parser_ok("MOD(GE(NUM[3],NUM[3]))", " 3 >= 3 "); } Test(parser, num_arith) { test_parser_ok("MOD(ADD(NUM[1],MUL(NUM[2],NUM[3])))", " 1 + 2 * 3 "); test_parser_ok("MOD(MUL(ADD(NUM[1],NUM[2]),NUM[3]))", " (1 + 2) * 3 "); test_parser_ok("MOD(SUB(NUM[1],DIV(NUM[2],NUM[3])))", " 1 - 2 / 3 "); test_parser_ok("MOD(DIV(SUB(NUM[1],NUM[2]),NUM[3]))", " (1 - 2) / 3 "); test_parser_ok("MOD(POW(NUM[2],ADD(NUM[1],NUM[2])))", " 2^(1+2) "); } Test(parser, bool_arith) { test_parser_ok("MOD(OR(AND(BOOL[true],BOOL[false]),NOT(BOOL[true])))", " true and false or not true "); test_parser_ok("MOD(ASSERT(AND(BOOL[true],BOOL[false])))", " assert (true and false) "); } Test(parser, var_decl) { test_parser_ok("MOD(VARDECL(IDENT[x],NUM[33]))", " let x = 33 "); test_parser_ok("MOD(VARDECL(IDENT[bim],MUL(NUM[3],NUM[6])))", " let bim = 3 * 6 "); } Test(parser, var_set) { test_parser_ok("MOD(VARSET(IDENT[y],BOOL[true]))", " y = true "); } Test(parser, block) { test_parser_ok("MOD(SCOPE(BLOCK))", " begin end "); test_parser_ok("MOD(SCOPE(BLOCK(ADD(NUM[1],NUM[2]))))", " begin 1 + 2 end "); test_parser_ok("MOD(SCOPE(BLOCK(VARSET(IDENT[y],BOOL[true])" ",VARSET(IDENT[z],BOOL[false]))))", " begin y = true z = false end "); } Test(parser, if_then_else) { test_parser_ok("MOD(IF(IDENT[x],BLOCK(IDENT[y])))", "if x then y end"); test_parser_ok("MOD(IF(IDENT[x],BLOCK(IDENT[y]),BLOCK(IDENT[z])))", "if x then y else z end"); test_parser_ok("MOD(IF(IDENT[x]," "BLOCK(IDENT[y])," "IF(IDENT[z],BLOCK(IDENT[u]),BLOCK(IDENT[v]))))", "if x then y else if z then u else v end"); } Test(parser, fun_decl) { test_parser_ok("MOD(FUNDECL(IDENT[f]," "PARAMS(IDENT[x])," "BLOCK(RETURN(IDENT[x]))))", "fun f(x) return x end"); test_parser_ok("MOD(FUNDECL(IDENT[f]," "PARAMS(IDENT[x],IDENT[y])," "BLOCK(RETURN(IDENT[x]))))", "fun f(x, y) return x end"); } Test(parser, fun_call) { test_parser_ok("MOD(FUNCALL(IDENT[hello],ARGS(" "NUM[1],BOOL[true],BOOL[false]" ")))", "hello(1, true, false)"); test_parser_ok("MOD(FUNCALL(IDENT[hello],ARGS(NUM[1])))", "hello(1)"); test_parser_ok("MOD(FUNCALL(IDENT[hello],ARGS))", "hello()"); test_parser_ok("MOD(ASSERT(EQ(FUNCALL(IDENT[hello],ARGS),NUM[1])))", "assert hello() == 1"); }