Got rid of gc_strdup, added prototype for alt lexer
[fw/sdcc] / src / altlex.c
1 /** @file altlex.c
2     An alternate lexer to SDCC.lex.
3     In development - ie messy and just plain wrong.
4 */
5 #include "common.h"
6 #include <assert.h>
7
8 FILE *yyin;
9
10 int yylineno;
11 int column;
12 char *currFname;
13 char *yytext;
14
15 /* Right.  What are the parts of the C stream?  From SDCC.lex:
16    D = [0..9]           digits
17    L = [a..z A..Z _]    alphanumerics and _
18    H = [a..f A..F 0-9]  Hex digits
19    E = [eE+-0-9]        Digits in a float
20    FS = [fFlL]          Specifiers for a float
21    IS = [uUlL]          Specifiers for a int
22
23    L[LD]*               A 'token' - cant think of a good name
24                         Check tokens against the reserved words.
25                         If match 
26                                 return the token id.
27                         else 
28                                 If in the typedef table, do stuff...
29                                 Blah.  See check_type()
30    0[xX]{H}+            Hex number - PENDING: specifiers
31    0{D}+                Octal number - PENDING: specifiers
32    {D}+                 Decimal - PENDING: specifiers
33    Floats               PENDING
34    
35    Exceptions:
36    Comment start        Strip until end of comment.
37    ...                  Ellipses
38
39    So the inputs are:
40       Skip whitespace
41       switch class
42          L      Try to read a token
43          D      Try to read a number
44          Punct  Try to read punct
45 */      
46
47 char linebuf[10000];
48 int linepos, linelen;
49
50 #define INLINE  inline
51
52 static int underflow(void)
53 {
54     linelen = fread(linebuf, 1, sizeof(linebuf), yyin);
55     if (linelen <= 0)
56         return EOF;
57     linepos = 0;
58     return linebuf[linepos++];
59 }
60
61 static int INLINE ygetc(void)
62 {
63     if (linepos < linelen)
64         return linebuf[linepos++];
65     else
66         return underflow();
67 };
68
69 static int INLINE yungetc(int c)
70 {
71     linebuf[--linepos] = c;
72     return 0;
73 }
74
75 #define GETC()          ygetc()
76 #define UNGETC(_a)      yungetc(_a)
77
78 //#define GETC()                fgetc(yyin);
79 //#define UNGETC(_a)    ungetc(_a, yyin)
80 #define ISL(_a)         (isalnum(_a) || _a == '_')
81 #define ISALNUM(_a)     isalnum(_a)
82 #define ISHEX(_a)       isalnum(_a)
83
84 char *stringLiteral (void)
85 {
86     static char line[1000];
87     int ch;
88     char *str = line;
89        
90     *str++ = '\"'                       ;
91     /* put into the buffer till we hit the */
92     /* first \" */
93     while (1) {
94
95         ch = GETC();
96         if (!ch)            break       ; /* end of input */
97         /* if it is a \ then everything allowed */
98         if (ch == '\\') {
99             *str++ = ch     ; /* backslash in place */
100             *str++ = GETC()             ; /* following char in place */
101             continue                    ;      /* carry on */
102         }
103              
104         /* if new line we have a new line break */
105         if (ch == '\n') break           ;
106          
107         /* if this is a quote then we have work to do */
108         /* find the next non whitespace character     */
109         /* if that is a double quote then carry on    */
110         if (ch == '\"') {
111          
112             while ((ch = GETC()) && isspace(ch)) ;
113             if (!ch) break              ; 
114             if (ch != '\"') {
115                 UNGETC(ch)                      ;
116                 break                   ;
117             }
118                   
119             continue            ;
120         }
121         *str++  = ch;     
122     }  
123     *str++ = '\"'                       ;
124     *str = '\0';
125     return line;
126 }
127
128 void discard_comments(int type)
129 {
130     int c;
131     if (type == '*') {
132         do {
133             c = GETC();
134             if (c == '*') {
135                 c = GETC();
136                 if (c == '/')
137                     return;
138             }
139             else if (c == EOF)
140                 return;
141         } while (1);
142     }
143     else if (type == '/') {
144         while (c != '\n' && c != EOF) {
145             c = GETC();
146         }
147     }
148     else {
149         assert(0);
150     }
151 }
152
153 #define TKEYWORD(_a)    return _a
154
155 int check_token(const char *sz)
156 {
157     if (!strcmp(sz, "at")) {
158         TKEYWORD(AT)  ; }
159     
160     else if (!strcmp(sz, "auto")) {
161          return(AUTO); }
162     
163     else if (!strcmp(sz, "bit")) {
164          TKEYWORD(BIT) ; }
165     
166     else if (!strcmp(sz, "break")) {
167          return(BREAK); }
168
169     else if (!strcmp(sz, "case")) {
170          return(CASE); }
171
172     else if (!strcmp(sz, "char")) {
173          return(CHAR); }
174
175     else if (!strcmp(sz, "code")) {
176          TKEYWORD(CODE); }
177
178     else if (!strcmp(sz, "const")) {
179          return(CONST); }
180
181     else if (!strcmp(sz, "continue")) {
182          return(CONTINUE); }
183
184     else if (!strcmp(sz, "critical")) {
185          TKEYWORD(CRITICAL); } 
186
187     else if (!strcmp(sz, "data")) {
188          TKEYWORD(DATA);   }
189
190     else if (!strcmp(sz, "default")) {
191          return(DEFAULT); }
192
193     else if (!strcmp(sz, "do")) {
194          return(DO); }
195
196     else if (!strcmp(sz, "double")) {
197          werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); }
198
199     else if (!strcmp(sz, "else")) {
200          return(ELSE); }
201
202     else if (!strcmp(sz, "enum")) {
203          return(ENUM); }
204
205     else if (!strcmp(sz, "extern")) {
206          return(EXTERN); }
207
208     else if (!strcmp(sz, "far")) {
209          TKEYWORD(XDATA);  }
210
211     else if (!strcmp(sz, "eeprom")) {
212          TKEYWORD(EEPROM);  }
213
214     else if (!strcmp(sz, "float")) {
215          return(FLOAT); }
216
217     else if (!strcmp(sz, "flash")) {
218          TKEYWORD(CODE);}
219
220     else if (!strcmp(sz, "for")) {
221          return(FOR); }
222
223     else if (!strcmp(sz, "goto")) {
224          return(GOTO); }
225
226     else if (!strcmp(sz, "idata")) {
227          TKEYWORD(IDATA);}
228
229     else if (!strcmp(sz, "if")) {
230          return(IF); }
231
232     else if (!strcmp(sz, "int")) {
233          return(INT); }
234
235     else if (!strcmp(sz, "interrupt")) {
236          return(INTERRUPT);}
237
238     else if (!strcmp(sz, "nonbanked")) {
239          TKEYWORD(NONBANKED);}
240
241     else if (!strcmp(sz, "banked")) {
242          TKEYWORD(BANKED);}
243
244     else if (!strcmp(sz, "long")) {
245          return(LONG); }
246
247     else if (!strcmp(sz, "near")) {
248          TKEYWORD(DATA);}
249
250     else if (!strcmp(sz, "pdata")) {
251          TKEYWORD(PDATA); }
252
253     else if (!strcmp(sz, "reentrant")) {
254          TKEYWORD(REENTRANT);}
255
256     else if (!strcmp(sz, "register")) {
257          return(REGISTER); }
258
259     else if (!strcmp(sz, "return")) {
260          return(RETURN); }
261
262     else if (!strcmp(sz, "sfr")) {
263          TKEYWORD(SFR)  ; }
264
265     else if (!strcmp(sz, "sbit")) {
266          TKEYWORD(SBIT) ; }
267
268     else if (!strcmp(sz, "short")) {
269          return(SHORT); }
270
271     else if (!strcmp(sz, "signed")) {
272          return(SIGNED); }
273
274     else if (!strcmp(sz, "sizeof")) {
275          return(SIZEOF); }
276
277     else if (!strcmp(sz, "sram")) {
278          TKEYWORD(XDATA);}
279
280     else if (!strcmp(sz, "static")) {
281          return(STATIC); }
282
283     else if (!strcmp(sz, "struct")) {
284          return(STRUCT); }
285
286     else if (!strcmp(sz, "switch")) {
287          return(SWITCH); }
288
289     else if (!strcmp(sz, "typedef")) {
290          return(TYPEDEF); }
291
292     else if (!strcmp(sz, "union")) {
293          return(UNION); }
294
295     else if (!strcmp(sz, "unsigned")) {
296          return(UNSIGNED); }
297
298     else if (!strcmp(sz, "void")) {
299          return(VOID); }
300
301     else if (!strcmp(sz, "volatile")) {
302          return(VOLATILE); }
303
304     else if (!strcmp(sz, "using")) {
305          TKEYWORD(USING); }
306
307     else if (!strcmp(sz, "while")) {
308          return(WHILE); }
309
310     else if (!strcmp(sz, "xdata")) {
311          TKEYWORD(XDATA); }
312
313     else if (!strcmp(sz, "_data")) {
314          TKEYWORD(_NEAR); }
315
316     else if (!strcmp(sz, "_code")) {
317          TKEYWORD(_CODE); }
318
319     else if (!strcmp(sz, "_eeprom")) {
320          TKEYWORD(_EEPROM); }
321
322     else if (!strcmp(sz, "_flash")) {
323          TKEYWORD(_CODE); }
324
325     else if (!strcmp(sz, "_generic")) {
326          TKEYWORD(_GENERIC); }
327
328     else if (!strcmp(sz, "_near")) {
329          TKEYWORD(_NEAR); }
330
331     else if (!strcmp(sz, "_sram")) {
332          TKEYWORD(_XDATA);}
333
334     else if (!strcmp(sz, "_xdata")) {
335          TKEYWORD(_XDATA);}
336
337     else if (!strcmp(sz, "_pdata")) {
338          TKEYWORD(_PDATA); }
339
340     else if (!strcmp(sz, "_idata")) {
341          TKEYWORD(_IDATA); }
342
343     /* check if it is in the typedef table */
344     if (findSym(TypedefTab,NULL,sz)) {
345         strcpy(yylval.yychar,sz);
346         return (TYPE_NAME) ;
347     }
348     else   {
349         strcpy (yylval.yychar,sz);
350         return(IDENTIFIER);
351     }
352 }
353
354 int yylex(void)
355 {
356     int c;
357     char line[128];
358     char *p;
359
360     c = GETC();
361     while (1) {
362         /* Handle comments first */
363         if (c == '/') {
364             int c2 = GETC();
365             if (c2 == '*' || c2 == '/') {
366                 discard_comments(c2);
367                 c = GETC();
368                 continue;
369             }
370             else
371                 UNGETC(c2);
372         }
373         switch (c) {
374         case EOF:
375             return 0;
376         case ' ':
377         case '\t':
378         case '\r':
379         case '\n':
380             /* Skip whitespace */
381             break;
382         case 'a': case 'b': case 'c': case 'd':
383         case 'e': case 'f': case 'g': case 'h':
384         case 'i': case 'j': case 'k': case 'l':
385         case 'm': case 'n': case 'o': case 'p':
386         case 'q': case 'r': case 's': case 't':
387         case 'u': case 'v': case 'w': case 'x':
388         case 'y': case 'z':
389         case 'A': case 'B': case 'C': case 'D':
390         case 'E': case 'F': case 'G': case 'H':
391         case 'I': case 'J': case 'K': case 'L':
392         case 'M': case 'N': case 'O': case 'P':
393         case 'Q': case 'R': case 'S': case 'T':
394         case 'U': case 'V': case 'W': case 'X':
395         case 'Y': case 'Z':
396         case '_':
397             /* Start of a token.  Parse. */
398             p = line;
399             *p++ = c;
400             c = GETC();
401             while (ISL(c)) {
402                 *p++ = c;
403                 c = GETC();
404             }
405             *p = '\0';
406             UNGETC(c);
407             return check_token(line);
408         case '0': case '1':
409         case '2': case '3': case '4': case '5':
410         case '6': case '7': case '8': case '9':
411             p = line;
412             *p++ = c;
413             c = GETC();
414             if (c == 'x' || c == 'X') {
415                 *p++ = c;
416                 c = GETC();
417             }
418             while (ISHEX(c)) {
419                 *p++ = c;
420                 c = GETC();
421             }
422             *p = '\0';
423             UNGETC(c);
424             yylval.val = constVal(line);
425             return CONSTANT;
426         case '\"':
427             /* A string */
428             p = stringLiteral();
429             yylval.val = strVal(p);
430             return(STRING_LITERAL);
431         case '\'':
432             /* ie '\n' */
433             break;
434         case '#':
435             /* Assume a pragma and toast the rest of the line. */
436             c = GETC();
437             while (c != '\n') {
438                 c = GETC();
439             }
440             break;
441         case '=':
442         case '&':
443         case '!':
444         case '-':
445         case '+':
446         case '*':
447         case '/':
448         case '%':
449         case '<':
450         case '>':
451         case '^':
452         case '|':
453             /* Cases which can be compounds */
454             return c;
455         case '{':
456             NestLevel++;
457             return c;
458         case '}':
459             NestLevel--;
460             return c;
461         case '.':
462             c = GETC();
463             if (c == '.') {
464                 c = GETC();
465                 if (c == '.') {
466                     return VAR_ARGS;
467                 }
468             }
469             UNGETC(c);
470             /* Fall through */
471         case ',':
472         case ':':
473         case '(': case ')':
474         case '[': case ']':
475         case '~':
476         case '?':
477             /* Special characters that cant be part of a composite */
478             return c;
479         default:
480             printf("Unhandled char %c\n", c);
481         }
482         c = GETC();
483     }
484     return 0;
485 }