hammer/src/backends/contextfree.h
Joe Rozner bb02aa18e7 Add warning message
Specify warning for internal only headers that are now installed for use
by extensions.
2013-11-21 22:09:25 -08:00

158 lines
5.2 KiB
C

/*
* NOTE: This is an internal header and installed for use by extensions. The
* API is not guaranteed stable.
*/
// This is an internal header; it provides macros to make desugaring cleaner.
#include <assert.h>
#include "../internal.h"
#ifndef HAMMER_CONTEXTFREE__H
#define HAMMER_CONTEXTFREE__H
// HCFStack
struct HCFStack_ {
HCFChoice **stack;
int count;
int cap;
HCFChoice *last_completed; // Last completed choice.
// XXX is last_completed still needed?
HCFChoice *prealloc; // If not NULL, will be used for the outermost choice.
};
#ifndef UNUSED
#define UNUSED __attribute__((unused))
#endif
static inline HCFChoice* h_cfstack_new_choice_raw(HAllocator *mm__, HCFStack *stk__) UNUSED;
static inline void h_cfstack_begin_choice(HAllocator *mm__, HCFStack *stk__) UNUSED;
static HCFStack* h_cfstack_new(HAllocator *mm__) UNUSED;
static HCFStack* h_cfstack_new(HAllocator *mm__) {
HCFStack *stack = h_new(HCFStack, 1);
stack->count = 0;
stack->cap = 4;
stack->stack = h_new(HCFChoice*, stack->cap);
stack->prealloc = NULL;
return stack;
}
static void h_cfstack_free(HAllocator *mm__, HCFStack *stk__) UNUSED;
static void h_cfstack_free(HAllocator *mm__, HCFStack *stk__) {
h_free(stk__->prealloc);
h_free(stk__->stack);
h_free(stk__);
}
static inline void h_cfstack_add_to_seq(HAllocator *mm__, HCFStack *stk__, HCFChoice *item) UNUSED;
static inline void h_cfstack_add_to_seq(HAllocator *mm__, HCFStack *stk__, HCFChoice *item) {
HCFChoice *cur_top = stk__->stack[stk__->count-1];
assert(cur_top->type == HCF_CHOICE);
assert(cur_top->seq[0] != NULL); // There must be at least one sequence...
stk__->last_completed = item;
for (int i = 0;; i++) {
if (cur_top->seq[i+1] == NULL) {
assert(cur_top->seq[i]->items != NULL);
for (int j = 0;; j++) {
if (cur_top->seq[i]->items[j] == NULL) {
cur_top->seq[i]->items = mm__->realloc(mm__, cur_top->seq[i]->items, sizeof(HCFChoice*) * (j+2));
cur_top->seq[i]->items[j] = item;
cur_top->seq[i]->items[j+1] = NULL;
return;
}
}
}
}
}
static inline HCFChoice* h_cfstack_new_choice_raw(HAllocator *mm__, HCFStack *stk__) {
HCFChoice *ret = stk__->prealloc? stk__->prealloc : h_new(HCFChoice, 1);
stk__->prealloc = NULL;
ret->reshape = NULL;
ret->action = NULL;
ret->pred = NULL;
ret->type = ~0; // invalid type
// Add it to the current sequence...
if (stk__->count > 0) {
h_cfstack_add_to_seq(mm__, stk__, ret);
}
return ret;
}
static inline void h_cfstack_add_charset(HAllocator *mm__, HCFStack *stk__, HCharset charset) {
HCFChoice *ni = h_cfstack_new_choice_raw(mm__, stk__);
ni->type = HCF_CHARSET;
ni->charset = charset;
stk__->last_completed = ni;
}
static inline void h_cfstack_add_char(HAllocator *mm__, HCFStack *stk__, uint8_t chr) {
HCFChoice *ni = h_cfstack_new_choice_raw(mm__, stk__);
ni->type = HCF_CHAR;
ni->chr = chr;
stk__->last_completed = ni;
}
static inline void h_cfstack_add_end(HAllocator *mm__, HCFStack *stk__) {
HCFChoice *ni = h_cfstack_new_choice_raw(mm__, stk__);
ni->type = HCF_END;
stk__->last_completed = ni;
}
static inline void h_cfstack_begin_choice(HAllocator *mm__, HCFStack *stk__) {
HCFChoice *choice = h_cfstack_new_choice_raw(mm__, stk__);
choice->type = HCF_CHOICE;
choice->seq = h_new(HCFSequence*, 1);
choice->seq[0] = NULL;
if (stk__->count + 1 > stk__->cap) {
assert(stk__->cap > 0);
stk__->cap *= 2;
stk__->stack = mm__->realloc(mm__, stk__->stack, stk__->cap * sizeof(HCFChoice*));
}
assert(stk__->cap >= 1);
stk__->stack[stk__->count++] = choice;
}
static inline void h_cfstack_begin_seq(HAllocator *mm__, HCFStack *stk__) {
HCFChoice *top = stk__->stack[stk__->count-1];
for (int i = 0;; i++) {
if (top->seq[i] == NULL) {
top->seq = mm__->realloc(mm__, top->seq, sizeof(HCFSequence*) * (i+2));
HCFSequence *seq = top->seq[i] = h_new(HCFSequence, 1);
top->seq[i+1] = NULL;
seq->items = h_new(HCFChoice*, 1);
seq->items[0] = NULL;
return;
}
}
}
static inline void h_cfstack_end_seq(HAllocator *mm__, HCFStack *stk__) UNUSED;
static inline void h_cfstack_end_seq(HAllocator *mm__, HCFStack *stk__) {
// do nothing. You should call this anyway.
}
static inline void h_cfstack_end_choice(HAllocator *mm__, HCFStack *stk__) UNUSED;
static inline void h_cfstack_end_choice(HAllocator *mm__, HCFStack *stk__) {
assert(stk__->count > 0);
stk__->last_completed = stk__->stack[stk__->count-1];
stk__->count--;
}
#define HCFS_APPEND(choice) h_cfstack_add_to_seq(mm__, stk__, (choice))
#define HCFS_DESUGAR(parser) h_desugar(mm__, stk__, parser)
#define HCFS_ADD_CHARSET(charset) h_cfstack_add_charset(mm__, stk__, (charset))
#define HCFS_ADD_CHAR(chr) h_cfstack_add_char(mm__, stk__, (chr))
#define HCFS_ADD_END() h_cfstack_add_end(mm__, stk__)
// The semicolons on BEGIN macros are intentional; pretend that they
// are control structures.
#define HCFS_BEGIN_CHOICE() h_cfstack_begin_choice(mm__, stk__);
#define HCFS_BEGIN_SEQ() h_cfstack_begin_seq(mm__, stk__);
#define HCFS_END_CHOICE() h_cfstack_end_choice(mm__, stk__)
#define HCFS_END_SEQ() h_cfstack_end_seq(mm__, stk__)
#define HCFS_THIS_CHOICE (stk__->stack[stk__->count-1])
#endif