From 7036d56d29798f6fb78c62b2c4bbbbcc677b1982 Mon Sep 17 00:00:00 2001 From: "kr.angelov" Date: Thu, 25 Sep 2014 11:59:40 +0000 Subject: [PATCH] the literals API is now exposed in Python --- src/runtime/python/pypgf.c | 114 +++++++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 10 deletions(-) diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index e1df97cd1..1ee9d5af4 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -1333,23 +1333,117 @@ Concr_parseval(ConcrObject* self, PyObject *args) { return Py_BuildValue("ddd", precision, recall, exact); } +typedef struct { + PgfLiteralCallback callback; + PyObject* pycallback; + GuFinalizer fin; +} PyPgfLiteralCallback; + +static PgfExprProb* +pypgf_literal_callback_match(PgfLiteralCallback* self, + size_t lin_idx, + GuString sentence, size_t* poffset, + GuPool *out_pool) +{ + PyPgfLiteralCallback* callback = + gu_container(self, PyPgfLiteralCallback, callback); + + PyObject* result = + PyObject_CallFunction(callback->pycallback, "isi", + lin_idx, sentence, *poffset); + if (result == NULL || result == Py_None) + return NULL; + + PgfExprProb* ep = gu_new(PgfExprProb, out_pool); + + ExprObject* pyexpr; + if (!PyArg_ParseTuple(result, "Ofi", &pyexpr, &ep->prob, poffset)) + return NULL; + ep->expr = pyexpr->expr; + + { + // This is an uggly hack. We first show the expression ep->expr + // and then we read it back but in out_pool. The whole purpose + // of this is to copy the expression from the temporary pool + // that was created in the Java binding to the parser pool. + // There should be a real copying function or even better + // there must be a way to avoid copying at all. + + GuPool* tmp_pool = gu_local_pool(); + + GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool); + GuStringBuf* sbuf = gu_string_buf(tmp_pool); + GuOut* out = gu_string_buf_out(sbuf); + + pgf_print_expr(ep->expr, NULL, 0, out, err); + + GuString str = gu_string_buf_freeze(sbuf, tmp_pool); + GuIn* in = gu_data_in((uint8_t*) str, strlen(str), tmp_pool); + + ep->expr = pgf_read_expr(in, out_pool, err); + if (!gu_ok(err) || gu_variant_is_null(ep->expr)) { + PyErr_SetString(PGFError, "The expression cannot be parsed"); + gu_pool_free(tmp_pool); + return NULL; + } + + gu_pool_free(tmp_pool); + } + + Py_DECREF(pyexpr); + + return ep; +} + +static GuEnum* +pypgf_literal_callback_predict(PgfLiteralCallback* self, + size_t lin_idx, + GuString prefix, + GuPool *out_pool) +{ + return NULL; +} + +static void +pypgf_literal_callback_fin(GuFinalizer* self) +{ + PyPgfLiteralCallback* callback = + gu_container(self, PyPgfLiteralCallback, fin); + + Py_XDECREF(callback->pycallback); +} + static PyObject* Concr_addLiteral(ConcrObject* self, PyObject *args) { - ExprObject* pyexpr = NULL; - const char* s_cat = NULL; - if (!PyArg_ParseTuple(args, "sO!", &s_cat, &pgf_ExprType, &pyexpr)) + PyObject* pycallback = NULL; + const char* cat = NULL; + if (!PyArg_ParseTuple(args, "sO", &cat, &pycallback)) return NULL; -/* - PgfLiteralCallback* callback = NULL; - GuPool* tmp_pool = gu_local_pool(); + GuPool* pool = pgf_concr_get_pool(self->concr); - PgfCId cat = gu_str_string(s_cat, tmp_pool); - - pgf_parser_add_literal(self->concr, cat, callback); + PyPgfLiteralCallback* callback = gu_new(PyPgfLiteralCallback, pool); + callback->callback.match = pypgf_literal_callback_match; + callback->callback.predict = pypgf_literal_callback_predict; + callback->pycallback = pycallback; + callback->fin.fn = pypgf_literal_callback_fin; + + gu_pool_finally(pool, &callback->fin); + + GuPool* tmp_pool = gu_local_pool(); + GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool); + pgf_concr_add_literal(self->concr, cat, &callback->callback, err); + + if (!gu_ok(err)) { + if (gu_exn_caught(err) == gu_type(PgfExn)) { + GuString msg = (GuString) gu_exn_caught_data(err); + PyErr_SetString(PGFError, msg); + } else { + PyErr_SetString(PGFError, "The literal cannot be added"); + } + } gu_pool_free(tmp_pool); -*/ Py_RETURN_NONE; }