153 lines
4.3 KiB
C
153 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);
|
|
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, ®ex, &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) return_code = PyList_Append(list, tuple);
|
|
Py_DECREF(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;
|
|
}
|