Merge remote-tracking branch 'mlp/master' into LL

This commit is contained in:
Sven M. Hallberg 2013-05-23 11:58:05 +02:00
commit 0b98b19ef0
44 changed files with 2785 additions and 992 deletions

View file

@ -41,7 +41,7 @@ HAMMER_PARTS := \
system_allocator.o \
benchmark.o \
cfgrammar.o \
actions.o \
glue.o \
$(PARSERS:%=parsers/%.o) \
$(BACKENDS:%=backends/%.o)
@ -50,6 +50,7 @@ TESTS := t_benchmark.o \
t_bitwriter.o \
t_parser.o \
t_grammar.o \
t_misc.o \
test_suite.o
OUTPUTS := libhammer.a \
@ -65,12 +66,15 @@ include ../common.mk
$(TESTS): CFLAGS += $(TEST_CFLAGS)
$(TESTS): LDFLAGS += $(TEST_LDFLAGS)
CFLAGS += -fPIC
all: libhammer.a
libhammer.a: $(HAMMER_PARTS)
bitreader.o: test_suite.h
hammer.o: hammer.h
glue.o: hammer.h glue.h
all: libhammer.a

View file

@ -1,60 +0,0 @@
// XXX to be consolidated with glue.c when merged upstream
#include <assert.h>
#include "hammer.h"
#include "internal.h"
#include "parsers/parser_internal.h"
const HParsedToken *h_act_first(const HParseResult *p) {
assert(p->ast);
assert(p->ast->token_type == TT_SEQUENCE);
assert(p->ast->seq->used > 0);
return p->ast->seq->elements[0];
}
const HParsedToken *h_act_second(const HParseResult *p) {
assert(p->ast);
assert(p->ast->token_type == TT_SEQUENCE);
assert(p->ast->seq->used > 0);
return p->ast->seq->elements[1];
}
const HParsedToken *h_act_last(const HParseResult *p) {
assert(p->ast);
assert(p->ast->token_type == TT_SEQUENCE);
assert(p->ast->seq->used > 0);
return p->ast->seq->elements[p->ast->seq->used-1];
}
static void act_flatten_(HCountedArray *seq, const HParsedToken *tok) {
if(tok == NULL) {
return;
} else if(tok->token_type == TT_SEQUENCE) {
size_t i;
for(i=0; i<tok->seq->used; i++)
act_flatten_(seq, tok->seq->elements[i]);
} else {
h_carray_append(seq, (HParsedToken *)tok);
}
}
const HParsedToken *h_act_flatten(const HParseResult *p) {
HCountedArray *seq = h_carray_new(p->arena);
act_flatten_(seq, p->ast);
HParsedToken *res = a_new_(p->arena, HParsedToken, 1);
res->token_type = TT_SEQUENCE;
res->seq = seq;
res->index = p->ast->index;
res->bit_offset = p->ast->bit_offset;
return res;
}
const HParsedToken *h_act_ignore(const HParseResult *p) {
return NULL;
}

View file

@ -86,14 +86,18 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
void setupLR(const HParser *p, HParseState *state, HLeftRec *rec_detect) {
if (!rec_detect->head) {
HRecursionHead *some = a_new(HRecursionHead, 1);
some->head_parser = p; some->involved_set = NULL; some->eval_set = NULL;
some->head_parser = p;
some->involved_set = h_slist_new(state->arena);
some->eval_set = NULL;
rec_detect->head = some;
}
assert(state->lr_stack->head != NULL);
HLeftRec *lr = state->lr_stack->head->elem;
while (lr && lr->rule != p) {
HSlistNode *head = state->lr_stack->head;
HLeftRec *lr;
while (head && (lr = head->elem)->rule != p) {
lr->head = rec_detect->head;
h_slist_push(lr->head->involved_set, (void*)lr->rule);
head = head->next;
}
}
@ -110,7 +114,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
HParseResult *old_res = old_cached->right->result;
// reset the eval_set of the head of the recursion at each beginning of growth
head->eval_set = head->involved_set;
head->eval_set = h_slist_copy(head->involved_set);
HParseResult *tmp_res = perform_lowlevel_parse(state, k->parser);
if (tmp_res) {

View file

@ -41,6 +41,26 @@ HSlist* h_slist_new(HArena *arena) {
return ret;
}
HSlist* h_slist_copy(HSlist *slist) {
HSlist *ret = h_slist_new(slist->arena);
HSlistNode *head = slist->head;
HSlistNode *tail;
if (head != NULL) {
h_slist_push(ret, head->elem);
tail = ret->head;
head = head->next;
}
while (head != NULL) {
// append head item to tail in a new node
HSlistNode *node = h_arena_malloc(slist->arena, sizeof(HSlistNode));
node->elem = head->elem;
node->next = NULL;
tail = tail->next = node;
head = head->next;
}
return ret;
}
void* h_slist_pop(HSlist *slist) {
HSlistNode *head = slist->head;
if (!head)

221
src/glue.c Normal file
View file

@ -0,0 +1,221 @@
#include <assert.h>
#include "glue.h"
#include "hammer.h"
#include "internal.h" // for h_carray_*
#include "parsers/parser_internal.h"
// Helper to build HAction's that pick one index out of a sequence.
const HParsedToken *h_act_index(int i, const HParseResult *p)
{
if(!p) return NULL;
const HParsedToken *tok = p->ast;
if(!tok || tok->token_type != TT_SEQUENCE)
return NULL;
const HCountedArray *seq = tok->seq;
size_t n = seq->used;
if(i<0 || (size_t)i>=n)
return NULL;
else
return tok->seq->elements[i];
}
const HParsedToken *h_act_first(const HParseResult *p) {
assert(p->ast);
assert(p->ast->token_type == TT_SEQUENCE);
assert(p->ast->seq->used > 0);
return p->ast->seq->elements[0];
}
const HParsedToken *h_act_second(const HParseResult *p) {
assert(p->ast);
assert(p->ast->token_type == TT_SEQUENCE);
assert(p->ast->seq->used > 0);
return p->ast->seq->elements[1];
}
const HParsedToken *h_act_last(const HParseResult *p) {
assert(p->ast);
assert(p->ast->token_type == TT_SEQUENCE);
assert(p->ast->seq->used > 0);
return p->ast->seq->elements[p->ast->seq->used-1];
}
static void act_flatten_(HCountedArray *seq, const HParsedToken *tok) {
if(tok == NULL) {
return;
} else if(tok->token_type == TT_SEQUENCE) {
size_t i;
for(i=0; i<tok->seq->used; i++)
act_flatten_(seq, tok->seq->elements[i]);
} else {
h_carray_append(seq, (HParsedToken *)tok);
}
}
const HParsedToken *h_act_flatten(const HParseResult *p) {
HCountedArray *seq = h_carray_new(p->arena);
act_flatten_(seq, p->ast);
HParsedToken *res = a_new_(p->arena, HParsedToken, 1);
res->token_type = TT_SEQUENCE;
res->seq = seq;
res->index = p->ast->index;
res->bit_offset = p->ast->bit_offset;
return res;
}
const HParsedToken *h_act_ignore(const HParseResult *p) {
return NULL;
}
// Low-level helper for the h_make family.
HParsedToken *h_make_(HArena *arena, HTokenType type)
{
HParsedToken *ret = h_arena_malloc(arena, sizeof(HParsedToken));
ret->token_type = type;
return ret;
}
HParsedToken *h_make(HArena *arena, HTokenType type, void *value)
{
assert(type >= TT_USER);
HParsedToken *ret = h_make_(arena, type);
ret->user = value;
return ret;
}
HParsedToken *h_make_seq(HArena *arena)
{
HParsedToken *ret = h_make_(arena, TT_SEQUENCE);
ret->seq = h_carray_new(arena);
return ret;
}
HParsedToken *h_make_seqn(HArena *arena, size_t n)
{
HParsedToken *ret = h_make_(arena, TT_SEQUENCE);
ret->seq = h_carray_new_sized(arena, n);
return ret;
}
HParsedToken *h_make_bytes(HArena *arena, size_t len)
{
HParsedToken *ret = h_make_(arena, TT_BYTES);
ret->bytes.len = len;
ret->bytes.token = h_arena_malloc(arena, len);
return ret;
}
HParsedToken *h_make_sint(HArena *arena, int64_t val)
{
HParsedToken *ret = h_make_(arena, TT_SINT);
ret->sint = val;
return ret;
}
HParsedToken *h_make_uint(HArena *arena, uint64_t val)
{
HParsedToken *ret = h_make_(arena, TT_UINT);
ret->uint = val;
return ret;
}
// XXX -> internal
HParsedToken *h_carray_index(const HCountedArray *a, size_t i)
{
assert(i < a->used);
return a->elements[i];
}
size_t h_seq_len(const HParsedToken *p)
{
assert(p != NULL);
assert(p->token_type == TT_SEQUENCE);
return p->seq->used;
}
HParsedToken **h_seq_elements(const HParsedToken *p)
{
assert(p != NULL);
assert(p->token_type == TT_SEQUENCE);
return p->seq->elements;
}
HParsedToken *h_seq_index(const HParsedToken *p, size_t i)
{
assert(p != NULL);
assert(p->token_type == TT_SEQUENCE);
return h_carray_index(p->seq, i);
}
HParsedToken *h_seq_index_path(const HParsedToken *p, size_t i, ...)
{
va_list va;
va_start(va, i);
HParsedToken *ret = h_seq_index_vpath(p, i, va);
va_end(va);
return ret;
}
HParsedToken *h_seq_index_vpath(const HParsedToken *p, size_t i, va_list va)
{
HParsedToken *ret = h_seq_index(p, i);
int j;
while((j = va_arg(va, int)) >= 0)
ret = h_seq_index(p, j);
return ret;
}
void h_seq_snoc(HParsedToken *xs, const HParsedToken *x)
{
assert(xs != NULL);
assert(xs->token_type == TT_SEQUENCE);
h_carray_append(xs->seq, (HParsedToken *)x);
}
void h_seq_append(HParsedToken *xs, const HParsedToken *ys)
{
assert(xs != NULL);
assert(xs->token_type == TT_SEQUENCE);
assert(ys != NULL);
assert(ys->token_type == TT_SEQUENCE);
for(size_t i=0; i<ys->seq->used; i++)
h_carray_append(xs->seq, ys->seq->elements[i]);
}
// Flatten nested sequences. Always returns a sequence.
// If input element is not a sequence, returns it as a singleton sequence.
const HParsedToken *h_seq_flatten(HArena *arena, const HParsedToken *p)
{
assert(p != NULL);
HParsedToken *ret = h_make_seq(arena);
switch(p->token_type) {
case TT_SEQUENCE:
// Flatten and append all.
for(size_t i; i<p->seq->used; i++) {
h_seq_append(ret, h_seq_flatten(arena, h_seq_index(p, i)));
}
break;
default:
// Make singleton sequence.
h_seq_snoc(ret, p);
break;
}
return ret;
}

256
src/glue.h Normal file
View file

@ -0,0 +1,256 @@
//
// API additions for writing grammar and semantic actions more concisely
//
//
// Quick Overview:
//
// Grammars can be succinctly specified with the family of H_RULE macros.
// H_RULE defines a plain parser variable. H_ARULE additionally attaches a
// semantic action; H_VRULE attaches a validation. H_AVRULE and H_VARULE
// combine both.
//
// A few standard semantic actions are defined below. The H_ACT_APPLY macro
// allows semantic actions to be defined by "partial application" of
// a generic action to fixed paramters.
//
// The definition of more complex semantic actions will usually consist of
// extracting data from the given parse tree and constructing a token of custom
// type to represent the result. A number of functions and convenience macros
// are provided to capture the most common cases and idioms.
//
// See the leading comment blocks on the sections below for more details.
//
#ifndef HAMMER_GLUE__H
#define HAMMER_GLUE__H
#include <assert.h>
#include "hammer.h"
//
// Grammar specification
//
// H_RULE is simply a short-hand for the typical declaration and definition of
// a parser variable. See its plain definition below. The goal is to save
// horizontal space as well as to provide a clear and unified look together with
// the other macro variants that stays close to an abstract PEG or BNF grammar.
// The latter goal is more specifically enabled by H_ARULE, H_VRULE, and their
// combinations as they allow the definition of syntax to be given without
// intermingling it with the semantic specifications.
//
// H_ARULE defines a variable just like H_RULE but attaches a semantic action
// to the result of the parser via h_action. The action is expected to be
// named act_<rulename>.
//
// H_VRULE is analogous to H_ARULE but attaches a validation via h_attr_bool.
// The validation is expected to be named validate_<rulename>.
//
// H_VARULE combines H_RULE with both an action and a validation. The action is
// attached before the validation, i.e. the validation receives as input the
// result of the action.
//
// H_AVRULE is like H_VARULE but the action is attached outside the validation,
// i.e. the validation receives the uninterpreted AST as input.
//
#define H_RULE(rule, def) const HParser *rule = def
#define H_ARULE(rule, def) const HParser *rule = h_action(def, act_ ## rule)
#define H_VRULE(rule, def) const HParser *rule = \
h_attr_bool(def, validate_ ## rule)
#define H_VARULE(rule, def) const HParser *rule = \
h_attr_bool(h_action(def, act_ ## rule), validate_ ## rule)
#define H_AVRULE(rule, def) const HParser *rule = \
h_action(h_attr_bool(def, validate_ ## rule), act_ ## rule)
//
// Pre-fab semantic actions
//
// A collection of generally useful semantic actions is provided.
//
// h_act_ignore is the action equivalent of the parser combinator h_ignore. It
// simply causes the AST it is applied to to be replaced with NULL. This most
// importantly causes it to be elided from the result of a surrounding
// h_sequence.
//
// h_act_index is of note as it is not itself suitable to be passed to
// h_action. It is parameterized by an index to be picked from a sequence
// token. It must be wrapped in a proper HAction to be used. The H_ACT_APPLY
// macro provides a concise way to define such a parameter-application wrapper.
//
// h_act_flatten acts on a token of possibly nested sequences by recursively
// flattening it into a single sequence. Cf. h_seq_flatten below.
//
// H_ACT_APPLY implements "partial application" for semantic actions. It
// defines a new action that supplies given parameters to a parameterized
// action such as h_act_index.
//
const HParsedToken *h_act_index(int i, const HParseResult *p);
const HParsedToken *h_act_first(const HParseResult *p);
const HParsedToken *h_act_second(const HParseResult *p);
const HParsedToken *h_act_last(const HParseResult *p);
const HParsedToken *h_act_flatten(const HParseResult *p);
const HParsedToken *h_act_ignore(const HParseResult *p);
// Define 'myaction' as a specialization of 'paction' by supplying the leading
// parameters.
#define H_ACT_APPLY(myaction, paction, ...) \
const HParsedToken *myaction(const HParseResult *p) { \
return paction(__VA_ARGS__, p); \
}
//
// Working with HParsedTokens
//
// The type HParsedToken represents a dynamically-typed universe of values.
// Declared below are constructors to turn ordinary values into their
// HParsedToken equivalents, extractors to retrieve the original values from
// inside an HParsedToken, and functions that inspect and modify tokens of
// sequence type directly.
//
// In addition, there are a number of short-hand macros that work with some
// conventions to eliminate common boilerplate. These conventions are listed
// below. Be sure to follow them if you want to use the respective macros.
//
// * The single argument to semantic actions should be called 'p'.
//
// The H_MAKE macros suppy 'p->arena' to their underlying h_make
// counterparts. The H_FIELD macros supply 'p->ast' to their underlying
// H_INDEX counterparts.
//
// * For each custom token type, there should be a typedef for the
// corresponding value type.
//
// H_CAST, H_INDEX and H_FIELD cast the void * user field of such a token to
// a pointer to the given type.
//
// * For each custom token type, say 'foo_t', there must be an integer
// constant 'TT_foo_t' to identify the token type. This constant must have a
// value greater or equal than TT_USER.
//
// One idiom is to define an enum for all custom token types and to assign a
// value of TT_USER to the first element. This can be viewed as extending
// the HTokenType enum.
//
// The H_MAKE and H_ASSERT macros derive the name of the token type constant
// from the given type name.
//
//
// The H_ALLOC macro is useful for allocating values of custom token types.
//
// The H_MAKE family of macros construct tokens of a given type. The native
// token types are indicated by a corresponding suffix such as in H_MAKE_SEQ.
// The form with no suffix is used for custom token types. This convention is
// also used for other macro and function families.
//
// The H_ASSERT family simply asserts that a given token has the expected type.
// It mainly serves as an implementation aid for H_CAST. Of note in that regard
// is that, unlike the standard 'assert' macro, these form _expressions_ that
// return the value of their token argument; thus they can be used in a
// "pass-through" fashion inside other expressions.
//
// The H_CAST family combines a type assertion with access to the
// statically-typed value inside a token.
//
// A number of functions h_seq_* operate on and inspect sequence tokens.
// Note that H_MAKE_SEQ takes no arguments and constructs an empty sequence.
// Therefore there are h_seq_snoc and h_seq_append to build up sequences.
//
// The macro families H_FIELD and H_INDEX combine index access on a sequence
// with a cast to the appropriate result type. H_FIELD is used to access the
// elements of the argument token 'p' in an action. H_INDEX allows any sequence
// token to be specified. Both macro families take an arbitrary number of index
// arguments, giving access to elements in nested sequences by path.
// These macros are very useful to avoid spaghetti chains of unchecked pointer
// dereferences.
//
// Standard short-hand for arena-allocating a variable in a semantic action.
#define H_ALLOC(TYP) ((TYP *) h_arena_malloc(p->arena, sizeof(TYP)))
// Token constructors...
HParsedToken *h_make(HArena *arena, HTokenType type, void *value);
HParsedToken *h_make_seq(HArena *arena); // Makes empty sequence.
HParsedToken *h_make_seqn(HArena *arena, size_t n); // Makes empty sequence of expected size n.
HParsedToken *h_make_bytes(HArena *arena, size_t len);
HParsedToken *h_make_sint(HArena *arena, int64_t val);
HParsedToken *h_make_uint(HArena *arena, uint64_t val);
// Standard short-hands to make tokens in an action.
#define H_MAKE(TYP, VAL) h_make(p->arena, TT_ ## TYP, VAL)
#define H_MAKE_SEQ() h_make_seq(p->arena)
#define H_MAKE_SEQN(N) h_make_seqn(p->arena, N)
#define H_MAKE_BYTES(LEN) h_make_bytes(p->arena, LEN)
#define H_MAKE_SINT(VAL) h_make_sint(p->arena, VAL)
#define H_MAKE_UINT(VAL) h_make_uint(p->arena, VAL)
// Extract (cast) type-specific value back from HParsedTokens...
// Pass-through assertion that a given token has the expected type.
#define h_assert_type(T,P) (assert(P->token_type == (HTokenType)T), P)
// Convenience short-hand forms of h_assert_type.
#define H_ASSERT(TYP, TOK) h_assert_type(TT_ ## TYP, TOK)
#define H_ASSERT_SEQ(TOK) h_assert_type(TT_SEQUENCE, TOK)
#define H_ASSERT_BYTES(TOK) h_assert_type(TT_BYTES, TOK)
#define H_ASSERT_SINT(TOK) h_assert_type(TT_SINT, TOK)
#define H_ASSERT_UINT(TOK) h_assert_type(TT_UINT, TOK)
// Assert expected type and return contained value.
#define H_CAST(TYP, TOK) ((TYP *) H_ASSERT(TYP, TOK)->user)
#define H_CAST_SEQ(TOK) (H_ASSERT_SEQ(TOK)->seq)
#define H_CAST_BYTES(TOK) (H_ASSERT_BYTES(TOK)->bytes)
#define H_CAST_SINT(TOK) (H_ASSERT_SINT(TOK)->sint)
#define H_CAST_UINT(TOK) (H_ASSERT_UINT(TOK)->uint)
// Sequence access...
// Return the length of a sequence.
size_t h_seq_len(const HParsedToken *p);
// Access a sequence's element array.
HParsedToken **h_seq_elements(const HParsedToken *p);
// Access a sequence element by index.
HParsedToken *h_seq_index(const HParsedToken *p, size_t i);
// Access an element in a nested sequence by a path of indices.
HParsedToken *h_seq_index_path(const HParsedToken *p, size_t i, ...);
HParsedToken *h_seq_index_vpath(const HParsedToken *p, size_t i, va_list va);
// Convenience macros combining (nested) index access and h_cast.
#define H_INDEX(TYP, SEQ, ...) H_CAST(TYP, H_INDEX_TOKEN(SEQ, __VA_ARGS__))
#define H_INDEX_SEQ(SEQ, ...) H_CAST_SEQ(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
#define H_INDEX_BYTES(SEQ, ...) H_CAST_BYTES(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
#define H_INDEX_SINT(SEQ, ...) H_CAST_SINT(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
#define H_INDEX_UINT(SEQ, ...) H_CAST_UINT(H_INDEX_TOKEN(SEQ, __VA_ARGS__))
#define H_INDEX_TOKEN(SEQ, ...) h_seq_index_path(SEQ, __VA_ARGS__, -1)
// Standard short-hand to access and cast elements on a sequence token.
#define H_FIELD(TYP, ...) H_INDEX(TYP, p->ast, __VA_ARGS__)
#define H_FIELD_SEQ(...) H_INDEX_SEQ(p->ast, __VA_ARGS__)
#define H_FIELD_BYTES(...) H_INDEX_BYTES(p->ast, __VA_ARGS__)
#define H_FIELD_SINT(...) H_INDEX_SINT(p->ast, __VA_ARGS__)
#define H_FIELD_UINT(...) H_INDEX_UINT(p->ast, __VA_ARGS__)
// Lower-level helper for h_seq_index.
HParsedToken *h_carray_index(const HCountedArray *a, size_t i); // XXX -> internal
// Sequence modification...
// Add elements to a sequence.
void h_seq_snoc(HParsedToken *xs, const HParsedToken *x); // append one
void h_seq_append(HParsedToken *xs, const HParsedToken *ys); // append many
// XXX TODO: Remove elements from a sequence.
// Flatten nested sequences into one.
const HParsedToken *h_seq_flatten(HArena *arena, const HParsedToken *p);
#endif

View file

@ -42,14 +42,15 @@ typedef enum HParserBackend_ {
} HParserBackend;
typedef enum HTokenType_ {
TT_NONE,
TT_BYTES,
TT_SINT,
TT_UINT,
TT_SEQUENCE,
// Before you change the explicit values of these, think of the poor bindings ;_;
TT_NONE = 1,
TT_BYTES = 2,
TT_SINT = 4,
TT_UINT = 8,
TT_SEQUENCE = 16,
TT_RESERVED_1, // reserved for backend-specific internal use
TT_ERR = 32,
TT_USER = 64,
TT_ERR,
TT_MAX
} HTokenType;
@ -60,13 +61,15 @@ typedef struct HCountedArray_ {
struct HParsedToken_ **elements;
} HCountedArray;
typedef struct HBytes_ {
const uint8_t *token;
size_t len;
} HBytes;
typedef struct HParsedToken_ {
HTokenType token_type;
union {
struct {
const uint8_t *token;
size_t len;
} bytes;
HBytes bytes;
int64_t sint;
uint64_t uint;
double dbl;
@ -175,14 +178,18 @@ typedef struct HBenchmarkResults_ {
rtype_t name(__VA_ARGS__, ...); \
rtype_t name##__m(HAllocator* mm__, __VA_ARGS__, ...); \
rtype_t name##__mv(HAllocator* mm__, __VA_ARGS__, va_list ap); \
rtype_t name##__v(__VA_ARGS__, va_list ap)
rtype_t name##__v(__VA_ARGS__, va_list ap); \
rtype_t name##__a(void *args[]); \
rtype_t name##__ma(HAllocator *mm__, void *args[])
// Note: this drops the attributes on the floor for the __v versions
#define HAMMER_FN_DECL_VARARGS_ATTR(attr, rtype_t, name, ...) \
rtype_t name(__VA_ARGS__, ...) attr; \
rtype_t name##__m(HAllocator* mm__, __VA_ARGS__, ...) attr; \
rtype_t name##__mv(HAllocator* mm__, __VA_ARGS__, va_list ap); \
rtype_t name##__v(__VA_ARGS__, va_list ap)
rtype_t name##__v(__VA_ARGS__, va_list ap); \
rtype_t name##__a(void *args[]); \
rtype_t name##__ma(HAllocator *mm__, void *args[])
// }}}

View file

@ -243,6 +243,7 @@ HCountedArray *h_carray_new(HArena * arena);
void h_carray_append(HCountedArray *array, void* item);
HSlist* h_slist_new(HArena *arena);
HSlist* h_slist_copy(HSlist *slist);
void* h_slist_pop(HSlist *slist);
void h_slist_push(HSlist *slist, void* item);
bool h_slist_find(HSlist *slist, const void* item);

View file

@ -126,3 +126,27 @@ HParser* h_choice__mv(HAllocator* mm__, const HParser* p, va_list ap_) {
return h_new_parser(mm__, &choice_vt, s);
}
HParser* h_choice__a(void *args[]) {
return h_choice__ma(&system_allocator, args);
}
HParser* h_choice__ma(HAllocator* mm__, void *args[]) {
size_t len = -1; // because do...while
const HParser *arg;
do {
arg=((HParser **)args)[++len];
} while(arg);
HSequence *s = h_new(HSequence, 1);
s->p_array = h_new(const HParser *, len);
for (size_t i = 0; i < len; i++) {
s->p_array[i] = ((HParser **)args)[i];
}
s->len = len;
HParser *ret = h_new(HParser, 1);
ret->vtable = &choice_vt; ret->env = (void*)s;
return ret;
}

View file

@ -144,3 +144,28 @@ HParser* h_sequence__mv(HAllocator* mm__, const HParser *p, va_list ap_) {
s->len = len;
return h_new_parser(mm__, &sequence_vt, s);
}
HParser* h_sequence__a(void *args[]) {
return h_sequence__ma(&system_allocator, args);
}
HParser* h_sequence__ma(HAllocator* mm__, void *args[]) {
size_t len = -1; // because do...while
const HParser *arg;
do {
arg=((HParser **)args)[++len];
} while(arg);
HSequence *s = h_new(HSequence, 1);
s->p_array = h_new(const HParser *, len);
for (size_t i = 0; i < len; i++) {
s->p_array[i] = ((HParser **)args)[i];
}
s->len = len;
HParser *ret = h_new(HParser, 1);
ret->vtable = &sequence_vt; ret->env = (void*)s;
return ret;
}

View file

@ -9,7 +9,7 @@ static HParseResult* parse_whitespace(void* env, HParseState *state) {
bak = state->input_stream;
c = h_read_bits(&state->input_stream, 8, false);
if (state->input_stream.overrun)
return NULL;
break;
} while (isspace(c));
state->input_stream = bak;
return h_do_parse((HParser*)env, state);

View file

@ -69,7 +69,11 @@ void h_pprint(FILE* stream, const HParsedToken* tok, int indent, int delta) {
fprintf(stream, "%*sUSER\n", indent, "");
break;
default:
assert_message(0, "Should not reach here.");
if(tok->token_type > TT_USER) {
fprintf(stream, "%*sUSER %d\n", indent, "", tok->token_type-TT_USER);
} else {
assert_message(0, "Should not reach here.");
}
}
}

16
src/t_misc.c Normal file
View file

@ -0,0 +1,16 @@
#include <glib.h>
#include "test_suite.h"
#include "hammer.h"
static void test_tt_user(void) {
g_check_cmpint(TT_USER, >, TT_NONE);
g_check_cmpint(TT_USER, >, TT_BYTES);
g_check_cmpint(TT_USER, >, TT_SINT);
g_check_cmpint(TT_USER, >, TT_UINT);
g_check_cmpint(TT_USER, >, TT_SEQUENCE);
g_check_cmpint(TT_USER, >, TT_ERR);
}
void register_misc_tests(void) {
g_test_add_func("/core/misc/tt_user", test_tt_user);
}

View file

@ -5,154 +5,159 @@
#include "test_suite.h"
#include "parsers/parser_internal.h"
static void test_token(void) {
static void test_token(gconstpointer backend) {
const HParser *token_ = h_token((const uint8_t*)"95\xa2", 3);
g_check_parse_ok(token_, "95\xa2", 3, "<39.35.a2>");
g_check_parse_failed(token_, "95", 2);
g_check_parse_ok(token_, (HParserBackend)GPOINTER_TO_INT(backend), "95\xa2", 3, "<39.35.a2>");
g_check_parse_failed(token_, (HParserBackend)GPOINTER_TO_INT(backend), "95", 2);
}
static void test_ch(void) {
static void test_ch(gconstpointer backend) {
const HParser *ch_ = h_ch(0xa2);
g_check_parse_ok(ch_, "\xa2", 1, "u0xa2");
g_check_parse_failed(ch_, "\xa3", 1);
g_check_parse_ok(ch_, (HParserBackend)GPOINTER_TO_INT(backend), "\xa2", 1, "u0xa2");
g_check_parse_failed(ch_, (HParserBackend)GPOINTER_TO_INT(backend), "\xa3", 1);
}
static void test_ch_range(void) {
static void test_ch_range(gconstpointer backend) {
const HParser *range_ = h_ch_range('a', 'c');
g_check_parse_ok(range_, "b", 1, "u0x62");
g_check_parse_failed(range_, "d", 1);
g_check_parse_ok(range_, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_failed(range_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1);
}
//@MARK_START
static void test_int64(void) {
static void test_int64(gconstpointer backend) {
const HParser *int64_ = h_int64();
g_check_parse_ok(int64_, "\xff\xff\xff\xfe\x00\x00\x00\x00", 8, "s-0x200000000");
g_check_parse_failed(int64_, "\xff\xff\xff\xfe\x00\x00\x00", 7);
g_check_parse_ok(int64_, (HParserBackend)GPOINTER_TO_INT(backend), "\xff\xff\xff\xfe\x00\x00\x00\x00", 8, "s-0x200000000");
g_check_parse_failed(int64_, (HParserBackend)GPOINTER_TO_INT(backend), "\xff\xff\xff\xfe\x00\x00\x00", 7);
}
static void test_int32(void) {
static void test_int32(gconstpointer backend) {
const HParser *int32_ = h_int32();
g_check_parse_ok(int32_, "\xff\xfe\x00\x00", 4, "s-0x20000");
g_check_parse_failed(int32_, "\xff\xfe\x00", 3);
g_check_parse_ok(int32_, (HParserBackend)GPOINTER_TO_INT(backend), "\xff\xfe\x00\x00", 4, "s-0x20000");
g_check_parse_failed(int32_, (HParserBackend)GPOINTER_TO_INT(backend), "\xff\xfe\x00", 3);
g_check_parse_ok(int32_, "\x00\x02\x00\x00", 4, "s0x20000");
g_check_parse_failed(int32_, "\x00\x02\x00", 3);
g_check_parse_ok(int32_, (HParserBackend)GPOINTER_TO_INT(backend), "\x00\x02\x00\x00", 4, "s0x20000");
g_check_parse_failed(int32_, (HParserBackend)GPOINTER_TO_INT(backend), "\x00\x02\x00", 3);
}
static void test_int16(void) {
static void test_int16(gconstpointer backend) {
const HParser *int16_ = h_int16();
g_check_parse_ok(int16_, "\xfe\x00", 2, "s-0x200");
g_check_parse_failed(int16_, "\xfe", 1);
g_check_parse_ok(int16_, (HParserBackend)GPOINTER_TO_INT(backend), "\xfe\x00", 2, "s-0x200");
g_check_parse_failed(int16_, (HParserBackend)GPOINTER_TO_INT(backend), "\xfe", 1);
g_check_parse_ok(int16_, "\x02\x00", 2, "s0x200");
g_check_parse_failed(int16_, "\x02", 1);
g_check_parse_ok(int16_, (HParserBackend)GPOINTER_TO_INT(backend), "\x02\x00", 2, "s0x200");
g_check_parse_failed(int16_, (HParserBackend)GPOINTER_TO_INT(backend), "\x02", 1);
}
static void test_int8(void) {
static void test_int8(gconstpointer backend) {
const HParser *int8_ = h_int8();
g_check_parse_ok(int8_, "\x88", 1, "s-0x78");
g_check_parse_failed(int8_, "", 0);
g_check_parse_ok(int8_, (HParserBackend)GPOINTER_TO_INT(backend), "\x88", 1, "s-0x78");
g_check_parse_failed(int8_, (HParserBackend)GPOINTER_TO_INT(backend), "", 0);
}
static void test_uint64(void) {
static void test_uint64(gconstpointer backend) {
const HParser *uint64_ = h_uint64();
g_check_parse_ok(uint64_, "\x00\x00\x00\x02\x00\x00\x00\x00", 8, "u0x200000000");
g_check_parse_failed(uint64_, "\x00\x00\x00\x02\x00\x00\x00", 7);
g_check_parse_ok(uint64_, (HParserBackend)GPOINTER_TO_INT(backend), "\x00\x00\x00\x02\x00\x00\x00\x00", 8, "u0x200000000");
g_check_parse_failed(uint64_, (HParserBackend)GPOINTER_TO_INT(backend), "\x00\x00\x00\x02\x00\x00\x00", 7);
}
static void test_uint32(void) {
static void test_uint32(gconstpointer backend) {
const HParser *uint32_ = h_uint32();
g_check_parse_ok(uint32_, "\x00\x02\x00\x00", 4, "u0x20000");
g_check_parse_failed(uint32_, "\x00\x02\x00", 3);
g_check_parse_ok(uint32_, (HParserBackend)GPOINTER_TO_INT(backend), "\x00\x02\x00\x00", 4, "u0x20000");
g_check_parse_failed(uint32_, (HParserBackend)GPOINTER_TO_INT(backend), "\x00\x02\x00", 3);
}
static void test_uint16(void) {
static void test_uint16(gconstpointer backend) {
const HParser *uint16_ = h_uint16();
g_check_parse_ok(uint16_, "\x02\x00", 2, "u0x200");
g_check_parse_failed(uint16_, "\x02", 1);
g_check_parse_ok(uint16_, (HParserBackend)GPOINTER_TO_INT(backend), "\x02\x00", 2, "u0x200");
g_check_parse_failed(uint16_, (HParserBackend)GPOINTER_TO_INT(backend), "\x02", 1);
}
static void test_uint8(void) {
static void test_uint8(gconstpointer backend) {
const HParser *uint8_ = h_uint8();
g_check_parse_ok(uint8_, "\x78", 1, "u0x78");
g_check_parse_failed(uint8_, "", 0);
g_check_parse_ok(uint8_, (HParserBackend)GPOINTER_TO_INT(backend), "\x78", 1, "u0x78");
g_check_parse_failed(uint8_, (HParserBackend)GPOINTER_TO_INT(backend), "", 0);
}
//@MARK_END
static void test_int_range(void) {
static void test_int_range(gconstpointer backend) {
const HParser *int_range_ = h_int_range(h_uint8(), 3, 10);
g_check_parse_ok(int_range_, "\x05", 1, "u0x5");
g_check_parse_failed(int_range_, "\xb", 1);
g_check_parse_ok(int_range_, (HParserBackend)GPOINTER_TO_INT(backend), "\x05", 1, "u0x5");
g_check_parse_failed(int_range_, (HParserBackend)GPOINTER_TO_INT(backend), "\xb", 1);
}
#if 0
static void test_float64(void) {
static void test_float64(gconstpointer backend) {
const HParser *float64_ = h_float64();
g_check_parse_ok(float64_, "\x3f\xf0\x00\x00\x00\x00\x00\x00", 8, 1.0);
g_check_parse_failed(float64_, "\x3f\xf0\x00\x00\x00\x00\x00", 7);
g_check_parse_ok(float64_, (HParserBackend)GPOINTER_TO_INT(backend), "\x3f\xf0\x00\x00\x00\x00\x00\x00", 8, 1.0);
g_check_parse_failed(float64_, (HParserBackend)GPOINTER_TO_INT(backend), "\x3f\xf0\x00\x00\x00\x00\x00", 7);
}
static void test_float32(void) {
static void test_float32(gconstpointer backend) {
const HParser *float32_ = h_float32();
g_check_parse_ok(float32_, "\x3f\x80\x00\x00", 4, 1.0);
g_check_parse_failed(float32_, "\x3f\x80\x00");
g_check_parse_ok(float32_, (HParserBackend)GPOINTER_TO_INT(backend), "\x3f\x80\x00\x00", 4, 1.0);
g_check_parse_failed(float32_, (HParserBackend)GPOINTER_TO_INT(backend), "\x3f\x80\x00");
}
#endif
static void test_whitespace(void) {
static void test_whitespace(gconstpointer backend) {
const HParser *whitespace_ = h_whitespace(h_ch('a'));
const HParser *whitespace_end = h_whitespace(h_end_p());
g_check_parse_ok(whitespace_, "a", 1, "u0x61");
g_check_parse_ok(whitespace_, " a", 2, "u0x61");
g_check_parse_ok(whitespace_, " a", 3, "u0x61");
g_check_parse_ok(whitespace_, "\ta", 2, "u0x61");
g_check_parse_failed(whitespace_, "_a", 2);
g_check_parse_ok(whitespace_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "u0x61");
g_check_parse_ok(whitespace_, (HParserBackend)GPOINTER_TO_INT(backend), " a", 2, "u0x61");
g_check_parse_ok(whitespace_, (HParserBackend)GPOINTER_TO_INT(backend), " a", 3, "u0x61");
g_check_parse_ok(whitespace_, (HParserBackend)GPOINTER_TO_INT(backend), "\ta", 2, "u0x61");
g_check_parse_failed(whitespace_, (HParserBackend)GPOINTER_TO_INT(backend), "_a", 2);
g_check_parse_ok(whitespace_end, (HParserBackend)GPOINTER_TO_INT(backend), "", 0, "NULL");
g_check_parse_ok(whitespace_end, (HParserBackend)GPOINTER_TO_INT(backend)," ", 2, "NULL");
g_check_parse_failed(whitespace_end, (HParserBackend)GPOINTER_TO_INT(backend)," x", 3);
}
static void test_left(void) {
static void test_left(gconstpointer backend) {
const HParser *left_ = h_left(h_ch('a'), h_ch(' '));
g_check_parse_ok(left_, "a ", 2, "u0x61");
g_check_parse_failed(left_, "a", 1);
g_check_parse_failed(left_, " ", 1);
g_check_parse_failed(left_, "ab", 2);
g_check_parse_ok(left_, (HParserBackend)GPOINTER_TO_INT(backend), "a ", 2, "u0x61");
g_check_parse_failed(left_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1);
g_check_parse_failed(left_, (HParserBackend)GPOINTER_TO_INT(backend), " ", 1);
g_check_parse_failed(left_, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2);
}
static void test_right(void) {
static void test_right(gconstpointer backend) {
const HParser *right_ = h_right(h_ch(' '), h_ch('a'));
g_check_parse_ok(right_, " a", 2, "u0x61");
g_check_parse_failed(right_, "a", 1);
g_check_parse_failed(right_, " ", 1);
g_check_parse_failed(right_, "ba", 2);
g_check_parse_ok(right_, (HParserBackend)GPOINTER_TO_INT(backend), " a", 2, "u0x61");
g_check_parse_failed(right_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1);
g_check_parse_failed(right_, (HParserBackend)GPOINTER_TO_INT(backend), " ", 1);
g_check_parse_failed(right_, (HParserBackend)GPOINTER_TO_INT(backend), "ba", 2);
}
static void test_middle(void) {
static void test_middle(gconstpointer backend) {
const HParser *middle_ = h_middle(h_ch(' '), h_ch('a'), h_ch(' '));
g_check_parse_ok(middle_, " a ", 3, "u0x61");
g_check_parse_failed(middle_, "a", 1);
g_check_parse_failed(middle_, " ", 1);
g_check_parse_failed(middle_, " a", 2);
g_check_parse_failed(middle_, "a ", 2);
g_check_parse_failed(middle_, " b ", 3);
g_check_parse_failed(middle_, "ba ", 3);
g_check_parse_failed(middle_, " ab", 3);
g_check_parse_ok(middle_, (HParserBackend)GPOINTER_TO_INT(backend), " a ", 3, "u0x61");
g_check_parse_failed(middle_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1);
g_check_parse_failed(middle_, (HParserBackend)GPOINTER_TO_INT(backend), " ", 1);
g_check_parse_failed(middle_, (HParserBackend)GPOINTER_TO_INT(backend), " a", 2);
g_check_parse_failed(middle_, (HParserBackend)GPOINTER_TO_INT(backend), "a ", 2);
g_check_parse_failed(middle_, (HParserBackend)GPOINTER_TO_INT(backend), " b ", 3);
g_check_parse_failed(middle_, (HParserBackend)GPOINTER_TO_INT(backend), "ba ", 3);
g_check_parse_failed(middle_, (HParserBackend)GPOINTER_TO_INT(backend), " ab", 3);
}
#include <ctype.h>
@ -189,7 +194,7 @@ const HParsedToken* upcase(const HParseResult *p) {
}
}
static void test_action(void) {
static void test_action(gconstpointer backend) {
const HParser *action_ = h_action(h_sequence(h_choice(h_ch('a'),
h_ch('A'),
NULL),
@ -199,158 +204,158 @@ static void test_action(void) {
NULL),
upcase);
g_check_parse_ok(action_, "ab", 2, "(u0x41 u0x42)");
g_check_parse_ok(action_, "AB", 2, "(u0x41 u0x42)");
g_check_parse_failed(action_, "XX", 2);
g_check_parse_ok(action_, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2, "(u0x41 u0x42)");
g_check_parse_ok(action_, (HParserBackend)GPOINTER_TO_INT(backend), "AB", 2, "(u0x41 u0x42)");
g_check_parse_failed(action_, (HParserBackend)GPOINTER_TO_INT(backend), "XX", 2);
}
static void test_in(void) {
static void test_in(gconstpointer backend) {
uint8_t options[3] = { 'a', 'b', 'c' };
const HParser *in_ = h_in(options, 3);
g_check_parse_ok(in_, "b", 1, "u0x62");
g_check_parse_failed(in_, "d", 1);
g_check_parse_ok(in_, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_failed(in_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1);
}
static void test_not_in(void) {
static void test_not_in(gconstpointer backend) {
uint8_t options[3] = { 'a', 'b', 'c' };
const HParser *not_in_ = h_not_in(options, 3);
g_check_parse_ok(not_in_, "d", 1, "u0x64");
g_check_parse_failed(not_in_, "a", 1);
g_check_parse_ok(not_in_, (HParserBackend)GPOINTER_TO_INT(backend), "d", 1, "u0x64");
g_check_parse_failed(not_in_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1);
}
static void test_end_p(void) {
static void test_end_p(gconstpointer backend) {
const HParser *end_p_ = h_sequence(h_ch('a'), h_end_p(), NULL);
g_check_parse_ok(end_p_, "a", 1, "(u0x61)");
g_check_parse_failed(end_p_, "aa", 2);
g_check_parse_ok(end_p_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "(u0x61)");
g_check_parse_failed(end_p_, (HParserBackend)GPOINTER_TO_INT(backend), "aa", 2);
}
static void test_nothing_p(void) {
static void test_nothing_p(gconstpointer backend) {
const HParser *nothing_p_ = h_nothing_p();
g_check_parse_failed(nothing_p_, "a", 1);
g_check_parse_failed(nothing_p_, (HParserBackend)GPOINTER_TO_INT(backend),"a", 1);
}
static void test_sequence(void) {
static void test_sequence(gconstpointer backend) {
const HParser *sequence_1 = h_sequence(h_ch('a'), h_ch('b'), NULL);
const HParser *sequence_2 = h_sequence(h_ch('a'), h_whitespace(h_ch('b')), NULL);
g_check_parse_ok(sequence_1, "ab", 2, "(u0x61 u0x62)");
g_check_parse_failed(sequence_1, "a", 1);
g_check_parse_failed(sequence_1, "b", 1);
g_check_parse_ok(sequence_2, "ab", 2, "(u0x61 u0x62)");
g_check_parse_ok(sequence_2, "a b", 3, "(u0x61 u0x62)");
g_check_parse_ok(sequence_2, "a b", 4, "(u0x61 u0x62)");
g_check_parse_ok(sequence_1, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2, "(u0x61 u0x62)");
g_check_parse_failed(sequence_1, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1);
g_check_parse_failed(sequence_1, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1);
g_check_parse_ok(sequence_2, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2, "(u0x61 u0x62)");
g_check_parse_ok(sequence_2, (HParserBackend)GPOINTER_TO_INT(backend), "a b", 3, "(u0x61 u0x62)");
g_check_parse_ok(sequence_2, (HParserBackend)GPOINTER_TO_INT(backend), "a b", 4, "(u0x61 u0x62)");
}
static void test_choice(void) {
static void test_choice(gconstpointer backend) {
const HParser *choice_ = h_choice(h_ch('a'), h_ch('b'), NULL);
g_check_parse_ok(choice_, "a", 1, "u0x61");
g_check_parse_ok(choice_, "b", 1, "u0x62");
g_check_parse_failed(choice_, "c", 1);
g_check_parse_ok(choice_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "u0x61");
g_check_parse_ok(choice_, (HParserBackend)GPOINTER_TO_INT(backend), "b", 1, "u0x62");
g_check_parse_failed(choice_, (HParserBackend)GPOINTER_TO_INT(backend), "c", 1);
}
static void test_butnot(void) {
static void test_butnot(gconstpointer backend) {
const HParser *butnot_1 = h_butnot(h_ch('a'), h_token((const uint8_t*)"ab", 2));
const HParser *butnot_2 = h_butnot(h_ch_range('0', '9'), h_ch('6'));
g_check_parse_ok(butnot_1, "a", 1, "u0x61");
g_check_parse_failed(butnot_1, "ab", 2);
g_check_parse_ok(butnot_1, "aa", 2, "u0x61");
g_check_parse_failed(butnot_2, "6", 1);
g_check_parse_ok(butnot_1, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "u0x61");
g_check_parse_failed(butnot_1, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2);
g_check_parse_ok(butnot_1, (HParserBackend)GPOINTER_TO_INT(backend), "aa", 2, "u0x61");
g_check_parse_failed(butnot_2, (HParserBackend)GPOINTER_TO_INT(backend), "6", 1);
}
static void test_difference(void) {
static void test_difference(gconstpointer backend) {
const HParser *difference_ = h_difference(h_token((const uint8_t*)"ab", 2), h_ch('a'));
g_check_parse_ok(difference_, "ab", 2, "<61.62>");
g_check_parse_failed(difference_, "a", 1);
g_check_parse_ok(difference_, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2, "<61.62>");
g_check_parse_failed(difference_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1);
}
static void test_xor(void) {
static void test_xor(gconstpointer backend) {
const HParser *xor_ = h_xor(h_ch_range('0', '6'), h_ch_range('5', '9'));
g_check_parse_ok(xor_, "0", 1, "u0x30");
g_check_parse_ok(xor_, "9", 1, "u0x39");
g_check_parse_failed(xor_, "5", 1);
g_check_parse_failed(xor_, "a", 1);
g_check_parse_ok(xor_, (HParserBackend)GPOINTER_TO_INT(backend), "0", 1, "u0x30");
g_check_parse_ok(xor_, (HParserBackend)GPOINTER_TO_INT(backend), "9", 1, "u0x39");
g_check_parse_failed(xor_, (HParserBackend)GPOINTER_TO_INT(backend), "5", 1);
g_check_parse_failed(xor_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1);
}
static void test_many(void) {
static void test_many(gconstpointer backend) {
const HParser *many_ = h_many(h_choice(h_ch('a'), h_ch('b'), NULL));
g_check_parse_ok(many_, "", 0, "()");
g_check_parse_ok(many_, "adef", 4, "(u0x61)");
g_check_parse_ok(many_, "bdef", 4, "(u0x62)");
g_check_parse_ok(many_, "aabbabadef", 10, "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)");
g_check_parse_ok(many_, "daabbabadef", 11, "()");
g_check_parse_ok(many_, (HParserBackend)GPOINTER_TO_INT(backend), "", 0, "()");
g_check_parse_ok(many_, (HParserBackend)GPOINTER_TO_INT(backend), "adef", 4, "(u0x61)");
g_check_parse_ok(many_, (HParserBackend)GPOINTER_TO_INT(backend), "bdef", 4, "(u0x62)");
g_check_parse_ok(many_, (HParserBackend)GPOINTER_TO_INT(backend), "aabbabadef", 10, "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)");
g_check_parse_ok(many_, (HParserBackend)GPOINTER_TO_INT(backend), "daabbabadef", 11, "()");
}
static void test_many1(void) {
static void test_many1(gconstpointer backend) {
const HParser *many1_ = h_many1(h_choice(h_ch('a'), h_ch('b'), NULL));
g_check_parse_failed(many1_, "", 0);
g_check_parse_ok(many1_, "adef", 4, "(u0x61)");
g_check_parse_ok(many1_, "bdef", 4, "(u0x62)");
g_check_parse_ok(many1_, "aabbabadef", 10, "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)");
g_check_parse_failed(many1_, "daabbabadef", 11);
g_check_parse_failed(many1_, (HParserBackend)GPOINTER_TO_INT(backend), "", 0);
g_check_parse_ok(many1_, (HParserBackend)GPOINTER_TO_INT(backend), "adef", 4, "(u0x61)");
g_check_parse_ok(many1_, (HParserBackend)GPOINTER_TO_INT(backend), "bdef", 4, "(u0x62)");
g_check_parse_ok(many1_, (HParserBackend)GPOINTER_TO_INT(backend), "aabbabadef", 10, "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)");
g_check_parse_failed(many1_, (HParserBackend)GPOINTER_TO_INT(backend), "daabbabadef", 11);
}
static void test_repeat_n(void) {
static void test_repeat_n(gconstpointer backend) {
const HParser *repeat_n_ = h_repeat_n(h_choice(h_ch('a'), h_ch('b'), NULL), 2);
g_check_parse_failed(repeat_n_, "adef", 4);
g_check_parse_ok(repeat_n_, "abdef", 5, "(u0x61 u0x62)");
g_check_parse_failed(repeat_n_, "dabdef", 6);
g_check_parse_failed(repeat_n_, (HParserBackend)GPOINTER_TO_INT(backend), "adef", 4);
g_check_parse_ok(repeat_n_, (HParserBackend)GPOINTER_TO_INT(backend), "abdef", 5, "(u0x61 u0x62)");
g_check_parse_failed(repeat_n_, (HParserBackend)GPOINTER_TO_INT(backend), "dabdef", 6);
}
static void test_optional(void) {
static void test_optional(gconstpointer backend) {
const HParser *optional_ = h_sequence(h_ch('a'), h_optional(h_choice(h_ch('b'), h_ch('c'), NULL)), h_ch('d'), NULL);
g_check_parse_ok(optional_, "abd", 3, "(u0x61 u0x62 u0x64)");
g_check_parse_ok(optional_, "acd", 3, "(u0x61 u0x63 u0x64)");
g_check_parse_ok(optional_, "ad", 2, "(u0x61 null u0x64)");
g_check_parse_failed(optional_, "aed", 3);
g_check_parse_failed(optional_, "ab", 2);
g_check_parse_failed(optional_, "ac", 2);
g_check_parse_ok(optional_, (HParserBackend)GPOINTER_TO_INT(backend), "abd", 3, "(u0x61 u0x62 u0x64)");
g_check_parse_ok(optional_, (HParserBackend)GPOINTER_TO_INT(backend), "acd", 3, "(u0x61 u0x63 u0x64)");
g_check_parse_ok(optional_, (HParserBackend)GPOINTER_TO_INT(backend), "ad", 2, "(u0x61 null u0x64)");
g_check_parse_failed(optional_, (HParserBackend)GPOINTER_TO_INT(backend), "aed", 3);
g_check_parse_failed(optional_, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2);
g_check_parse_failed(optional_, (HParserBackend)GPOINTER_TO_INT(backend), "ac", 2);
}
static void test_ignore(void) {
static void test_ignore(gconstpointer backend) {
const HParser *ignore_ = h_sequence(h_ch('a'), h_ignore(h_ch('b')), h_ch('c'), NULL);
g_check_parse_ok(ignore_, "abc", 3, "(u0x61 u0x63)");
g_check_parse_failed(ignore_, "ac", 2);
g_check_parse_ok(ignore_, (HParserBackend)GPOINTER_TO_INT(backend), "abc", 3, "(u0x61 u0x63)");
g_check_parse_failed(ignore_, (HParserBackend)GPOINTER_TO_INT(backend), "ac", 2);
}
static void test_sepBy(void) {
static void test_sepBy(gconstpointer backend) {
const HParser *sepBy_ = h_sepBy(h_choice(h_ch('1'), h_ch('2'), h_ch('3'), NULL), h_ch(','));
g_check_parse_ok(sepBy_, "1,2,3", 5, "(u0x31 u0x32 u0x33)");
g_check_parse_ok(sepBy_, "1,3,2", 5, "(u0x31 u0x33 u0x32)");
g_check_parse_ok(sepBy_, "1,3", 3, "(u0x31 u0x33)");
g_check_parse_ok(sepBy_, "3", 1, "(u0x33)");
g_check_parse_ok(sepBy_, "", 0, "()");
g_check_parse_ok(sepBy_, (HParserBackend)GPOINTER_TO_INT(backend), "1,2,3", 5, "(u0x31 u0x32 u0x33)");
g_check_parse_ok(sepBy_, (HParserBackend)GPOINTER_TO_INT(backend), "1,3,2", 5, "(u0x31 u0x33 u0x32)");
g_check_parse_ok(sepBy_, (HParserBackend)GPOINTER_TO_INT(backend), "1,3", 3, "(u0x31 u0x33)");
g_check_parse_ok(sepBy_, (HParserBackend)GPOINTER_TO_INT(backend), "3", 1, "(u0x33)");
g_check_parse_ok(sepBy_, (HParserBackend)GPOINTER_TO_INT(backend), "", 0, "()");
}
static void test_sepBy1(void) {
static void test_sepBy1(gconstpointer backend) {
const HParser *sepBy1_ = h_sepBy1(h_choice(h_ch('1'), h_ch('2'), h_ch('3'), NULL), h_ch(','));
g_check_parse_ok(sepBy1_, "1,2,3", 5, "(u0x31 u0x32 u0x33)");
g_check_parse_ok(sepBy1_, "1,3,2", 5, "(u0x31 u0x33 u0x32)");
g_check_parse_ok(sepBy1_, "1,3", 3, "(u0x31 u0x33)");
g_check_parse_ok(sepBy1_, "3", 1, "(u0x33)");
g_check_parse_failed(sepBy1_, "", 0);
g_check_parse_ok(sepBy1_, (HParserBackend)GPOINTER_TO_INT(backend), "1,2,3", 5, "(u0x31 u0x32 u0x33)");
g_check_parse_ok(sepBy1_, (HParserBackend)GPOINTER_TO_INT(backend), "1,3,2", 5, "(u0x31 u0x33 u0x32)");
g_check_parse_ok(sepBy1_, (HParserBackend)GPOINTER_TO_INT(backend), "1,3", 3, "(u0x31 u0x33)");
g_check_parse_ok(sepBy1_, (HParserBackend)GPOINTER_TO_INT(backend), "3", 1, "(u0x33)");
g_check_parse_failed(sepBy1_, (HParserBackend)GPOINTER_TO_INT(backend), "", 0);
}
static void test_epsilon_p(void) {
static void test_epsilon_p(gconstpointer backend) {
const HParser *epsilon_p_1 = h_sequence(h_ch('a'), h_epsilon_p(), h_ch('b'), NULL);
const HParser *epsilon_p_2 = h_sequence(h_epsilon_p(), h_ch('a'), NULL);
const HParser *epsilon_p_3 = h_sequence(h_ch('a'), h_epsilon_p(), NULL);
g_check_parse_ok(epsilon_p_1, "ab", 2, "(u0x61 u0x62)");
g_check_parse_ok(epsilon_p_2, "a", 1, "(u0x61)");
g_check_parse_ok(epsilon_p_3, "a", 1, "(u0x61)");
g_check_parse_ok(epsilon_p_1, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2, "(u0x61 u0x62)");
g_check_parse_ok(epsilon_p_2, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "(u0x61)");
g_check_parse_ok(epsilon_p_3, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "(u0x61)");
}
bool validate_test_ab(HParseResult *p) {
@ -363,78 +368,163 @@ bool validate_test_ab(HParseResult *p) {
return (p->ast->seq->elements[0]->uint == p->ast->seq->elements[1]->uint);
}
static void test_attr_bool(void) {
static void test_attr_bool(gconstpointer backend) {
const HParser *ab_ = h_attr_bool(h_many1(h_choice(h_ch('a'), h_ch('b'), NULL)),
validate_test_ab);
g_check_parse_ok(ab_, "aa", 2, "(u0x61 u0x61)");
g_check_parse_ok(ab_, "bb", 2, "(u0x62 u0x62)");
g_check_parse_failed(ab_, "ab", 2);
g_check_parse_ok(ab_, (HParserBackend)GPOINTER_TO_INT(backend), "aa", 2, "(u0x61 u0x61)");
g_check_parse_ok(ab_, (HParserBackend)GPOINTER_TO_INT(backend), "bb", 2, "(u0x62 u0x62)");
g_check_parse_failed(ab_, (HParserBackend)GPOINTER_TO_INT(backend), "ab", 2);
}
static void test_and(void) {
static void test_and(gconstpointer backend) {
const HParser *and_1 = h_sequence(h_and(h_ch('0')), h_ch('0'), NULL);
const HParser *and_2 = h_sequence(h_and(h_ch('0')), h_ch('1'), NULL);
const HParser *and_3 = h_sequence(h_ch('1'), h_and(h_ch('2')), NULL);
g_check_parse_ok(and_1, "0", 1, "(u0x30)");
g_check_parse_failed(and_2, "0", 1);
g_check_parse_ok(and_3, "12", 2, "(u0x31)");
g_check_parse_ok(and_1, (HParserBackend)GPOINTER_TO_INT(backend), "0", 1, "(u0x30)");
g_check_parse_failed(and_2, (HParserBackend)GPOINTER_TO_INT(backend), "0", 1);
g_check_parse_ok(and_3, (HParserBackend)GPOINTER_TO_INT(backend), "12", 2, "(u0x31)");
}
static void test_not(void) {
static void test_not(gconstpointer backend) {
const HParser *not_1 = h_sequence(h_ch('a'), h_choice(h_ch('+'), h_token((const uint8_t*)"++", 2), NULL), h_ch('b'), NULL);
const HParser *not_2 = h_sequence(h_ch('a'),
h_choice(h_sequence(h_ch('+'), h_not(h_ch('+')), NULL),
h_token((const uint8_t*)"++", 2),
NULL), h_ch('b'), NULL);
g_check_parse_ok(not_1, "a+b", 3, "(u0x61 u0x2b u0x62)");
g_check_parse_failed(not_1, "a++b", 4);
g_check_parse_ok(not_2, "a+b", 3, "(u0x61 (u0x2b) u0x62)");
g_check_parse_ok(not_2, "a++b", 4, "(u0x61 <2b.2b> u0x62)");
g_check_parse_ok(not_1, (HParserBackend)GPOINTER_TO_INT(backend), "a+b", 3, "(u0x61 u0x2b u0x62)");
g_check_parse_failed(not_1, (HParserBackend)GPOINTER_TO_INT(backend), "a++b", 4);
g_check_parse_ok(not_2, (HParserBackend)GPOINTER_TO_INT(backend), "a+b", 3, "(u0x61 (u0x2b) u0x62)");
g_check_parse_ok(not_2, (HParserBackend)GPOINTER_TO_INT(backend), "a++b", 4, "(u0x61 <2b.2b> u0x62)");
}
static void test_leftrec(gconstpointer backend) {
const HParser *a_ = h_ch('a');
HParser *lr_ = h_indirect();
h_bind_indirect(lr_, h_choice(h_sequence(lr_, a_, NULL), a_, NULL));
g_check_parse_ok(lr_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "u0x61");
g_check_parse_ok(lr_, (HParserBackend)GPOINTER_TO_INT(backend), "aa", 2, "(u0x61 u0x61)");
g_check_parse_ok(lr_, (HParserBackend)GPOINTER_TO_INT(backend), "aaa", 3, "((u0x61 u0x61) u0x61)");
}
void register_parser_tests(void) {
g_test_add_func("/core/parser/token", test_token);
g_test_add_func("/core/parser/ch", test_ch);
g_test_add_func("/core/parser/ch_range", test_ch_range);
g_test_add_func("/core/parser/int64", test_int64);
g_test_add_func("/core/parser/int32", test_int32);
g_test_add_func("/core/parser/int16", test_int16);
g_test_add_func("/core/parser/int8", test_int8);
g_test_add_func("/core/parser/uint64", test_uint64);
g_test_add_func("/core/parser/uint32", test_uint32);
g_test_add_func("/core/parser/uint16", test_uint16);
g_test_add_func("/core/parser/uint8", test_uint8);
g_test_add_func("/core/parser/int_range", test_int_range);
g_test_add_data_func("/core/parser/packrat/token", GINT_TO_POINTER(PB_PACKRAT), test_token);
g_test_add_data_func("/core/parser/packrat/ch", GINT_TO_POINTER(PB_PACKRAT), test_ch);
g_test_add_data_func("/core/parser/packrat/ch_range", GINT_TO_POINTER(PB_PACKRAT), test_ch_range);
g_test_add_data_func("/core/parser/packrat/int64", GINT_TO_POINTER(PB_PACKRAT), test_int64);
g_test_add_data_func("/core/parser/packrat/int32", GINT_TO_POINTER(PB_PACKRAT), test_int32);
g_test_add_data_func("/core/parser/packrat/int16", GINT_TO_POINTER(PB_PACKRAT), test_int16);
g_test_add_data_func("/core/parser/packrat/int8", GINT_TO_POINTER(PB_PACKRAT), test_int8);
g_test_add_data_func("/core/parser/packrat/uint64", GINT_TO_POINTER(PB_PACKRAT), test_uint64);
g_test_add_data_func("/core/parser/packrat/uint32", GINT_TO_POINTER(PB_PACKRAT), test_uint32);
g_test_add_data_func("/core/parser/packrat/uint16", GINT_TO_POINTER(PB_PACKRAT), test_uint16);
g_test_add_data_func("/core/parser/packrat/uint8", GINT_TO_POINTER(PB_PACKRAT), test_uint8);
g_test_add_data_func("/core/parser/packrat/int_range", GINT_TO_POINTER(PB_PACKRAT), test_int_range);
#if 0
g_test_add_func("/core/parser/float64", test_float64);
g_test_add_func("/core/parser/float32", test_float32);
g_test_add_data_func("/core/parser/packrat/float64", GINT_TO_POINTER(PB_PACKRAT), test_float64);
g_test_add_data_func("/core/parser/packrat/float32", GINT_TO_POINTER(PB_PACKRAT), test_float32);
#endif
g_test_add_func("/core/parser/whitespace", test_whitespace);
g_test_add_func("/core/parser/left", test_left);
g_test_add_func("/core/parser/right", test_right);
g_test_add_func("/core/parser/middle", test_middle);
g_test_add_func("/core/parser/action", test_action);
g_test_add_func("/core/parser/in", test_in);
g_test_add_func("/core/parser/not_in", test_not_in);
g_test_add_func("/core/parser/end_p", test_end_p);
g_test_add_func("/core/parser/nothing_p", test_nothing_p);
g_test_add_func("/core/parser/sequence", test_sequence);
g_test_add_func("/core/parser/choice", test_choice);
g_test_add_func("/core/parser/butnot", test_butnot);
g_test_add_func("/core/parser/difference", test_difference);
g_test_add_func("/core/parser/xor", test_xor);
g_test_add_func("/core/parser/many", test_many);
g_test_add_func("/core/parser/many1", test_many1);
g_test_add_func("/core/parser/repeat_n", test_repeat_n);
g_test_add_func("/core/parser/optional", test_optional);
g_test_add_func("/core/parser/sepBy", test_sepBy);
g_test_add_func("/core/parser/sepBy1", test_sepBy1);
g_test_add_func("/core/parser/epsilon_p", test_epsilon_p);
g_test_add_func("/core/parser/attr_bool", test_attr_bool);
g_test_add_func("/core/parser/and", test_and);
g_test_add_func("/core/parser/not", test_not);
g_test_add_func("/core/parser/ignore", test_ignore);
g_test_add_data_func("/core/parser/packrat/whitespace", GINT_TO_POINTER(PB_PACKRAT), test_whitespace);
g_test_add_data_func("/core/parser/packrat/left", GINT_TO_POINTER(PB_PACKRAT), test_left);
g_test_add_data_func("/core/parser/packrat/right", GINT_TO_POINTER(PB_PACKRAT), test_right);
g_test_add_data_func("/core/parser/packrat/middle", GINT_TO_POINTER(PB_PACKRAT), test_middle);
g_test_add_data_func("/core/parser/packrat/action", GINT_TO_POINTER(PB_PACKRAT), test_action);
g_test_add_data_func("/core/parser/packrat/in", GINT_TO_POINTER(PB_PACKRAT), test_in);
g_test_add_data_func("/core/parser/packrat/not_in", GINT_TO_POINTER(PB_PACKRAT), test_not_in);
g_test_add_data_func("/core/parser/packrat/end_p", GINT_TO_POINTER(PB_PACKRAT), test_end_p);
g_test_add_data_func("/core/parser/packrat/nothing_p", GINT_TO_POINTER(PB_PACKRAT), test_nothing_p);
g_test_add_data_func("/core/parser/packrat/sequence", GINT_TO_POINTER(PB_PACKRAT), test_sequence);
g_test_add_data_func("/core/parser/packrat/choice", GINT_TO_POINTER(PB_PACKRAT), test_choice);
g_test_add_data_func("/core/parser/packrat/butnot", GINT_TO_POINTER(PB_PACKRAT), test_butnot);
g_test_add_data_func("/core/parser/packrat/difference", GINT_TO_POINTER(PB_PACKRAT), test_difference);
g_test_add_data_func("/core/parser/packrat/xor", GINT_TO_POINTER(PB_PACKRAT), test_xor);
g_test_add_data_func("/core/parser/packrat/many", GINT_TO_POINTER(PB_PACKRAT), test_many);
g_test_add_data_func("/core/parser/packrat/many1", GINT_TO_POINTER(PB_PACKRAT), test_many1);
g_test_add_data_func("/core/parser/packrat/repeat_n", GINT_TO_POINTER(PB_PACKRAT), test_repeat_n);
g_test_add_data_func("/core/parser/packrat/optional", GINT_TO_POINTER(PB_PACKRAT), test_optional);
g_test_add_data_func("/core/parser/packrat/sepBy", GINT_TO_POINTER(PB_PACKRAT), test_sepBy);
g_test_add_data_func("/core/parser/packrat/sepBy1", GINT_TO_POINTER(PB_PACKRAT), test_sepBy1);
g_test_add_data_func("/core/parser/packrat/epsilon_p", GINT_TO_POINTER(PB_PACKRAT), test_epsilon_p);
g_test_add_data_func("/core/parser/packrat/attr_bool", GINT_TO_POINTER(PB_PACKRAT), test_attr_bool);
g_test_add_data_func("/core/parser/packrat/and", GINT_TO_POINTER(PB_PACKRAT), test_and);
g_test_add_data_func("/core/parser/packrat/not", GINT_TO_POINTER(PB_PACKRAT), test_not);
g_test_add_data_func("/core/parser/packrat/ignore", GINT_TO_POINTER(PB_PACKRAT), test_ignore);
g_test_add_data_func("/core/parser/leftrec", GINT_TO_POINTER(PB_PACKRAT), test_leftrec);
g_test_add_data_func("/core/parser/llk/token", GINT_TO_POINTER(PB_LLk), test_token);
g_test_add_data_func("/core/parser/llk/ch", GINT_TO_POINTER(PB_LLk), test_ch);
g_test_add_data_func("/core/parser/llk/ch_range", GINT_TO_POINTER(PB_LLk), test_ch_range);
g_test_add_data_func("/core/parser/llk/int64", GINT_TO_POINTER(PB_LLk), test_int64);
g_test_add_data_func("/core/parser/llk/int32", GINT_TO_POINTER(PB_LLk), test_int32);
g_test_add_data_func("/core/parser/llk/int16", GINT_TO_POINTER(PB_LLk), test_int16);
g_test_add_data_func("/core/parser/llk/int8", GINT_TO_POINTER(PB_LLk), test_int8);
g_test_add_data_func("/core/parser/llk/uint64", GINT_TO_POINTER(PB_LLk), test_uint64);
g_test_add_data_func("/core/parser/llk/uint32", GINT_TO_POINTER(PB_LLk), test_uint32);
g_test_add_data_func("/core/parser/llk/uint16", GINT_TO_POINTER(PB_LLk), test_uint16);
g_test_add_data_func("/core/parser/llk/uint8", GINT_TO_POINTER(PB_LLk), test_uint8);
g_test_add_data_func("/core/parser/llk/int_range", GINT_TO_POINTER(PB_LLk), test_int_range);
#if 0
g_test_add_data_func("/core/parser/llk/float64", GINT_TO_POINTER(PB_LLk), test_float64);
g_test_add_data_func("/core/parser/llk/float32", GINT_TO_POINTER(PB_LLk), test_float32);
#endif
g_test_add_data_func("/core/parser/llk/whitespace", GINT_TO_POINTER(PB_LLk), test_whitespace);
g_test_add_data_func("/core/parser/llk/left", GINT_TO_POINTER(PB_LLk), test_left);
g_test_add_data_func("/core/parser/llk/right", GINT_TO_POINTER(PB_LLk), test_right);
g_test_add_data_func("/core/parser/llk/middle", GINT_TO_POINTER(PB_LLk), test_middle);
g_test_add_data_func("/core/parser/llk/action", GINT_TO_POINTER(PB_LLk), test_action);
g_test_add_data_func("/core/parser/llk/in", GINT_TO_POINTER(PB_LLk), test_in);
g_test_add_data_func("/core/parser/llk/not_in", GINT_TO_POINTER(PB_LLk), test_not_in);
g_test_add_data_func("/core/parser/llk/end_p", GINT_TO_POINTER(PB_LLk), test_end_p);
g_test_add_data_func("/core/parser/llk/nothing_p", GINT_TO_POINTER(PB_LLk), test_nothing_p);
g_test_add_data_func("/core/parser/llk/sequence", GINT_TO_POINTER(PB_LLk), test_sequence);
g_test_add_data_func("/core/parser/llk/choice", GINT_TO_POINTER(PB_LLk), test_choice);
g_test_add_data_func("/core/parser/llk/many", GINT_TO_POINTER(PB_LLk), test_many);
g_test_add_data_func("/core/parser/llk/many1", GINT_TO_POINTER(PB_LLk), test_many1);
g_test_add_data_func("/core/parser/llk/optional", GINT_TO_POINTER(PB_LLk), test_optional);
g_test_add_data_func("/core/parser/llk/sepBy", GINT_TO_POINTER(PB_LLk), test_sepBy);
g_test_add_data_func("/core/parser/llk/sepBy1", GINT_TO_POINTER(PB_LLk), test_sepBy1);
g_test_add_data_func("/core/parser/llk/epsilon_p", GINT_TO_POINTER(PB_LLk), test_epsilon_p);
g_test_add_data_func("/core/parser/llk/attr_bool", GINT_TO_POINTER(PB_LLk), test_attr_bool);
g_test_add_data_func("/core/parser/llk/ignore", GINT_TO_POINTER(PB_LLk), test_ignore);
g_test_add_data_func("/core/parser/leftrec", GINT_TO_POINTER(PB_LLk), test_leftrec);
g_test_add_data_func("/core/parser/regex/token", GINT_TO_POINTER(PB_REGULAR), test_token);
g_test_add_data_func("/core/parser/regex/ch", GINT_TO_POINTER(PB_REGULAR), test_ch);
g_test_add_data_func("/core/parser/regex/ch_range", GINT_TO_POINTER(PB_REGULAR), test_ch_range);
g_test_add_data_func("/core/parser/regex/int64", GINT_TO_POINTER(PB_REGULAR), test_int64);
g_test_add_data_func("/core/parser/regex/int32", GINT_TO_POINTER(PB_REGULAR), test_int32);
g_test_add_data_func("/core/parser/regex/int16", GINT_TO_POINTER(PB_REGULAR), test_int16);
g_test_add_data_func("/core/parser/regex/int8", GINT_TO_POINTER(PB_REGULAR), test_int8);
g_test_add_data_func("/core/parser/regex/uint64", GINT_TO_POINTER(PB_REGULAR), test_uint64);
g_test_add_data_func("/core/parser/regex/uint32", GINT_TO_POINTER(PB_REGULAR), test_uint32);
g_test_add_data_func("/core/parser/regex/uint16", GINT_TO_POINTER(PB_REGULAR), test_uint16);
g_test_add_data_func("/core/parser/regex/uint8", GINT_TO_POINTER(PB_REGULAR), test_uint8);
g_test_add_data_func("/core/parser/regex/int_range", GINT_TO_POINTER(PB_REGULAR), test_int_range);
#if 0
g_test_add_data_func("/core/parser/regex/float64", GINT_TO_POINTER(PB_REGULAR), test_float64);
g_test_add_data_func("/core/parser/regex/float32", GINT_TO_POINTER(PB_REGULAR), test_float32);
#endif
g_test_add_data_func("/core/parser/regex/whitespace", GINT_TO_POINTER(PB_REGULAR), test_whitespace);
g_test_add_data_func("/core/parser/regex/left", GINT_TO_POINTER(PB_REGULAR), test_left);
g_test_add_data_func("/core/parser/regex/right", GINT_TO_POINTER(PB_REGULAR), test_right);
g_test_add_data_func("/core/parser/regex/middle", GINT_TO_POINTER(PB_REGULAR), test_middle);
g_test_add_data_func("/core/parser/regex/action", GINT_TO_POINTER(PB_REGULAR), test_action);
g_test_add_data_func("/core/parser/regex/in", GINT_TO_POINTER(PB_REGULAR), test_in);
g_test_add_data_func("/core/parser/regex/not_in", GINT_TO_POINTER(PB_REGULAR), test_not_in);
g_test_add_data_func("/core/parser/regex/end_p", GINT_TO_POINTER(PB_REGULAR), test_end_p);
g_test_add_data_func("/core/parser/regex/nothing_p", GINT_TO_POINTER(PB_REGULAR), test_nothing_p);
g_test_add_data_func("/core/parser/regex/sequence", GINT_TO_POINTER(PB_REGULAR), test_sequence);
g_test_add_data_func("/core/parser/regex/choice", GINT_TO_POINTER(PB_REGULAR), test_choice);
g_test_add_data_func("/core/parser/regex/many", GINT_TO_POINTER(PB_REGULAR), test_many);
g_test_add_data_func("/core/parser/regex/many1", GINT_TO_POINTER(PB_REGULAR), test_many1);
g_test_add_data_func("/core/parser/regex/optional", GINT_TO_POINTER(PB_REGULAR), test_optional);
g_test_add_data_func("/core/parser/regex/sepBy", GINT_TO_POINTER(PB_REGULAR), test_sepBy);
g_test_add_data_func("/core/parser/regex/sepBy1", GINT_TO_POINTER(PB_REGULAR), test_sepBy1);
g_test_add_data_func("/core/parser/regex/epsilon_p", GINT_TO_POINTER(PB_REGULAR), test_epsilon_p);
g_test_add_data_func("/core/parser/regex/attr_bool", GINT_TO_POINTER(PB_REGULAR), test_attr_bool);
g_test_add_data_func("/core/parser/regex/ignore", GINT_TO_POINTER(PB_REGULAR), test_ignore);
}

View file

@ -23,6 +23,7 @@ extern void register_bitreader_tests();
extern void register_bitwriter_tests();
extern void register_parser_tests();
extern void register_grammar_tests();
extern void register_misc_tests();
extern void register_benchmark_tests();
int main(int argc, char** argv) {
@ -33,6 +34,7 @@ int main(int argc, char** argv) {
register_bitwriter_tests();
register_parser_tests();
register_grammar_tests();
register_misc_tests();
register_benchmark_tests();
g_test_run();

View file

@ -83,8 +83,8 @@
} \
} while(0)
#define g_check_parse_failed(parser, input, inp_len) do { \
int skip = h_compile((HParser *)(parser), PB_LLk, NULL); \
#define g_check_parse_failed(parser, backend, input, inp_len) do { \
int skip = h_compile((HParser *)(parser), (HParserBackend)backend, NULL); \
if(skip != 0) { \
g_test_message("Backend not applicable, skipping test"); \
break; \
@ -96,9 +96,9 @@
} \
} while(0)
#define g_check_parse_ok(parser, input, inp_len, result) do { \
int skip = h_compile((HParser *)(parser), PB_LLk, NULL); \
if(skip) { \
#define g_check_parse_ok(parser, backend, input, inp_len, result) do { \
int skip = h_compile((HParser *)(parser), (HParserBackend) backend, NULL); \
if(skip) { \
g_test_message("Backend not applicable, skipping test"); \
break; \
} \