record conflicts in a special HLRAction type
This commit is contained in:
parent
168760b10a
commit
54ba62bfb7
4 changed files with 56 additions and 15 deletions
|
|
@ -138,7 +138,8 @@ int h_lrtable_put(HLRTable *tbl, size_t state, HCFChoice *x, HLRAction *action)
|
||||||
HLRAction *prev = h_hashtable_get(tbl->rows[state], x);
|
HLRAction *prev = h_hashtable_get(tbl->rows[state], x);
|
||||||
if(prev && prev != action) {
|
if(prev && prev != action) {
|
||||||
// conflict
|
// conflict
|
||||||
h_slist_push(tbl->inadeq, (void *)(uintptr_t)state);
|
action = h_lr_conflict(tbl->arena, prev, action);
|
||||||
|
h_hashtable_put(tbl->rows[state], x, action);
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
h_hashtable_put(tbl->rows[state], x, action);
|
h_hashtable_put(tbl->rows[state], x, action);
|
||||||
|
|
@ -221,6 +222,7 @@ int h_lalr_compile(HAllocator* mm__, HParser* parser, const void* params)
|
||||||
|
|
||||||
for(HSlistNode *x=inadeq->head; x; x=x->next) {
|
for(HSlistNode *x=inadeq->head; x; x=x->next) {
|
||||||
size_t state = (uintptr_t)x->elem;
|
size_t state = (uintptr_t)x->elem;
|
||||||
|
bool inadeq = false;
|
||||||
|
|
||||||
// clear old forall entry, it's being replaced by more fine-grained ones
|
// clear old forall entry, it's being replaced by more fine-grained ones
|
||||||
table->forall[state] = NULL;
|
table->forall[state] = NULL;
|
||||||
|
|
@ -255,7 +257,8 @@ int h_lalr_compile(HAllocator* mm__, HParser* parser, const void* params)
|
||||||
if(fs->end_branch) {
|
if(fs->end_branch) {
|
||||||
HCFChoice *terminal = h_arena_malloc(arena, sizeof(HCFChoice));
|
HCFChoice *terminal = h_arena_malloc(arena, sizeof(HCFChoice));
|
||||||
terminal->type = HCF_END;
|
terminal->type = HCF_END;
|
||||||
h_lrtable_put(table, state, terminal, action);
|
if(h_lrtable_put(table, state, terminal, action) < 0)
|
||||||
|
inadeq = true;
|
||||||
}
|
}
|
||||||
H_FOREACH(fs->char_branches, void *key, HStringMap *m)
|
H_FOREACH(fs->char_branches, void *key, HStringMap *m)
|
||||||
if(!m->epsilon_branch)
|
if(!m->epsilon_branch)
|
||||||
|
|
@ -265,10 +268,14 @@ int h_lalr_compile(HAllocator* mm__, HParser* parser, const void* params)
|
||||||
terminal->type = HCF_CHAR;
|
terminal->type = HCF_CHAR;
|
||||||
terminal->chr = key_char((HCharKey)key);
|
terminal->chr = key_char((HCharKey)key);
|
||||||
|
|
||||||
h_lrtable_put(table, state, terminal, action);
|
if(h_lrtable_put(table, state, terminal, action) < 0)
|
||||||
|
inadeq = true;
|
||||||
H_END_FOREACH // lookahead character
|
H_END_FOREACH // lookahead character
|
||||||
} H_END_FOREACH // enhanced production
|
} H_END_FOREACH // enhanced production
|
||||||
H_END_FOREACH // reducible item
|
H_END_FOREACH // reducible item
|
||||||
|
|
||||||
|
if(inadeq)
|
||||||
|
h_slist_push(table->inadeq, (void *)(uintptr_t)state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,25 @@ HLRAction *h_reduce_action(HArena *arena, const HLRItem *item)
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adds 'new' to the branches of 'action'
|
||||||
|
// returns a 'action' if it is already of type HLR_CONFLICT
|
||||||
|
// allocates a new HLRAction otherwise
|
||||||
|
HLRAction *h_lr_conflict(HArena *arena, HLRAction *action, HLRAction *new)
|
||||||
|
{
|
||||||
|
if(action->type != HLR_CONFLICT) {
|
||||||
|
HLRAction *old = action;
|
||||||
|
action = h_arena_malloc(arena, sizeof(HLRAction));
|
||||||
|
action->type = HLR_CONFLICT;
|
||||||
|
action->branches = h_slist_new(arena);
|
||||||
|
h_slist_push(action->branches, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(action->type == HLR_CONFLICT);
|
||||||
|
h_slist_push(action->branches, new);
|
||||||
|
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* LR driver */
|
/* LR driver */
|
||||||
|
|
@ -239,6 +258,8 @@ bool h_lrengine_step(HLREngine *engine, const HLRAction *action)
|
||||||
if(action == NULL)
|
if(action == NULL)
|
||||||
return false; // no handle recognizable in input, terminate
|
return false; // no handle recognizable in input, terminate
|
||||||
|
|
||||||
|
assert(action->type == HLR_SHIFT || action->type == HLR_REDUCE);
|
||||||
|
|
||||||
if(action->type == HLR_SHIFT) {
|
if(action->type == HLR_SHIFT) {
|
||||||
h_slist_push(left, (void *)(uintptr_t)engine->state);
|
h_slist_push(left, (void *)(uintptr_t)engine->state);
|
||||||
h_slist_pop(right); // symbol (discard)
|
h_slist_pop(right); // symbol (discard)
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,22 @@ typedef struct HLRItem_ {
|
||||||
} HLRItem;
|
} HLRItem;
|
||||||
|
|
||||||
typedef struct HLRAction_ {
|
typedef struct HLRAction_ {
|
||||||
enum {HLR_SHIFT, HLR_REDUCE} type;
|
enum {HLR_SHIFT, HLR_REDUCE, HLR_CONFLICT} type;
|
||||||
union {
|
union {
|
||||||
size_t nextstate; // used with SHIFT
|
// used with HLR_SHIFT
|
||||||
|
size_t nextstate;
|
||||||
|
|
||||||
|
// used with HLR_REDUCE
|
||||||
struct {
|
struct {
|
||||||
HCFChoice *lhs; // symbol carrying semantic actions etc.
|
HCFChoice *lhs; // symbol carrying semantic actions etc.
|
||||||
size_t length; // # of symbols in rhs
|
size_t length; // # of symbols in rhs
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
HCFChoice **rhs; // NB: the rhs symbols are not needed for the parse
|
HCFChoice **rhs; // NB: the rhs symbols are not needed for the parse
|
||||||
#endif
|
#endif
|
||||||
} production; // used with REDUCE
|
} production;
|
||||||
|
|
||||||
|
// used with HLR_CONFLICT
|
||||||
|
HSlist *branches; // list of possible HLRActions
|
||||||
};
|
};
|
||||||
} HLRAction;
|
} HLRAction;
|
||||||
|
|
||||||
|
|
@ -104,6 +110,7 @@ void h_lrtable_free(HLRTable *table);
|
||||||
HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table);
|
HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table);
|
||||||
HLRAction *h_reduce_action(HArena *arena, const HLRItem *item);
|
HLRAction *h_reduce_action(HArena *arena, const HLRItem *item);
|
||||||
HLRAction *h_shift_action(HArena *arena, size_t nextstate);
|
HLRAction *h_shift_action(HArena *arena, size_t nextstate);
|
||||||
|
HLRAction *h_lr_conflict(HArena *arena, HLRAction *action, HLRAction *new);
|
||||||
|
|
||||||
bool h_eq_symbol(const void *p, const void *q);
|
bool h_eq_symbol(const void *p, const void *q);
|
||||||
bool h_eq_lr_itemset(const void *p, const void *q);
|
bool h_eq_lr_itemset(const void *p, const void *q);
|
||||||
|
|
|
||||||
|
|
@ -182,23 +182,29 @@ HLRTable *h_lr0_table(HCFGrammar *g, const HLRDFA *dfa)
|
||||||
|
|
||||||
// add reduce entries, record inadequate states
|
// add reduce entries, record inadequate states
|
||||||
for(size_t i=0; i<dfa->nstates; i++) {
|
for(size_t i=0; i<dfa->nstates; i++) {
|
||||||
|
bool inadeq = false;
|
||||||
|
|
||||||
// find reducible items in state
|
// find reducible items in state
|
||||||
H_FOREACH_KEY(dfa->states[i], HLRItem *item)
|
H_FOREACH_KEY(dfa->states[i], HLRItem *item)
|
||||||
if(item->mark == item->len) { // mark at the end
|
if(item->mark == item->len) { // mark at the end
|
||||||
// check for conflicts
|
HLRAction *reduce = h_reduce_action(arena, item);
|
||||||
// XXX store more informative stuff in the inadeq records?
|
|
||||||
|
// check for reduce/reduce conflict on forall
|
||||||
if(table->forall[i]) {
|
if(table->forall[i]) {
|
||||||
// reduce/reduce conflict with a previous item
|
reduce = h_lr_conflict(arena, table->forall[i], reduce);
|
||||||
h_slist_push(table->inadeq, (void *)(uintptr_t)i);
|
inadeq = true;
|
||||||
} else if(!h_hashtable_empty(table->rows[i])) {
|
|
||||||
// shift/reduce conflict with one of the row's entries
|
|
||||||
h_slist_push(table->inadeq, (void *)(uintptr_t)i);
|
|
||||||
}
|
}
|
||||||
|
table->forall[i] = reduce;
|
||||||
|
|
||||||
// set reduce action for the entire row
|
// check for shift/reduce conflict with other entries
|
||||||
table->forall[i] = h_reduce_action(arena, item);
|
// NOTE: these are not recorded as HLR_CONFLICTs at this point
|
||||||
|
if(!h_hashtable_empty(table->rows[i]))
|
||||||
|
inadeq = true;
|
||||||
}
|
}
|
||||||
H_END_FOREACH
|
H_END_FOREACH
|
||||||
|
|
||||||
|
if(inadeq)
|
||||||
|
h_slist_push(table->inadeq, (void *)(uintptr_t)i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue