#include #include #include #include #define a_new_(arena, typ, count) ((typ*)h_arena_malloc((arena), sizeof(typ)*(count))) namespace { using namespace ::hammer; TEST(ParserTypes, Token) { Parser p = Token("95\xA2"); EXPECT_TRUE(ParsesTo(p, "95\xA2", "<39.35.a2>")); EXPECT_TRUE(ParseFails(p, "95")); } TEST(ParserTypes, Ch) { Parser p = Ch(0xA2); EXPECT_TRUE(ParsesTo(p, "\xA2", "u0xa2")); EXPECT_TRUE(ParseFails(p, "\xA3")); } TEST(ParserTypes, ChRange) { Parser p = ChRange('a', 'c'); EXPECT_TRUE(ParsesTo(p, "b", "u0x62")); EXPECT_TRUE(ParseFails(p, "d")); } TEST(ParserTypes, Int64) { Parser p = Int64(); EXPECT_TRUE(ParsesTo(p, std::string("\xff\xff\xff\xfe\x00\x00\x00\x00", 8), "s-0x200000000")); EXPECT_TRUE(ParseFails(p, std::string("\xff\xff\xff\xfe\x00\x00\x00", 7))); } TEST(ParserTypes, Int32) { Parser p = Int32(); EXPECT_TRUE(ParsesTo(p, std::string("\xff\xfe\x00\x00", 4), "s-0x20000")); EXPECT_TRUE(ParseFails(p, std::string("\xff\xfe\x00", 3))); EXPECT_TRUE(ParsesTo(p, std::string("\x00\x02\x00\x00",4) ,"s0x20000")); EXPECT_TRUE(ParseFails(p, std::string("\x00\x02\x00", 3))); } TEST(ParserTypes, Int16) { Parser p = Int16(); EXPECT_TRUE(ParsesTo(p, std::string("\xfe\x00", 2), "s-0x200")); EXPECT_TRUE(ParseFails(p, "\xfe")); EXPECT_TRUE(ParsesTo(p, std::string("\x02\x00", 2), "s0x200")); EXPECT_TRUE(ParseFails(p, "\x01")); } TEST(ParserTypes, Int8) { Parser p = Int8(); EXPECT_TRUE(ParsesTo(p, "\x88", "s-0x78")); EXPECT_TRUE(ParseFails(p, "")); } TEST(ParserTypes, Uint64) { Parser p = Uint64(); EXPECT_TRUE(ParsesTo(p, std::string("\x00\x00\x00\x02\x00\x00\x00\x00", 8), "u0x200000000")); EXPECT_TRUE(ParseFails(p, std::string("\x00\x00\x00\x02\x00\x00\x00", 7))); } TEST(ParserTypes, Uint32) { Parser p = Uint32(); EXPECT_TRUE(ParsesTo(p, std::string("\x00\x02\x00\x00", 4), "u0x20000")); EXPECT_TRUE(ParseFails(p, std::string("\x00\x02\x00", 3))); } TEST(ParserTypes, Uint16) { Parser p = Uint16(); EXPECT_TRUE(ParsesTo(p, std::string("\x02\x00", 2), "u0x200")); EXPECT_TRUE(ParseFails(p, "\x02")); } TEST(ParserTypes, Uint8) { Parser p = Uint8(); EXPECT_TRUE(ParsesTo(p, "\x78", "u0x78")); EXPECT_TRUE(ParseFails(p, "")); } TEST(ParserTypes, IntRange) { Parser p = IntRange(Uint8(), 3, 10); EXPECT_TRUE(ParsesTo(p, "\x05", "u0x5")); EXPECT_TRUE(ParseFails(p, "\xb")); } TEST(ParserTypes, Whitespace) { Parser p = Whitespace(Ch('a')); Parser q = Whitespace(End()); EXPECT_TRUE(ParsesTo(p, "a", "u0x61")); EXPECT_TRUE(ParsesTo(p, " a", "u0x61")); EXPECT_TRUE(ParsesTo(p, " a", "u0x61")); EXPECT_TRUE(ParsesTo(p, "\ta", "u0x61")); EXPECT_TRUE(ParseFails(p, "_a")); EXPECT_TRUE(ParsesTo(q, "", "NULL")); EXPECT_TRUE(ParsesTo(q, " ", "NULL")); EXPECT_TRUE(ParseFails(p, " x")); } TEST(ParserTypes, Left) { Parser p = Left(Ch('a'), Ch(' ')); EXPECT_TRUE(ParsesTo(p, "a ", "u0x61")); EXPECT_TRUE(ParseFails(p, "a")); EXPECT_TRUE(ParseFails(p, " ")); EXPECT_TRUE(ParseFails(p, "ab")); } TEST(ParserTypes, Right) { Parser p = Right(Ch(' '), Ch('a')); EXPECT_TRUE(ParsesTo(p, " a", "u0x61")); EXPECT_TRUE(ParseFails(p, "a")); EXPECT_TRUE(ParseFails(p, " ")); EXPECT_TRUE(ParseFails(p, "ba")); } TEST(ParserTypes, Middle) { Parser p = Middle(Ch(' '), Ch('a'), Ch(' ')); EXPECT_TRUE(ParsesTo(p, " a ", "u0x61")); EXPECT_TRUE(ParseFails(p, "a")); EXPECT_TRUE(ParseFails(p, " ")); EXPECT_TRUE(ParseFails(p, " a")); EXPECT_TRUE(ParseFails(p, " b ")); EXPECT_TRUE(ParseFails(p, "ba ")); EXPECT_TRUE(ParseFails(p, " ab")); } #include HParsedToken* upcase(const HParseResult *p, void* user_data) { switch(p->ast->token_type) { case TT_SEQUENCE: { HParsedToken *ret = a_new_(p->arena, HParsedToken, 1); HCountedArray *seq = h_carray_new_sized(p->arena, p->ast->seq->used); ret->token_type = TT_SEQUENCE; for (size_t i=0; iast->seq->used; ++i) { if (TT_UINT == ((HParsedToken*)p->ast->seq->elements[i])->token_type) { HParsedToken *tmp = a_new_(p->arena, HParsedToken, 1); tmp->token_type = TT_UINT; tmp->uint = toupper(((HParsedToken*)p->ast->seq->elements[i])->uint); h_carray_append(seq, tmp); } else { h_carray_append(seq, p->ast->seq->elements[i]); } } ret->seq = seq; return ret; } case TT_UINT: { HParsedToken *ret = a_new_(p->arena, HParsedToken, 1); ret->token_type = TT_UINT; ret->uint = toupper(p->ast->uint); return ret; } default: return (HParsedToken*)p->ast; } } TEST(ParserTypes, Action) { Parser p = Action(Sequence(Choice(Ch('a'), Ch('A'), NULL), Choice(Ch('b'), Ch('B'), NULL), NULL), upcase); EXPECT_TRUE(ParsesTo(p, "ab", "(u0x41 u0x42)")); EXPECT_TRUE(ParsesTo(p, "AB", "(u0x41 u0x42)")); EXPECT_TRUE(ParseFails(p, "XX")); } TEST(ParserTypes, In) { Parser p = In("abc"); EXPECT_TRUE(ParsesTo(p, "b", "u0x62")); EXPECT_TRUE(ParseFails(p, "d")); } TEST(ParserTypes, NotIn) { Parser p = NotIn("abc"); EXPECT_TRUE(ParsesTo(p, "d", "u0x64")); EXPECT_TRUE(ParseFails(p, "a")); } TEST(ParserTypes, End) { Parser p = Sequence(Ch('a'), End(), NULL); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParseFails(p, "aa")); } TEST(ParserTypes, Nothing) { Parser p = Nothing(); EXPECT_TRUE(ParseFails(p, "a")); } TEST(ParserTypes, Sequence) { Parser p = Sequence(Ch('a'), Ch('b'), NULL); Parser q = Sequence(Ch('a'), Whitespace(Ch('b')), NULL); EXPECT_TRUE(ParsesTo(p, "ab", "(u0x61 u0x62)")); EXPECT_TRUE(ParseFails(p, "a")); EXPECT_TRUE(ParseFails(p, "b")); EXPECT_TRUE(ParsesTo(q, "ab", "(u0x61 u0x62)")); EXPECT_TRUE(ParsesTo(q, "a b", "(u0x61 u0x62)")); EXPECT_TRUE(ParsesTo(q, "a b", "(u0x61 u0x62)")); } TEST(ParserTypes, Choice) { Parser p = Choice(Ch('a'), Ch('b'), NULL); EXPECT_TRUE(ParsesTo(p, "a", "u0x61")); EXPECT_TRUE(ParsesTo(p, "b", "u0x62")); EXPECT_TRUE(ParseFails(p, "c")); } TEST(ParserTypes, ButNot) { Parser p = ButNot(Ch('a'), Token("ab")); Parser q = ButNot(ChRange('0', '9'), Ch('6')); EXPECT_TRUE(ParsesTo(p, "a", "u0x61")); EXPECT_TRUE(ParseFails(p, "ab")); EXPECT_TRUE(ParsesTo(p, "aa", "u0x61")); EXPECT_TRUE(ParseFails(q, "6")); } TEST(ParserTypes, Difference) { Parser p = Difference(Token("ab"), Ch('a')); EXPECT_TRUE(ParsesTo(p, "ab", "<61.62>")); EXPECT_TRUE(ParseFails(p, "a")); } TEST(ParserTypes, Xor) { Parser p = Xor(ChRange('0', '6'), ChRange('5', '9')); EXPECT_TRUE(ParsesTo(p, "0", "u0x30")); EXPECT_TRUE(ParsesTo(p, "9", "u0x39")); EXPECT_TRUE(ParseFails(p, "5")); EXPECT_TRUE(ParseFails(p, "a")); } TEST(ParserTypes, Many) { Parser p = Many(Choice(Ch('a'), Ch('b'), NULL)); EXPECT_TRUE(ParsesTo(p, "", "()")); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "b", "(u0x62)")); EXPECT_TRUE(ParsesTo(p, "aabbaba", "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)")); } TEST(ParserTypes, Many1) { Parser p = Many1(Choice(Ch('a'), Ch('b'), NULL)); EXPECT_TRUE(ParseFails(p, "")); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "b", "(u0x62)")); EXPECT_TRUE(ParsesTo(p, "aabbaba", "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)")); EXPECT_TRUE(ParseFails(p, "daabbabadef")); } TEST(ParserTypes, RepeatN) { Parser p = RepeatN(Choice(Ch('a'), Ch('b'), NULL), 2); EXPECT_TRUE(ParseFails(p, "adef")); EXPECT_TRUE(ParsesTo(p, "abdef", "(u0x61 u0x62)")); EXPECT_TRUE(ParseFails(p, "dabdef")); } TEST(ParserTypes, Optional) { Parser p = Sequence(Ch('a'), Optional(Choice(Ch('b'), Ch('c'), NULL)), Ch('d'), NULL); EXPECT_TRUE(ParsesTo(p, "abd", "(u0x61 u0x62 u0x64)")); EXPECT_TRUE(ParsesTo(p, "acd", "(u0x61 u0x63 u0x64)")); EXPECT_TRUE(ParsesTo(p, "ad", "(u0x61 null u0x64)")); EXPECT_TRUE(ParseFails(p, "aed")); EXPECT_TRUE(ParseFails(p, "ab")); EXPECT_TRUE(ParseFails(p, "ac")); } TEST(ParserTypes, Ignore) { Parser p = Sequence(Ch('a'), Ignore(Ch('b')), Ch('c'), NULL); EXPECT_TRUE(ParsesTo(p, "abc", "(u0x61 u0x63)")); EXPECT_TRUE(ParseFails(p, "ac")); } TEST(ParserTypes, SepBy) { Parser p = SepBy(Choice(Ch('1'), Ch('2'), Ch('3'), NULL), Ch(',')); EXPECT_TRUE(ParsesTo(p, "1,2,3", "(u0x31 u0x32 u0x33)")); EXPECT_TRUE(ParsesTo(p, "1,3,2", "(u0x31 u0x33 u0x32)")); EXPECT_TRUE(ParsesTo(p, "1,3", "(u0x31 u0x33)")); EXPECT_TRUE(ParsesTo(p, "3", "(u0x33)")); EXPECT_TRUE(ParsesTo(p, "", "()")); } TEST(ParserTypes, SepBy1) { Parser p = SepBy1(Choice(Ch('1'), Ch('2'), Ch('3'), NULL), Ch(',')); EXPECT_TRUE(ParsesTo(p, "1,2,3", "(u0x31 u0x32 u0x33)")); EXPECT_TRUE(ParsesTo(p, "1,3,2", "(u0x31 u0x33 u0x32)")); EXPECT_TRUE(ParsesTo(p, "1,3", "(u0x31 u0x33)")); EXPECT_TRUE(ParsesTo(p, "3", "(u0x33)")); EXPECT_TRUE(ParseFails(p, "")); } TEST(ParserTypes, EpsilonP) { Parser p = Sequence(Ch('a'), Epsilon(), Ch('b'), NULL); Parser q = Sequence(Epsilon(), Ch('a'), NULL); Parser r = Sequence(Ch('a'), Epsilon(), NULL); EXPECT_TRUE(ParsesTo(p, "ab", "(u0x61 u0x62)")); EXPECT_TRUE(ParsesTo(q, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(r, "a", "(u0x61)")); } bool validate_test_ab(HParseResult *p, void* user_data) { if (TT_SEQUENCE != p->ast->token_type) return false; if (TT_UINT != p->ast->seq->elements[0]->token_type) return false; if (TT_UINT != p->ast->seq->elements[1]->token_type) return false; return (p->ast->seq->elements[0]->uint == p->ast->seq->elements[1]->uint); } TEST(ParserTypes, AttrBool) { Parser p = AttrBool(Many1(Choice(Ch('a'), Ch('b'), NULL)), validate_test_ab, NULL); EXPECT_TRUE(ParsesTo(p, "aa", "(u0x61 u0x61)")); EXPECT_TRUE(ParsesTo(p, "bb", "(u0x62 u0x62)")); EXPECT_TRUE(ParseFails(p, "ab")); } TEST(ParserTypes, And) { Parser p = Sequence(And(Ch('0')), Ch('0'), NULL); Parser q = Sequence(And(Ch('0')), Ch('1'), NULL); Parser r = Sequence(Ch('1'), And(Ch('2')), NULL); EXPECT_TRUE(ParsesTo(p, "0", "(u0x30)")); EXPECT_TRUE(ParseFails(q, "0")); EXPECT_TRUE(ParsesTo(r, "12", "(u0x31)")); } TEST(ParserTypes, Not) { Parser p = Sequence(Ch('a'), Choice(Ch('+'), Token("++"), NULL), Ch('b'), NULL); Parser q = Sequence(Ch('a'), Choice(Sequence(Ch('+'), Not(Ch('+')), NULL), Token("++"), NULL), Ch('b'), NULL); EXPECT_TRUE(ParsesTo(p, "a+b", "(u0x61 u0x2b u0x62)")); EXPECT_TRUE(ParseFails(p, "a++b")); EXPECT_TRUE(ParsesTo(q, "a+b", "(u0x61 (u0x2b) u0x62)")); EXPECT_TRUE(ParsesTo(q, "a++b", "(u0x61 <2b.2b> u0x62)")); } /* TEST(ParserTypes, Leftrec) { Indirect p = Indirect(); p.bind(Choice(Sequence(p, Ch('a'), NULL), Epsilon(), NULL)); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "aa", "((u0x61) u0x61)")); EXPECT_TRUE(ParsesTo(p, "aaa", "(((u0x61) u0x61) u0x61)")); } */ TEST(ParserTypes, Rightrec) { Indirect p = Indirect(); p.bind(Choice(Sequence(Ch('a'), p, NULL), Epsilon(), NULL)); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "aa", "(u0x61 (u0x61))")); EXPECT_TRUE(ParsesTo(p, "aaa", "(u0x61 (u0x61 (u0x61)))")); } }; int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }