| @@ -62,13 +62,136 @@ static void expecteq( | |||
| } | |||
| } | |||
| static void lexeq(BXVariables &vars, const char *str, std::initializer_list<BXParser::Token> list) { | |||
| INFO("Source: " << str); | |||
| bufio::ISStream stream(str); | |||
| BXParser parser(stream); | |||
| parser.readToken(vars); | |||
| size_t i = 1; | |||
| for (auto &expected: list) { | |||
| BXParser::Token tok = parser.readToken(vars); | |||
| if (tok.kind != expected.kind) { | |||
| INFO("Expected: " << (int)expected.kind); | |||
| INFO("Actual: " << (int)tok.kind); | |||
| FAIL("Token " << i << " doesn't match"); | |||
| } | |||
| if (tok.str != expected.str) { | |||
| INFO("Expected: '" << expected.str << '\''); | |||
| INFO("Actual: '" << tok.str << '\''); | |||
| FAIL("Token " << i << "'s string doesn't match"); | |||
| } | |||
| if (tok.kind == BXParser::TokenKind::E_O_F) { | |||
| return; | |||
| } | |||
| i += 1; | |||
| } | |||
| } | |||
| static void lexeq(const char *str, std::initializer_list<BXParser::Token> list) { | |||
| BXVariables vars; | |||
| lexeq(vars, str, list); | |||
| } | |||
| TEST_CASE("BXParser lex", "[BXParser][lex]") { | |||
| lexeq("hello world", { | |||
| { BXParser::TokenKind::STRING, "hello" }, | |||
| { BXParser::TokenKind::STRING, "world" }, | |||
| { BXParser::TokenKind::E_O_F }, | |||
| }); | |||
| lexeq("hello := what's up", { | |||
| { BXParser::TokenKind::STRING, "hello" }, | |||
| { BXParser::TokenKind::COLON_EQUALS }, | |||
| { BXParser::TokenKind::STRING, "what's" }, | |||
| { BXParser::TokenKind::STRING, "up" }, | |||
| { BXParser::TokenKind::E_O_F }, | |||
| }); | |||
| lexeq("\t\t \t, := += =+\n\n\r\nhello", { | |||
| { BXParser::TokenKind::INDENTATION }, | |||
| { BXParser::TokenKind::COMMA }, | |||
| { BXParser::TokenKind::COLON_EQUALS }, | |||
| { BXParser::TokenKind::PLUS_EQUALS }, | |||
| { BXParser::TokenKind::EQUALS_PLUS }, | |||
| { BXParser::TokenKind::NEWLINE }, | |||
| { BXParser::TokenKind::STRING, "hello" }, | |||
| { BXParser::TokenKind::E_O_F }, | |||
| }); | |||
| } | |||
| TEST_CASE("BXParser lex string interpolation", "[BXParser][lex]") { | |||
| BXVariables vars = { | |||
| { "foo", { "hello"} }, | |||
| }; | |||
| lexeq(vars, "hey \"$foo\" lol", { | |||
| { BXParser::TokenKind::STRING, "hey" }, | |||
| { BXParser::TokenKind::STRING, "hello" }, | |||
| { BXParser::TokenKind::STRING, "lol" }, | |||
| }); | |||
| lexeq(vars, "hey \"no$foo\" lol", { | |||
| { BXParser::TokenKind::STRING, "hey" }, | |||
| { BXParser::TokenKind::STRING, "nohello" }, | |||
| { BXParser::TokenKind::STRING, "lol" }, | |||
| }); | |||
| lexeq(vars, "hey \"Xx${foo}xX\" lol", { | |||
| { BXParser::TokenKind::STRING, "hey" }, | |||
| { BXParser::TokenKind::STRING, "XxhelloxX" }, | |||
| { BXParser::TokenKind::STRING, "lol" }, | |||
| }); | |||
| } | |||
| TEST_CASE("BXParser lex string interpolation without quotes", "[BXParser][lex]") { | |||
| BXVariables vars = { | |||
| { "foo", { "hello"} }, | |||
| }; | |||
| lexeq(vars, "hey Xx$foo lol", { | |||
| { BXParser::TokenKind::STRING, "hey" }, | |||
| { BXParser::TokenKind::STRING, "Xxhello" }, | |||
| { BXParser::TokenKind::STRING, "lol" }, | |||
| }); | |||
| lexeq(vars, "hey Xx${ foo }xX lol", { | |||
| { BXParser::TokenKind::STRING, "hey" }, | |||
| { BXParser::TokenKind::STRING, "XxhelloxX" }, | |||
| { BXParser::TokenKind::STRING, "lol" }, | |||
| }); | |||
| } | |||
| TEST_CASE("BXParser lex array expansion", "[BXParser][lex]") { | |||
| lexeq("hey $foo lol", { | |||
| { BXParser::TokenKind::STRING, "hey" }, | |||
| { BXParser::TokenKind::EXPANSION, "foo" }, | |||
| { BXParser::TokenKind::STRING, "lol" }, | |||
| }); | |||
| lexeq("hey ${foo} lol", { | |||
| { BXParser::TokenKind::STRING, "hey" }, | |||
| { BXParser::TokenKind::EXPANSION, "foo" }, | |||
| { BXParser::TokenKind::STRING, "lol" }, | |||
| }); | |||
| lexeq("hey ${ \tfoo\n \n} lol", { | |||
| { BXParser::TokenKind::STRING, "hey" }, | |||
| { BXParser::TokenKind::EXPANSION, "foo" }, | |||
| { BXParser::TokenKind::STRING, "lol" }, | |||
| }); | |||
| } | |||
| TEST_CASE("BXParser parsing", "[BXParser][parse]") { | |||
| expecteq("hello := 10 world := 20", { | |||
| expecteq("hello := 10, world := 20", { | |||
| { "hello", { "10" } }, | |||
| { "world", { "20" } }, | |||
| }); | |||
| expecteq("foo := hello world bar := 10 20 30 baz := 0", { | |||
| expecteq("foo := hello world, bar := 10 20 30, baz := 0", { | |||
| { "foo", { "hello", "world" } }, | |||
| { "bar", { "10", "20", "30" } }, | |||
| { "baz", { "0" } }, | |||
| @@ -76,27 +199,33 @@ TEST_CASE("BXParser parsing", "[BXParser][parse]") { | |||
| } | |||
| TEST_CASE("BXParser parsing variables", "[BXParser][parse]") { | |||
| expecteq("foo := \"hello world\" bar := $foo", { | |||
| expecteq("foo := \"hello world\", bar := $foo", { | |||
| { "foo", { "hello world" } }, | |||
| { "bar", { "hello world" } }, | |||
| }); | |||
| expecteq("foo := hello world bar := hey $foo what's up", { | |||
| expecteq("foo := hello world, bar := hey $foo what's up", { | |||
| { "foo", { "hello", "world" } }, | |||
| { "bar", { "hey", "hello", "world", "what's", "up" } }, | |||
| }); | |||
| } | |||
| TEST_CASE("BXParser append/prepend", "[BXParser][parse]") { | |||
| expecteq("foo := 10 foo += 20 foo += 30", { | |||
| expecteq("foo := 10, foo += 20, foo += 30", { | |||
| { "foo", { "10", "20", "30" } }, | |||
| }); | |||
| expecteq("foo := 10 foo =+ 20 foo =+ 30", { | |||
| expecteq("foo := 10, foo =+ 20, foo =+ 30", { | |||
| { "foo", { "30", "20", "10" } }, | |||
| }); | |||
| } | |||
| TEST_CASE("BXParser |=", "[BXParser][parse]") { | |||
| expecteq("foo := 10, foo |= 10, foo |= 20", { | |||
| { "foo", { "10", "20" } }, | |||
| }); | |||
| } | |||
| TEST_CASE("BXParser newline separation", "[BXParser][parse]") { | |||
| expecteq( | |||
| "foo := 10 20\n" | |||
| @@ -105,3 +234,14 @@ TEST_CASE("BXParser newline separation", "[BXParser][parse]") { | |||
| { "bar", { "30", "40" } }, | |||
| }); | |||
| } | |||
| TEST_CASE("BXParser newline continuation", "[BXParser][parse]") { | |||
| expecteq( | |||
| "foo := 10 20\n" | |||
| "\t30 40\n" | |||
| "bar := hello world\n" | |||
| "\tbaz \":=\" 30\n", { | |||
| { "foo", { "10", "20", "30", "40" } }, | |||
| { "bar", { "hello", "world", "baz", ":=", "30" } }, | |||
| }); | |||
| } | |||