Merge branch 'fix-left-recursion' into base64-example

This commit is contained in:
Sven M. Hallberg 2013-01-10 01:23:38 +01:00
commit 88566ab81b
8 changed files with 61 additions and 6 deletions

View file

@ -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 \

View file

@ -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) {

View file

@ -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)

View file

@ -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_ {

View file

@ -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
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

@ -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);
} }

View file

@ -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();