#include "commons.h" #include #include #include static void test_parser(char const* oracle, char const* source) { struct parser parser; parser_init(&parser); struct node* ast = parser_try_new_root(&parser, source); cr_assert_neq(NULL, ast, "%s", parser.error_msg); { char buf[GUX_STR_SIZE]; node_str(ast, buf, GUX_STR_SIZE); cr_assert_str_eq(oracle, buf); } parser_free(&parser); } static void test_parser_fail(char const* source) { struct parser parser; parser_init(&parser); struct node* ast = parser_try_new_root(&parser, source); if (ast) { char msg[GUX_STR_SIZE]; node_str(ast, msg, GUX_STR_SIZE); cr_assert_eq(NULL, ast, "ast = %s", msg); } cr_assert_eq(NULL, ast); } Test(parser, boolean) { test_parser_fail("true"); test_parser_fail(";"); test_parser("ROOT(BOOL[true])", "true;"); } Test(parser, assert) { test_parser("ROOT(ASSERT(BOOL[false]))", "assert false;"); test_parser_fail("assert;"); } Test(parser, bool_arith) { test_parser("ROOT(NOT(NOT(BOOL[true])))", "!!true;"); test_parser("ROOT(OR(OR(BOOL[true],BOOL[false]),BOOL[false]))", "true || false || false;"); test_parser("ROOT(OR(AND(BOOL[true],BOOL[false]),BOOL[true]))", "true && false || true;"); test_parser("ROOT(AND(BOOL[true],OR(BOOL[false],BOOL[true])))", "true && (false || true);"); test_parser("ROOT(OR(AND(BOOL[true],NOT(BOOL[false])),BOOL[true]))", "true && !false || true;"); } Test(parser, eqne) { test_parser("ROOT(EQ(BOOL[true],BOOL[false]))", "true == false;"); test_parser("ROOT(NE(BOOL[true],BOOL[false]))", "true != false;"); } Test(parser, num) { test_parser("ROOT(EQ(INT[3],INT[-7]))", "3 == -7;"); test_parser("ROOT(NE(FLOAT[2.9],FLOAT[-3.]))", "2.9 != -3.;"); test_parser("ROOT(NE(STRING[bim],STRING[bam]))", "'bim' != 'bam';"); } Test(parser, arithmetic) { test_parser("ROOT(ADD(INT[1],MUL(INT[2],INT[3])))", "1 + 2 * 3;"); test_parser("ROOT(MUL(ADD(INT[1],INT[2]),INT[3]))", "(1 + 2) * 3;"); test_parser("ROOT(SUB(INT[1],DIV(INT[2],INT[3])))", "1 - 2 / 3;"); test_parser("ROOT(DIV(SUB(INT[1],INT[2]),INT[3]))", "(1 - 2) / 3;"); } Test(parser, cmp) { test_parser("ROOT(LT(ADD(INT[1],INT[1]),INT[3]))", "1 + 1 < 3;"); test_parser("ROOT(AND(LE(INT[0],INT[2]),GE(FLOAT[5.0],FLOAT[1.0])))", "0 <= 2 && 5.0 >= 1.0;"); } Test(parser, vardecl) { test_parser("ROOT(CONSTDECL[x](INT[3]))", "x := 3;"); test_parser("ROOT(CONSTDECL[x](TYPE[string],STRING[bim]))", "x : string = 'bim';"); test_parser("ROOT(VARDECL[x](INT[3]))", "var x := 3;"); test_parser("ROOT(VARDECL[x](TYPE[string],STRING[bim]))", "var x : string = 'bim';"); } Test(parser, assign) { test_parser("ROOT(ASSIGN(IDENT[x],INT[45]))", "x = 45;"); } Test(parser, block) { test_parser("ROOT(BLOCK(ASSIGN(IDENT[x],INT[2]),ADD(INT[1],INT[1])))", "{ x = 2; 1 + 1;}"); } Test(parser, if_block) { test_parser("ROOT(IF(IDENT[a],BLOCK(INT[0])))", "if a { 0; }"); test_parser("ROOT(IF(IDENT[a],BLOCK(INT[0]),BLOCK(INT[1])))", "if a { 0; } else { 1; }"); test_parser("ROOT(IF(IDENT[a],BLOCK(" "INT[0]" "),IF(IDENT[b],BLOCK(" "INT[1]" "),BLOCK(" "INT[2]" "))))", "if a { 0; } else if b { 1; } else { 2; }"); } Test(parser, while_block) { test_parser("ROOT(WHILE(BOOL[true],BLOCK(INT[0])))", "while true { 0; }"); } Test(parser, while_break_continue) { test_parser("ROOT(WHILE(BOOL[true],BLOCK(BREAK,CONTINUE)))", "while true { break; continue; }"); }