C++ bindings now work!

This commit is contained in:
Meredith L. Patterson 2014-01-16 18:58:36 +01:00
parent a942880d50
commit 7e5e0f00b6
7 changed files with 195 additions and 86 deletions

View file

@ -19,6 +19,10 @@
#define HAMMER_ALLOCATOR__H__ #define HAMMER_ALLOCATOR__H__
#include <sys/types.h> #include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
// TODO(thequux): Turn this into an "HAllocatorVtable", and add a wrapper that also takes an environment pointer. // TODO(thequux): Turn this into an "HAllocatorVtable", and add a wrapper that also takes an environment pointer.
typedef struct HAllocator_ { typedef struct HAllocator_ {
void* (*alloc)(struct HAllocator_* allocator, size_t size); void* (*alloc)(struct HAllocator_* allocator, size_t size);
@ -44,5 +48,8 @@ typedef struct {
void h_allocator_stats(HArena *arena, HArenaStats *stats); void h_allocator_stats(HArena *arena, HArenaStats *stats);
#ifdef __cplusplus
}
#endif
#endif // #ifndef LIB_ALLOCATOR__H__ #endif // #ifndef LIB_ALLOCATOR__H__

2
src/bindings/cpp/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
hammer_test
test_detail.xml

View file

@ -2,7 +2,7 @@
Import("env libhammer_shared") Import("env libhammer_shared")
cppenv = env.Clone() cppenv = env.Clone()
cppenv.Append(CPPPATH=[".", "vendor/gtest-1.7.0/fused-src"]) cppenv.Append(CPPPATH=[".", "vendor/gtest-1.7.0/fused-src", "../.."])
cppenv.MergeFlags("-Wno-missing-field-initializers -DGTEST_HAS_PTHREAD=0") cppenv.MergeFlags("-Wno-missing-field-initializers -DGTEST_HAS_PTHREAD=0")

View file

@ -1,7 +1,10 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <hammer/hammer.hpp> #include <hammer/hammer.hpp>
#include <hammer/internal.h>
#include <hammer/hammer_test.hpp> #include <hammer/hammer_test.hpp>
#define a_new_(arena, typ, count) ((typ*)h_arena_malloc((arena), sizeof(typ)*(count)))
namespace { namespace {
using namespace ::hammer; using namespace ::hammer;
TEST(ParserTypes, Token) { TEST(ParserTypes, Token) {
@ -24,23 +27,23 @@ namespace {
TEST(ParserTypes, Int64) { TEST(ParserTypes, Int64) {
Parser p = Int64(); Parser p = Int64();
EXPECT_TRUE(ParsesTo(p, "\xff\xff\xff\xfe\x00\x00\x00\x00", "s-0x200000000")); EXPECT_TRUE(ParsesTo(p, std::string("\xff\xff\xff\xfe\x00\x00\x00\x00", 8), "s-0x200000000"));
EXPECT_TRUE(ParseFails(p, "\xff\xff\xff\xfe\x00\x00\x00")); EXPECT_TRUE(ParseFails(p, std::string("\xff\xff\xff\xfe\x00\x00\x00", 7)));
} }
TEST(ParserTypes, Int32) { TEST(ParserTypes, Int32) {
Parser p = Int32(); Parser p = Int32();
EXPECT_TRUE(ParsesTo(p, "\xff\xfe\x00\x00", "s-0x20000")); EXPECT_TRUE(ParsesTo(p, std::string("\xff\xfe\x00\x00", 4), "s-0x20000"));
EXPECT_TRUE(ParseFails(p, "\xff\xfe\x00")); EXPECT_TRUE(ParseFails(p, std::string("\xff\xfe\x00", 3)));
EXPECT_TRUE(ParsesTo(p, "\x00\x02\x00\x00","s0x20000")); EXPECT_TRUE(ParsesTo(p, std::string("\x00\x02\x00\x00",4) ,"s0x20000"));
EXPECT_TRUE(ParseFails(p, "\x00\x02\x00")); EXPECT_TRUE(ParseFails(p, std::string("\x00\x02\x00", 3)));
} }
TEST(ParserTypes, Int16) { TEST(ParserTypes, Int16) {
Parser p = Int16(); Parser p = Int16();
EXPECT_TRUE(ParsesTo(p, "\xfe\x00", "s-0x200")); EXPECT_TRUE(ParsesTo(p, std::string("\xfe\x00", 2), "s-0x200"));
EXPECT_TRUE(ParseFails(p, "\xfe")); EXPECT_TRUE(ParseFails(p, "\xfe"));
EXPECT_TRUE(ParsesTo(p, "\x02\x00", "s0x200")); EXPECT_TRUE(ParsesTo(p, std::string("\x02\x00", 2), "s0x200"));
EXPECT_TRUE(ParseFails(p, "\x01")); EXPECT_TRUE(ParseFails(p, "\x01"));
} }
@ -52,19 +55,19 @@ namespace {
TEST(ParserTypes, Uint64) { TEST(ParserTypes, Uint64) {
Parser p = Uint64(); Parser p = Uint64();
EXPECT_TRUE(ParsesTo(p, "\x00\x00\x00\x02\x00\x00\x00\x00", "u0x200000000")); EXPECT_TRUE(ParsesTo(p, std::string("\x00\x00\x00\x02\x00\x00\x00\x00", 8), "u0x200000000"));
EXPECT_TRUE(ParseFails(p, "\x00\x00\x00\x02\x00\x00\x00")); EXPECT_TRUE(ParseFails(p, std::string("\x00\x00\x00\x02\x00\x00\x00", 7)));
} }
TEST(ParserTypes, Uint32) { TEST(ParserTypes, Uint32) {
Parser p = Uint32(); Parser p = Uint32();
EXPECT_TRUE(ParsesTo(p, "\x00\x02\x00\x00", "u0x20000")); EXPECT_TRUE(ParsesTo(p, std::string("\x00\x02\x00\x00", 4), "u0x20000"));
EXPECT_TRUE(ParseFails(p, "\x00\x02\x00")); EXPECT_TRUE(ParseFails(p, std::string("\x00\x02\x00", 3)));
} }
TEST(ParserTypes, Uint16) { TEST(ParserTypes, Uint16) {
Parser p = Uint16(); Parser p = Uint16();
EXPECT_TRUE(ParsesTo(p, "\x02\x00", "u0x200")); EXPECT_TRUE(ParsesTo(p, std::string("\x02\x00", 2), "u0x200"));
EXPECT_TRUE(ParseFails(p, "\x02")); EXPECT_TRUE(ParseFails(p, "\x02"));
} }
@ -82,7 +85,7 @@ namespace {
TEST(ParserTypes, Whitespace) { TEST(ParserTypes, Whitespace) {
Parser p = Whitespace(Ch('a')); Parser p = Whitespace(Ch('a'));
Parser q = Whitespace(EndP()); 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, " a", "u0x61"));
EXPECT_TRUE(ParsesTo(p, " a", "u0x61")); EXPECT_TRUE(ParsesTo(p, " a", "u0x61"));
@ -121,13 +124,45 @@ namespace {
EXPECT_TRUE(ParseFails(p, " ab")); EXPECT_TRUE(ParseFails(p, " ab"));
} }
// TODO action function #include <ctype.h>
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; i<p->ast->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) { TEST(ParserTypes, Action) {
Parser p = Action(Sequence(Choice(Ch('a'), Ch('A'), NULL), Parser p = Action(Sequence(Choice(Ch('a'), Ch('A'), NULL),
Choice(Ch('b'), Ch('B'), NULL), Choice(Ch('b'), Ch('B'), NULL),
NULL), NULL),
toupper); // this won't compile upcase);
EXPECT_TRUE(ParsesTo(p, "ab", "(u0x41 u0x42)")); EXPECT_TRUE(ParsesTo(p, "ab", "(u0x41 u0x42)"));
EXPECT_TRUE(ParsesTo(p, "AB", "(u0x41 u0x42)")); EXPECT_TRUE(ParsesTo(p, "AB", "(u0x41 u0x42)"));
EXPECT_TRUE(ParseFails(p, "XX")); EXPECT_TRUE(ParseFails(p, "XX"));
@ -145,14 +180,14 @@ namespace {
EXPECT_TRUE(ParseFails(p, "a")); EXPECT_TRUE(ParseFails(p, "a"));
} }
TEST(ParserTypes, EndP) { TEST(ParserTypes, End) {
Parser p = Sequence(Ch('a'), EndP(), NULL); Parser p = Sequence(Ch('a'), End(), NULL);
EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)"));
EXPECT_TRUE(ParseFails(p, "aa")); EXPECT_TRUE(ParseFails(p, "aa"));
} }
TEST(ParserTypes, NothingP) { TEST(ParserTypes, Nothing) {
Parser p = NothingP(); Parser p = Nothing();
EXPECT_TRUE(ParseFails(p, "a")); EXPECT_TRUE(ParseFails(p, "a"));
} }
@ -207,7 +242,7 @@ namespace {
TEST(ParserTypes, Many1) { TEST(ParserTypes, Many1) {
Parser p = Many1(Choice(Ch('a'), Ch('b'), NULL)); Parser p = Many1(Choice(Ch('a'), Ch('b'), NULL));
EXPECT_TRUE(ParseFails(p, "", "()")); EXPECT_TRUE(ParseFails(p, ""));
EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)"));
EXPECT_TRUE(ParsesTo(p, "b", "(u0x62)")); EXPECT_TRUE(ParsesTo(p, "b", "(u0x62)"));
EXPECT_TRUE(ParsesTo(p, "aabbaba", "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)")); EXPECT_TRUE(ParsesTo(p, "aabbaba", "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)"));
@ -232,7 +267,7 @@ namespace {
} }
TEST(ParserTypes, Ignore) { TEST(ParserTypes, Ignore) {
Parser p = Sequence(Ch('a'), Ignore(Ch('b'), Ch('c'), NULL)); Parser p = Sequence(Ch('a'), Ignore(Ch('b')), Ch('c'), NULL);
EXPECT_TRUE(ParsesTo(p, "abc", "(u0x61 u0x63)")); EXPECT_TRUE(ParsesTo(p, "abc", "(u0x61 u0x63)"));
EXPECT_TRUE(ParseFails(p, "ac")); EXPECT_TRUE(ParseFails(p, "ac"));
} }
@ -256,15 +291,23 @@ namespace {
} }
TEST(ParserTypes, EpsilonP) { TEST(ParserTypes, EpsilonP) {
Parser p = Sequence(Ch('a'), EpsilonP(), Ch('b'), NULL); Parser p = Sequence(Ch('a'), Epsilon(), Ch('b'), NULL);
Parser q = Sequence(EpsilonP(), Ch('a'), NULL); Parser q = Sequence(Epsilon(), Ch('a'), NULL);
Parser r = Sequence(Ch('a'), EpsilonP(), NULL); Parser r = Sequence(Ch('a'), Epsilon(), NULL);
EXPECT_TRUE(ParsesTo(p, "ab", "(u0x61 u0x62)")); EXPECT_TRUE(ParsesTo(p, "ab", "(u0x61 u0x62)"));
EXPECT_TRUE(ParsesTo(q, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(q, "a", "(u0x61)"));
EXPECT_TRUE(ParsesTo(r, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(r, "a", "(u0x61)"));
} }
bool validate_test_ab() { return false; } 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) { TEST(ParserTypes, AttrBool) {
Parser p = AttrBool(Many1(Choice(Ch('a'), Ch('b'), NULL)), Parser p = AttrBool(Many1(Choice(Ch('a'), Ch('b'), NULL)),
@ -293,21 +336,21 @@ namespace {
Ch('b'), NULL); Ch('b'), NULL);
EXPECT_TRUE(ParsesTo(p, "a+b", "(u0x61 u0x2b u0x62)")); EXPECT_TRUE(ParsesTo(p, "a+b", "(u0x61 u0x2b u0x62)"));
EXPECT_TRUE(ParseFails(p, "a++b")); EXPECT_TRUE(ParseFails(p, "a++b"));
EXPECT_TRUE(ParsesTo(p, "a+b", "(u0x61 (u0x2b) u0x62)")); EXPECT_TRUE(ParsesTo(q, "a+b", "(u0x61 (u0x2b) u0x62)"));
EXPECT_TRUE(ParsesTo(p, "a++b", "(u0x61 <2b.2b> u0x62)")); EXPECT_TRUE(ParsesTo(q, "a++b", "(u0x61 <2b.2b> u0x62)"));
} }
/*
TEST(ParserTypes, Leftrec) { TEST(ParserTypes, Leftrec) {
IndirectParser p = Indirect(); Indirect p = Indirect();
p.bind(Choice(Sequence(p, Ch('a'), NULL), EpsilonP(), NULL)); p.bind(Choice(Sequence(p, Ch('a'), NULL), Epsilon(), NULL));
EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)"));
EXPECT_TRUE(ParsesTo(p, "aa", "((u0x61) u0x61)")); EXPECT_TRUE(ParsesTo(p, "aa", "((u0x61) u0x61)"));
EXPECT_TRUE(ParsesTo(p, "aaa", "(((u0x61) u0x61) u0x61)")); EXPECT_TRUE(ParsesTo(p, "aaa", "(((u0x61) u0x61) u0x61)"));
} }
*/
TEST(ParserTypes, Rightrec) { TEST(ParserTypes, Rightrec) {
IndirectParser p = Indirect(); Indirect p = Indirect();
p.bind(Choice(Sequence(Ch('a'), p, NULL), EpsilonP(), NULL)); p.bind(Choice(Sequence(Ch('a'), p, NULL), Epsilon(), NULL));
EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)"));
EXPECT_TRUE(ParsesTo(p, "aa", "(u0x61 (u0x61))")); EXPECT_TRUE(ParsesTo(p, "aa", "(u0x61 (u0x61))"));
EXPECT_TRUE(ParsesTo(p, "aaa", "(u0x61 (u0x61 (u0x61)))")); EXPECT_TRUE(ParsesTo(p, "aaa", "(u0x61 (u0x61 (u0x61)))"));

View file

@ -4,6 +4,9 @@
#include <hammer/hammer.h> #include <hammer/hammer.h>
#include <string> #include <string>
#include <stdint.h> #include <stdint.h>
#include <cstdarg>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused"
namespace hammer { namespace hammer {
class ParseResult; class ParseResult;
@ -12,9 +15,9 @@ namespace hammer {
const HParser *parser; const HParser *parser;
Parser(const HParser* inner) : parser(inner) {} Parser(const HParser* inner) : parser(inner) {}
Parser(const Parser &other) : parser(other.parser) {}
ParseResult parse(std::string string); //static Parser nil = Parser(NULL);
ParseResult parse(const std::string &string);
}; };
class ParsedToken { class ParsedToken {
@ -39,7 +42,7 @@ namespace hammer {
void* getUser() const {return token->user;} void* getUser() const {return token->user;}
uint64_t getUint() const {return token->uint;} uint64_t getUint() const {return token->uint;}
int64_t getSint() const {return token->sint;} int64_t getSint() const {return token->sint;}
// TODO: Sequence GetSeq() const {return Sequence(token->seq);} // TODO: Sequence getSeq() const {return Sequence(token->seq);}
std::string getBytes() const {return std::string((char*)token->bytes.token, token->bytes.len); } std::string getBytes() const {return std::string((char*)token->bytes.token, token->bytes.len); }
@ -78,7 +81,7 @@ namespace hammer {
} }
}; };
inline ParseResult Parser::parse(std::string string) { inline ParseResult Parser::parse(const std::string &string) {
return ParseResult(h_parse(parser, (uint8_t*)string.data(), string.length())); return ParseResult(h_parse(parser, (uint8_t*)string.data(), string.length()));
} }
@ -96,66 +99,109 @@ namespace hammer {
return Parser(h_ch_range(lower,upper)); return Parser(h_ch_range(lower,upper));
} }
static inline Parser int64() { return Parser(h_int64()); } static inline Parser Int64() { return Parser(h_int64()); }
static inline Parser int32() { return Parser(h_int32()); } static inline Parser Int32() { return Parser(h_int32()); }
static inline Parser int16() { return Parser(h_int16()); } static inline Parser Int16() { return Parser(h_int16()); }
static inline Parser int8 () { return Parser(h_int8 ()); } static inline Parser Int8 () { return Parser(h_int8 ()); }
static inline Parser uint64() { return Parser(h_uint64()); } static inline Parser Uint64() { return Parser(h_uint64()); }
static inline Parser uint32() { return Parser(h_uint32()); } static inline Parser Uint32() { return Parser(h_uint32()); }
static inline Parser uint16() { return Parser(h_uint16()); } static inline Parser Uint16() { return Parser(h_uint16()); }
static inline Parser uint8 () { return Parser(h_uint8 ()); } static inline Parser Uint8 () { return Parser(h_uint8 ()); }
static inline Parser int_range(Parser p, int64_t lower, int64_t upper) { static inline Parser IntRange(Parser p, int64_t lower, int64_t upper) {
return Parser(h_int_range(p.parser, lower, upper)); return Parser(h_int_range(p.parser, lower, upper));
} }
static inline Parser bits(size_t len, bool sign) { return Parser(h_bits(len, sign)); } static inline Parser Bits(size_t len, bool sign) { return Parser(h_bits(len, sign)); }
static inline Parser whitespace(Parser p) { return Parser(h_whitespace(p.parser)); } static inline Parser Whitespace(Parser p) { return Parser(h_whitespace(p.parser)); }
static inline Parser left(Parser p, Parser q) { return Parser(h_left(p.parser, q.parser)); } static inline Parser Left(Parser p, Parser q) { return Parser(h_left(p.parser, q.parser)); }
static inline Parser right(Parser p, Parser q) { return Parser(h_right(p.parser, q.parser)); } static inline Parser Right(Parser p, Parser q) { return Parser(h_right(p.parser, q.parser)); }
static inline Parser middle(Parser p, Parser q, Parser r) { static inline Parser Middle(Parser p, Parser q, Parser r) {
return Parser(h_middle(p.parser, q.parser, r.parser)); return Parser(h_middle(p.parser, q.parser, r.parser));
} }
// TODO: Define Action // User is responsible for ensuring that function remains allocated.
//Parser action(Parser p, Action a); Parser Action(Parser p, HAction action, void* user_data) {
return Parser(h_action(p.parser, action, user_data));
}
static inline Parser in(std::string charset); Parser Action(Parser p, HAction action) {
static inline Parser in(const uint8_t *charset, size_t length); return Parser(h_action(p.parser, action, NULL));
static inline Parser in(std::set<uint8_t> charset); }
static inline Parser not_in(std::string charset); Parser AttrBool(Parser p, HPredicate pred, void* user_data) {
static inline Parser not_in(const uint8_t *charset, size_t length); return Parser(h_attr_bool(p.parser, pred, user_data));
static inline Parser not_in(std::set<uint8_t> charset); }
static inline Parser end() { return Parser(h_end_p()); } Parser AttrBool(Parser p, HPredicate pred) {
static inline Parser nothing() { return Parser(h_nothing_p()); } return Parser(h_attr_bool(p.parser, pred, NULL));
}
static inline Parser In(const std::string &charset) {
return Parser(h_in((const uint8_t*)charset.data(), charset.length()));
}
static inline Parser In(const uint8_t *charset, size_t length) {
return Parser(h_in(charset, length));
}
/* TODO
static inline Parser In(std::set<uint8_t> charset) {
}
*/
static inline Parser NotIn(const std::string &charset) {
return Parser(h_not_in((const uint8_t*)charset.data(), charset.length()));
}
static inline Parser NotIn(const uint8_t *charset, size_t length) {
return Parser(h_not_in(charset, length));
}
/* TODO
static inline Parser NotIn(std::set<uint8_t> charset) { }
*/
static inline Parser End() { return Parser(h_end_p()); }
static inline Parser Nothing() { return Parser(h_nothing_p()); }
// TODO: figure out varargs // TODO: figure out varargs
//Parser sequence(); static inline Parser Sequence(Parser p, ...) {
// va_list ap;
//Parser choice(); va_start(ap, p);
// old-skool reinterpret_cast<HParser*>(p)
HParser* ret = h_sequence__v(*(HParser**)(void*)&p,
ap);
va_end(ap);
return Parser(ret);
}
static inline Parser butnot(Parser p1, Parser p2) { return Parser(h_butnot(p1.parser, p2.parser)); } static inline Parser Choice(Parser p, ...) {
static inline Parser difference(Parser p1, Parser p2) { return Parser(h_difference(p1.parser, p2.parser)); } va_list ap;
static inline Parser xor_(Parser p1, Parser p2) { return Parser(h_xor(p1.parser, p2.parser)); } va_start(ap, p);
static inline Parser many(Parser p) { return Parser(h_many(p.parser)); } // old-skool reinterpret_cast<HParser*>(p)
static inline Parser many1(Parser p) { return Parser(h_many1(p.parser)); } HParser* ret = h_choice__v(*(HParser**)(void*)&p,
static inline Parser repeat_n(Parser p, size_t n) { return Parser(h_repeat_n(p.parser, n)); } ap);
static inline Parser optional(Parser p) { return Parser(h_optional(p.parser)); } va_end(ap);
static inline Parser ignore(Parser p) { return Parser(h_ignore(p.parser)); } return Parser(ret);
static inline Parser sepBy(Parser p, Parser sep) { return Parser(h_sepBy(p.parser, sep.parser)); } }
static inline Parser sepBy1(Parser p, Parser sep) { return Parser(h_sepBy1(p.parser, sep.parser)); }
static inline Parser epsilon() { return Parser(h_epsilon_p()); } static inline Parser ButNot(Parser p1, Parser p2) { return Parser(h_butnot(p1.parser, p2.parser)); }
static inline Parser length_value(Parser length, Parser value) { return Parser(h_length_value(length.parser, value.parser)); } static inline Parser Difference(Parser p1, Parser p2) { return Parser(h_difference(p1.parser, p2.parser)); }
static inline Parser Xor(Parser p1, Parser p2) { return Parser(h_xor(p1.parser, p2.parser)); }
static inline Parser Many(Parser p) { return Parser(h_many(p.parser)); }
static inline Parser Many1(Parser p) { return Parser(h_many1(p.parser)); }
static inline Parser RepeatN(Parser p, size_t n) { return Parser(h_repeat_n(p.parser, n)); }
static inline Parser Optional(Parser p) { return Parser(h_optional(p.parser)); }
static inline Parser Ignore(Parser p) { return Parser(h_ignore(p.parser)); }
static inline Parser SepBy(Parser p, Parser sep) { return Parser(h_sepBy(p.parser, sep.parser)); }
static inline Parser SepBy1(Parser p, Parser sep) { return Parser(h_sepBy1(p.parser, sep.parser)); }
static inline Parser Epsilon() { return Parser(h_epsilon_p()); }
static inline Parser LengthValue(Parser length, Parser value) { return Parser(h_length_value(length.parser, value.parser)); }
// Was attr_bool in the old C bindings. // Was attr_bool in the old C bindings.
// TODO: Figure out closure // TODO: Figure out closure
//Parser validate(Parser p, Predicate pred); //Parser validate(Parser p, Predicate pred);
static inline Parser and_(Parser p) { return Parser(h_and(p.parser)); } static inline Parser And(Parser p) { return Parser(h_and(p.parser)); }
static inline Parser not_(Parser p) { return Parser(h_not(p.parser)); } static inline Parser Not(Parser p) { return Parser(h_not(p.parser)); }
class Indirect : public Parser { class Indirect : public Parser {
public: public:
@ -169,4 +215,6 @@ namespace hammer {
// return Parser(foo); // return Parser(foo);
//} //}
} }
#pragma GCC diagnostic pop
#endif #endif

View file

@ -7,9 +7,8 @@
#define HAMMER_DECL_UNUSED __attribute__((unused)) #define HAMMER_DECL_UNUSED __attribute__((unused))
#pragma GCC diagnostic push static ::testing::AssertionResult ParseFails (hammer::Parser parser,
#pragma GCC diagnostic ignored "-Wunused" const std::string &input) HAMMER_DECL_UNUSED;
static ::testing::AssertionResult ParseFails (hammer::Parser parser, static ::testing::AssertionResult ParseFails (hammer::Parser parser,
const std::string &input) { const std::string &input) {
hammer::ParseResult result = parser.parse(input); hammer::ParseResult result = parser.parse(input);
@ -20,6 +19,8 @@ static ::testing::AssertionResult ParseFails (hammer::Parser parser,
} }
} }
static ::testing::AssertionResult ParsesOK(hammer::Parser parser,
const std::string &input) HAMMER_DECL_UNUSED;
static ::testing::AssertionResult ParsesOK(hammer::Parser parser, static ::testing::AssertionResult ParsesOK(hammer::Parser parser,
const std::string &input) { const std::string &input) {
hammer::ParseResult result = parser.parse(input); hammer::ParseResult result = parser.parse(input);
@ -30,6 +31,9 @@ static ::testing::AssertionResult ParsesOK(hammer::Parser parser,
} }
} }
static ::testing::AssertionResult ParsesTo(hammer::Parser parser,
const std::string &input,
const std::string &expected_result) HAMMER_DECL_UNUSED;
static ::testing::AssertionResult ParsesTo(hammer::Parser parser, static ::testing::AssertionResult ParsesTo(hammer::Parser parser,
const std::string &input, const std::string &input,
const std::string &expected_result) { const std::string &expected_result) {
@ -47,6 +51,4 @@ static ::testing::AssertionResult ParsesTo(hammer::Parser parser,
} }
} }
#pragma GCC diagnostic pop
#endif // defined(HAMMER_HAMMER_TEST__HPP) #endif // defined(HAMMER_HAMMER_TEST__HPP)

View file

@ -47,8 +47,13 @@
#define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count)))) #define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count))))
#define h_free(addr) (mm__->free(mm__, (addr))) #define h_free(addr) (mm__->free(mm__, (addr)))
#ifndef __cplusplus
#define false 0 #define false 0
#define true 1 #define true 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
// This is going to be generally useful. // This is going to be generally useful.
static inline void h_generic_free(HAllocator *allocator, void* ptr) { static inline void h_generic_free(HAllocator *allocator, void* ptr) {
@ -388,5 +393,7 @@ bool h_not_regular(HRVMProg*, void*);
#include <stdlib.h> #include <stdlib.h>
#define h_arena_malloc(a, s) malloc(s) #define h_arena_malloc(a, s) malloc(s)
#endif #endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif // #ifndef HAMMER_INTERNAL__H #endif // #ifndef HAMMER_INTERNAL__H