forked from GitHub/gf-core
forgot to add probspace.(cxx|h)
This commit is contained in:
210
src/runtime/c/pgf/probspace.cxx
Normal file
210
src/runtime/c/pgf/probspace.cxx
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
#include "data.h"
|
||||||
|
|
||||||
|
static
|
||||||
|
int entry_cmp(PgfProbspaceEntry *entry1, PgfProbspaceEntry *entry2)
|
||||||
|
{
|
||||||
|
int cmp = textcmp(&(*entry1->cat), &(*entry2->cat));
|
||||||
|
if (cmp != 0)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
|
if (entry1->fun->prob < entry2->fun->prob)
|
||||||
|
return -1;
|
||||||
|
else if (entry1->fun->prob > entry2->fun->prob)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return textcmp(&entry1->fun->name, &entry2->fun->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PgfProbspace probspace_insert(PgfProbspace space,
|
||||||
|
PgfProbspaceEntry *entry)
|
||||||
|
{
|
||||||
|
if (space == 0) {
|
||||||
|
return Node<PgfProbspaceEntry>::new_node(*entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmp = entry_cmp(entry,&space->value);
|
||||||
|
if (cmp < 0) {
|
||||||
|
PgfProbspace left = probspace_insert(space->left,entry);
|
||||||
|
space = Node<PgfProbspaceEntry>::upd_node(space,left,space->right);
|
||||||
|
return Node<PgfProbspaceEntry>::balanceL(space);
|
||||||
|
} else if (cmp > 0) {
|
||||||
|
PgfProbspace right = probspace_insert(space->right,entry);
|
||||||
|
space = Node<PgfProbspaceEntry>::upd_node(space, space->left, right);
|
||||||
|
return Node<PgfProbspaceEntry>::balanceR(space);
|
||||||
|
} else {
|
||||||
|
space = Node<PgfProbspaceEntry>::upd_node(space,space->left,space->right);
|
||||||
|
space->value = *entry;
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PgfProbspace probspace_insert(PgfProbspace space,
|
||||||
|
ref<PgfAbsFun> fun,
|
||||||
|
ref<PgfDTyp> type)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < type->hypos->len; i++) {
|
||||||
|
ref<PgfHypo> hypo = vector_elem(type->hypos,i);
|
||||||
|
space = probspace_insert(space,fun,hypo->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
PgfProbspaceEntry entry;
|
||||||
|
entry.cat = ref<PgfText>::from_ptr(&type->name);
|
||||||
|
entry.fun = fun;
|
||||||
|
space = probspace_insert(space,&entry);
|
||||||
|
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
PGF_INTERNAL
|
||||||
|
PgfProbspace probspace_insert(PgfProbspace space,
|
||||||
|
ref<PgfAbsFun> fun)
|
||||||
|
{
|
||||||
|
return probspace_insert(space,fun,fun->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PgfProbspace probspace_delete(PgfProbspace space, PgfProbspaceEntry *entry)
|
||||||
|
{
|
||||||
|
if (space == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmp = entry_cmp(entry,&space->value);
|
||||||
|
if (cmp < 0) {
|
||||||
|
PgfProbspace left = probspace_delete(space->left, entry);
|
||||||
|
space = Node<PgfProbspaceEntry>::upd_node(space,left,space->right);
|
||||||
|
return Node<PgfProbspaceEntry>::balanceR(space);
|
||||||
|
} else if (cmp > 0) {
|
||||||
|
PgfProbspace right = probspace_delete(space->right, entry);
|
||||||
|
space = Node<PgfProbspaceEntry>::upd_node(space,space->left,right);
|
||||||
|
return Node<PgfProbspaceEntry>::balanceL(space);
|
||||||
|
} else {
|
||||||
|
if (space->left == 0) {
|
||||||
|
Node<PgfProbspaceEntry>::release(space);
|
||||||
|
return space->right;
|
||||||
|
} else if (space->right == 0) {
|
||||||
|
Node<PgfProbspaceEntry>::release(space);
|
||||||
|
return space->left;
|
||||||
|
} else if (space->left->sz > space->right->sz) {
|
||||||
|
PgfProbspace node;
|
||||||
|
PgfProbspace left = Node<PgfProbspaceEntry>::pop_last(space->left, &node);
|
||||||
|
node = Node<PgfProbspaceEntry>::upd_node(node, left, space->right);
|
||||||
|
Node<PgfProbspaceEntry>::release(space);
|
||||||
|
return Node<PgfProbspaceEntry>::balanceR(node);
|
||||||
|
} else {
|
||||||
|
PgfProbspace node;
|
||||||
|
PgfProbspace right = Node<PgfProbspaceEntry>::pop_first(space->right, &node);
|
||||||
|
node = Node<PgfProbspaceEntry>::upd_node(node, space->left, right);
|
||||||
|
Node<PgfProbspaceEntry>::release(space);
|
||||||
|
return Node<PgfProbspaceEntry>::balanceL(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PgfProbspace probspace_delete(PgfProbspace space,
|
||||||
|
ref<PgfAbsFun> fun,
|
||||||
|
ref<PgfDTyp> type)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < type->hypos->len; i++) {
|
||||||
|
ref<PgfHypo> hypo = vector_elem(type->hypos,i);
|
||||||
|
space = probspace_delete(space,fun,hypo->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
PgfProbspaceEntry entry;
|
||||||
|
entry.cat = ref<PgfText>::from_ptr(&type->name);
|
||||||
|
entry.fun = fun;
|
||||||
|
space = probspace_delete(space,&entry);
|
||||||
|
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
|
PGF_INTERNAL
|
||||||
|
PgfProbspace probspace_delete(PgfProbspace space, ref<PgfAbsFun> fun)
|
||||||
|
{
|
||||||
|
return probspace_delete(space,fun,fun->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
PGF_INTERNAL_DECL
|
||||||
|
PgfProbspace probspace_delete_by_cat(PgfProbspace space, PgfText *cat,
|
||||||
|
PgfItor* itor, PgfExn *err)
|
||||||
|
{
|
||||||
|
if (space == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmp = textcmp(cat,&(*space->value.cat));
|
||||||
|
if (cmp < 0) {
|
||||||
|
PgfProbspace left = probspace_delete_by_cat(space->left, cat, itor, err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return Node<PgfProbspaceEntry>::link(space,left,space->right);
|
||||||
|
} else if (cmp > 0) {
|
||||||
|
PgfProbspace right = probspace_delete_by_cat(space->right, cat, itor, err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return Node<PgfProbspaceEntry>::link(space,space->left,right);
|
||||||
|
} else {
|
||||||
|
itor->fn(itor, &space->value.fun->name, space->value.fun.as_object(), err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
PgfProbspace left = probspace_delete_by_cat(space->left, cat, itor, err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
PgfProbspace right = probspace_delete_by_cat(space->right, cat, itor, err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Node<PgfProbspaceEntry>::release(space);
|
||||||
|
|
||||||
|
return Node<PgfProbspaceEntry>::link(left,right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void probspace_iter(PgfProbspace space, PgfText *cat,
|
||||||
|
PgfItor* itor, bool all, PgfExn *err)
|
||||||
|
{
|
||||||
|
if (space == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int cmp = textcmp(cat,&(*space->value.cat));
|
||||||
|
if (cmp < 0) {
|
||||||
|
probspace_iter(space->left, cat, itor, all, err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return;
|
||||||
|
} else if (cmp > 0) {
|
||||||
|
probspace_iter(space->right, cat, itor, all, err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
probspace_iter(space->left, cat, itor, all, err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (all || space->value.cat == ref<PgfText>::from_ptr(&space->value.fun->type->name)) {
|
||||||
|
itor->fn(itor, &space->value.fun->name, space->value.fun.as_object(), err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
probspace_iter(space->right, cat, itor, all, err);
|
||||||
|
if (err->type != PGF_EXN_NONE)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PGF_INTERNAL
|
||||||
|
void probspace_release(PgfProbspace space)
|
||||||
|
{
|
||||||
|
if (space == 0)
|
||||||
|
return;
|
||||||
|
probspace_release(space->left);
|
||||||
|
probspace_release(space->right);
|
||||||
|
Node<PgfProbspaceEntry>::release(space);
|
||||||
|
}
|
||||||
73
src/runtime/c/pgf/probspace.h
Normal file
73
src/runtime/c/pgf/probspace.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#ifndef PROBSPACE_H
|
||||||
|
#define PROBSPACE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The probspace is an index where abstract functions are ordered by
|
||||||
|
* the tripple of (category,probability,name). Here the category is
|
||||||
|
* any of the categories used in the type of the function.
|
||||||
|
*
|
||||||
|
* When a new function is created, it is inserted first in
|
||||||
|
* the namespace of functions and after that in the probspace.
|
||||||
|
* The insertion in the probspace is done once for every category in
|
||||||
|
* the type of the function. The insertion with a result category is
|
||||||
|
* always done after the insertion with the argument categories.
|
||||||
|
* This means that we can easily identify functions which return a given
|
||||||
|
* category by just checking that:
|
||||||
|
*
|
||||||
|
* entry->cat == ref<PgfText>::from_ptr(&fun->type->name);
|
||||||
|
*
|
||||||
|
* The later is important when the index is used in tree generation
|
||||||
|
* and parsing.
|
||||||
|
*
|
||||||
|
* The index has the following uses:
|
||||||
|
*
|
||||||
|
* - When a category is removed we must also remove all functions that
|
||||||
|
* use it in their types, otherwise the data will be inconsistant.
|
||||||
|
* We use the index to find which functions to remove.
|
||||||
|
*
|
||||||
|
* - When a lincat is removed we must remove all lins from the same
|
||||||
|
* language which depend on the lincat. We identify them through
|
||||||
|
* the abstract types and whence through this index.
|
||||||
|
*
|
||||||
|
* - When we do exhaustive or random generation, we need to know
|
||||||
|
* which functions return a given category. We simply go through
|
||||||
|
* the index but also check the above condition to distinguish the case
|
||||||
|
* where the category is consumed from the case where the category is
|
||||||
|
* returned. In exhaustive generation, to ensure that all results
|
||||||
|
* are returned in decreasing probability order, we must consume
|
||||||
|
* functions in the same order. This is the reason why we keep the
|
||||||
|
* index sorted by probability.
|
||||||
|
*
|
||||||
|
* - When a function is removed, we must remove it both from
|
||||||
|
* the namespace as well as from the probspace. Since the index is
|
||||||
|
* sorted by function name, as well, we use that to find which entry
|
||||||
|
* to remove.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct PGF_INTERNAL_DECL PgfProbspaceEntry {
|
||||||
|
ref<PgfText> cat;
|
||||||
|
ref<PgfAbsFun> fun;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ref<Node<PgfProbspaceEntry>> PgfProbspace;
|
||||||
|
|
||||||
|
PGF_INTERNAL_DECL
|
||||||
|
PgfProbspace probspace_insert(PgfProbspace space,
|
||||||
|
ref<PgfAbsFun> fun);
|
||||||
|
|
||||||
|
PGF_INTERNAL_DECL
|
||||||
|
PgfProbspace probspace_delete(PgfProbspace space,
|
||||||
|
ref<PgfAbsFun> fun);
|
||||||
|
|
||||||
|
PGF_INTERNAL_DECL
|
||||||
|
PgfProbspace probspace_delete_by_cat(PgfProbspace space, PgfText *cat,
|
||||||
|
PgfItor* itor, PgfExn *err);
|
||||||
|
|
||||||
|
PGF_INTERNAL_DECL
|
||||||
|
void probspace_iter(PgfProbspace space, PgfText *cat,
|
||||||
|
PgfItor* itor, bool all, PgfExn *err);
|
||||||
|
|
||||||
|
PGF_INTERNAL_DECL
|
||||||
|
void probspace_release(PgfProbspace space);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user