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_bitwriter.o \
|
||||
t_parser.o \
|
||||
t_misc.o \
|
||||
test_suite.o
|
||||
|
||||
OUTPUTS := libhammer.a \
|
||||
|
|
|
|||
|
|
@ -77,14 +77,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +105,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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -43,9 +43,8 @@ typedef enum HTokenType_ {
|
|||
TT_SINT,
|
||||
TT_UINT,
|
||||
TT_SEQUENCE,
|
||||
TT_USER = 64,
|
||||
TT_ERR,
|
||||
TT_MAX
|
||||
TT_USER = 64
|
||||
} HTokenType;
|
||||
|
||||
typedef struct HCountedArray_ {
|
||||
|
|
|
|||
|
|
@ -209,6 +209,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);
|
||||
|
|
|
|||
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)");
|
||||
}
|
||||
|
||||
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) {
|
||||
g_test_add_func("/core/parser/token", test_token);
|
||||
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/not", test_not);
|
||||
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_bitwriter_tests();
|
||||
extern void register_parser_tests();
|
||||
extern void register_misc_tests();
|
||||
extern void register_benchmark_tests();
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
@ -31,6 +32,7 @@ int main(int argc, char** argv) {
|
|||
register_bitreader_tests();
|
||||
register_bitwriter_tests();
|
||||
register_parser_tests();
|
||||
register_misc_tests();
|
||||
register_benchmark_tests();
|
||||
|
||||
g_test_run();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue