//-----------------------------------------------------------------------------
namespace {
+ //-------------------------------------------------------------------------
+ // Recognize Individual Operators
+ //-------------------------------------------------------------------------
TEST(Recognize_And_Ignore_Whitespace)
{
std::string input("foo \t\r\n foo");
TestLexerWithInput( input, expected );
}
+ //-------------------------------------------------------------------------
+ // Recognize Individual Operators
+ //-------------------------------------------------------------------------
TEST(Recognize_And_Ignore_Comments)
{
std::string input(
TestLexerWithInput( input, expected );
}
+ //-------------------------------------------------------------------------
+ // Recognize Individual Operators
+ //-------------------------------------------------------------------------
TEST(Recognize_Valid_IDs)
{
std::string input(
TestLexerWithInput( input, expected );
}
+ //-------------------------------------------------------------------------
+ // Test Number Recognition
+ //-------------------------------------------------------------------------
TEST(Recognize_Valid_Numbers)
{
std::string input(
TestLexerThrowsException( missing_exp );
}
+ //-------------------------------------------------------------------------
+ // Test Character Recognition
+ //-------------------------------------------------------------------------
TEST(Recognize_Valid_Characters)
{
std::string input(
TestLexerWithInput( input, expected );
}
+ //-------------------------------------------------------------------------
+ // Test String Recognition
+ //-------------------------------------------------------------------------
TEST(Recognize_Valid_Strings)
{
std::string input(
TestLexerWithInput( input, expected );
}
+ //-------------------------------------------------------------------------
+ // Test Symbol Recognition
+ //-------------------------------------------------------------------------
TEST(Recognize_Valid_Symbols)
{
std::string input(
TestLexerWithInput( input, expected );
}
- TEST(Recognize_Valid_Operators)
+ //-------------------------------------------------------------------------
+ // Test Individual Operators
+ //-------------------------------------------------------------------------
+ TEST(Recognize_Left_Bracket)
{
- std::string input(
- // Recognize single character operators
- "[ ] ( ) { } , + * / . % - "
- // Recognize multi character operators and similar single char ones
- "= == ! != < <= > >= | || && : := @ @="
- );
- eTokenTypes expected[] = {
- LBRACK, RBRACK, LPAR, RPAR, LBRACE, RBRACE, COMMA, ADD, MUL, DIV,
- MEMB, MACRO, SUB, ASSIGN, EQ, NOT, NE, LT, LTE, GT, GTE, PIPE, OR,
- AND, SEP, DEFN, MAP, IMPORT,
- (eTokenTypes)EOF
- };
+ std::string input("[");
+ eTokenTypes expected[] = { LBRACK, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Right_Bracket)
+ {
+ std::string input("]");
+ eTokenTypes expected[] = { RBRACK, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Left_Paren)
+ {
+ std::string input("(");
+ eTokenTypes expected[] = { LPAR, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Right_Paren)
+ {
+ std::string input(")");
+ eTokenTypes expected[] = { RPAR, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Left_Brace)
+ {
+ std::string input("{");
+ eTokenTypes expected[] = { LBRACE, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Right_Brace)
+ {
+ std::string input("}");
+ eTokenTypes expected[] = { RBRACE, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Comma)
+ {
+ std::string input(",");
+ eTokenTypes expected[] = { COMMA, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Addition_Op)
+ {
+ std::string input("+");
+ eTokenTypes expected[] = { ADD, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Multiplication_Op)
+ {
+ std::string input("*");
+ eTokenTypes expected[] = { MUL, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Division_Op)
+ {
+ std::string input("/");
+ eTokenTypes expected[] = { DIV, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Member_Accessor_Op)
+ {
+ std::string input(".");
+ eTokenTypes expected[] = { MEMB, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Macro_Op)
+ {
+ std::string input("%");
+ eTokenTypes expected[] = { MACRO, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Subtraction_Op)
+ {
+ std::string input("-");
+ eTokenTypes expected[] = { SUB, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Assignment_Op)
+ {
+ std::string input("=");
+ eTokenTypes expected[] = { ASSIGN, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Equal_Comparison_Op)
+ {
+ std::string input("==");
+ eTokenTypes expected[] = { EQ, (eTokenTypes)EOF };
TestLexerWithInput( input, expected );
}
+ TEST(Recognize_Not_Op)
+ {
+ std::string input("!");
+ eTokenTypes expected[] = { NOT, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Not_Equal_Op)
+ {
+ std::string input("!=");
+ eTokenTypes expected[] = { NE, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Less_Than_Op)
+ {
+ std::string input("<");
+ eTokenTypes expected[] = { LT, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Less_Than_Equal_Op)
+ {
+ std::string input("<=");
+ eTokenTypes expected[] = { LTE, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Greater_Than_Op)
+ {
+ std::string input(">");
+ eTokenTypes expected[] = { GT, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Greater_Than_Or_Equal_Op)
+ {
+ std::string input(">=");
+ eTokenTypes expected[] = { GTE, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Pipe)
+ {
+ std::string input("|");
+ eTokenTypes expected[] = { PIPE, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Or_Op)
+ {
+ std::string input("||");
+ eTokenTypes expected[] = { OR, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_And_Op)
+ {
+ std::string input("&&");
+ eTokenTypes expected[] = { AND, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Seperator)
+ {
+ std::string input(":");
+ eTokenTypes expected[] = { SEP, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Definition_Op)
+ {
+ std::string input(":=");
+ eTokenTypes expected[] = { DEFN, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Map_Op)
+ {
+ std::string input("@");
+ eTokenTypes expected[] = { MAP, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Recognize_Import_Op)
+ {
+ std::string input("@=");
+ eTokenTypes expected[] = { IMPORT, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ //-------------------------------------------------------------------------
+ // Test Exceptional Cases
+ //-------------------------------------------------------------------------
TEST(Throw_Exceptions_For_Exceptional_Cases)
{
- // Make sure invalud number literals throw exceptions where appropriate
+ // Make sure invalid number literals throw exceptions where appropriate
std::string num_exception1("1.0e-");
TestLexerThrowsException( num_exception1 );
std::string multi_op_exception1("&");
TestLexerThrowsException( multi_op_exception1 );
}
+
+ //-------------------------------------------------------------------------
+ // Test General Corner Cases
+ //-------------------------------------------------------------------------
+ TEST(Handle_An_Empty_Input_Stream)
+ {
+ std::string input("");
+ eTokenTypes expected[] = { (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
+ TEST(Handle_Recognition_At_The_End_Of_Input)
+ {
+ std::string input("[");
+ eTokenTypes expected[] = { LBRACK, (eTokenTypes)EOF };
+ TestLexerWithInput( input, expected );
+ }
+
}
--- /dev/null
+// Unit Test Framework Includes
+#include "UnitTest++.h"
+
+// Supporting Includes
+#include <sstream>
+#include "exception.h"
+#include "ivisitor.h"
+
+// File To Test
+#include "dlparser.h"
+
+using namespace UnitTest;
+
+//-----------------------------------------------------------------------------
+// Helper Functions
+//-----------------------------------------------------------------------------
+class TreeTester : public IVisitor {
+ public:
+ eTokenTypes* expected_types;
+ unsigned int cur_index;
+ TreeTester(eTokenTypes expected[]) : IVisitor(), expected_types(expected), cur_index(0) {}
+ private:
+ void afterChildren(AST* cur, int depth) {
+ CHECK_EQUAL( expected_types[ cur_index ], cur->type() );
+ cur_index = (expected_types[cur_index] == PROGRAM) ? cur_index : (cur_index + 1);
+ }
+
+ // Not Used Here
+ void beforeVisit(AST* cur, int depth) {}
+ void afterVisit(AST* cur, int depth) {}
+ void beforeChildren(AST* cur, int depth) {}
+ void beforeChild(AST* cur, int depth) {}
+ void afterChild(AST* cur, int depth) {}
+};
+
+
+
+//-----------------------------------------------------------------------------
+// Helper Functions
+//-----------------------------------------------------------------------------
+void TestParserWithInput(std::string& input, eTokenTypes expected_types[])
+{
+ // Setup
+ std::istringstream input_stream(input);
+ DLParser parser;
+ TreeTester tester(expected_types);
+
+ // Parse the test input
+ parser.input( new DLLexer( input_stream ) );
+ parser.parse();
+
+ // Test the tree against expected format
+ parser.process( tester );
+}
+
+//void TestParserThrowsException(std::string& input)
+//{
+// // Setup
+// //std::istringstream input_stream(input);
+// //DLLexer* lexer = new DLLexer(input_stream);
+//
+// //CHECK_THROW( lexer->next(), Exception );
+//
+// // Cleanup
+// //delete lexer;
+//}
+
+//-----------------------------------------------------------------------------
+// Begin Unit Tests
+//-----------------------------------------------------------------------------
+namespace {
+
+ //-------------------------------------------------------------------------
+ // Test Parsing of Data Type Literals
+ //-------------------------------------------------------------------------
+
+ // Vector Literals
+ //----------------
+ TEST(Parse_An_Empty_Vector)
+ {
+ std::string input("[]");
+ eTokenTypes expected[] = {
+ VECTOR,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_An_Vector_With_One_Item)
+ {
+ std::string input("[1]");
+ eTokenTypes expected[] = {
+ NUM, VECTOR,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Vector_Of_Two_Items)
+ {
+ std::string input("[1,2]");
+ eTokenTypes expected[] = {
+ NUM, NUM, VECTOR,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Vector_Of_Three_Items)
+ {
+ std::string input("[1,2,3]");
+ eTokenTypes expected[] = {
+ NUM, NUM, NUM, VECTOR,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Vector_With_Trailing_Commas)
+ {
+ std::string input("[1,]");
+ eTokenTypes expected[] = {
+ NUM, VECTOR,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // List Literals
+ //--------------
+ TEST(Parse_A_List)
+ {
+ std::string input("()");
+ eTokenTypes expected[] = {
+ LIST,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_An_List_With_One_Item)
+ {
+ std::string input("(1,)"); // Comma is required here
+ eTokenTypes expected[] = {
+ NUM, LIST,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_List_Of_Two_Items)
+ {
+ std::string input("(1,2)");
+ eTokenTypes expected[] = {
+ NUM, NUM, LIST,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_List_Of_Three_Items)
+ {
+ std::string input("(1,2,3)");
+ eTokenTypes expected[] = {
+ NUM, NUM, NUM, LIST,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_List_With_Trailing_Commas)
+ {
+ std::string input("(1,)");
+ eTokenTypes expected[] = {
+ NUM, LIST,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_List_With_Heterogeneous_Elements)
+ {
+ std::string input("(1,$foo,bar)");
+ eTokenTypes expected[] = {
+ NUM, SYMBOL, ID, LIST,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // Block Literals
+ //---------------
+ TEST(Parse_A_Block_With_No_Parameters)
+ {
+ std::string input("{}");
+ eTokenTypes expected[] = {
+ PARAMS, BLOCK, FUNC,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Block_With_One_Param)
+ {
+ std::string input("{|a|}");
+ eTokenTypes expected[] = {
+ ID, PARAMS, BLOCK, FUNC,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Block_With_Two_Params)
+ {
+ std::string input("{|a,b|}");
+ eTokenTypes expected[] = {
+ ID, ID, PARAMS, BLOCK, FUNC,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Block_With_Two_Params_That_Performs_An_Addition_Operation)
+ {
+ std::string input("{|a,b| a + b}");
+ eTokenTypes expected[] = {
+ ID, ID, PARAMS, ID, ID, ADD, BLOCK, FUNC,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // Map Literals
+ //-------------
+ TEST(Parse_An_Empty_Map)
+ {
+ std::string input("@{}");
+ eTokenTypes expected[] = {
+ MAP,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Map_With_One_Entry)
+ {
+ std::string input("@{ $foo : 42 }");
+ eTokenTypes expected[] = {
+ SYMBOL, NUM, SEP, MAP,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Map_With_Two_Entries)
+ {
+ std::string input("@{ $foo : 42, $bar : 42 }");
+ eTokenTypes expected[] = {
+ SYMBOL, NUM, SEP, SYMBOL, NUM, SEP, MAP,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Maps_Should_Allow_A_Trailing_Comma)
+ {
+ std::string input("@{ $foo : 42, $bar : 42, }");
+ eTokenTypes expected[] = {
+ SYMBOL, NUM, SEP, SYMBOL, NUM, SEP, MAP,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // Id Literals
+ //------------
+ TEST(Parse_An_Id)
+ {
+ std::string input("foo");
+ eTokenTypes expected[] = {
+ ID,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // Number Literals
+ //----------------
+ TEST(Parse_A_Num)
+ {
+ std::string input("42");
+ eTokenTypes expected[] = {
+ NUM,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // Character Literals
+ //-------------------
+ TEST(Parse_A_Char)
+ {
+ std::string input("'a'");
+ eTokenTypes expected[] = {
+ CHAR,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // String Literals
+ //----------------
+ TEST(Parse_A_String)
+ {
+ std::string input("\"\"");
+ eTokenTypes expected[] = {
+ STRING,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // Symbol Literals
+ //----------------
+ TEST(Parse_A_Symbol)
+ {
+ std::string input("$foo");
+ eTokenTypes expected[] = {
+ SYMBOL,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ //-------------------------------------------------------------------------
+ // Test Operators And Operator Precedence
+ //-------------------------------------------------------------------------
+
+ // Member Accessor
+ //----------------
+ TEST(Parse_A_Member_Acces_One_Level_Deep)
+ {
+ std::string input("foo.bar");
+ eTokenTypes expected[] = {
+ ID, ID, MEMB,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ TEST(Parse_A_Member_Acces_Two_Levels_Deep)
+ {
+ std::string input("foo.bar.somethin");
+ eTokenTypes expected[] = {
+ ID, ID, ID, MEMB, MEMB,
+ PROGRAM
+ };
+ TestParserWithInput( input, expected );
+ }
+
+ // Grouping Expression
+ //--------------------
+ //TEST(Parse_A_Grouping_Expression_With_A_Lower_Priority_Statement)
+ //{
+ // std::string input("(foo.bar).somethin");
+ // eTokenTypes expected[] = {
+ // ID, ID, MEMB, ID, MEMB,
+ // PROGRAM
+ // };
+ // TestParserWithInput( input, expected );
+ //}
+
+ //TEST(Parse_A_Grouping_Expression_With_A_Higher_Priority_Statement)
+ //{
+ // std::string input("(1+1).somethin");
+ // eTokenTypes expected[] = {
+ // NUM, NUM, ADD, ID, MEMB,
+ // PROGRAM
+ // };
+ // TestParserWithInput( input, expected );
+ //}
+
+ // Function Application
+ //---------------------
+
+ // Collection Access
+ //------------------
+
+ //-------------------------------------------------------------------------
+ // Test General Corner Cases
+ //-------------------------------------------------------------------------
+ TEST(Parse_An_Empty_Program)
+ {
+ std::string input("");
+ eTokenTypes expected[] = { PROGRAM };
+ TestParserWithInput( input, expected );
+ }
+}