compiler: Support for i18n through $"string" syntax (generates .pot, requires libintl...
[sdk] / compiler / libec / src / lexer.l
1 D         [0-9]
2 L         [a-zA-Z_]
3 H         [a-fA-F0-9]
4 E         [Ee][+-]?{D}+
5 FS         (f|F|l|L)
6 IS         (u|U|l|L)*
7 IDENT    {L}({L}|{D})*
8
9 %{
10 import "ecdefs"
11 #define YYLTYPE Location
12
13 #include "grammar.eh"
14
15 bool echoOn = true;
16 public void SetEchoOn(bool b) { echoOn = b; }
17
18 extern YYLTYPE type_yylloc;
19 extern YYLTYPE expression_yylloc;
20
21 extern File fileInput;
22 int preprocessor();
23 int comment();
24
25 void TESTTTT()
26 {
27    yylloc.end.charPos += yyleng;
28    yylloc.end.pos += yyleng;
29    type_yylloc.end.charPos += yyleng;
30    type_yylloc.end.pos += yyleng;
31    expression_yylloc.end.charPos += yyleng;
32    expression_yylloc.end.pos += yyleng;
33 }
34
35 #define YY_USER_ACTION  \
36    TESTTTT();
37
38    /*
39    yylloc.end.charPos += yyleng;
40    yylloc.end.pos += yyleng;
41    */
42
43 #define YY_INPUT(buf,result,max_size) \
44    result = fileInput.Read(buf, 1, max_size) \
45
46 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
47 File fileStack[MAX_INCLUDE_DEPTH];
48 char sourceFileStack[MAX_INCLUDE_DEPTH][MAX_LOCATION];
49 public void SetSomeSourceFileStack(char * fileName, int index) { strcpy(sourceFileStack[index], fileName); }
50 YYLTYPE locStack[MAX_INCLUDE_DEPTH];
51 AccessMode declModeStack[MAX_INCLUDE_DEPTH];
52 int include_stack_ptr = 0;
53
54 #define uint _uint
55 default:
56
57 %}
58
59 %%
60
61 %{
62    yylloc.start = yylloc.end; 
63    type_yylloc.start = type_yylloc.end; 
64    expression_yylloc.start = expression_yylloc.end; 
65 %}
66
67 "#"                  { preprocessor(); }
68 "/*"                 { comment(); }
69 "//"                 { commentCPP(); }
70
71 "auto"               { return(AUTO); }
72 "break"              { return(BREAK); }
73 "case"               { return(CASE); }
74 "char"               { return(CHAR); }
75 "const"              { return(CONST); }
76 "continue"           { return(CONTINUE); }
77 "default"            { return(DEFAULT); }
78 "do"                 { return(DO); }
79 "double"             { return(DOUBLE); }
80 "else"               { return(ELSE); }
81 "enum"               { return(ENUM); }
82 "extern"             { return(EXTERN); }
83 "float"              { return(FLOAT); }
84 "for"                { return(FOR); }
85 "goto"               { return(GOTO); }
86 "if"                 { return(IF); }
87 "int"                { return(INT); }
88 "uint"               { return(UINT); }
89  /* "uint16"            { return(UINT16); } */
90  /* "uint32"            { return(UINT32); } */
91  /* "bool"              { return(BOOL_TOKEN); } */
92 "long"               { return(LONG); }
93 "register"           { return(REGISTER); }
94 "return"             { return(RETURN); }
95 "short"              { return(SHORT); }
96 "signed"             { return(SIGNED); }
97 "__signed__"         { return(SIGNED); }
98 "sizeof"             { return(SIZEOF); }
99 "static"             { return(STATIC); }
100 "struct"             { return(STRUCT); }
101 "switch"             { return(SWITCH); }
102 "typedef"            { return(TYPEDEF); }
103 "union"              { return(UNION); }
104 "unsigned"           { return(UNSIGNED); }
105 "void"               { return(VOID); }
106 "volatile"           { return(VOLATILE); }
107 "__volatile__"       { return(VOLATILE); }
108 "while"              { return(WHILE); }
109
110 "property"           { return(PROPERTY); }
111 "set"                { return(SETPROP); }    // TODO: Don't make this a keyword...
112 "get"                { return(GETPROP); }    // TODO: Don't make this a keyword...
113 "isset"              { return(ISPROPSET); }    // TODO: Don't make this a keyword...
114 "class"              { return(CLASS); }
115 "thisclass"          { return(THISCLASS); }
116 "virtual"            { return(VIRTUAL); }
117 "delete"             { return(DELETE); }
118 "new"                { return(NEWOP); }
119 "new0"               { return(NEW0OP); }
120 "renew"              { return(RENEW); }
121 "renew0"             { return(RENEW0); }
122 "import"             { return(IMPORT); }
123 "define"             { return(DEFINE); }
124 "__int64"            { return(INT64); }
125 "int64"              { return(INT64); }
126 "__builtin_va_list"  { return(VALIST); }
127 "__builtin_va_arg"   { return(VAARG); }
128
129  /* "__attribute__".?"(("({D}|{L})*"))" { return(EXT_ATTRIB); } */
130
131  /* DID I MEAN? "__attribute__"" "*"(("" "*({D}|{L})*" "*("("({D}|{L})*(" "*","" "*({D}|{L})*)*" "*")")?" "*"))" { return(EXT_ATTRIB); } */
132
133 "__attribute__"(" "*)"(("(" "*)({D}|{L})*(" "*)("("({D}|{L}|\")*((" "*)","(" "*)({D}|{L}|\")*)*(" "*)")")?(" "*)(","(" "*)({D}|{L})*(" "*)("("({D}|{L}|\")*((" "*)","(" "*)({D}|{L}|\")*)*(" "*)")")?(" "*))*"))" { return(EXT_ATTRIB); }
134 "__attribute"(" "*)"(("(" "*)({D}|{L})*(" "*)("("({D}|{L}|\")*((" "*)","(" "*)({D}|{L}|\")*)*(" "*)")")?(" "*)(","(" "*)({D}|{L})*(" "*)("("({D}|{L}|\")*((" "*)","(" "*)({D}|{L}|\")*)*(" "*)")")?(" "*))*"))" { return(EXT_ATTRIB); }
135
136  /* "__attribute__".?"((".?({D}|{L})*.?("("({D}|{L})*(.?",".?({D}|{L})*)*.?")")?.?"))" { return(EXT_ATTRIB); } */
137  /* "__attribute".?"((".?({D}|{L})*.?("("({D}|{L})*(.?",".?({D}|{L})*)*.?")")?.?"))" { return(EXT_ATTRIB); }*/
138
139 "__inline__"               { return(EXT_STORAGE); }
140 "_inline"                  { return(EXT_STORAGE); }
141 "__inline"                 { return(EXT_STORAGE); }
142 "inline"                   { return(EXT_STORAGE); }
143 "__declspec("({D}|{L})*")" { return(EXT_STORAGE); }
144 "dllexport"                { return(EXT_STORAGE); }
145 "dllimport"                { return(EXT_STORAGE); }
146 "__cdecl"                  { return(EXT_DECL); }
147 "__stdcall"                { return(EXT_DECL); }
148 "__stdcall__"              { return(EXT_DECL); }
149 "_stdcall"                 { return(EXT_DECL); }
150 "stdcall"                  { return(EXT_DECL); }
151 "__restrict"               { return(EXT_DECL); }
152 "__const"                  { return(EXT_DECL); }
153 "__restrict__"             { return(EXT_DECL); }
154 "public"                   { return(PUBLIC); }
155 "private"                  { return(PRIVATE); }
156 "typed_object"             { return(TYPED_OBJECT); }
157 "any_object"               { return(ANY_OBJECT); }
158 "incref"                   { return(_INCREF); }
159 "__extension__"            { return(EXTENSION); }
160 "_extension_"              { return(EXTENSION); }
161 "__asm__"                  { return(ASM); }
162 "asm"                      { return(ASM); }
163 "__asm"                    { return(ASM); }
164 "__typeof"                 { return(TYPEOF); }
165 "watch"                    { return(WATCH); }
166 "stopwatching"             { return(STOPWATCHING); }
167 "firewatchers"             { return(FIREWATCHERS); }
168 "watchable"                { return(WATCHABLE); }
169 "class_designer"           { return(CLASS_DESIGNER); }
170 "class_no_expansion"       { return(CLASS_NO_EXPANSION); }
171 "class_fixed"              { return(CLASS_FIXED); }
172 "class_default_property"   { return(CLASS_DEFAULT_PROPERTY); }
173 "property_category"        { return(PROPERTY_CATEGORY); }
174 "class_data"               { return(CLASS_DATA); }
175 "class_property"           { return(CLASS_PROPERTY); }
176 "subclass"                 { return(SUBCLASS); }
177 "namespace"                { return(NAMESPACE); }
178 "dbtable"                  { return(DBTABLE); }
179 "dbfield"                  { return(DBFIELD); }
180 "dbindex"                  { return(DBINDEX); }
181 "database_open"            { return(DATABASE_OPEN); }
182       
183 ("::"|(({IDENT}"&"?"::")*)){IDENT}?    { return(check_type()); }     // {L}({L}|{D})*      { return(check_type()); }  // ("::"|(({IDENT}"::")*)){IDENT}  { return(check_type()); }     // {L}({L}|{D})*      { return(check_type()); }
184
185 0[xX]{H}+{IS}?          { return(CONSTANT); }
186 0{D}+{IS}?              { return(CONSTANT); }
187 {D}+{IS}?               { return(CONSTANT); }
188 L?'(\\.|[^\\'])+'       { return(CONSTANT); }
189
190 {D}+{E}{FS}?            { return(CONSTANT); }
191 {D}*"."{D}+({E})?{FS}?  { return(CONSTANT); }
192 {D}+"."{D}*({E})?{FS}?  { return(CONSTANT); }
193
194 L?\"(\\.|[^\\"])*\"     { return(STRING_LITERAL); }
195
196 "..."       { return(ELLIPSIS); }
197 ">>="       { return(RIGHT_ASSIGN); }
198 "<<="       { return(LEFT_ASSIGN); }
199 "+="        { return(ADD_ASSIGN); }
200 "-="        { return(SUB_ASSIGN); }
201 "*="        { return(MUL_ASSIGN); }
202 "/="        { return(DIV_ASSIGN); }
203 "%="        { return(MOD_ASSIGN); }
204 "&="        { return(AND_ASSIGN); }
205 "^="        { return(XOR_ASSIGN); }
206 "|="        { return(OR_ASSIGN); }
207 ">>"        { return(RIGHT_OP); }
208 "<<"        { return(LEFT_OP); }
209 "++"        { return(INC_OP); }
210 "--"        { return(DEC_OP); }
211 "->"        { return(PTR_OP); }
212 "&&"        { return(AND_OP); }
213 "||"        { return(OR_OP); }
214 "<="        { return(LE_OP); }
215 ">="        { return(GE_OP); }
216 "=="        { return(EQ_OP); }
217 "!="        { return(NE_OP); }
218    /* "::"        { return(CLASS_OP); } */
219 ";"         { return(';'); }
220 ("{"|"<%")  { return('{'); }
221 ("}"|"%>")  { return('}'); }
222 ","         { return(','); }
223 ":"         { return(':'); }
224 "="         { return('='); }
225 "("         { return('('); }
226 ")"         { return(')'); }
227 ("["|"<:")  { return('['); }
228 ("]"|":>")  { return(']'); }
229 "."         { return('.'); }
230 "&"         { return('&'); }
231 "!"         { return('!'); }
232 "~"         { return('~'); }
233 "-"         { return('-'); }
234 "+"         { return('+'); }
235 "*"         { return('*'); }
236 "/"         { return('/'); }
237 "%"         { return('%'); }
238 "<"         { return('<'); }
239 ">"         { return('>'); }
240 "^"         { return('^'); }
241 "|"         { return('|'); }
242 "?"         { return('?'); }
243 "$"         { return('$'); }
244
245 <<EOF>> {
246       if ( --include_stack_ptr < 0 )
247       {
248          yyterminate();
249       }
250       else
251       {
252          delete fileInput;
253          yy_delete_buffer( YY_CURRENT_BUFFER );
254          fileInput = fileStack[include_stack_ptr];
255          yylloc = locStack[include_stack_ptr];
256          type_yylloc = locStack[include_stack_ptr];
257          expression_yylloc = locStack[include_stack_ptr];
258          yy_switch_to_buffer(include_stack[include_stack_ptr] );
259          defaultDeclMode = declMode = declModeStack[include_stack_ptr];
260       }
261    }
262
263
264 [ \v\f]   { yylloc.start = yylloc.end; type_yylloc.start = type_yylloc.end; expression_yylloc.start = expression_yylloc.end;}
265 [\n+]    { 
266    yylloc.end.charPos = 1; yylloc.end.line += yyleng; yylloc.start = yylloc.end; 
267    type_yylloc.end.charPos = 1; type_yylloc.end.line += yyleng; type_yylloc.start = type_yylloc.end; 
268    expression_yylloc.end.charPos = 1; expression_yylloc.end.line += yyleng; expression_yylloc.start = expression_yylloc.end; 
269    }
270 [\t]     { 
271    yylloc.start.charPos++ /*= 3 - (yylloc.start.col % 3)*/; yylloc.end.charPos = yylloc.start.charPos; yylloc.start.pos = yylloc.end.pos; 
272    expression_yylloc.start.charPos++ /*= 3 - (expression_yylloc.start.col % 3)*/; expression_yylloc.end.charPos = expression_yylloc.start.charPos; expression_yylloc.start.pos = expression_yylloc.end.pos; 
273    type_yylloc.start.charPos++ /*= 3 - (type_yylloc.start.col % 3)*/; type_yylloc.end.charPos = type_yylloc.start.charPos; type_yylloc.start.pos = type_yylloc.end.pos; 
274    }
275
276 .         { yylloc.start = yylloc.end; expression_yylloc.start = expression_yylloc.end;  type_yylloc.start = type_yylloc.end; }
277
278 %%
279
280 yywrap()
281 {
282    return(1);
283 }
284
285 int comment()
286 {
287    int c, last = 0;
288    for(;;)
289    {
290       c = input();
291       if(c == EOF) break;
292
293       // fputc(c, output);
294       // putchar(c);
295       if(c == '\n')
296       {
297          yylloc.end.charPos = 1;
298          yylloc.end.pos++;
299          yylloc.end.line++;
300       }
301       else if (c == '\t')
302       {
303          yylloc.end.charPos++ /* += 3 - (yylloc.end.col % 3)*/;
304          yylloc.end.pos++;
305       }
306       else
307       {
308          yylloc.end.charPos++;
309          yylloc.end.pos++;
310       }
311       if(c == '/' && last == '*')
312          break;
313       last = c;
314    }
315    yylloc.start = yylloc.end;
316    return 0;
317 }
318
319 int commentCPP()
320 {
321    int c, last = 0;
322    for(;;)
323    {
324       c = input();
325       if(c == EOF) break;
326
327       // fputc(c, output);
328       // putchar(c);
329       if(c == '\n')
330       {
331          yylloc.end.charPos = 1;
332          yylloc.end.pos++;
333          yylloc.end.line++;
334          break;
335       }
336       else if (c == '\t')
337       {
338          yylloc.end.charPos++ /* += 3 - (yylloc.end.col % 3)*/;
339          yylloc.end.pos++;
340       }
341       else
342       {
343          yylloc.end.charPos++;
344          yylloc.end.pos++;
345       }
346       last = c;
347    }
348    yylloc.start = yylloc.end;
349    return 0;
350 }
351
352 int preprocessor()
353 {
354    int c, last = 0;
355    int count = 0;
356    char line[1024];
357
358    line[0] = '\0';
359
360    for(;;)
361    {
362       c = input();
363       if(c == EOF) break;
364
365       if(c == '\n')
366       {
367          yylloc.end.charPos = 1;
368          yylloc.end.pos++;
369          yylloc.end.line++;
370          if(last != '\\')
371          {
372             char * pointer = line + 1;
373             int lineNumber;
374             line[count] = 0;
375             lineNumber = GetValue(&pointer);
376             if(lineNumber)
377             {
378                char fileName[MAX_LOCATION];
379                
380                int inOut;
381                GetString(&pointer, fileName, MAX_LOCATION);
382                inOut = GetValue(&pointer);
383                               
384                if(inOut == 1)
385                {
386                   char extension[MAX_EXTENSION];
387
388                   defaultDeclMode = declModeStack[include_stack_ptr] = declMode;
389
390                   GetExtension(fileName, extension);
391                   if(!strcmp(extension, "c") || !strcmp(extension, "h"))
392                      declMode = defaultDeclMode = defaultAccess;
393
394                   include_stack_ptr++;
395                }
396                else if(inOut == 2)
397                {
398                   include_stack_ptr--;
399                   defaultDeclMode = declMode = declModeStack[include_stack_ptr];
400                }
401
402                yylloc.end.charPos = 1;
403                yylloc.end.line = lineNumber;
404                //yylloc.end.pos -= count;
405                yylloc.end.included = (include_stack_ptr > 0) ? GetIncludeFileID(fileName) : 0;
406             }
407             /*
408             int lineNumber = strtol(line+1, &endPtr, 0);
409             if(lineNumber)
410             {
411                GetString(&
412                endPtr
413
414                yylloc.end.charPos = 1;
415                yylloc.end.line = lineNumber;
416                yylloc.end.pos -= count;
417             }
418             */
419             break;
420          }
421          count = 0;
422       }
423       else if (c == '\t')
424       {
425          yylloc.end.charPos++ /* += 3 - (yylloc.end.col % 3)*/;
426          yylloc.end.pos++;
427          line[count++] = c;
428       }
429       else
430       {
431          yylloc.end.pos++;
432          if(c != '\r')
433          {
434             yylloc.end.charPos++;
435             line[count++] = c;
436          }
437       }
438       last = c;
439    }   
440    yylloc.start = yylloc.end;
441    line[count] = 0;
442
443    TrimLSpaces(line, line);
444    for(c = 0; line[c] && line[c] != ' '; c++);
445    if(!strncmp(line, "include", c))
446    {
447       char includeFile[MAX_LOCATION] = "";
448
449       strcpy(line, line+c);
450       TrimLSpaces(line, line);
451       if(line[0] == '\"')
452       {
453          for(c = 1; line[c]; c++)
454          {
455             if(line[c] == '\"')
456             {
457                strncpy(includeFile, line+1, c-1);
458                includeFile[c-1] = '\0';
459                break;
460             }
461          }
462       }
463       else if(line[0] == '<')
464       {
465          for(c = 1; line[c]; c++)
466             if(line[c] == '>')
467             {
468                strncpy(includeFile, line+1, c-1);
469                includeFile[c-1] = '\0';
470                break;
471             }
472       }
473
474       if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
475       {
476          fprintf( stderr, "Includes nested too deeply" );
477          exit( 1 );
478       }
479
480       if(inCompiler || !FindIncludeFileID(includeFile))
481       {
482          File file = OpenIncludeFile(includeFile);
483          if(file)
484          {
485             char extension[MAX_EXTENSION];
486
487             fileStack[include_stack_ptr] = fileInput;
488             locStack[include_stack_ptr] = yylloc;
489             defaultDeclMode = declModeStack[include_stack_ptr] = declMode;
490             include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
491
492             yylloc.start.charPos = yylloc.end.charPos = 1;
493             yylloc.start.line = yylloc.end.line = 1;
494             yylloc.start.pos = yylloc.end.pos = 0;
495             yylloc.start.included = yylloc.end.included = GetIncludeFileID(includeFile);
496
497             GetExtension(includeFile, extension);
498             if(!strcmp(extension, "c") || !strcmp(extension, "h"))
499                declMode = defaultDeclMode = defaultAccess;
500
501             fileInput = file;
502             yy_switch_to_buffer( yy_create_buffer( fileInput, YY_BUF_SIZE ) );
503             BEGIN(INITIAL);
504          }
505          else
506             printf("");
507       }
508    }
509    return 0;
510 }
511
512 public void resetScanner()
513 {
514    YY_FLUSH_BUFFER;
515    yylloc.start.charPos = yylloc.end.charPos = 1;
516    yylloc.start.line = yylloc.end.line = 1;
517    yylloc.start.pos = yylloc.end.pos = 0;
518    yylloc.start.included = yylloc.end.included = false;
519
520    expression_yylloc.start.charPos = expression_yylloc.end.charPos = 1;
521    expression_yylloc.start.line = expression_yylloc.end.line = 1;
522    expression_yylloc.start.pos = expression_yylloc.end.pos = 0;
523    expression_yylloc.start.included = expression_yylloc.end.included = false;
524
525    type_yylloc.start.charPos = type_yylloc.end.charPos = 1;
526    type_yylloc.start.line = type_yylloc.end.line = 1;
527    type_yylloc.start.pos = type_yylloc.end.pos = 0;
528    type_yylloc.start.included = type_yylloc.end.included = false;
529
530    include_stack_ptr = 0;
531 }
532
533 void resetScannerPos(CodePosition pos)
534 {
535    YY_FLUSH_BUFFER;
536    yylloc.start = yylloc.end = pos;
537    type_yylloc.start = type_yylloc.end = pos;
538    expression_yylloc.start = expression_yylloc.end = pos;
539 }