From: Mike D. Lowis Date: Sun, 17 Jun 2012 22:36:53 +0000 (-0400) Subject: Finished tests for DLParser X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=ad823028690a06a6dd4932acb8130ae87ec7d1bb;p=archive%2Fdlang.git Finished tests for DLParser --- diff --git a/tests/test_dlparser.cpp b/tests/test_dlparser.cpp index a8d3ca7..a179c09 100644 --- a/tests/test_dlparser.cpp +++ b/tests/test_dlparser.cpp @@ -16,6 +16,22 @@ using namespace UnitTest; //----------------------------------------------------------------------------- // Helper Functions //----------------------------------------------------------------------------- + +#define PROGRAM(num, ...) new AST(PROGRAM, "", num, __VA_ARGS__) +#define DEFINE(a,b) new AST(DEFINE,"", 2, a, b) +#define ASSIGN(a,b) new AST(ASSIGN,"", 2, a, b) +#define BEGIN(num, ...) new AST(BEGIN, "", num, __VA_ARGS__) +#define IF(num, ...) new AST(IF,"", num, __VA_ARGS__) +#define LAMBDA(num, ...) new AST(LAMBDA,"", num, __VA_ARGS__) +#define MACRO(num, ...) new AST(MACRO,"", num, __VA_ARGS__) +#define LIST(num, ...) new AST(LIST,"", num, __VA_ARGS__) +#define APPLY(a,b) new AST(APPLY, "", 2, a, b) +#define ID(text) new AST(ID,text) +#define NUM(text) new AST(NUM,text) +#define CHAR(text) new AST(CHAR,text) +#define STRING(text) new AST(STRING,text) +#define SYMBOL(text) new AST(SYMBOL,text) + #define CHECK_AST(left,right) CheckASTsForEquality( left, right, __LINE__ ) void CheckASTsForEquality(AST* left, AST* right, int line) { @@ -50,9 +66,18 @@ namespace { //------------------------------------------------------------------------- TEST(Verify_isSyntaxName_recognizes_a_registered_syntax) { - DLParser parser; + class TestDLParser : public DLParser + { + public: + using DLParser::syntaxes; + }; + std::string syn_name ("foobar"); + Syntax* syntax = new Syntax(); + TestDLParser parser; std::istringstream input("foobar"); parser.input(new DLLexer(input)); + syntax->name( syn_name ); + parser.syntaxes[ syntax->name() ] = syntax; CHECK( true == parser.isSyntaxName() ); } @@ -211,7 +236,391 @@ namespace { DLParser parser; std::istringstream input("foobar"); parser.input(new DLLexer(input)); - //CHECK( false == parser.getCoreFormId() ); - CHECK( false ); + CHECK( UNKNOWN == parser.getCoreFormId() ); + } + + //------------------------------------------------------------------------- + // Test parse + //------------------------------------------------------------------------- + TEST(Verify_parse_calls_Program_subrule) + { + DLParser parser; + AST* result = NULL; + AST* expected = PROGRAM( 1, NUM("+5") ); + std::istringstream input("5"); + parser.input(new DLLexer(input)); + parser.parse(); + result = parser.ast()->clone(); + CHECK_AST( result, expected ); + } + + //------------------------------------------------------------------------- + // Test Program + //------------------------------------------------------------------------- + TEST(Verify_Program_can_parse_a_group_of_expressions) + { + DLParser parser; + AST* result = NULL; + AST* expected = PROGRAM( 2, NUM("+5"), NUM("+5") ); + std::istringstream input("5 5"); + parser.input(new DLLexer(input)); + parser.parse(); + result = parser.ast()->clone(); + CHECK_AST( result, expected ); + } + + //------------------------------------------------------------------------- + // Test Expression + //------------------------------------------------------------------------- + TEST(Verify_Expression_parses_a_core_form) + { + DLParser parser; + AST* result = NULL; + AST* expected = DEFINE( ID("foo"), NUM("+5") ); + std::istringstream input("def foo 5"); + parser.input(new DLLexer(input)); + result = parser.CoreForm(); + CHECK_AST( result, expected ); + } + + TEST(Verify_Expression_parses_a_basic_expression) + { + DLParser parser; + AST* result = NULL; + AST* expected = ID("foo"); + std::istringstream input("foo"); + parser.input(new DLLexer(input)); + result = parser.Expression(); + CHECK_AST( result, expected ); + } + + TEST(Verify_Expression_parses_a_traditional_function_call) + { + DLParser parser; + AST* result = NULL; + AST* expected = APPLY( + ID("foo"), + LIST( 2, + NUM("+5"), + NUM("+5") )); + std::istringstream input("foo(5 5)"); + parser.input(new DLLexer(input)); + result = parser.Expression(); + CHECK_AST( result, expected ); + } + + //------------------------------------------------------------------------- + // Test CoreForm + //------------------------------------------------------------------------- + TEST(Verify_CoreForm_parses_def_expression) + { + DLParser parser; + AST* result = NULL; + AST* expected = DEFINE( ID("foo"), NUM("+5") ); + std::istringstream input("def foo 5"); + parser.input(new DLLexer(input)); + result = parser.CoreForm(); + CHECK_AST( result, expected ); + } + + TEST(Verify_CoreForm_parses_set_expression) + { + DLParser parser; + AST* result = NULL; + AST* expected = ASSIGN( ID("foo"), NUM("+5") ); + std::istringstream input("set foo 5"); + parser.input(new DLLexer(input)); + result = parser.CoreForm(); + CHECK_AST( result, expected ); + } + + TEST(Verify_CoreForm_parses_begin_expression) + { + DLParser parser; + AST* result = NULL; + AST* expected = BEGIN( 1, + LIST( 1, + APPLY( + ID("+"), + LIST( 2, + NUM("+1"), + NUM("+1") )))); + std::istringstream input("begin (1 + 1) end"); + parser.input(new DLLexer(input)); + result = parser.CoreForm(); + CHECK_AST( result, expected ); + } + + TEST(Verify_CoreForm_parses_if_expression_with_no_else) + { + DLParser parser; + AST* result = NULL; + AST* expected = IF( 2, NUM("+1"), NUM("+2") ); + std::istringstream input("if 1 2 end"); + parser.input(new DLLexer(input)); + result = parser.CoreForm(); + CHECK_AST( result, expected ); + } + + TEST(Verify_CoreForm_parses_if_expression_with_else) + { + DLParser parser; + AST* result = NULL; + AST* expected = IF( 3, NUM("+1"), NUM("+2"), NUM("+3")); + std::istringstream input("if 1 2 3 end"); + parser.input(new DLLexer(input)); + result = parser.CoreForm(); + CHECK_AST( result, expected ); + } + + TEST(Verify_CoreForm_parses_function_expression) + { + DLParser parser; + AST* result = NULL; + AST* expected = LAMBDA( 2, + LIST( 1, + ID("a" )), + LIST( 1, + APPLY( + ID( "+" ), + LIST( 2, + ID( "a" ), + NUM( "+1" ) )))); + std::istringstream input("func(a) (a + 1) end"); + parser.input(new DLLexer(input)); + result = parser.CoreForm(); + CHECK_AST( result, expected ); + } + + TEST(Verify_CoreForm_parses_macro_expression) + { + DLParser parser; + AST* result = NULL; + AST* expected = MACRO( 2, + LIST( 1, + ID("a" )), + LIST( 1, + APPLY( + ID( "+" ), + LIST( 2, + ID( "a" ), + NUM( "+1" ) )))); + std::istringstream input("macro(a) (a + 1) end"); + parser.input(new DLLexer(input)); + result = parser.CoreForm(); + CHECK_AST( result, expected ); + } + + TEST(Verify_CoreForm_throws_exception_for_unknown_form) + { + DLParser parser; + std::istringstream input("foo"); + parser.input(new DLLexer(input)); + CHECK_THROW( parser.CoreForm(), Exception ); + } + + //------------------------------------------------------------------------- + // Test BasicExp + //------------------------------------------------------------------------- + TEST(Verify_BasicExp_recognizes_an_infix_function_application) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( APPLY, "", 2, + new AST( ID, "+" ), + new AST( LIST, "", 2, + new AST( NUM, "+1" ), + new AST( NUM, "+2" ) )); + std::istringstream input("(1 + 2)"); + parser.input(new DLLexer(input)); + result = parser.BasicExp(); + CHECK_AST( result, expected ); + } + + TEST(Verify_BasicExp_recognizes_a_literal) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( ID, "foo" ); + std::istringstream input("foo"); + parser.input(new DLLexer(input)); + result = parser.BasicExp(); + CHECK_AST( result, expected ); + } + + //------------------------------------------------------------------------- + // Test Literal + //------------------------------------------------------------------------- + TEST(Verify_Literal_parses_an_id) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( ID, "foo" ); + std::istringstream input("foo"); + parser.input(new DLLexer(input)); + result = parser.Literal(); + CHECK_AST( result, expected ); + } + + TEST(Verify_Literal_parses_a_char) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( CHAR, "a" ); + std::istringstream input("'a'"); + parser.input(new DLLexer(input)); + result = parser.Literal(); + CHECK_AST( result, expected ); + } + + TEST(Verify_Literal_parses_a_string) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( STRING, "" ); + std::istringstream input("\"\""); + parser.input(new DLLexer(input)); + result = parser.Literal(); + CHECK_AST( result, expected ); + } + + TEST(Verify_Literal_parses_a_symbol) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( SYMBOL, "foo" ); + std::istringstream input("$foo"); + parser.input(new DLLexer(input)); + result = parser.Literal(); + CHECK_AST( result, expected ); + } + + TEST(Verify_Literal_parses_a_num) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( NUM, "+5" ); + std::istringstream input("5"); + parser.input(new DLLexer(input)); + result = parser.Literal(); + CHECK_AST( result, expected ); + } + + TEST(Verify_Literal_throws_exception_if_no_literal_found) + { + DLParser parser; + std::istringstream input("("); + parser.input(new DLLexer(input)); + CHECK_THROW( parser.Literal(), Exception ); + } + + //------------------------------------------------------------------------- + // Test ExpList + //------------------------------------------------------------------------- + TEST(Verify_ExpList_parses_an_empty_exp_list) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( LIST, "" ); + std::istringstream input("end"); + parser.input(new DLLexer(input)); + result = parser.ExpList(TERM); + CHECK_AST( result, expected ); + } + + TEST(Verify_ExpList_parses_an_exp_list_with_1_item) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( LIST, "", 1, + new AST(NUM, "+5") ); + std::istringstream input("5 end"); + parser.input(new DLLexer(input)); + result = parser.ExpList(TERM); + CHECK_AST( result, expected ); + } + + TEST(Verify_ExpList_parses_an_exp_list_with_2_items) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( LIST, "", 2, + new AST(NUM, "+5"), + new AST(NUM, "+5") ); + std::istringstream input("5 5 end"); + parser.input(new DLLexer(input)); + result = parser.ExpList(TERM); + CHECK_AST( result, expected ); + } + + TEST(Verify_ExpList_throws_an_exception_when_no_terminator_found) + { + DLParser parser; + std::istringstream input("a"); + parser.input(new DLLexer(input)); + CHECK_THROW( parser.ExpList(TERM), Exception ); + } + + //------------------------------------------------------------------------- + // Test IdList + //------------------------------------------------------------------------- + TEST(Verify_IdList_parses_an_empty_list) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( LIST, "" ); + std::istringstream input("()"); + parser.input(new DLLexer(input)); + result = parser.IdList(); + CHECK_AST( result, expected ); + } + + TEST(Verify_IdList_parses_a_list_with_one_id) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( LIST, "", 1, + new AST(ID,"a") ); + std::istringstream input("(a)"); + parser.input(new DLLexer(input)); + result = parser.IdList(); + CHECK_AST( result, expected ); + } + + TEST(Verify_IdList_parses_a_list_with_two_ids) + { + DLParser parser; + AST* result = NULL; + AST* expected = new AST( LIST, "", 2, + new AST(ID,"a"), + new AST(ID,"b") ); + std::istringstream input("(a b)"); + parser.input(new DLLexer(input)); + result = parser.IdList(); + CHECK_AST( result, expected ); + } + + TEST(Verify_IdList_throws_exception_on_missing_left_paren) + { + DLParser parser; + std::istringstream input("a b)"); + parser.input(new DLLexer(input)); + CHECK_THROW( parser.IdList(), Exception ); + } + + TEST(Verify_IdList_throws_exception_on_missing_right_paren) + { + DLParser parser; + std::istringstream input("(a b"); + parser.input(new DLLexer(input)); + CHECK_THROW( parser.IdList(), Exception ); + } + + TEST(Verify_IdList_throws_exception_when_list_contains_non_id) + { + DLParser parser; + std::istringstream input("(a 5)"); + parser.input(new DLLexer(input)); + CHECK_THROW( parser.IdList(), Exception ); } }