summaryrefslogtreecommitdiff
path: root/src/runtime/python/pypgf.c
diff options
context:
space:
mode:
authorprasanth.kolachina <prasanth.kolachina@cse.gu.se>2015-04-27 15:47:57 +0000
committerprasanth.kolachina <prasanth.kolachina@cse.gu.se>2015-04-27 15:47:57 +0000
commitdedad558a8ef70226374733e1d6edcba22c5def7 (patch)
tree2776451b682ba9bbfd792d38324b2d091d18085f /src/runtime/python/pypgf.c
parent9b723af9955e0e244a3dfda37aa32d41fc7963e3 (diff)
Python linearizeAll with lazyness
linearizeAll function will take an expression and an optional n keyword argument and return an iterator to the n-variant linearizations of the expression.
Diffstat (limited to 'src/runtime/python/pypgf.c')
-rw-r--r--src/runtime/python/pypgf.c104
1 files changed, 100 insertions, 4 deletions
diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c
index 4725695ff..470592139 100644
--- a/src/runtime/python/pypgf.c
+++ b/src/runtime/python/pypgf.c
@@ -1031,6 +1031,7 @@ Iter_fetch_token(IterObject* self)
return res;
}
+
static IterObject*
Iter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
@@ -1214,7 +1215,7 @@ pypgf_literal_callback_match(PgfLiteralCallback* self,
lin_idx, sentence, *poffset);
if (result == NULL)
return NULL;
-
+
if (result == Py_None) {
Py_DECREF(result);
return NULL;
@@ -1224,7 +1225,8 @@ pypgf_literal_callback_match(PgfLiteralCallback* self,
ExprObject* pyexpr;
if (!PyArg_ParseTuple(result, "Ofi", &pyexpr, &ep->prob, poffset))
- return NULL;
+ return NULL;
+
ep->expr = pyexpr->expr;
{
@@ -1306,7 +1308,7 @@ pypgf_new_callbacks_map(PgfConcr* concr, PyObject *py_callbacks,
callback->fin.fn = pypgf_literal_callback_fin;
Py_XINCREF(callback->pycallback);
-
+
gu_pool_finally(pool, &callback->fin);
pgf_callbacks_map_add_literal(concr, callbacks,
@@ -1476,14 +1478,18 @@ Concr_linearize(ConcrObject* self, PyObject *args)
pgf_linearize(self->concr, pyexpr->expr, out, err);
if (!gu_ok(err)) {
- if (gu_exn_caught(err, PgfLinNonExist))
+ if (gu_exn_caught(err, PgfLinNonExist)) {
+ gu_pool_free(tmp_pool);
Py_RETURN_NONE;
+ }
else if (gu_exn_caught(err, PgfExn)) {
GuString msg = (GuString) gu_exn_caught_data(err);
PyErr_SetString(PGFError, msg);
+ gu_pool_free(tmp_pool);
return NULL;
} else {
PyErr_SetString(PGFError, "The abstract tree cannot be linearized");
+ gu_pool_free(tmp_pool);
return NULL;
}
}
@@ -1496,6 +1502,93 @@ Concr_linearize(ConcrObject* self, PyObject *args)
}
static PyObject*
+Iter_fetch_linearization(IterObject* self)
+{
+restart:;
+ GuStringBuf* sbuf = gu_string_buf(self->pool);
+ GuOut* out = gu_string_buf_out(sbuf);
+ GuExn* err = gu_new_exn(self->pool);
+
+ PgfCncTree ctree = gu_next(self->res, PgfCncTree, self->pool);
+ if (gu_variant_is_null(ctree)) {
+ return NULL;
+ }
+ pgf_lzr_wrap_linref(ctree, self->pool); // to reduce tuple of strings to a single string;
+
+ // Linearize the concrete tree as a simple sequence of strings.
+ ConcrObject* pyconcr = (ConcrObject*)self->container;
+ pgf_lzr_linearize_simple(pyconcr->concr, ctree, 0, out, err, self->pool);
+
+ if (!gu_ok(err)) {
+ if (gu_exn_caught(err, PgfLinNonExist)) {
+ // encountered nonExist. Unfortunately there
+ // might be some output printed already. The
+ // right solution should be to use GuStringBuf.
+ gu_exn_clear(err);
+ goto restart;
+ }
+ else if (gu_exn_caught(err, PgfExn)) {
+ GuString msg = (GuString) gu_exn_caught_data(err);
+ PyErr_SetString(PGFError, msg);
+ return NULL;
+ } else {
+ PyErr_SetString(PGFError, "The abstract tree cannot be linearized");
+ return NULL;
+ }
+ }
+ GuString str = gu_string_buf_freeze(sbuf, self->pool);
+ PyObject* pystr = PyString_FromString(str);
+ return pystr;
+}
+
+static PyObject*
+Concr_linearizeAll(ConcrObject* self, PyObject *args, PyObject *keywds)
+{
+ static char *kwlist[] = {"expression", "n", NULL};
+ ExprObject* pyexpr = NULL;
+ int max_count = -1;
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!|i", kwlist,
+ &pgf_ExprType, &pyexpr, &max_count))
+ return NULL;
+
+ GuPool* pool = gu_new_pool();
+ GuExn* err = gu_exn(pool);
+
+ GuEnum* cts = pgf_lzr_concretize(self->concr, pyexpr->expr, err, pool);
+ if (!gu_ok(err)) {
+ if (gu_exn_caught(err, PgfExn)) {
+ GuString msg = (GuString) gu_exn_caught_data(err);
+ PyErr_SetString(PGFError, msg);
+ gu_pool_free(pool);
+ return NULL;
+ } else {
+ PyErr_SetString(PGFError, "The abstract tree cannot be linearized");
+ gu_pool_free(pool);
+ return NULL;
+ }
+ }
+
+ IterObject* pyres = (IterObject*) pgf_IterType.tp_alloc(&pgf_IterType, 0);
+ if (pyres == NULL) {
+ gu_pool_free(pool);
+ return NULL;
+ }
+
+ pyres->grammar = self->grammar;
+ Py_XINCREF(pyres->grammar);
+ pyres->container = (PyObject*)self;
+ Py_INCREF(pyres->container);
+ pyres->pool = pool;
+ pyres->max_count = max_count;
+ pyres->counter = 0;
+ pyres->fetch = Iter_fetch_linearization;
+ pyres->res = cts;
+
+ return (PyObject*)pyres;
+
+}
+
+static PyObject*
Concr_tabularLinearize(ConcrObject* self, PyObject *args)
{
ExprObject* pyexpr;
@@ -2054,6 +2147,9 @@ static PyMethodDef Concr_methods[] = {
{"linearize", (PyCFunction)Concr_linearize, METH_VARARGS,
"Takes an abstract tree and linearizes it to a string"
},
+ {"linearizeAll", (PyCFunction)Concr_linearizeAll, METH_VARARGS | METH_KEYWORDS,
+ "Takes an abstract tree and linearizes with all variants"
+ },
{"tabularLinearize", (PyCFunction)Concr_tabularLinearize, METH_VARARGS,
"Takes an abstract tree and linearizes it to a table containing all fields"
},