Line data Source code
1 : #include "Python.h"
2 : #include "../Parser/tokenizer.h"
3 :
4 : static struct PyModuleDef _tokenizemodule;
5 :
6 : typedef struct {
7 : PyTypeObject *TokenizerIter;
8 : } tokenize_state;
9 :
10 : static tokenize_state *
11 326 : get_tokenize_state(PyObject *module) {
12 326 : return (tokenize_state *)PyModule_GetState(module);
13 : }
14 :
15 : #define _tokenize_get_state_by_type(type) \
16 : get_tokenize_state(PyType_GetModuleByDef(type, &_tokenizemodule))
17 :
18 : #include "clinic/Python-tokenize.c.h"
19 :
20 : /*[clinic input]
21 : module _tokenizer
22 : class _tokenizer.tokenizeriter "tokenizeriterobject *" "_tokenize_get_state_by_type(type)->TokenizerIter"
23 : [clinic start generated code]*/
24 : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=96d98ee2fef7a8bc]*/
25 :
26 : typedef struct
27 : {
28 : PyObject_HEAD struct tok_state *tok;
29 : } tokenizeriterobject;
30 :
31 : /*[clinic input]
32 : @classmethod
33 : _tokenizer.tokenizeriter.__new__ as tokenizeriter_new
34 :
35 : source: str
36 : [clinic start generated code]*/
37 :
38 : static PyObject *
39 114 : tokenizeriter_new_impl(PyTypeObject *type, const char *source)
40 : /*[clinic end generated code: output=7fd9f46cf9263cbb input=4384b368407375c6]*/
41 : {
42 114 : tokenizeriterobject *self = (tokenizeriterobject *)type->tp_alloc(type, 0);
43 114 : if (self == NULL) {
44 0 : return NULL;
45 : }
46 114 : PyObject *filename = PyUnicode_FromString("<string>");
47 114 : if (filename == NULL) {
48 0 : return NULL;
49 : }
50 114 : self->tok = _PyTokenizer_FromUTF8(source, 1);
51 114 : if (self->tok == NULL) {
52 0 : Py_DECREF(filename);
53 0 : return NULL;
54 : }
55 114 : self->tok->filename = filename;
56 114 : return (PyObject *)self;
57 : }
58 :
59 : static PyObject *
60 1045 : tokenizeriter_next(tokenizeriterobject *it)
61 : {
62 : const char *start;
63 : const char *end;
64 1045 : int type = _PyTokenizer_Get(it->tok, &start, &end);
65 1045 : if (type == ERRORTOKEN && PyErr_Occurred()) {
66 30 : return NULL;
67 : }
68 1015 : if (type == ERRORTOKEN || type == ENDMARKER) {
69 84 : PyErr_SetString(PyExc_StopIteration, "EOF");
70 84 : return NULL;
71 : }
72 931 : PyObject *str = NULL;
73 931 : if (start == NULL || end == NULL) {
74 24 : str = PyUnicode_FromString("");
75 : }
76 : else {
77 907 : str = PyUnicode_FromStringAndSize(start, end - start);
78 : }
79 931 : if (str == NULL) {
80 0 : return NULL;
81 : }
82 :
83 931 : Py_ssize_t size = it->tok->inp - it->tok->buf;
84 931 : PyObject *line = PyUnicode_DecodeUTF8(it->tok->buf, size, "replace");
85 931 : if (line == NULL) {
86 0 : Py_DECREF(str);
87 0 : return NULL;
88 : }
89 931 : const char *line_start = type == STRING ? it->tok->multi_line_start : it->tok->line_start;
90 931 : int lineno = type == STRING ? it->tok->first_lineno : it->tok->lineno;
91 931 : int end_lineno = it->tok->lineno;
92 931 : int col_offset = -1;
93 931 : int end_col_offset = -1;
94 931 : if (start != NULL && start >= line_start) {
95 907 : col_offset = (int)(start - line_start);
96 : }
97 931 : if (end != NULL && end >= it->tok->line_start) {
98 907 : end_col_offset = (int)(end - it->tok->line_start);
99 : }
100 :
101 931 : return Py_BuildValue("(NiiiiiN)", str, type, lineno, end_lineno, col_offset, end_col_offset, line);
102 : }
103 :
104 : static void
105 114 : tokenizeriter_dealloc(tokenizeriterobject *it)
106 : {
107 114 : PyTypeObject *tp = Py_TYPE(it);
108 114 : _PyTokenizer_Free(it->tok);
109 114 : tp->tp_free(it);
110 114 : Py_DECREF(tp);
111 114 : }
112 :
113 : static PyType_Slot tokenizeriter_slots[] = {
114 : {Py_tp_new, tokenizeriter_new},
115 : {Py_tp_dealloc, tokenizeriter_dealloc},
116 : {Py_tp_getattro, PyObject_GenericGetAttr},
117 : {Py_tp_iter, PyObject_SelfIter},
118 : {Py_tp_iternext, tokenizeriter_next},
119 : {0, NULL},
120 : };
121 :
122 : static PyType_Spec tokenizeriter_spec = {
123 : .name = "_tokenize.TokenizerIter",
124 : .basicsize = sizeof(tokenizeriterobject),
125 : .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE),
126 : .slots = tokenizeriter_slots,
127 : };
128 :
129 : static int
130 2 : tokenizemodule_exec(PyObject *m)
131 : {
132 2 : tokenize_state *state = get_tokenize_state(m);
133 2 : if (state == NULL) {
134 0 : return -1;
135 : }
136 :
137 2 : state->TokenizerIter = (PyTypeObject *)PyType_FromModuleAndSpec(m, &tokenizeriter_spec, NULL);
138 2 : if (state->TokenizerIter == NULL) {
139 0 : return -1;
140 : }
141 2 : if (PyModule_AddType(m, state->TokenizerIter) < 0) {
142 0 : return -1;
143 : }
144 :
145 2 : return 0;
146 : }
147 :
148 : static PyMethodDef tokenize_methods[] = {
149 : {NULL, NULL, 0, NULL} /* Sentinel */
150 : };
151 :
152 : static PyModuleDef_Slot tokenizemodule_slots[] = {
153 : {Py_mod_exec, tokenizemodule_exec},
154 : {0, NULL}
155 : };
156 :
157 : static int
158 320 : tokenizemodule_traverse(PyObject *m, visitproc visit, void *arg)
159 : {
160 320 : tokenize_state *state = get_tokenize_state(m);
161 320 : Py_VISIT(state->TokenizerIter);
162 320 : return 0;
163 : }
164 :
165 : static int
166 4 : tokenizemodule_clear(PyObject *m)
167 : {
168 4 : tokenize_state *state = get_tokenize_state(m);
169 4 : Py_CLEAR(state->TokenizerIter);
170 4 : return 0;
171 : }
172 :
173 : static void
174 2 : tokenizemodule_free(void *m)
175 : {
176 2 : tokenizemodule_clear((PyObject *)m);
177 2 : }
178 :
179 : static struct PyModuleDef _tokenizemodule = {
180 : PyModuleDef_HEAD_INIT,
181 : .m_name = "_tokenize",
182 : .m_size = sizeof(tokenize_state),
183 : .m_slots = tokenizemodule_slots,
184 : .m_methods = tokenize_methods,
185 : .m_traverse = tokenizemodule_traverse,
186 : .m_clear = tokenizemodule_clear,
187 : .m_free = tokenizemodule_free,
188 : };
189 :
190 : PyMODINIT_FUNC
191 2 : PyInit__tokenize(void)
192 : {
193 2 : return PyModuleDef_Init(&_tokenizemodule);
194 : }
|