mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-09-17 07:46:00 -06:00
add parsing API
This commit is contained in:
+196
-5
@@ -58,6 +58,197 @@ Concr_getLanguageCode(ConcrObject *self, void *closure)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef struct IterObject {
|
||||||
|
PyObject_HEAD
|
||||||
|
PgfDB *db;
|
||||||
|
PyObject* source;
|
||||||
|
int max_count;
|
||||||
|
int counter;
|
||||||
|
PgfExprEnum* res;
|
||||||
|
} IterObject;
|
||||||
|
|
||||||
|
static IterObject*
|
||||||
|
Iter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
IterObject* self = (IterObject *)type->tp_alloc(type, 0);
|
||||||
|
if (self != NULL) {
|
||||||
|
self->db = NULL;
|
||||||
|
self->source = NULL;
|
||||||
|
self->max_count = -1;
|
||||||
|
self->counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Iter_dealloc(IterObject* self)
|
||||||
|
{
|
||||||
|
Py_XDECREF(self->source);
|
||||||
|
pgf_free_expr_enum(self->res);
|
||||||
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
Iter_init(IterObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
Iter_iter(IterObject *self)
|
||||||
|
{
|
||||||
|
Py_INCREF(self);
|
||||||
|
return (PyObject*) self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
Iter_iternext(IterObject *self)
|
||||||
|
{
|
||||||
|
if (self->max_count >= 0 && self->counter >= self->max_count) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
self->counter++;
|
||||||
|
|
||||||
|
prob_t prob;
|
||||||
|
PyObject *expr =
|
||||||
|
(PyObject*) self->res->vtbl->fetch(self->res, self->db, &prob);
|
||||||
|
if (expr == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
PyObject *tup = PyTuple_New(2);
|
||||||
|
if (tup == NULL) {
|
||||||
|
Py_DECREF(expr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyTuple_SetItem(tup, 0, expr);
|
||||||
|
PyTuple_SetItem(tup, 1, PyFloat_FromDouble(prob));
|
||||||
|
return tup;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef Iter_methods[] = {
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyTypeObject pgf_IterType = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
//0, /*ob_size*/
|
||||||
|
"pgf.Iter", /*tp_name*/
|
||||||
|
sizeof(IterObject), /*tp_basicsize*/
|
||||||
|
0, /*tp_itemsize*/
|
||||||
|
(destructor)Iter_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*/
|
||||||
|
0, /*tp_str*/
|
||||||
|
0, /*tp_getattro*/
|
||||||
|
0, /*tp_setattro*/
|
||||||
|
0, /*tp_as_buffer*/
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||||
|
"an iterator over a sequence of expressions",/*tp_doc*/
|
||||||
|
0, /*tp_traverse */
|
||||||
|
0, /*tp_clear */
|
||||||
|
0, /*tp_richcompare */
|
||||||
|
0, /*tp_weaklistoffset */
|
||||||
|
(getiterfunc) Iter_iter, /*tp_iter */
|
||||||
|
(iternextfunc) Iter_iternext, /*tp_iternext */
|
||||||
|
Iter_methods, /*tp_methods */
|
||||||
|
0, /*tp_members */
|
||||||
|
0, /*tp_getset */
|
||||||
|
0, /*tp_base */
|
||||||
|
0, /*tp_dict */
|
||||||
|
0, /*tp_descr_get */
|
||||||
|
0, /*tp_descr_set */
|
||||||
|
0, /*tp_dictoffset */
|
||||||
|
(initproc)Iter_init, /*tp_init */
|
||||||
|
0, /*tp_alloc */
|
||||||
|
(newfunc) Iter_new, /*tp_new */
|
||||||
|
};
|
||||||
|
|
||||||
|
static TypeObject*
|
||||||
|
pgf_type_from_object(PyObject* obj) {
|
||||||
|
if (PyUnicode_Check(obj)) {
|
||||||
|
PgfText *input = PyUnicode_AsPgfText(obj);
|
||||||
|
PgfType type = pgf_read_type(input, &unmarshaller);
|
||||||
|
FreePgfText(input);
|
||||||
|
if (type == 0) {
|
||||||
|
PyErr_SetString(PGFError, "type cannot be parsed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (TypeObject *)type;
|
||||||
|
} else if (obj->ob_type == &pgf_TypeType) {
|
||||||
|
return (TypeObject*) obj;
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "the start category should be a string or a type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IterObject*
|
||||||
|
Concr_parse(ConcrObject* self, PyObject *args, PyObject *keywds)
|
||||||
|
{
|
||||||
|
static char *kwlist[] = {"sentence", "cat", "n", NULL};
|
||||||
|
|
||||||
|
const char *sentence = NULL;
|
||||||
|
size_t sentence_size;
|
||||||
|
PyObject* start = NULL;
|
||||||
|
int max_count = -1;
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s#|Oi", kwlist,
|
||||||
|
&sentence, &sentence_size,
|
||||||
|
&start, &max_count))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
IterObject* pyres = (IterObject*)
|
||||||
|
pgf_IterType.tp_alloc(&pgf_IterType, 0);
|
||||||
|
if (pyres == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pyres->db = self->grammar->db;
|
||||||
|
pyres->source = (PyObject*) self;
|
||||||
|
Py_XINCREF(pyres->source);
|
||||||
|
|
||||||
|
pyres->max_count = max_count;
|
||||||
|
pyres->counter = 0;
|
||||||
|
|
||||||
|
PgfExn err;
|
||||||
|
|
||||||
|
TypeObject *type;
|
||||||
|
if (start == NULL) {
|
||||||
|
type = (TypeObject *) pgf_start_cat(self->grammar->db, self->grammar->revision, &unmarshaller, &err);
|
||||||
|
if (handleError(err) != PGF_EXN_NONE) {
|
||||||
|
Py_DECREF(pyres);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type = pgf_type_from_object(start);
|
||||||
|
}
|
||||||
|
if (type == NULL) {
|
||||||
|
Py_DECREF(pyres);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PgfText *text_sentence = CString_AsPgfText(sentence, sentence_size);
|
||||||
|
pyres->res = (PgfExprEnum*)
|
||||||
|
pgf_parse(self->grammar->db, self->concr, (PgfType) type,
|
||||||
|
&marshaller, &unmarshaller,
|
||||||
|
text_sentence, &err);
|
||||||
|
FreePgfText(text_sentence);
|
||||||
|
if (handleError(err) != PGF_EXN_NONE) {
|
||||||
|
Py_DECREF(pyres);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pyres;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
Concr_linearize(ConcrObject* self, PyObject *args)
|
Concr_linearize(ConcrObject* self, PyObject *args)
|
||||||
{
|
{
|
||||||
@@ -568,17 +759,15 @@ static PyGetSetDef Concr_getseters[] = {
|
|||||||
static PyMethodDef Concr_methods[] = {
|
static PyMethodDef Concr_methods[] = {
|
||||||
/* {"printName", (PyCFunction)Concr_printName, METH_VARARGS,
|
/* {"printName", (PyCFunction)Concr_printName, METH_VARARGS,
|
||||||
"Returns the print name of a function or category"
|
"Returns the print name of a function or category"
|
||||||
},
|
},*/
|
||||||
{"parse", (PyCFunction)Concr_parse, METH_VARARGS | METH_KEYWORDS,
|
{"parse", (PyCFunction)Concr_parse, METH_VARARGS | METH_KEYWORDS,
|
||||||
"Parses a string and returns an iterator over the abstract trees for this sentence\n\n"
|
"Parses a string and returns an iterator over the abstract trees for this sentence\n\n"
|
||||||
"Named arguments:\n"
|
"Named arguments:\n"
|
||||||
"- sentence (string)\n"
|
"- sentence (string)\n"
|
||||||
"- cat (string); OPTIONAL, default: the startcat of the grammar\n"
|
"- cat (string); OPTIONAL, default: the startcat of the grammar\n"
|
||||||
"- n (int), max. trees; OPTIONAL, default: extract all trees\n"
|
"- n (int), max. trees; OPTIONAL, default: extract all trees\n"
|
||||||
"- heuristics (double >= 0.0); OPTIONAL, default: taken from the flags in the grammar\n"
|
|
||||||
"- callbacks (list of category and callback); OPTIONAL, default: built-in callbacks only for Int, String and Float"
|
|
||||||
},
|
},
|
||||||
{"complete", (PyCFunction)Concr_complete, METH_VARARGS | METH_KEYWORDS,
|
/*{"complete", (PyCFunction)Concr_complete, METH_VARARGS | METH_KEYWORDS,
|
||||||
"Parses a partial string and returns a list with the top n possible next tokens"
|
"Parses a partial string and returns a list with the top n possible next tokens"
|
||||||
"Named arguments:\n"
|
"Named arguments:\n"
|
||||||
"- sentence (string or a (string,pgf.BIND) tuple. The later indicates that the sentence ends with a BIND token)\n"
|
"- sentence (string or a (string,pgf.BIND) tuple. The later indicates that the sentence ends with a BIND token)\n"
|
||||||
@@ -1663,7 +1852,7 @@ static PyMethodDef PGF_methods[] = {
|
|||||||
"Checks whether a function is a constructor"
|
"Checks whether a function is a constructor"
|
||||||
},
|
},
|
||||||
{"generateRandom", (PyCFunction)PGF_generateRandom, METH_VARARGS | METH_KEYWORDS,
|
{"generateRandom", (PyCFunction)PGF_generateRandom, METH_VARARGS | METH_KEYWORDS,
|
||||||
"Generates a random abstract syntax trees of the given type"
|
"Generates a random abstract syntax tree of the given type"
|
||||||
},
|
},
|
||||||
{"graphvizAbstractTree", (PyCFunction)PGF_graphvizAbstractTree, METH_VARARGS | METH_KEYWORDS,
|
{"graphvizAbstractTree", (PyCFunction)PGF_graphvizAbstractTree, METH_VARARGS | METH_KEYWORDS,
|
||||||
"Renders an abstract syntax tree in a Graphviz format"
|
"Renders an abstract syntax tree in a Graphviz format"
|
||||||
@@ -2174,6 +2363,7 @@ MOD_INIT(pgf)
|
|||||||
#endif
|
#endif
|
||||||
TYPE_READY(pgf_BracketType);
|
TYPE_READY(pgf_BracketType);
|
||||||
TYPE_READY(pgf_BINDType);
|
TYPE_READY(pgf_BINDType);
|
||||||
|
TYPE_READY(pgf_IterType);
|
||||||
|
|
||||||
MOD_DEF(m, "pgf", "The Runtime for the Portable Grammar Format in Python", module_methods);
|
MOD_DEF(m, "pgf", "The Runtime for the Portable Grammar Format in Python", module_methods);
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
@@ -2197,6 +2387,7 @@ MOD_INIT(pgf)
|
|||||||
ADD_TYPE("Type", pgf_TypeType);
|
ADD_TYPE("Type", pgf_TypeType);
|
||||||
ADD_TYPE("Bracket", pgf_BracketType);
|
ADD_TYPE("Bracket", pgf_BracketType);
|
||||||
ADD_TYPE("BIND", pgf_BINDType);
|
ADD_TYPE("BIND", pgf_BINDType);
|
||||||
|
ADD_TYPE("Iter", pgf_IterType);
|
||||||
|
|
||||||
Py_INCREF(Py_True);
|
Py_INCREF(Py_True);
|
||||||
ADD_TYPE_DIRECT("BIND_TYPE_EXPLICIT", Py_True);
|
ADD_TYPE_DIRECT("BIND_TYPE_EXPLICIT", Py_True);
|
||||||
|
|||||||
Reference in New Issue
Block a user