a914b38d300a6d60dba68b1e53076d47ece94c8f
[c_to_python.git] / ansi_c_lex.l
1 %e  1019
2 %p  2807
3 %n  371
4 %k  284
5 %a  1213
6 %o  1117
7
8 O   [0-7]
9 D   [0-9]
10 NZ  [1-9]
11 L   [a-zA-Z_]
12 A   [a-zA-Z_0-9]
13 H   [a-fA-F0-9]
14 HP  (0[xX])
15 E   ([Ee][+-]?{D}+)
16 P   ([Pp][+-]?{D}+)
17 FS  (f|F|l|L)
18 IS  (((u|U)(l|L|ll|LL)?)|((l|L|ll|LL)(u|U)?))
19 CP  (u|U|L)
20 SP  (u8|u|U|L)
21 ES  (\\(['"\?\\abfnrtv]|[0-7]{1,3}|x[a-fA-F0-9]+))
22 WS  [ \t\v\n\f]
23
24 %{
25 #include "Python.h"
26 #include "structmember.h"
27 #include <setjmp.h>
28 #include <stdbool.h>
29
30 #include "yaccmodule.h"
31
32 PyDoc_STRVAR(lex_doc_string, \
33 "lex is an interface to a flex-generated lexical analyzer.\n");
34
35 /* filled in at module initialization time */
36 static PyObject *work;
37 static PyObject *work_factory;
38
39 typedef struct {
40   PyObject_HEAD
41
42   /* filled in by lex.yylex.__init(), no change during iteration */
43   PyObject *root, *mark, *yychunk_iter;
44
45   /* filled in by YY_INPUT() each time we go on to a new chunk */
46   PyObject *YY_INPUT_bytes;
47   Py_ssize_t YY_INPUT_bytes_off, YY_INPUT_bytes_len;
48 } lex_yylexObject;
49
50 /* filled in by lex.yylex.__next__() each time iterator invoked */
51 static lex_yylexObject *yylex_self;
52 static jmp_buf yylex_abort;
53 static Py_ssize_t yytext_pos, yytext_off, yytext_len;
54
55 static void yyerror(const char *); /* prints grammar violation message */
56 static bool get_cursor(lex_yylexObject *self, Py_ssize_t i, Py_ssize_t *pos, Py_ssize_t *off);
57 static bool set_cursor(lex_yylexObject *self, Py_ssize_t i, Py_ssize_t pos, Py_ssize_t off);
58 static bool new_cursor(lex_yylexObject *self, Py_ssize_t i, Py_ssize_t pos, Py_ssize_t off);
59 static bool pop_cursors(lex_yylexObject *self, Py_ssize_t i);
60 static bool apply_markup(const char *format, ...);
61 static bool next_YY_INPUT_chunk(lex_yylexObject *self);
62 static bool next_yytext_chunk(lex_yylexObject *self);
63 /*static bool skip_yytext_byte(lex_yylexObject *self, int c);*/ /* NO PROTOTYPE, IT'S A MACRO */
64 static bool skip_yytext(lex_yylexObject *self);
65 static bool skip_comment(lex_yylexObject *self);
66
67 #define YY_INPUT(buf, result, max_size) \
68   do { \
69  /*printf("YY_INPUT()\n");*/ \
70     if (yylex_self->YY_INPUT_bytes_off >= yylex_self->YY_INPUT_bytes_len && !next_YY_INPUT_chunk(yylex_self)) \
71       longjmp(yylex_abort, 1); \
72     Py_ssize_t len = yylex_self->YY_INPUT_bytes_len - yylex_self->YY_INPUT_bytes_off; \
73     if (len > max_size) \
74       len = max_size; \
75     /* note: don't call PyBytes_AS_STRING on Py_None (possible if len == 0) */ \
76     if (len) { \
77       memcpy(buf, PyBytes_AS_STRING(yylex_self->YY_INPUT_bytes) + yylex_self->YY_INPUT_bytes_off, len); \
78       yylex_self->YY_INPUT_bytes_off += len; \
79     } \
80     result = len; \
81  /*printf("YY_INPUT() returns \""); fwrite(buf, result, 1, stdout); printf("\"\n");*/ \
82   } while (0)
83
84 #define SKIP() \
85   do { \
86     if (!skip_yytext(yylex_self)) \
87       return -1; \
88   } \
89   while (0)
90
91 #define MARK() \
92   do { \
93     if (!new_cursor(yylex_self, -1, yytext_pos, yytext_off)) \
94       return -1; \
95   } \
96   while (0)
97
98 #define APPLY(tag) \
99    do { \
100     Py_ssize_t len = PyObject_Length(yylex_self->mark); \
101     if ( \
102       len < 0 || \
103       !apply_markup( \
104         "OOnnOs", \
105         yylex_self->root, \
106         yylex_self->mark, \
107         len - 3, \
108         len - 2, \
109         work_factory, \
110         tag \
111       ) \
112     ) \
113       return -1; \
114   } \
115   while (0)
116
117 #define sym_type(self, identifier) IDENTIFIER /* with no symbol table, fake it */
118 %}
119
120 %%
121 "/*"                                    { SKIP(); if (!skip_comment(yylex_self)) return -1; }
122 "//".*                                  { SKIP(); /* consume //-comment */ }
123
124 "auto"                                  { MARK(); SKIP(); MARK(); return AUTO; }
125 "break"                                 { MARK(); SKIP(); MARK(); return BREAK; }
126 "case"                                  { MARK(); SKIP(); MARK(); return CASE; }
127 "char"                                  { MARK(); SKIP(); MARK(); return CHAR; }
128 "const"                                 { MARK(); SKIP(); MARK(); return CONST; }
129 "continue"                              { MARK(); SKIP(); MARK(); return CONTINUE; }
130 "default"                               { MARK(); SKIP(); MARK(); return DEFAULT; }
131 "do"                                    { MARK(); SKIP(); MARK(); return DO; }
132 "double"                                { MARK(); SKIP(); MARK(); return DOUBLE; }
133 "else"                                  { MARK(); SKIP(); MARK(); return ELSE; }
134 "enum"                                  { MARK(); SKIP(); MARK(); return ENUM; }
135 "extern"                                { MARK(); SKIP(); MARK(); return EXTERN; }
136 "float"                                 { MARK(); SKIP(); MARK(); return FLOAT; }
137 "for"                                   { MARK(); SKIP(); MARK(); return FOR; }
138 "goto"                                  { MARK(); SKIP(); MARK(); return GOTO; }
139 "if"                                    { MARK(); SKIP(); MARK(); return IF; }
140 "inline"                                { MARK(); SKIP(); MARK(); return INLINE; }
141 "int"                                   { MARK(); SKIP(); MARK(); return INT; }
142 "long"                                  { MARK(); SKIP(); MARK(); return LONG; }
143 "register"                              { MARK(); SKIP(); MARK(); return REGISTER; }
144 "restrict"                              { MARK(); SKIP(); MARK(); return RESTRICT; }
145 "return"                                { MARK(); SKIP(); MARK(); return RETURN; }
146 "short"                                 { MARK(); SKIP(); MARK(); return SHORT; }
147 "signed"                                { MARK(); SKIP(); MARK(); return SIGNED; }
148 "sizeof"                                { MARK(); SKIP(); MARK(); return SIZEOF; }
149 "static"                                { MARK(); SKIP(); MARK(); return STATIC; }
150 "struct"                                { MARK(); SKIP(); MARK(); return STRUCT; }
151 "switch"                                { MARK(); SKIP(); MARK(); return SWITCH; }
152 "typedef"                               { MARK(); SKIP(); MARK(); return TYPEDEF; }
153 "union"                                 { MARK(); SKIP(); MARK(); return UNION; }
154 "unsigned"                              { MARK(); SKIP(); MARK(); return UNSIGNED; }
155 "void"                                  { MARK(); SKIP(); MARK(); return VOID; }
156 "volatile"                              { MARK(); SKIP(); MARK(); return VOLATILE; }
157 "while"                                 { MARK(); SKIP(); MARK(); return WHILE; }
158 "_Alignas"                              { MARK(); SKIP(); MARK(); return ALIGNAS; }
159 "_Alignof"                              { MARK(); SKIP(); MARK(); return ALIGNOF; }
160 "_Atomic"                               { MARK(); SKIP(); MARK(); return ATOMIC; }
161 "_Bool"                                 { MARK(); SKIP(); MARK(); return BOOL; }
162 "_Complex"                              { MARK(); SKIP(); MARK(); return COMPLEX; }
163 "_Generic"                              { MARK(); SKIP(); MARK(); return GENERIC; }
164 "_Imaginary"                            { MARK(); SKIP(); MARK(); return IMAGINARY; }
165 "_Noreturn"                             { MARK(); SKIP(); MARK(); return NORETURN; }
166 "_Static_assert"                        { MARK(); SKIP(); MARK(); return STATIC_ASSERT; }
167 "_Thread_local"                         { MARK(); SKIP(); MARK(); return THREAD_LOCAL; }
168 "__func__"                              { MARK(); SKIP(); MARK(); return FUNC_NAME; }
169 "size_t"                                { MARK(); SKIP(); MARK(); return TYPEDEF_NAME; /* THIS IS A HACK FOR NOW */ }
170
171 (?<Identifier>{L}{A}*) {
172   MARK();
173   SKIP();
174   MARK(); 
175   switch (sym_type(self, yytext))
176   {
177   case TYPEDEF_NAME:        /* previously defined */
178     APPLY("TypedefName");
179     return TYPEDEF_NAME;
180   case ENUMERATION_CONSTANT:    /* previously defined */
181     APPLY("EnumerationConstant");
182     return ENUMERATION_CONSTANT;
183   default:              /* includes undefined */
184     APPLY("Identifier");
185     return IDENTIFIER;
186   }
187 }
188
189 (?<ExpressionIntLiteral>{HP}{H}+{IS}?)                          { MARK(); SKIP(); MARK(); APPLY("ExpressionIntLiteral"); return I_CONSTANT; }
190 (?<ExpressionIntLiteral>{NZ}{D}*{IS}?)                          { MARK(); SKIP(); MARK(); APPLY("ExpressionIntLiteral"); return I_CONSTANT; }
191 (?<ExpressionIntLiteral>"0"{O}*{IS}?)                           { MARK(); SKIP(); MARK(); APPLY("ExpressionIntLiteral"); return I_CONSTANT; }
192 (?<ExpressionIntLiteral>{CP}?"'"([^'\\\n]|{ES})+"'")            { MARK(); SKIP(); MARK(); APPLY("ExpressionIntLiteral"); return I_CONSTANT; }
193
194 (?<ExpressionFloatLiteral>{D}+{E}{FS}?)                         { MARK(); SKIP(); MARK(); APPLY("ExpressionFloatLiteral"); return F_CONSTANT; }
195 (?<ExpressionFloatLiteral>{D}*"."{D}+{E}?{FS}?)                 { MARK(); SKIP(); MARK(); APPLY("ExpressionFloatLiteral"); return F_CONSTANT; }
196 (?<ExpressionFloatLiteral>{D}+"."{E}?{FS}?)                     { MARK(); SKIP(); MARK(); APPLY("ExpressionFloatLiteral"); return F_CONSTANT; }
197 (?<ExpressionFloatLiteral>{HP}{H}+{P}{FS}?)                     { MARK(); SKIP(); MARK(); APPLY("ExpressionFloatLiteral"); return F_CONSTANT; }
198 (?<ExpressionFloatLiteral>{HP}{H}*"."{H}+{P}{FS}?)                      { MARK(); SKIP(); MARK(); APPLY("ExpressionFloatLiteral"); return F_CONSTANT; }
199 (?<ExpressionFloatLiteral>{HP}{H}+"."{P}{FS}?)                  { MARK(); SKIP(); MARK(); APPLY("ExpressionFloatLiteral"); return F_CONSTANT; }
200
201 ({SP}?\"([^"\\\n]|{ES})*\"{WS}*)+       { MARK(); SKIP(); MARK(); APPLY("ExpressionStringLiteral"); return STRING_LITERAL;; }
202
203 "..."                                   { MARK(); SKIP(); MARK(); return ELLIPSIS; }
204 ">>="                                   { MARK(); SKIP(); MARK(); return RIGHT_ASSIGN; }
205 "<<="                                   { MARK(); SKIP(); MARK(); return LEFT_ASSIGN; }
206 "+="                                    { MARK(); SKIP(); MARK(); return ADD_ASSIGN; }
207 "-="                                    { MARK(); SKIP(); MARK(); return SUB_ASSIGN; }
208 "*="                                    { MARK(); SKIP(); MARK(); return MUL_ASSIGN; }
209 "/="                                    { MARK(); SKIP(); MARK(); return DIV_ASSIGN; }
210 "%="                                    { MARK(); SKIP(); MARK(); return MOD_ASSIGN; }
211 "&="                                    { MARK(); SKIP(); MARK(); return AND_ASSIGN; }
212 "^="                                    { MARK(); SKIP(); MARK(); return XOR_ASSIGN; }
213 "|="                                    { MARK(); SKIP(); MARK(); return OR_ASSIGN; }
214 ">>"                                    { MARK(); SKIP(); MARK(); return RIGHT_OP; }
215 "<<"                                    { MARK(); SKIP(); MARK(); return LEFT_OP; }
216 "++"                                    { MARK(); SKIP(); MARK(); return INC_OP; }
217 "--"                                    { MARK(); SKIP(); MARK(); return DEC_OP; }
218 "->"                                    { MARK(); SKIP(); MARK(); return PTR_OP; }
219 "&&"                                    { MARK(); SKIP(); MARK(); return AND_OP; }
220 "||"                                    { MARK(); SKIP(); MARK(); return OR_OP; }
221 "<="                                    { MARK(); SKIP(); MARK(); return LE_OP; }
222 ">="                                    { MARK(); SKIP(); MARK(); return GE_OP; }
223 "=="                                    { MARK(); SKIP(); MARK(); return EQ_OP; }
224 "!="                                    { MARK(); SKIP(); MARK(); return NE_OP; }
225 ";"                                     { MARK(); SKIP(); MARK(); return ';'; }
226 ("{"|"<%")                              { MARK(); SKIP(); MARK(); return '{'; }
227 ("}"|"%>")                              { MARK(); SKIP(); MARK(); return '}'; }
228 ","                                     { MARK(); SKIP(); MARK(); return ','; }
229 ":"                                     { MARK(); SKIP(); MARK(); return ':'; }
230 "="                                     { MARK(); SKIP(); MARK(); return '='; }
231 "("                                     { MARK(); SKIP(); MARK(); return '('; }
232 ")"                                     { MARK(); SKIP(); MARK(); return ')'; }
233 ("["|"<:")                              { MARK(); SKIP(); MARK(); return '['; }
234 ("]"|":>")                              { MARK(); SKIP(); MARK(); return ']'; }
235 "."                                     { MARK(); SKIP(); MARK(); return '.'; }
236 "&"                                     { MARK(); SKIP(); MARK(); return '&'; }
237 "!"                                     { MARK(); SKIP(); MARK(); return '!'; }
238 "~"                                     { MARK(); SKIP(); MARK(); return '~'; }
239 "-"                                     { MARK(); SKIP(); MARK(); return '-'; }
240 "+"                                     { MARK(); SKIP(); MARK(); return '+'; }
241 "*"                                     { MARK(); SKIP(); MARK(); return '*'; }
242 "/"                                     { MARK(); SKIP(); MARK(); return '/'; }
243 "%"                                     { MARK(); SKIP(); MARK(); return '%'; }
244 "<"                                     { MARK(); SKIP(); MARK(); return '<'; }
245 ">"                                     { MARK(); SKIP(); MARK(); return '>'; }
246 "^"                                     { MARK(); SKIP(); MARK(); return '^'; }
247 "|"                                     { MARK(); SKIP(); MARK(); return '|'; }
248 "?"                                     { MARK(); SKIP(); MARK(); return '?'; }
249
250 {WS}+                                   { SKIP(); /* whitespace separates tokens */ }
251 .                                       { SKIP(); /* discard bad characters */ }
252 <<EOF>>                                 { MARK(); return 0; }
253
254 %%
255
256 int yywrap(void)    /* called at end of input */
257 {
258  /*printf("yywrap()\n");*/
259   return 1;       /* terminate now */
260 }
261
262 static void yyerror(const char *s) {
263   fflush(stdout);
264   fprintf(stderr, "*** %s\n", s);
265 }
266
267 static bool get_cursor(lex_yylexObject *self, Py_ssize_t i, Py_ssize_t *pos, Py_ssize_t *off) {
268  /*printf("get_cursor() %zd\n", i);*/
269   /* (pos, off) = self->mark[index] */
270   PyObject *index = PyLong_FromSsize_t(i);
271   if (index == NULL)
272     goto error0;
273   PyObject *cursor = PyObject_GetItem(self->mark, index);
274   if (cursor == NULL)
275     goto error1;
276   if (!PyArg_ParseTuple(cursor, "nn", pos, off)) {
277     Py_DECREF(cursor);
278   error1:
279     Py_DECREF(index);
280   error0:
281     return false;
282   }
283   Py_DECREF(cursor);
284   Py_DECREF(index);
285  /*printf("get_cursor() returns %zd %zd\n", *pos, *off);*/
286   return true;
287 }
288
289 static bool set_cursor(lex_yylexObject *self, Py_ssize_t i, Py_ssize_t pos, Py_ssize_t off) {
290  /*printf("set_cursor() %zd %zd %zd\n", i, pos, off);*/
291   /* self->mark[index] = (pos, off) */
292   PyObject *index = PyLong_FromSsize_t(i);
293   if (index == NULL)
294     goto error0;
295   PyObject *cursor = Py_BuildValue("nn", pos, off);
296   if (cursor == NULL)
297     goto error1;
298   if (PyObject_SetItem(self->mark, index, cursor)) {
299     Py_DECREF(cursor);
300   error1:
301     Py_DECREF(index);
302   error0:
303     return false;
304   }
305   Py_DECREF(cursor);
306   Py_DECREF(index);
307   return true;
308 }
309
310 static bool new_cursor(lex_yylexObject *self, Py_ssize_t i, Py_ssize_t pos, Py_ssize_t off) {
311  /*printf("new_cursor() %zd %zd %zd\n", i, pos, off);*/
312   /* self->mark[i:i] = [(pos, off)] */
313   PyObject *index = PyLong_FromSsize_t(i);
314   if (index == NULL)
315     goto error0;
316   PyObject *slice = PySlice_New(index, index, NULL);
317   if (slice == NULL)
318     goto error1;
319   PyObject *list = PyList_New(1);
320   if (list == NULL)
321     goto error2;
322   PyObject *cursor = Py_BuildValue("nn", pos, off);
323   if (cursor == NULL)
324     goto error3;
325   PyList_SET_ITEM(list, 0, cursor);
326   if (PyObject_SetItem(self->mark, slice, list)) {
327   error3:
328     Py_DECREF(list);
329   error2:
330     Py_DECREF(slice);
331   error1:
332     Py_DECREF(index);
333   error0:
334     return false;
335   }
336   Py_DECREF(list);
337   Py_DECREF(slice);
338   Py_DECREF(index);
339   return true;
340 }
341
342 static bool pop_cursors(lex_yylexObject *self, Py_ssize_t i) {
343  /*printf("pop_cursors() %zd\n", i);*/
344   /* del self->mark[i:] */
345   PyObject *start = PyLong_FromSsize_t(i);
346   if (start == NULL)
347     goto error0;
348   PyObject *slice = PySlice_New(start, NULL, NULL);
349   if (slice == NULL)
350     goto error1;
351   if (PyObject_DelItem(self->mark, slice)) {
352     Py_DECREF(slice);
353   error1:
354     Py_DECREF(start);
355   error0:
356     return false;
357   }
358   Py_DECREF(slice);
359   Py_DECREF(start);
360   return true;
361 }
362
363 static bool apply_markup(const char *format, ...) {
364   PyObject *apply_markup = PyObject_GetAttrString(work, "apply_markup");
365   if (apply_markup == NULL)
366     goto error0;
367
368   va_list argp;
369   va_start(argp, format);
370   PyObject *args = Py_VaBuildValue(format, argp);
371   va_end(argp);
372   if (args == NULL)
373     goto error1;
374
375   PyObject *result = PyObject_CallObject(apply_markup, args);
376   if (result == NULL) {
377     Py_DECREF(args);
378   error1:
379     Py_DECREF(apply_markup);
380   error0:
381     return false;
382   }
383
384   Py_DECREF(result);
385   Py_DECREF(args);
386   Py_DECREF(apply_markup);
387   return true;
388 }
389
390 static bool next_YY_INPUT_chunk(lex_yylexObject *self) {
391  /*printf("next_YY_INPUT_chunk()\n");*/
392   /* cursor is not cached, since we'd have to re-cache every time we enter */
393   /* iterator, whereas we are only supposed to read new chunks occasionally */
394   Py_ssize_t pos, off, len;
395   if (!get_cursor(self, -1, &pos, &off))
396     goto error0;
397
398   PyObject *tail;
399   while (true) {
400     /* re-check the length, as tail could have got longer in the meantime */
401     tail = PyObject_CallMethod(work, "get_tail", "On", self->root, pos);
402     if (tail == NULL)
403       goto error0;
404     len = PyObject_Length(tail);
405     if (len < 0)
406       goto error1;
407
408     /* see if now need to do more data from the same chunk */
409     if (off < len)
410       break;
411     Py_DECREF(tail);
412  
413     /* if last chunk try to extend it, otherwise go on to next */
414     Py_ssize_t root_len = PyObject_Length(self->root);
415     if (root_len < 0)
416       goto error0;
417     if (pos + 1 >= root_len) {
418       if (self->yychunk_iter != Py_None){
419         PyObject *result = PyObject_CallMethod(self->yychunk_iter, "__next__", "");
420         if (result != NULL) {
421           Py_DECREF(result);
422           continue; /* re-check current chunk, in case extended */
423         }
424         if (!PyErr_ExceptionMatches(PyExc_StopIteration))
425           goto error0;
426         PyErr_Clear();
427       }
428
429       /* it is not an error to run out of data, empty return indicates EOF */
430       Py_INCREF(Py_None);
431       Py_DECREF(self->YY_INPUT_bytes);
432       self->YY_INPUT_bytes = Py_None;
433       self->YY_INPUT_bytes_off = 0;
434       self->YY_INPUT_bytes_len = 0;
435       return true;
436     }
437     ++pos;
438     off = 0;
439   }
440
441   /* got something we can return, advance cursor by unicode length of data */
442   if (!set_cursor(self, -1, pos, off + len))
443     goto error1;
444
445   /* check for less efficient case when caller has appended to the chunk, */
446   /* requires a large copy that caller can avoid by only adding new chunks */
447   if (off >= 0) {
448     PyObject *index = PyLong_FromSsize_t(off);
449     if (index == NULL)
450       goto error1;
451     PyObject *slice = PySlice_New(index, NULL, NULL);
452     if (slice == NULL)
453       goto error2;
454     PyObject *item = PyObject_GetItem(tail, slice);
455     if (item == NULL) {
456       Py_DECREF(slice);
457     error2:
458       Py_DECREF(index);
459       goto error1;
460     }
461     Py_DECREF(tail);
462     tail = item;
463     Py_DECREF(slice);
464     Py_DECREF(index);
465   }
466
467   /* convert entire chunk to UTF-8, then use for multiple YY_INPUT() calls */
468   PyObject *bytes = PyUnicode_AsUTF8String(tail);
469   if (bytes == NULL)
470     goto error1;
471   len = PyObject_Length(bytes);
472   if (len < 0) {
473     Py_DECREF(bytes);
474   error1:
475     Py_DECREF(tail);
476   error0:
477     return false;
478   }
479   Py_DECREF(self->YY_INPUT_bytes);
480   self->YY_INPUT_bytes = bytes;
481   self->YY_INPUT_bytes_off = 0;
482   self->YY_INPUT_bytes_len = len;
483
484   Py_DECREF(tail);
485   return true;
486 }
487
488 static bool next_yytext_chunk(lex_yylexObject *self) {
489   while (true) {
490     /* re-cache the length, as tail could have got longer in the meantime */
491     PyObject *tail = PyObject_CallMethod(work, "get_tail", "On", self->root, yytext_pos);
492     if (tail == NULL)
493       goto error0;
494     yytext_len = PyObject_Length(tail);
495     if (yytext_len < 0) {
496       Py_DECREF(tail);
497     error0:
498       return false;
499     }
500     Py_DECREF(tail);
501   
502     /* see if now need to do more data from the same chunk */
503     if (yytext_off < yytext_len)
504       break;
505   
506     /* go on to next chunk (note: it can't go past YY_INPUT cursor) */
507     ++yytext_pos;
508     yytext_off = 0;
509   }
510   return true;
511 }
512
513 #define skip_yytext_byte(self, c) \
514   do { \
515     if ((c & 0xc0) != 0x80) { \
516  /*printf("'%c' %ld %ld\n", c, yytext_off, yytext_len);*/ \
517       if (yytext_off >= yytext_len && !next_yytext_chunk(self)) \
518         return false; \
519       ++yytext_off; \
520     } \
521   } while (0)
522
523 static bool skip_yytext(lex_yylexObject *self) {
524   int c;
525   for (char *p = yytext; (c = *p) != 0; ++p)
526     skip_yytext_byte(self, c);
527   return true;
528 }
529
530 static bool skip_comment(lex_yylexObject *self) {
531   int c;
532   while ((c = input()) != 0) {
533     if (c == '*') {
534       skip_yytext_byte(self, '*');
535       while ((c = input()) == '*')
536         skip_yytext_byte(self, '*');
537
538       if (c == '/') {
539         skip_yytext_byte(self, '/');
540         return true;
541       }
542
543       if (c == 0)
544         break;
545     }
546     skip_yytext_byte(self, c);
547   }
548   yyerror("unterminated comment");
549   return true;
550 }
551
552 static PyObject *lex_yylex_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
553   lex_yylexObject *self;
554
555   self = (lex_yylexObject *)type->tp_alloc(type, 0);
556   Py_INCREF(Py_None);
557   self->root = Py_None;
558   Py_INCREF(Py_None);
559   self->mark = Py_None;
560   Py_INCREF(Py_None);
561   self->yychunk_iter = Py_None;
562   Py_INCREF(Py_None);
563   self->YY_INPUT_bytes = Py_None;
564   return (PyObject *)self;
565 }
566
567 static void lex_yylex_dealloc(lex_yylexObject *self) {
568   Py_DECREF(self->root);
569   Py_DECREF(self->mark);
570   Py_DECREF(self->yychunk_iter);
571   Py_DECREF(self->YY_INPUT_bytes);
572   Py_TYPE(self)->tp_free((PyObject *)self);
573 }
574
575 static int lex_yylex_init(lex_yylexObject *self, PyObject *args, PyObject *kwargs) {
576   PyObject *root, *mark, *yychunk_iter = Py_None;
577   if (!PyArg_ParseTuple(args, "OO|O", &root, &mark, &yychunk_iter))
578     goto error0;
579
580   Py_INCREF(root);
581   Py_DECREF(self->root);
582   self->root = root;
583
584   Py_INCREF(mark);
585   Py_DECREF(self->mark);
586   self->mark = mark;
587
588   if (yychunk_iter == Py_None)
589     Py_INCREF(Py_None);
590   else {
591     yychunk_iter = PyObject_GetIter(yychunk_iter);
592     if (yychunk_iter == NULL)
593       goto error1;
594   }
595   Py_DECREF(self->yychunk_iter);
596   self->yychunk_iter = yychunk_iter;
597
598   /* mark[:] = [(-1, 0), (-1, 0)] */
599   /* the first is the yytext cursor, it will be advanced one unicode code */
600   /* point for each UTF-8 non-continuation character scanned in yytext; */
601   /* the second is the YY_INPUT cursor, it will be advanced by the chunk */
602   /* length in unicode code points each time we convert a chunk to UTF-8; */
603   /* each cursor consists of (pos, off) referring to root[pos].tail[off:], */
604   /* chunks accessed using work.get_tail(), so pos == -1 for root[pos].text */
605   if (!pop_cursors(self, 0) || !new_cursor(self, 0, -1, 0) || !new_cursor(self, 1, -1, 0)) {
606   error1:
607     /* don't keep useless references to user data structures after error */
608     Py_INCREF(Py_None);
609     Py_DECREF(self->root);
610     self->root = Py_None;
611     Py_INCREF(Py_None);
612     Py_DECREF(self->mark);
613     self->mark = Py_None;
614     Py_INCREF(Py_None);
615     Py_DECREF(self->yychunk_iter);
616     self->yychunk_iter = Py_None;
617   error0:
618     return -1;
619   }
620
621   Py_INCREF(Py_None);
622   Py_DECREF(self->YY_INPUT_bytes);
623   self->YY_INPUT_bytes = Py_None;
624   self->YY_INPUT_bytes_off = 0;
625   self->YY_INPUT_bytes_len = 0;
626
627   return 0;
628 }
629  
630 static PyObject *lex_yylex_iter(PyObject *self) {
631   Py_INCREF(self);
632   return self;
633 }
634
635 static PyObject *lex_yylex_iternext(lex_yylexObject *self) {
636  /*printf("lex_yylex_iternext()\n");*/
637   if (self->root == Py_None || self->mark == Py_None) {
638     PyErr_SetNone(PyExc_StopIteration);
639     goto error0;
640   }
641
642   /* cache yytext_pos, yytext_off, yytext_len for quickly scanning yytext */
643   if (!get_cursor(self, -2, &yytext_pos, &yytext_off))
644     goto error1;
645   PyObject *tail = PyObject_CallMethod(work, "get_tail", "On", self->root, yytext_pos);
646   if (tail == NULL)
647     goto error1;
648   yytext_len = PyObject_Length(tail);
649   if (yytext_len < 0) {
650     Py_DECREF(tail);
651     goto error1;
652   }
653   Py_DECREF(tail);
654
655   yylex_self = self;
656   if (setjmp(yylex_abort))
657     goto error1;
658
659   (void)yyunput; /* fix defined but not used warning */
660   int token = yylex();
661   if (token == -1)
662     goto error1;
663
664   if (token == 0) {
665     /* finished, automatically delete YY_INPUT cursor and drop references */
666     if (!pop_cursors(self, -1)) {
667     error1:
668       /* don't keep useless references to user data structures after error */
669       Py_INCREF(Py_None);
670       Py_DECREF(self->root);
671       self->root = Py_None;
672       Py_INCREF(Py_None);
673       Py_DECREF(self->mark);
674       self->mark = Py_None;
675       Py_INCREF(Py_None);
676       Py_DECREF(self->yychunk_iter);
677       self->yychunk_iter = Py_None;
678     error0:
679       return NULL;
680     }
681     /* don't keep useless references to user data structures after EOF */
682     Py_INCREF(Py_None);
683     Py_DECREF(self->root);
684     self->root = Py_None;
685     Py_INCREF(Py_None);
686     Py_DECREF(self->mark);
687     self->mark = Py_None;
688     Py_INCREF(Py_None);
689     Py_DECREF(self->yychunk_iter);
690     self->yychunk_iter = Py_None;
691   }
692
693  /*printf("lex_yylex_iternext() returns %d\n", token);*/
694   return PyLong_FromLong((long)token);
695 }
696
697 static int lex_yylex_traverse(lex_yylexObject *self, visitproc visit, void *arg)
698 {
699   Py_VISIT(self->root);
700   Py_VISIT(self->mark);
701   Py_VISIT(self->yychunk_iter);
702   Py_VISIT(self->YY_INPUT_bytes);
703   return 0;
704 }
705
706 static int lex_yylex_clear(lex_yylexObject *self)
707 {
708   Py_CLEAR(self->root);
709   Py_CLEAR(self->mark);
710   Py_CLEAR(self->yychunk_iter);
711   Py_CLEAR(self->YY_INPUT_bytes);
712   return 0;
713 }
714
715 static PyMemberDef lex_yylex_members[] = {
716     {
717       "root",
718       T_OBJECT_EX,
719       offsetof(lex_yylexObject,
720       root),
721       0,
722       "root element, stack of sub-elements (treated as characters) and text"
723     },
724     {
725       "mark",
726       T_OBJECT_EX,
727       offsetof(lex_yylexObject,
728       mark),
729       0,
730       "list containing cursors, -2 current position, -1 next read position"
731     },
732     {
733       "yychunk_iter",
734       T_OBJECT_EX,
735       offsetof(lex_yylexObject,
736       yychunk_iter),
737       0,
738       "iterator for new input chunks (or None)"
739     },
740     {
741       "YY_INPUT_bytes",
742       T_OBJECT_EX,
743       offsetof(lex_yylexObject,
744       YY_INPUT_bytes),
745       0,
746       "UTF-8 encoding of current chunk to scan"
747     },
748     {
749       "YY_INPUT_bytes_off",
750       T_PYSSIZET,
751       offsetof(lex_yylexObject,
752       YY_INPUT_bytes_off),
753       0,
754       "current offset in UTF-8 text"
755     },
756     {
757       "YY_INPUT_bytes_len",
758       T_PYSSIZET,
759       offsetof(lex_yylexObject,
760       YY_INPUT_bytes_len),
761       0,
762       "maximum offset in UTF-8 text (inclusive)"
763     },
764     {}
765 };
766
767 static PyTypeObject lex_yylexType = {
768   PyVarObject_HEAD_INIT(NULL, 0)
769   "lex.yylex",               /* tp_name */
770   sizeof(lex_yylexObject),   /* tp_basicsize */
771   0,                         /* tp_itemsize */
772   (destructor)lex_yylex_dealloc, /* tp_dealloc */
773   0,                         /* tp_print */
774   0,                         /* tp_getattr */
775   0,                         /* tp_setattr */
776   0,                         /* tp_reserved */
777   0,                         /* tp_repr */
778   0,                         /* tp_as_number */
779   0,                         /* tp_as_sequence */
780   0,                         /* tp_as_mapping */
781   0,                         /* tp_hash  */
782   0,                         /* tp_call */
783   0,                         /* tp_str */
784   0,                         /* tp_getattro */
785   0,                         /* tp_setattro */
786   0,                         /* tp_as_buffer */
787   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
788   "Lexical token iterator",  /* tp_doc */
789   (traverseproc)lex_yylex_traverse, /* tp_traverse */
790   (inquiry)lex_yylex_clear,  /* tp_clear */
791   0,                         /* tp_richcompare */
792   0,                         /* tp_weaklistoffset */
793   (getiterfunc)lex_yylex_iter, /* tp_iter */
794   (iternextfunc)lex_yylex_iternext, /* tp_iternext */
795   0,                         /* tp_methods */
796   lex_yylex_members,         /* tp_members */
797   0,                         /* tp_getset */
798   0,                         /* tp_base */
799   0,                         /* tp_dict */
800   0,                         /* tp_descr_get */
801   0,                         /* tp_descr_set */
802   0,                         /* tp_dictoffset */
803   (initproc)lex_yylex_init,  /* tp_init */
804   0,                         /* tp_alloc */
805   lex_yylex_new              /* tp_new */
806 };
807
808 static int lex_traverse(PyObject *self, visitproc visit, void *arg)
809 {
810   Py_VISIT(work);
811   Py_VISIT(work_factory);
812   return 0;
813 }
814
815 static int lex_clear(PyObject *self)
816 {
817   Py_CLEAR(work);
818   Py_CLEAR(work_factory);
819   return 0;
820 }
821
822 static struct PyModuleDef lexmodule = {
823   PyModuleDef_HEAD_INIT,
824   "lex",
825   lex_doc_string,
826   -1,
827   NULL,
828   NULL,
829   lex_traverse,
830   lex_clear
831 };
832
833 PyMODINIT_FUNC PyInit_lex(void)
834 {
835   if (work != NULL) {
836     PyErr_SetString(
837       PyExc_RuntimeError,
838       "lex module cannot be re-imported or sub-interpreted\n"
839     );
840     goto error0;
841   }
842
843   PyObject *module = PyModule_Create(&lexmodule);
844   if (module == NULL)
845     goto error0;
846
847   if (
848     PyType_Ready(&lex_yylexType) ||
849     PyModule_AddObject(module, "yylex", (PyObject *)&lex_yylexType)
850   )
851     goto error1;
852   Py_INCREF(&lex_yylexType);
853
854   work = PyImport_ImportModule("work");
855   if (work == NULL)
856     goto error1;
857   work_factory = PyObject_GetAttrString(work, "factory");
858   if (work_factory == NULL) {
859     Py_DECREF(work);
860     work = NULL;
861   error1:
862     Py_DECREF(module);
863   error0:
864     return NULL;
865   }
866
867   return module;
868 }