Merge branch 'fix-left-recursion' into base64-example
This commit is contained in:
commit
88566ab81b
8 changed files with 61 additions and 6 deletions
|
|
@ -45,6 +45,7 @@ TESTS := t_benchmark.o \
|
||||||
t_bitreader.o \
|
t_bitreader.o \
|
||||||
t_bitwriter.o \
|
t_bitwriter.o \
|
||||||
t_parser.o \
|
t_parser.o \
|
||||||
|
t_misc.o \
|
||||||
test_suite.o
|
test_suite.o
|
||||||
|
|
||||||
OUTPUTS := libhammer.a \
|
OUTPUTS := libhammer.a \
|
||||||
|
|
|
||||||
|
|
@ -77,14 +77,18 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
|
||||||
void setupLR(const HParser *p, HParseState *state, HLeftRec *rec_detect) {
|
void setupLR(const HParser *p, HParseState *state, HLeftRec *rec_detect) {
|
||||||
if (!rec_detect->head) {
|
if (!rec_detect->head) {
|
||||||
HRecursionHead *some = a_new(HRecursionHead, 1);
|
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;
|
rec_detect->head = some;
|
||||||
}
|
}
|
||||||
assert(state->lr_stack->head != NULL);
|
assert(state->lr_stack->head != NULL);
|
||||||
HLeftRec *lr = state->lr_stack->head->elem;
|
HSlistNode *head = state->lr_stack->head;
|
||||||
while (lr && lr->rule != p) {
|
HLeftRec *lr;
|
||||||
|
while (head && (lr = head->elem)->rule != p) {
|
||||||
lr->head = rec_detect->head;
|
lr->head = rec_detect->head;
|
||||||
h_slist_push(lr->head->involved_set, (void*)lr->rule);
|
h_slist_push(lr->head->involved_set, (void*)lr->rule);
|
||||||
|
head = head->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,7 +105,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
|
||||||
HParseResult *old_res = old_cached->right->result;
|
HParseResult *old_res = old_cached->right->result;
|
||||||
|
|
||||||
// reset the eval_set of the head of the recursion at each beginning of growth
|
// 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);
|
HParseResult *tmp_res = perform_lowlevel_parse(state, k->parser);
|
||||||
|
|
||||||
if (tmp_res) {
|
if (tmp_res) {
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,26 @@ HSlist* h_slist_new(HArena *arena) {
|
||||||
return ret;
|
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) {
|
void* h_slist_pop(HSlist *slist) {
|
||||||
HSlistNode *head = slist->head;
|
HSlistNode *head = slist->head;
|
||||||
if (!head)
|
if (!head)
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,8 @@ typedef enum HTokenType_ {
|
||||||
TT_SINT,
|
TT_SINT,
|
||||||
TT_UINT,
|
TT_UINT,
|
||||||
TT_SEQUENCE,
|
TT_SEQUENCE,
|
||||||
TT_USER = 64,
|
|
||||||
TT_ERR,
|
TT_ERR,
|
||||||
TT_MAX
|
TT_USER = 64
|
||||||
} HTokenType;
|
} HTokenType;
|
||||||
|
|
||||||
typedef struct HCountedArray_ {
|
typedef struct HCountedArray_ {
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,7 @@ HCountedArray *h_carray_new(HArena * arena);
|
||||||
void h_carray_append(HCountedArray *array, void* item);
|
void h_carray_append(HCountedArray *array, void* item);
|
||||||
|
|
||||||
HSlist* h_slist_new(HArena *arena);
|
HSlist* h_slist_new(HArena *arena);
|
||||||
|
HSlist* h_slist_copy(HSlist *slist);
|
||||||
void* h_slist_pop(HSlist *slist);
|
void* h_slist_pop(HSlist *slist);
|
||||||
void h_slist_push(HSlist *slist, void* item);
|
void h_slist_push(HSlist *slist, void* item);
|
||||||
bool h_slist_find(HSlist *slist, const void* item);
|
bool h_slist_find(HSlist *slist, const void* item);
|
||||||
|
|
|
||||||
16
src/t_misc.c
Normal file
16
src/t_misc.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -365,6 +365,17 @@ static void test_not(void) {
|
||||||
g_check_parse_ok(not_2, "a++b", 4, "(u0x61 <2b.2b> u0x62)");
|
g_check_parse_ok(not_2, "a++b", 4, "(u0x61 <2b.2b> u0x62)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_leftrec(void) {
|
||||||
|
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_, "a", 1, "u0x61");
|
||||||
|
g_check_parse_ok(lr_, "aa", 2, "(u0x61 u0x61)");
|
||||||
|
g_check_parse_ok(lr_, "aaa", 3, "((u0x61 u0x61) u0x61)");
|
||||||
|
}
|
||||||
|
|
||||||
void register_parser_tests(void) {
|
void register_parser_tests(void) {
|
||||||
g_test_add_func("/core/parser/token", test_token);
|
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", test_ch);
|
||||||
|
|
@ -406,4 +417,5 @@ void register_parser_tests(void) {
|
||||||
g_test_add_func("/core/parser/and", test_and);
|
g_test_add_func("/core/parser/and", test_and);
|
||||||
g_test_add_func("/core/parser/not", test_not);
|
g_test_add_func("/core/parser/not", test_not);
|
||||||
g_test_add_func("/core/parser/ignore", test_ignore);
|
g_test_add_func("/core/parser/ignore", test_ignore);
|
||||||
|
g_test_add_func("/core/parser/leftrec", test_leftrec);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
extern void register_bitreader_tests();
|
extern void register_bitreader_tests();
|
||||||
extern void register_bitwriter_tests();
|
extern void register_bitwriter_tests();
|
||||||
extern void register_parser_tests();
|
extern void register_parser_tests();
|
||||||
|
extern void register_misc_tests();
|
||||||
extern void register_benchmark_tests();
|
extern void register_benchmark_tests();
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
@ -31,6 +32,7 @@ int main(int argc, char** argv) {
|
||||||
register_bitreader_tests();
|
register_bitreader_tests();
|
||||||
register_bitwriter_tests();
|
register_bitwriter_tests();
|
||||||
register_parser_tests();
|
register_parser_tests();
|
||||||
|
register_misc_tests();
|
||||||
register_benchmark_tests();
|
register_benchmark_tests();
|
||||||
|
|
||||||
g_test_run();
|
g_test_run();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue