diff --git a/src/bindings/cpp/cpp_tests.cpp b/src/bindings/cpp/cpp_tests.cpp
index b8eda68fe368074443d7d44c7d46ce2003af9fdc..b6bfb439197a3c744a1f5d165153a0169a67ecb7 100644
--- a/src/bindings/cpp/cpp_tests.cpp
+++ b/src/bindings/cpp/cpp_tests.cpp
@@ -15,6 +15,304 @@ namespace {
     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, "\xff\xff\xff\xfe\x00\x00\x00\x00", "s-0x200000000"));
+    EXPECT_TRUE(ParseFails(p, "\xff\xff\xff\xfe\x00\x00\x00"));
+  }
+
+  TEST(ParserTypes, Int32) {
+    Parser p = Int32();
+    EXPECT_TRUE(ParsesTo(p, "\xff\xfe\x00\x00", "s-0x20000"));
+    EXPECT_TRUE(ParseFails(p, "\xff\xfe\x00"));
+    EXPECT_TRUE(ParsesTo(p, "\x00\x02\x00\x00","s0x20000"));
+    EXPECT_TRUE(ParseFails(p, "\x00\x02\x00"));
+  }
+
+  TEST(ParserTypes, Int16) {
+    Parser p = Int16();
+    EXPECT_TRUE(ParsesTo(p, "\xfe\x00", "s-0x200"));
+    EXPECT_TRUE(ParseFails(p, "\xfe"));
+    EXPECT_TRUE(ParsesTo(p, "\x02\x00", "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, "\x00\x00\x00\x02\x00\x00\x00\x00", "u0x200000000"));
+    EXPECT_TRUE(ParseFails(p, "\x00\x00\x00\x02\x00\x00\x00"));
+  }
+
+  TEST(ParserTypes, Uint32) {
+    Parser p = Uint32();
+    EXPECT_TRUE(ParsesTo(p, "\x00\x02\x00\x00", "u0x20000"));
+    EXPECT_TRUE(ParseFails(p, "\x00\x02\x00"));
+  }
+
+  TEST(ParserTypes, Uint16) {
+    Parser p = Uint16();
+    EXPECT_TRUE(ParsesTo(p, "\x02\x00", "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(EndP());
+    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"));
+  }
+
+  // TODO action function
+
+  TEST(ParserTypes, Action) {
+    Parser p = Action(Sequence(Choice(Ch('a'), Ch('A'), NULL),
+			       Choice(Ch('b'), Ch('B'), NULL),
+			       NULL),
+		      toupper); // this won't compile
+    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, EndP) {
+    Parser p = Sequence(Ch('a'), EndP(), NULL);
+    EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)"));
+    EXPECT_TRUE(ParseFails(p, "aa"));
+  }
+
+  TEST(ParserTypes, NothingP) {
+    Parser p = NothingP();
+    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'), EpsilonP(), Ch('b'), NULL);
+    Parser q = Sequence(EpsilonP(), Ch('a'), NULL);
+    Parser r = Sequence(Ch('a'), EpsilonP(), NULL);
+    EXPECT_TRUE(ParsesTo(p, "ab", "(u0x61 u0x62)"));
+    EXPECT_TRUE(ParsesTo(q, "a", "(u0x61)"));
+    EXPECT_TRUE(ParsesTo(r, "a", "(u0x61)"));
+  }
+
+  bool validate_test_ab() { return false; }
+
+  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(p, "a+b", "(u0x61 (u0x2b) u0x62)"));
+    EXPECT_TRUE(ParsesTo(p, "a++b", "(u0x61 <2b.2b> u0x62)"));
+  }
+
+  TEST(ParserTypes, Leftrec) {
+    IndirectParser p = Indirect();
+    p.bind(Choice(Sequence(p, Ch('a'), NULL), EpsilonP(), 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) {
+    IndirectParser p = Indirect();
+    p.bind(Choice(Sequence(Ch('a'), p, NULL), EpsilonP(), 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) {