refactor h_llk_lookup to take the input stream as argument

This commit is contained in:
Sven M. Hallberg 2013-05-20 21:28:16 +02:00
parent fb3aae7aec
commit 91c04314a4

View file

@ -19,8 +19,18 @@ typedef struct HLLkTable_ {
} HLLkTable; } HLLkTable;
/* Interface to look up an entry in the parse table. */ /* Interface to look up an entry in the parse table. */
const HCFSequence *h_llk_lookup(const HLLkTable *table, const HCFChoice *x, HCFToken tok) const HCFSequence *h_llk_lookup(const HLLkTable *table, const HCFChoice *x,
HInputStream lookahead)
{ {
// note the lookahead stream is passed by value, i.e. a copy
// reading bits from it does not consume them from the input
HCFToken tok;
uint8_t c = h_read_bits(&lookahead, 8, false);
if(lookahead.overrun)
tok = end_token;
else
tok = char_token(c);
const HHashTable *row = h_hashtable_get(table->rows, x); const HHashTable *row = h_hashtable_get(table->rows, x);
assert(row != NULL); // the table should have one row for each nonterminal assert(row != NULL); // the table should have one row for each nonterminal
@ -200,19 +210,8 @@ HParseResult *h_llk_parse(HAllocator* mm__, const HParser* parser, HInputStream*
// initialize with the start symbol on the stack. // initialize with the start symbol on the stack.
h_slist_push(stack, table->start); h_slist_push(stack, table->start);
HCFToken lookahead = 0; // 0 = empty
// when we empty the stack, the parse is complete. // when we empty the stack, the parse is complete.
while(!h_slist_empty(stack)) { while(!h_slist_empty(stack)) {
// fill up lookahead buffer as required
if(lookahead == 0) {
uint8_t c = h_read_bits(stream, 8, false);
if(stream->overrun)
lookahead = end_token;
else
lookahead = char_token(c);
}
// pop top of stack for inspection // pop top of stack for inspection
HCFChoice *x = h_slist_pop(stack); HCFChoice *x = h_slist_pop(stack);
assert(x != NULL); assert(x != NULL);
@ -229,7 +228,7 @@ HParseResult *h_llk_parse(HAllocator* mm__, const HParser* parser, HInputStream*
seq = h_carray_new(arena); seq = h_carray_new(arena);
// look up applicable production in parse table // look up applicable production in parse table
const HCFSequence *p = h_llk_lookup(table, x, lookahead); const HCFSequence *p = h_llk_lookup(table, x, *stream);
if(p == NULL) if(p == NULL)
goto no_parse; goto no_parse;
@ -260,18 +259,17 @@ HParseResult *h_llk_parse(HAllocator* mm__, const HParser* parser, HInputStream*
// x is a terminal or simple charset; match against input // x is a terminal or simple charset; match against input
// consume the input token // consume the input token
HCFToken input = lookahead; uint8_t input = h_read_bits(stream, 8, false);
lookahead = 0;
switch(x->type) { switch(x->type) {
case HCF_END: case HCF_END:
if(input != end_token) if(!stream->overrun)
goto no_parse; goto no_parse;
tok = NULL; tok = NULL;
break; break;
case HCF_CHAR: case HCF_CHAR:
if(input != char_token(x->chr)) if(input != x->chr)
goto no_parse; goto no_parse;
tok = h_arena_malloc(arena, sizeof(HParsedToken)); tok = h_arena_malloc(arena, sizeof(HParsedToken));
tok->token_type = TT_UINT; tok->token_type = TT_UINT;
@ -279,13 +277,13 @@ HParseResult *h_llk_parse(HAllocator* mm__, const HParser* parser, HInputStream*
break; break;
case HCF_CHARSET: case HCF_CHARSET:
if(input == end_token) if(stream->overrun)
goto no_parse; goto no_parse;
if(!charset_isset(x->charset, token_char(input))) if(!charset_isset(x->charset, input))
goto no_parse; goto no_parse;
tok = h_arena_malloc(arena, sizeof(HParsedToken)); tok = h_arena_malloc(arena, sizeof(HParsedToken));
tok->token_type = TT_UINT; tok->token_type = TT_UINT;
tok->uint = token_char(input); tok->uint = input;
break; break;
default: // should not be reached default: // should not be reached
@ -338,6 +336,15 @@ HParserBackendVTable h__llk_backend_vtable = {
// dummy! // dummy!
int test_llk(void) int test_llk(void)
{ {
/* for k=2:
S -> A | B
A -> X Y a
B -> Y b
X -> x | ''
Y -> y -- for k=3 use "yy"
*/
HParser *c = h_many(h_ch('x')); HParser *c = h_many(h_ch('x'));
HParser *q = h_sequence(c, h_ch('y'), NULL); HParser *q = h_sequence(c, h_ch('y'), NULL);
HParser *p = h_choice(q, h_end_p(), NULL); HParser *p = h_choice(q, h_end_p(), NULL);