pyliblex/src/pyliblexmodule.c

151 lines
4.3 KiB
C

#include "pyliblexmodule.h"
#include "liblex.h"
#include "eval.h"
static void _pyliblex_free_eval(PyObject* object){
eval_config* config = PyCapsule_GetPointer(object, NULL);
if(config){
liblex_result result = eval_config_free(config);
if(result != LIBLEX_SUCCESS){
PyErr_NoMemory();
}
}
}
static PyObject* pyliblex_init(PyObject* self, PyObject* args){
PyObject* return_object = NULL;
eval_config* config = malloc(sizeof(*config));
if(config){
eval_config_init(config);
return_object = PyCapsule_New(config, NULL, _pyliblex_free_eval);
} else {
return_object = PyErr_NoMemory();
}
return return_object;
}
static PyObject* pyliblex_add_definition(PyObject* self, PyObject* args){
PyObject* return_object = NULL;
PyObject* capsule;
const char* regex;
int id;
if(PyArg_ParseTuple(args, "Osi", &capsule, &regex, &id)) {
eval_config* config = PyCapsule_GetPointer(capsule, NULL);
if(config){
liblex_result result = eval_config_add(config, regex, id);
if(result == LIBLEX_MALLOC){
return_object = PyErr_NoMemory();
} else if(result != LIBLEX_SUCCESS){
PyErr_SetString(invalid_regex_exception, "Unable to construct regex.");
} else {
Py_INCREF(Py_None);
return_object = Py_None;
}
}
}
return return_object;
}
static int _pyliblex_add_match(void* data, va_list args){
int return_code = 0;
match* match = data;
const char* string = va_arg(args, const char*);
PyObject* list = va_arg(args, PyObject*);
PyObject* string_object = NULL;
PyObject* int_object = NULL;
PyObject* tuple = NULL;
string_object = PyUnicode_FromStringAndSize(string + match->from, match->to - match->from);
int_object = PyLong_FromLong(match->pattern);
if(string_object && int_object){
tuple = PyTuple_New(2);
if(tuple){
return_code = PyTuple_SetItem(tuple, 0, string_object);
if(return_code == 0) return_code = PyTuple_SetItem(tuple, 1, int_object);
}
}
if(tuple) {
if(return_code != 0) Py_DECREF(tuple);
else return_code = PyList_Append(list, tuple);
}
return return_code;
}
static PyObject* pyliblex_lex(PyObject* self, PyObject* args){
PyObject* return_object = NULL;
PyObject* capsule;
const char* string;
if(PyArg_ParseTuple(args, "Os", &capsule, &string)) {
eval_config* config = PyCapsule_GetPointer(capsule, NULL);
if(config){
ll match_ll;
liblex_result result;
ll_init(&match_ll);
result = eval_all(string, 0, config, &match_ll);
if(result == LIBLEX_MALLOC){
return_object = PyErr_NoMemory();
} if(result != LIBLEX_SUCCESS){
PyErr_SetString(failed_lex_exception, "Unable to parse text.");
} else {
int return_code = 0;
PyObject* list = PyList_New(0);
if(list){
return_code = ll_foreach(&match_ll, NULL, compare_always, _pyliblex_add_match, string, list);
if(return_code != 0) {
Py_DECREF(list);
list = PyList_New(0);
}
}
ll_foreach(&match_ll, NULL, compare_always, eval_foreach_match_free);
ll_clear(&match_ll);
return_object = list;
}
ll_free(&match_ll);
}
}
return return_object;
}
static PyObject* pyliblex_test(PyObject* self, PyObject* args) {
return PyUnicode_FromString("Test from liblex!");
}
PyMODINIT_FUNC PyInit_pyliblex() {
invalid_regex_exception = NULL;
failed_lex_exception = NULL;
PyObject* module = NULL;
int clear_exceptions = 1;
invalid_regex_exception = PyErr_NewException("pyliblex.InvalidRegexException", NULL, NULL);
failed_lex_exception = PyErr_NewException("pyliblex.FailedLexException", NULL, NULL);
if(invalid_regex_exception && failed_lex_exception){
module = PyModule_Create(&module_object);
if(module) {
if(!(PyModule_AddObject(module, "InvalidRegexException", invalid_regex_exception) ||
PyModule_AddObject(module, "FailedLexException", failed_lex_exception))){
Py_INCREF(invalid_regex_exception);
Py_INCREF(failed_lex_exception);
clear_exceptions = 0;
} else {
Py_DECREF(module);
module = NULL;
}
}
}
if(clear_exceptions){
if(invalid_regex_exception) Py_DECREF(invalid_regex_exception);
if(failed_lex_exception) Py_DECREF(failed_lex_exception);
}
return module;
}