mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-21 09:02:50 -06:00
fix all space leaks in PgfLRTableMaker
This commit is contained in:
@@ -117,7 +117,8 @@ struct PgfLRTableMaker::Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void *p) {
|
void operator delete(void *p) {
|
||||||
free(p);
|
if (((Item *) p)->ref_cnt == 0)
|
||||||
|
free(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -194,13 +195,11 @@ void PgfLRTableMaker::CCat::register_item(Item *item) {
|
|||||||
PgfLRTableMaker::CCat::~CCat() {
|
PgfLRTableMaker::CCat::~CCat() {
|
||||||
for (Item *item : items) {
|
for (Item *item : items) {
|
||||||
item->ref_cnt--;
|
item->ref_cnt--;
|
||||||
if (item->ref_cnt == 0)
|
delete item;
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
for (Item *item : suspended) {
|
for (Item *item : suspended) {
|
||||||
item->ref_cnt--;
|
item->ref_cnt--;
|
||||||
if (item->ref_cnt == 0)
|
delete item;
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
for (Production *prod : prods) {
|
for (Production *prod : prods) {
|
||||||
delete prod;
|
delete prod;
|
||||||
@@ -384,8 +383,8 @@ bool PgfLRTableMaker::CompareKey3::operator() (const Key3& k1, const Key3& k2) c
|
|||||||
|
|
||||||
struct PgfLRTableMaker::State {
|
struct PgfLRTableMaker::State {
|
||||||
size_t id;
|
size_t id;
|
||||||
std::vector<Item*> items;
|
std::vector<Item*> items; // The seed items for this state
|
||||||
std::vector<Item*> completed;
|
std::vector<Item*> completed; // Completed items that will become reductions
|
||||||
std::map<Key1,State*,CompareKey1> ccats1;
|
std::map<Key1,State*,CompareKey1> ccats1;
|
||||||
std::map<Key2,State*,CompareKey2> ccats2;
|
std::map<Key2,State*,CompareKey2> ccats2;
|
||||||
std::map<Key3,State*,CompareKey3> tokens;
|
std::map<Key3,State*,CompareKey3> tokens;
|
||||||
@@ -399,14 +398,12 @@ struct PgfLRTableMaker::State {
|
|||||||
~State() {
|
~State() {
|
||||||
for (Item *item : items) {
|
for (Item *item : items) {
|
||||||
item->ref_cnt--;
|
item->ref_cnt--;
|
||||||
if (item->ref_cnt == 0)
|
delete item;
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Item *item : completed) {
|
for (Item *item : completed) {
|
||||||
item->ref_cnt--;
|
item->ref_cnt--;
|
||||||
if (item->ref_cnt == 0)
|
delete item;
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,6 +411,12 @@ struct PgfLRTableMaker::State {
|
|||||||
items.push_back(item); item->ref_cnt++;
|
items.push_back(item); item->ref_cnt++;
|
||||||
push_heap(items.begin(), items.end(), compare_item);
|
push_heap(items.begin(), items.end(), compare_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item *pop_item() {
|
||||||
|
Item *item = items.back(); items.pop_back();
|
||||||
|
item->ref_cnt--;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PgfLRTableMaker::PgfLRTableMaker(ref<PgfAbstr> abstr, ref<PgfConcr> concr)
|
PgfLRTableMaker::PgfLRTableMaker(ref<PgfAbstr> abstr, ref<PgfConcr> concr)
|
||||||
@@ -709,38 +712,62 @@ void PgfLRTableMaker::symbol(State *state, Fold fold, Item *item, PgfSymbol sym)
|
|||||||
item->ccat->register_item(item);
|
item->ccat->register_item(item);
|
||||||
} else {
|
} else {
|
||||||
auto symkp = ref<PgfSymbolKP>::untagged(sym);
|
auto symkp = ref<PgfSymbolKP>::untagged(sym);
|
||||||
|
Item *new_item1 = NULL;
|
||||||
|
Item *new_item2 = NULL;
|
||||||
for (size_t i = 0; i < symkp->alts.len; i++) {
|
for (size_t i = 0; i < symkp->alts.len; i++) {
|
||||||
Item *new_item = new (item) Item; new_item->sym_idx++;
|
|
||||||
ref<PgfSequence> form = symkp->alts.data[i].form;
|
ref<PgfSequence> form = symkp->alts.data[i].form;
|
||||||
if (form->syms.len == 0) {
|
if (form->syms.len == 0) {
|
||||||
process(state, fold, new_item);
|
if (!new_item1) {
|
||||||
|
new_item1 = new (item) Item;
|
||||||
|
new_item1->sym_idx++;
|
||||||
|
}
|
||||||
|
process(state, fold, new_item1);
|
||||||
} else {
|
} else {
|
||||||
auto &next_state = state->tokens[Key3(form,0)];
|
auto &next_state = state->tokens[Key3(form,0)];
|
||||||
if (next_state == NULL) {
|
if (next_state == NULL) {
|
||||||
next_state = new State;
|
next_state = new State;
|
||||||
}
|
}
|
||||||
new_item->stk_size++;
|
if (!new_item2) {
|
||||||
next_state->push_item(new_item);
|
new_item2 = new (item) Item;
|
||||||
|
new_item2->sym_idx++;
|
||||||
|
new_item2->stk_size++;
|
||||||
|
}
|
||||||
|
next_state->push_item(new_item2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *new_item = new (item) Item; new_item->sym_idx++;
|
|
||||||
ref<PgfSequence> form = symkp->default_form;
|
ref<PgfSequence> form = symkp->default_form;
|
||||||
if (form->syms.len == 0) {
|
if (form->syms.len == 0) {
|
||||||
process(state, fold, new_item);
|
if (!new_item1) {
|
||||||
|
new_item1 = new (item) Item;
|
||||||
|
new_item1->sym_idx++;
|
||||||
|
}
|
||||||
|
process(state, fold, new_item1);
|
||||||
} else {
|
} else {
|
||||||
auto &next_state = state->tokens[Key3(form,0)];
|
auto &next_state = state->tokens[Key3(form,0)];
|
||||||
if (next_state == NULL) {
|
if (next_state == NULL) {
|
||||||
next_state = new State;
|
next_state = new State;
|
||||||
}
|
}
|
||||||
new_item->stk_size++;
|
if (!new_item2) {
|
||||||
next_state->push_item(new_item);
|
new_item2 = new (item) Item;
|
||||||
|
new_item2->sym_idx++;
|
||||||
|
new_item2->stk_size++;
|
||||||
|
}
|
||||||
|
next_state->push_item(new_item2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the items are not owned by anyone, we must delete them
|
||||||
|
if (new_item1 != NULL)
|
||||||
|
delete new_item1;
|
||||||
|
if (new_item2 != NULL)
|
||||||
|
delete new_item2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case PgfSymbolBIND::tag: {
|
case PgfSymbolBIND::tag: {
|
||||||
if (fold != PROBE)
|
if (fold == PROBE) {
|
||||||
{
|
item->ccat->productive = true;
|
||||||
|
item->ccat->register_item(item);
|
||||||
|
} else {
|
||||||
if (state->bind_state == NULL) {
|
if (state->bind_state == NULL) {
|
||||||
state->bind_state = new State;
|
state->bind_state = new State;
|
||||||
}
|
}
|
||||||
@@ -753,33 +780,35 @@ void PgfLRTableMaker::symbol(State *state, Fold fold, Item *item, PgfSymbol sym)
|
|||||||
}
|
}
|
||||||
case PgfSymbolSOFTBIND::tag:
|
case PgfSymbolSOFTBIND::tag:
|
||||||
case PgfSymbolSOFTSPACE::tag: {
|
case PgfSymbolSOFTSPACE::tag: {
|
||||||
if (fold != PROBE)
|
if (fold == PROBE) {
|
||||||
{
|
item->ccat->productive = true;
|
||||||
|
item->ccat->register_item(item);
|
||||||
|
} else {
|
||||||
// SOFT_BIND && SOFT_SPACE also allow a space
|
// SOFT_BIND && SOFT_SPACE also allow a space
|
||||||
item = new (item) Item();
|
Item *new_item = new (item) Item();
|
||||||
item->sym_idx++;
|
new_item->sym_idx++;
|
||||||
process(state,fold,item);
|
process(state,fold,new_item);
|
||||||
|
delete new_item;
|
||||||
|
|
||||||
// Now we handle the case where there is no space
|
// Now we handle the case where there is no space.
|
||||||
if (state->bind_state == NULL) {
|
if (state->bind_state == NULL) {
|
||||||
state->bind_state = new State;
|
state->bind_state = new State;
|
||||||
}
|
}
|
||||||
item = new (item) Item();
|
new_item = new (item) Item();
|
||||||
item->stk_size++;
|
new_item->stk_size++;
|
||||||
state->bind_state->push_item(item);
|
state->bind_state->push_item(new_item);
|
||||||
|
delete new_item;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PgfSymbolCAPIT::tag:
|
case PgfSymbolCAPIT::tag:
|
||||||
case PgfSymbolALLCAPIT::tag: {
|
case PgfSymbolALLCAPIT::tag: {
|
||||||
// We just ignore CAPIT && ALLCAPIT during parsing
|
// We just ignore CAPIT && ALLCAPIT during parsing
|
||||||
item->sym_idx++;
|
item = new (item) Item(); item->sym_idx++;
|
||||||
process(state,fold,item);
|
process(state,fold,item);
|
||||||
|
delete item;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
if (item->ref_cnt == 0)
|
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,6 +857,8 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, T cat,
|
|||||||
|
|
||||||
predict(state, fold, new_item, cat, index);
|
predict(state, fold, new_item, cat, index);
|
||||||
|
|
||||||
|
delete new_item;
|
||||||
|
|
||||||
size_t i = n_terms;
|
size_t i = n_terms;
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
i--;
|
i--;
|
||||||
@@ -846,9 +877,6 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, T cat,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item->ref_cnt == 0)
|
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, ref<PgfText> cat, size_t lin_idx)
|
void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, ref<PgfText> cat, size_t lin_idx)
|
||||||
@@ -871,6 +899,7 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, ref<PgfText>
|
|||||||
} else if (fold == PROBE && ccat->prods.size() > 0) {
|
} else if (fold == PROBE && ccat->prods.size() > 0) {
|
||||||
Item *new_item = new(item,ccat) Item;
|
Item *new_item = new(item,ccat) Item;
|
||||||
process(state,fold,new_item);
|
process(state,fold,new_item);
|
||||||
|
delete new_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fold == PROBE) {
|
if (fold == PROBE) {
|
||||||
@@ -896,6 +925,7 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, ref<PgfText>
|
|||||||
if (fold == INIT && ccat->prods.size() > 0) {
|
if (fold == INIT && ccat->prods.size() > 0) {
|
||||||
Item *new_item = new (item, ccat) Item;
|
Item *new_item = new (item, ccat) Item;
|
||||||
process(state, fold, new_item);
|
process(state, fold, new_item);
|
||||||
|
delete new_item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -916,6 +946,7 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, CCat *ccat, s
|
|||||||
Production *prod = ccat->prods[i];
|
Production *prod = ccat->prods[i];
|
||||||
Item *item = new(new_ccat, prod, lin_idx) Item;
|
Item *item = new(new_ccat, prod, lin_idx) Item;
|
||||||
process(NULL, PROBE, item);
|
process(NULL, PROBE, item);
|
||||||
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -926,13 +957,13 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, CCat *ccat, s
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (new_ccat->productive) {
|
if (new_ccat->productive) {
|
||||||
auto &new_state = state->ccats2[Key2(new_ccat,lin_idx)];
|
auto &next_state = state->ccats2[Key2(new_ccat,lin_idx)];
|
||||||
if (new_state == NULL) {
|
if (next_state == NULL) {
|
||||||
new_state = new State;
|
next_state = new State;
|
||||||
}
|
}
|
||||||
new_state->push_item(new(item,lin_idx) Item);
|
next_state->push_item(new(item,lin_idx) Item);
|
||||||
|
|
||||||
if (new_state->items.size() == 1) {
|
if (next_state->items.size() == 1) {
|
||||||
for (size_t i = 0; i < new_ccat->items.size(); i++) {
|
for (size_t i = 0; i < new_ccat->items.size(); i++) {
|
||||||
process(state, REPEAT, new_ccat->items[i]);
|
process(state, REPEAT, new_ccat->items[i]);
|
||||||
}
|
}
|
||||||
@@ -941,6 +972,7 @@ void PgfLRTableMaker::predict(State *state, Fold fold, Item *item, CCat *ccat, s
|
|||||||
if (fold == INIT && new_ccat->prods.size() > 0) {
|
if (fold == INIT && new_ccat->prods.size() > 0) {
|
||||||
Item *new_item = new (item, new_ccat) Item;
|
Item *new_item = new (item, new_ccat) Item;
|
||||||
process(state, fold, new_item);
|
process(state, fold, new_item);
|
||||||
|
delete new_item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -958,6 +990,7 @@ void PgfLRTableMaker::predict(ref<PgfAbsFun> absfun, CCat *ccat)
|
|||||||
size_t seq_idx = n_fields * i + ccat->lin_idx;
|
size_t seq_idx = n_fields * i + ccat->lin_idx;
|
||||||
Item *item = new(ccat, lin, seq_idx) Item;
|
Item *item = new(ccat, lin, seq_idx) Item;
|
||||||
process(NULL, PROBE, item);
|
process(NULL, PROBE, item);
|
||||||
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -984,12 +1017,10 @@ void PgfLRTableMaker::complete(State *state, Fold fold, Item *item)
|
|||||||
if (susp != NULL) {
|
if (susp != NULL) {
|
||||||
Item *new_item = new (susp, item->ccat) Item;
|
Item *new_item = new (susp, item->ccat) Item;
|
||||||
process(state, PROBE, new_item);
|
process(state, PROBE, new_item);
|
||||||
|
delete new_item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item->ref_cnt == 0)
|
|
||||||
delete item;
|
|
||||||
} else {
|
} else {
|
||||||
state->completed.push_back(item); item->ref_cnt++;
|
state->completed.push_back(item); item->ref_cnt++;
|
||||||
|
|
||||||
@@ -1045,7 +1076,7 @@ ref<PgfLRTable> PgfLRTableMaker::make()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (!state->items.empty()) {
|
while (!state->items.empty()) {
|
||||||
Item *item = state->items.back(); state->items.pop_back();
|
Item *item = state->pop_item();
|
||||||
|
|
||||||
#if defined(DEBUG_AUTOMATON) && !defined(DEBUG_STATE_CREATION)
|
#if defined(DEBUG_AUTOMATON) && !defined(DEBUG_STATE_CREATION)
|
||||||
// The order in which we process the items should not matter,
|
// The order in which we process the items should not matter,
|
||||||
@@ -1055,9 +1086,8 @@ ref<PgfLRTable> PgfLRTableMaker::make()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
process(state, INIT, item);
|
process(state, INIT, item);
|
||||||
item->ref_cnt--;
|
|
||||||
if (item->ref_cnt == 0)
|
delete item;
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &i : state->ccats1) {
|
for (auto &i : state->ccats1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user