From f050609101e25fdee6f884a0da43dafa8889772e Mon Sep 17 00:00:00 2001 From: "kr.angelov" Date: Thu, 18 Apr 2013 13:37:09 +0000 Subject: added API for computing bracketed strings from Python and C --- src/runtime/python/pypgf.c | 263 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 262 insertions(+), 1 deletion(-) (limited to 'src/runtime/python') diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index 95d92fbce..dd1c9d2ce 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include static PyObject* PGFError; @@ -731,6 +733,258 @@ Concr_linearize(ConcrObject* self, PyObject *args) return pystr; } +typedef struct { + PyObject_HEAD + PyObject* cat; + int fid; + int lindex; + PyObject* fun; + PyObject* children; +} BracketObject; + +static void +Bracket_dealloc(BracketObject* self) +{ + Py_XDECREF(self->cat); + Py_XDECREF(self->fun); + Py_XDECREF(self->children); + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject * +Bracket_repr(BracketObject *self) +{ + PyObject *repr = + PyString_FromFormat("(%s:%d", PyString_AsString(self->cat), self->fid); + if (repr == NULL) { + return NULL; + } + + PyObject *space = PyString_FromString(" "); + + size_t len = PyList_Size(self->children); + for (size_t i = 0; i < len; i++) { + PyObject *child = PyList_GetItem(self->children, i); + + PyString_Concat(&repr, space); + if (repr == NULL) { + Py_DECREF(space); + return NULL; + } + + PyObject *child_str = child->ob_type->tp_str(child); + if (child_str == NULL) { + Py_DECREF(repr); + Py_DECREF(space); + return NULL; + } + + PyString_Concat(&repr, child_str); + if (repr == NULL) { + Py_DECREF(space); + return NULL; + } + } + + Py_DECREF(space); + + PyObject *str = PyString_FromString(")"); + PyString_Concat(&repr, str); + if (repr == NULL) { + Py_DECREF(str); + return NULL; + } + Py_DECREF(str); + + return repr; +} + +static PyMemberDef Bracket_members[] = { + {"cat", T_OBJECT_EX, offsetof(BracketObject, cat), READONLY, + "the syntactic category for this bracket"}, + {"fun", T_OBJECT_EX, offsetof(BracketObject, fun), READONLY, + "the abstract function for this bracket"}, + {"fid", T_INT, offsetof(BracketObject, fid), READONLY, + "an unique id which identifies this bracket in the whole bracketed string"}, + {"lindex", T_INT, offsetof(BracketObject, lindex), READONLY, + "the constituent index"}, + {"children", T_OBJECT_EX, offsetof(BracketObject, children), READONLY, + "a list with the children of this bracket"}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject pgf_BracketType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "pgf.Bracket", /*tp_name*/ + sizeof(BracketObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)Bracket_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + (reprfunc) Bracket_repr, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "a linearization bracket", /*tp_doc*/ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + 0, /*tp_methods */ + Bracket_members, /*tp_members */ + 0, /*tp_getset */ + 0, /*tp_base */ + 0, /*tp_dict */ + 0, /*tp_descr_get */ + 0, /*tp_descr_set */ + 0, /*tp_dictoffset */ + 0, /*tp_init */ + 0, /*tp_alloc */ + 0, /*tp_new */ +}; + +typedef struct { + PgfLinFuncs* funcs; + GuBuf* stack; + PyObject* list; +} PgfBracketLznState; + +static void +pgf_bracket_lzn_symbol_tokens(PgfLinFuncs** funcs, PgfTokens toks) +{ + PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs); + + size_t len = gu_seq_length(toks); + for (size_t i = 0; i < len; i++) { + PgfToken tok = gu_seq_get(toks, PgfToken, i); + PyObject* str = gu2py_string(tok); + PyList_Append(state->list, str); + Py_DECREF(str); + } +} + +static void +pgf_bracket_lzn_expr_literal(PgfLinFuncs** funcs, PgfLiteral lit) +{ + PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs); + + GuVariantInfo i = gu_variant_open(lit); + switch (i.tag) { + case PGF_LITERAL_STR: { + PgfLiteralStr* lstr = i.data; + PyObject* str = gu2py_string(lstr->val); + PyList_Append(state->list, str); + Py_DECREF(str); + break; + } + case PGF_LITERAL_INT: { + PgfLiteralInt* lint = i.data; + PyObject* str = PyString_FromFormat("%d", lint->val); + PyList_Append(state->list, str); + Py_DECREF(str); + break; + } + case PGF_LITERAL_FLT: { + PgfLiteralFlt* lflt = i.data; + PyObject* str = PyString_FromFormat("%f", lflt->val); + PyList_Append(state->list, str); + Py_DECREF(str); + break; + } + default: + gu_impossible(); + } +} + +static void +pgf_bracket_lzn_begin_phrase(PgfLinFuncs** funcs, PgfCId cat, int fid, int lindex, PgfCId fun) +{ + PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs); + + gu_buf_push(state->stack, PyObject*, state->list); + state->list = PyList_New(0); +} + +static void +pgf_bracket_lzn_end_phrase(PgfLinFuncs** funcs, PgfCId cat, int fid, int lindex, PgfCId fun) +{ + PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs); + + PyObject* parent = gu_buf_pop(state->stack, PyObject*); + + if (PyList_Size(state->list) > 0) { + BracketObject* bracket = (BracketObject *) + pgf_BracketType.tp_alloc(&pgf_BracketType, 0); + if (bracket != NULL) { + bracket->cat = gu2py_string(cat); + bracket->fid = fid; + bracket->lindex = lindex; + bracket->fun = gu2py_string(fun); + bracket->children = state->list; + PyList_Append(parent, (PyObject*) bracket); + Py_DECREF(bracket); + } + } else { + Py_DECREF(state->list); + } + + state->list = parent; +} + +static PgfLinFuncs pgf_bracket_lin_funcs = { + .symbol_tokens = pgf_bracket_lzn_symbol_tokens, + .expr_literal = pgf_bracket_lzn_expr_literal, + .begin_phrase = pgf_bracket_lzn_begin_phrase, + .end_phrase = pgf_bracket_lzn_end_phrase +}; + +static PyObject* +Concr_bracketedLinearize(ConcrObject* self, PyObject *args) +{ + ExprObject* pyexpr; + if (!PyArg_ParseTuple(args, "O!", &pgf_ExprType, &pyexpr)) + return NULL; + + GuPool* tmp_pool = gu_local_pool(); + + GuEnum* cts = + pgf_lzr_concretize(self->concr, pyexpr->expr, tmp_pool); + PgfCncTree ctree = gu_next(cts, PgfCncTree, tmp_pool); + if (gu_variant_is_null(ctree)) { + PyErr_SetString(PGFError, "The abstract tree cannot be linearized"); + gu_pool_free(tmp_pool); + return NULL; + } + + PyObject* list = PyList_New(0); + + PgfBracketLznState state; + state.funcs = &pgf_bracket_lin_funcs; + state.stack = gu_new_buf(PyObject*, tmp_pool); + state.list = list; + pgf_lzr_linearize(self->concr, ctree, 0, &state.funcs); + + gu_pool_free(tmp_pool); + + PyObject* bracket = PyList_GetItem(list, 0); + Py_INCREF(bracket); + Py_DECREF(list); + + return bracket; +} + static PyObject* Concr_getName(ConcrObject *self, void *closure) { @@ -753,7 +1007,10 @@ static PyMethodDef Concr_methods[] = { "Parses a string and returns an iterator over the abstract trees for this sentence" }, {"linearize", (PyCFunction)Concr_linearize, METH_VARARGS, - "Takes an abstract tree and linearizes it to a sentence" + "Takes an abstract tree and linearizes it to a string" + }, + {"bracketedLinearize", (PyCFunction)Concr_bracketedLinearize, METH_VARARGS, + "Takes an abstract tree and linearizes it to a bracketed string" }, {NULL} /* Sentinel */ }; @@ -1234,6 +1491,9 @@ initpgf(void) if (PyType_Ready(&pgf_ConcrType) < 0) return; + if (PyType_Ready(&pgf_BracketType) < 0) + return; + if (PyType_Ready(&pgf_ExprType) < 0) return; @@ -1260,4 +1520,5 @@ initpgf(void) Py_INCREF(&pgf_PGFType); Py_INCREF(&pgf_ConcrType); Py_INCREF(&pgf_ExprIterType); + Py_INCREF(&pgf_BracketType); } -- cgit v1.2.3