]> git.draconx.ca Git - gob-dx.git/blob - src/lexer.l
Release 0.92.2
[gob-dx.git] / src / lexer.l
1 /* GOB C Preprocessor
2  * Copyright (C) 1999 the Free Software Foundation.
3  *
4  * Author: George Lebl
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the  Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19  * USA.
20  */
21 %{
22
23 #include "config.h"
24 #include <glib.h>
25 #include <string.h>
26
27 #include "parse.h"
28 #include "main.h"
29 #include "util.h"
30
31 static int parenth_depth = 0;
32 static int before_comment = INITIAL;
33 static gboolean class_after_c = FALSE;
34 static int code_type = CCODE;
35
36 static GString *cbuf = NULL;
37 int ccode_line = 1;
38
39 GList *include_files = NULL;
40 /* 0 no, 1 means yes, 2+ means don't even start looking anymore */
41 static int look_for_includes = 0;
42
43 int line_no = 1;
44
45 static void
46 clear_cbuf(void)
47 {
48         if(!cbuf) {
49                 cbuf = g_string_new("");
50         } else {
51                 cbuf = g_string_assign(cbuf,"");
52         }
53 }
54
55 static void
56 add_to_cbuf(char *s)
57 {
58         if(!cbuf) {
59                 cbuf = g_string_new(s);
60         } else {
61                 cbuf = g_string_append(cbuf,s);
62         }
63 }
64
65 %}
66
67 %x COMMENT
68 %x C_CODE
69 %x C_CODE_STRING
70 %x CLASS_CODE
71 %x CLASS_CODE_I
72
73 %%
74
75 <*>\n                   { line_no++; REJECT; }
76
77 <*>MOTHERFUCKER         { fprintf(stderr,"You are a bad bad person!\n"); REJECT; }
78
79 \/\/.*$                 { ; /*comment, ignore*/ }
80 <C_CODE>^#[ \t]*include[ \t][<"][^\n">]*[>"] {
81         if(look_for_includes==1) {
82                 char *p;
83                 char *file;
84                 char *str = g_strdup(yytext);
85                 file = strchr(str,'"');
86                 if(!file) file = strchr(str,'<');
87                 file++;
88                 p = strchr(file,'"');
89                 if(!p) p = strchr(file,'>');
90                 *p = '\0';
91                 include_files = g_list_prepend(include_files,g_strdup(file));
92                 g_free(str);
93         }
94         REJECT;
95 }
96
97 <C_CODE>\/\/.*$         { add_to_cbuf(yytext); /*comment, ignore*/ }
98 <CLASS_CODE>\/\/.*$     { ; /*comment, ignore*/ }
99 <CLASS_CODE_I>\/\/.*$   { ; /*comment, ignore*/ }
100 \/\*            {BEGIN(COMMENT); before_comment = INITIAL; }
101 <C_CODE>\/\*    {
102         add_to_cbuf(yytext);
103         BEGIN(COMMENT);
104         before_comment = C_CODE;
105 }
106 <CLASS_CODE>\/\*        {BEGIN(COMMENT); before_comment = CLASS_CODE; }
107 <CLASS_CODE_I>\/\*      {BEGIN(COMMENT); before_comment = CLASS_CODE_I; }
108 <COMMENT>\*\/   {
109         if(before_comment == C_CODE) add_to_cbuf(yytext);
110         BEGIN(before_comment);
111                 }
112 <COMMENT>.      {
113         /* comment, ignore */
114         if(before_comment == C_CODE) add_to_cbuf(yytext);
115                 }
116 <COMMENT>\n     {
117         /* comment, ignore */
118         if(before_comment == C_CODE) add_to_cbuf(yytext);
119                 }
120
121 ^\%(ht|headertop)\{             {
122                         BEGIN(C_CODE);
123                         parenth_depth = 1;
124                         class_after_c = FALSE;
125                         code_type = HTCODE;
126                         clear_cbuf();
127                         ccode_line = line_no;
128                 }
129 ^\%(ph|privateheader)\{         {
130                         BEGIN(C_CODE);
131                         parenth_depth = 1;
132                         class_after_c = FALSE;
133                         code_type = PHCODE;
134                         clear_cbuf();
135                         ccode_line = line_no;
136                 }
137 ^\%(h|header)\{         {
138                         BEGIN(C_CODE);
139                         parenth_depth = 1;
140                         class_after_c = FALSE;
141                         code_type = HCODE;
142                         clear_cbuf();
143                         ccode_line = line_no;
144                 }
145 ^\%\{           {
146                         BEGIN(C_CODE);
147                         parenth_depth = 1;
148                         class_after_c = FALSE;
149                         code_type = CCODE;
150                         clear_cbuf();
151                         ccode_line = line_no;
152                         if(look_for_includes==0)
153                                 look_for_includes=1;
154                 }
155 <C_CODE>^\%\}   {
156                         BEGIN(INITIAL);
157                         yylval.cbuf = cbuf;
158                         cbuf = NULL;
159                         if(look_for_includes==1)
160                                 look_for_includes=0;
161                         return code_type;
162                 }
163
164 <C_CODE>\'\{\'          { add_to_cbuf(yytext); }
165 <C_CODE>\'\\\{\'        { add_to_cbuf(yytext); }
166 <C_CODE>\'\}\'          { add_to_cbuf(yytext); }
167 <C_CODE>\'\\\}\'        { add_to_cbuf(yytext); }
168 <C_CODE>\'\"\'          { add_to_cbuf(yytext); }
169 <C_CODE>\'\\\"\'        { add_to_cbuf(yytext); }
170         
171 <C_CODE>\\.     { add_to_cbuf(yytext); }
172 <C_CODE>\"      {
173                         BEGIN(C_CODE_STRING);
174                         add_to_cbuf(yytext);
175                 }
176 <C_CODE_STRING>\\.      { add_to_cbuf(yytext); }
177 <C_CODE_STRING>\"       {
178                                 BEGIN(C_CODE);
179                                 add_to_cbuf(yytext);
180                         }
181 <C_CODE_STRING>.        { add_to_cbuf(yytext); }
182 <C_CODE_STRING>\n       { add_to_cbuf(yytext); }
183
184 <C_CODE>\{      {
185                         parenth_depth++;
186                         add_to_cbuf(yytext);
187                 }
188 <C_CODE>\}      {
189                         parenth_depth--;
190                         if(parenth_depth<0) {
191                                 REJECT;
192                         } else if(parenth_depth==0 && class_after_c) {
193                                 BEGIN(CLASS_CODE_I);
194                                 yylval.cbuf = cbuf;
195                                 cbuf = NULL;
196                                 return CCODE;
197                         }
198                         add_to_cbuf(yytext);
199                 }
200
201 <C_CODE>.       { add_to_cbuf(yytext); }
202 <C_CODE>\n      { add_to_cbuf(yytext); }
203
204 class           {
205                         look_for_includes = 2;
206                         BEGIN(CLASS_CODE);
207                         return CLASS;
208                 }
209
210 ^[ \t]*requires[ \t]+[0-9]+\.[0-9]+\.[0-9]+[\t ]*$      {
211                         int maj = 0,min = 0,pl = 0;
212                         int rmaj = 0,rmin = 0,rpl = 0;
213                         char *p;
214                         
215                         sscanf(VERSION,"%d.%d.%d",&rmaj,&rmin,&rpl);
216                         p = strchr(yytext,'r');
217                         g_assert(p); /* we MUST have found it */
218                         sscanf(p,"requires %d.%d.%d",&maj,&min,&pl);
219                         if(rmaj < maj ||
220                            (rmaj == maj && rmin < min) ||
221                            (rmaj == maj && rmin == min && rpl < pl)) {
222                                 char *s;
223                                 s = g_strdup_printf(
224                                     "GOB version %d.%d.%d required "
225                                     "(this is %s)\n"
226                                     "To upgrade your gob, see: "
227                                     "http://www.5z.com/jirka/gob.html",
228                                     maj,min,pl,VERSION);
229                                 print_error(FALSE,s, line_no);
230                                 g_free(s);
231                         }
232                 }
233
234 <CLASS_CODE,CLASS_CODE_I>class|this     {
235                         if(for_cpp) {
236                                 char *s;
237                                 s = g_strdup_printf("'%s' keyword should not "
238                                                     "be used when generating "
239                                                     "C++ code",yytext);
240                                 print_error(TRUE,s, line_no);
241                                 g_free(s);
242                         }
243                         REJECT;
244                 }
245
246 <CLASS_CODE>from        {return FROM;}
247
248 <CLASS_CODE_I>void      {return VOID;}
249 <CLASS_CODE_I>struct    {return STRUCT;}
250 <CLASS_CODE_I>union     {return UNION;}
251 <CLASS_CODE_I>enum      {return ENUM;}
252 <CLASS_CODE_I>signed    {return SIGNED;}
253 <CLASS_CODE_I>unsigned  {return UNSIGNED;}
254 <CLASS_CODE_I>long      {return LONG;}
255 <CLASS_CODE_I>short     {return SHORT;}
256 <CLASS_CODE_I>int       {return INT;}
257 <CLASS_CODE_I>float     {return FLOAT;}
258 <CLASS_CODE_I>double    {return DOUBLE;}
259 <CLASS_CODE_I>char      {return CHAR;}
260 <CLASS_CODE_I>const     {return CONST;}
261
262 <CLASS_CODE_I>\.\.\.    {return THREEDOTS;}
263
264 <CLASS_CODE_I>public    {yylval.line = line_no; return PUBLIC;}
265 <CLASS_CODE_I>private   {yylval.line = line_no; return PRIVATE;}
266 <CLASS_CODE_I>protected {yylval.line = line_no; return PROTECTED;}
267 <CLASS_CODE_I>argument  {yylval.line = line_no; return ARGUMENT;}
268 <CLASS_CODE_I>virtual   {yylval.line = line_no; return VIRTUAL;}
269 <CLASS_CODE_I>signal    {yylval.line = line_no; return SIGNAL;}
270 <CLASS_CODE_I>override  {yylval.line = line_no; return OVERRIDE;}
271 <CLASS_CODE_I>onerror   {return ONERROR;}
272 <CLASS_CODE_I>0|[1-9][0-9]*|0x[0-9a-fA-F]+|0[0-7]+|[0-9]*\.[0-9]+|\.[0-9][0-9]* {
273                         yylval.id = g_strdup(yytext);
274                         return NUMBER;
275                 }
276 <CLASS_CODE,CLASS_CODE_I>:?[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z0-9_]*)+      {
277                         yylval.id = g_strdup(yytext);
278                         return TYPETOKEN;
279                 }
280 <CLASS_CODE,CLASS_CODE_I>[A-Za-z_][A-Za-z0-9_]* {
281                         yylval.id = g_strdup(yytext);
282                         return TOKEN;
283                 }
284
285 <CLASS_CODE_I>(\[[0-9]*\])+     {
286                         yylval.id = g_strdup(yytext);
287                         return ARRAY_DIM;
288                 }
289
290 <CLASS_CODE>\{  {
291                         BEGIN(CLASS_CODE_I);
292                         return '{';
293                 }
294 <CLASS_CODE_I>\{        {
295                         BEGIN(C_CODE);
296                         parenth_depth=1;
297                         class_after_c = TRUE;
298                         yylval.line = line_no;
299                         clear_cbuf();
300                         ccode_line = line_no;
301                         return '{';
302                 }
303 <CLASS_CODE_I>\}        {
304                                 BEGIN(INITIAL);
305                                 return '}';
306                         }
307
308 <CLASS_CODE,CLASS_CODE_I,INITIAL>[\t ]  ;  /*ignore*/
309
310 <*>.            {
311                         yylval.line = line_no;
312                         return yytext[0];
313                 }
314
315 <*>[\n\r]       ;  /*ignore*/