summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkr.angelov <kr.angelov@gmail.com>2014-07-06 19:49:17 +0000
committerkr.angelov <kr.angelov@gmail.com>2014-07-06 19:49:17 +0000
commite52d5bf7157e59ef46eda96d07d8131e9f6f0ed2 (patch)
treed02af48aba5c9d2b7ced85d1839117f6c9100f2c /src
parentac1e58817b62cb80d58d283ccad372d69210af65 (diff)
embedded mode for GF grammar in Python. Only generation for now
Diffstat (limited to 'src')
-rw-r--r--src/runtime/c/pgf/pgf.c7
-rw-r--r--src/runtime/c/pgf/pgf.h4
-rw-r--r--src/runtime/python/pypgf.c106
3 files changed, 116 insertions, 1 deletions
diff --git a/src/runtime/c/pgf/pgf.c b/src/runtime/c/pgf/pgf.c
index ee736616c..60e838e84 100644
--- a/src/runtime/c/pgf/pgf.c
+++ b/src/runtime/c/pgf/pgf.c
@@ -198,3 +198,10 @@ pgf_concr_add_literal(PgfConcr *concr, PgfCId cat,
gu_map_put(concr->callbacks, cnccat,
PgfLiteralCallback*, callback);
}
+
+PgfExprProb*
+pgf_fun_get_ep(void* value)
+{
+ PgfAbsFun* absfun = *((PgfAbsFun**) value);
+ return &absfun->ep;
+}
diff --git a/src/runtime/c/pgf/pgf.h b/src/runtime/c/pgf/pgf.h
index d6de05e90..7cddbbcae 100644
--- a/src/runtime/c/pgf/pgf.h
+++ b/src/runtime/c/pgf/pgf.h
@@ -189,4 +189,8 @@ void
pgf_check_type(PgfPGF* gr, PgfType** ty,
GuExn* exn, GuPool* pool);
+// internal
+PgfExprProb*
+pgf_fun_get_ep(void* value);
+
#endif // PGF_H_
diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c
index 2e3a82b44..2f04df4b0 100644
--- a/src/runtime/python/pypgf.c
+++ b/src/runtime/python/pypgf.c
@@ -65,6 +65,9 @@ Expr_initLiteral(ExprObject *self, PyObject *lit);
static int
Expr_initApp(ExprObject *self, const char* fname, PyObject *args);
+static ExprObject*
+Expr_call(ExprObject* e, PyObject* args, PyObject* kw);
+
static PyObject*
Expr_unpack(ExprObject* self, PyObject *args);
@@ -184,7 +187,7 @@ static PyTypeObject pgf_ExprType = {
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc) Expr_hash, /*tp_hash */
- 0, /*tp_call*/
+ (ternaryfunc) Expr_call, /*tp_call*/
(reprfunc) Expr_repr, /*tp_str*/
(getattrofunc) Expr_getattro,/*tp_getattro*/
0, /*tp_setattro*/
@@ -302,6 +305,51 @@ Expr_initApp(ExprObject *self, const char* fname, PyObject *args)
return 0;
}
+static ExprObject*
+Expr_call(ExprObject* self, PyObject* args, PyObject* kw)
+{
+ ExprObject* pyexpr = (ExprObject*) pgf_ExprType.tp_alloc(&pgf_ExprType, 0);
+ if (pyexpr == NULL)
+ return NULL;
+
+ size_t n_args = PyTuple_Size(args);
+
+ pyexpr->master = PyTuple_New(n_args+1);
+ if (pyexpr->master == NULL) {
+ Py_DECREF(pyexpr);
+ return NULL;
+ }
+
+ PyTuple_SetItem(pyexpr->master, 0, (PyObject*) self);
+ Py_INCREF(self);
+
+ pyexpr->pool = gu_new_pool();
+ pyexpr->expr = self->expr;
+
+ for (Py_ssize_t i = 0; i < n_args; i++) {
+ PyObject* obj = PyTuple_GetItem(args, i);
+ if (obj->ob_type != &pgf_ExprType) {
+ PyErr_SetString(PyExc_TypeError, "the arguments must be expressions");
+ return NULL;
+ }
+
+ PyTuple_SetItem(pyexpr->master, i+1, obj);
+ Py_INCREF(obj);
+
+ PgfExpr fun = pyexpr->expr;
+ PgfExpr arg = ((ExprObject*) obj)->expr;
+
+ PgfExprApp* e =
+ gu_new_variant(PGF_EXPR_APP,
+ PgfExprApp,
+ &pyexpr->expr, pyexpr->pool);
+ e->fun = fun;
+ e->arg = arg;
+ }
+
+ return pyexpr;
+}
+
static PyObject*
Expr_unpack(ExprObject* self, PyObject *fargs)
{
@@ -2343,6 +2391,56 @@ PGF_graphvizAbstractTree(PGFObject* self, PyObject *args) {
return pystr;
}
+static void
+pgf_embed_funs(GuMapItor* fn, const void* key, void* value, GuExn* err)
+{
+ PyPGFClosure* clo = (PyPGFClosure*) fn;
+
+ PgfCId name = (PgfCId) key;
+
+ ExprObject* pyexpr = (ExprObject*) pgf_ExprType.tp_alloc(&pgf_ExprType, 0);
+ if (pyexpr == NULL) {
+ gu_raise(err, PgfExn);
+ return;
+ }
+
+ pyexpr->expr = pgf_fun_get_ep(value)->expr;
+
+ if (PyModule_AddObject(clo->object, name, (PyObject*) pyexpr) != 0) {
+ gu_raise(err, PgfExn);
+ }
+}
+
+static PyObject*
+PGF_embed(PGFObject* self, PyObject *args)
+{
+ PgfCId modname;
+ if (!PyArg_ParseTuple(args, "s", &modname))
+ return NULL;
+
+ PyObject *m = PyImport_AddModule(modname);
+ if (m == NULL)
+ return NULL;
+
+ GuPool* tmp_pool = gu_local_pool();
+
+ // Create an exception frame that catches all errors.
+ GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool);
+
+ PyPGFClosure clo = { { pgf_embed_funs }, self, m };
+ pgf_iter_functions(self->pgf, &clo.fn, err);
+ if (!gu_ok(err)) {
+ Py_DECREF(m);
+ gu_pool_free(tmp_pool);
+ return NULL;
+ }
+
+ gu_pool_free(tmp_pool);
+
+ Py_INCREF(m);
+ return m;
+}
+
static PyGetSetDef PGF_getseters[] = {
{"abstractName",
(getter)PGF_getAbstractName, NULL,
@@ -2396,6 +2494,12 @@ static PyMethodDef PGF_methods[] = {
{"graphvizAbstractTree", (PyCFunction)PGF_graphvizAbstractTree, METH_VARARGS,
"Renders an abstract syntax tree in a Graphviz format"
},
+ {"embed", (PyCFunction)PGF_embed, METH_VARARGS,
+ "embed(mod_name) creates a Python module with name mod_name, which "
+ "contains one Python object for every abstract function in the grammar. "
+ "The module can be imported to make it easier to construct abstract "
+ "syntax trees."
+ },
{NULL} /* Sentinel */
};