#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, ®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) 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; }