* support/Util/NewAlloc.c (freeTrace): Changed free for the gc case to not free...
[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     Inspired by the gcc lexer, c-lex.c.
5 */
6 #include "common.h"
7 #include "reswords.h"
8 #include <assert.h>
9
10 #define DUMP_OUTPUT             0
11
12 /* Right.  What are the parts of the C stream?  From SDCC.lex:
13    D = [0..9]           digits
14    L = [a..z A..Z _]    alphanumerics and _
15    H = [a..f A..F 0-9]  Hex digits
16    E = [eE+-0-9]        Digits in a float
17    FS = [fFlL]          Specifiers for a float
18    IS = [uUlL]          Specifiers for a int
19
20    L[LD]*               A 'token' - cant think of a good name
21    Check tokens against the reserved words.
22    If match 
23    return the token id.
24    else 
25    If in the typedef table, do stuff...
26    Blah.  See check_type()
27    0[xX]{H}+            Hex number - PENDING: specifiers
28    0{D}+                Octal number - PENDING: specifiers
29    {D}+                 Decimal - PENDING: specifiers
30    Floats               PENDING
31
32    Exceptions:
33    Comment start        Strip until end of comment.
34    ...                  Ellipses
35
36    So the inputs are:
37    Skip whitespace
38    switch class
39    L    Try to read a token
40    D    Try to read a number
41    Punct        Try to read punct
42  */
43
44 extern int fatalError;
45 extern int lineno;
46 extern char *filename;
47
48 FILE *yyin;
49
50 int yylineno;
51 char *currFname;
52 char *yytext;
53
54 static char linebuf[10000];
55 static int linepos, linelen;
56 static int end_of_file;
57
58 #ifdef __GNUC__
59 #define INLINE  inline
60 #else
61 #define INLINE
62 #endif
63
64 #define ERRSINK stderr
65
66 static void 
67 error (const char *sz,...)
68 {
69   va_list ap;
70   fatalError++;
71
72   if (filename && lineno)
73     {
74       fprintf (ERRSINK, "%s(%d):", filename, lineno);
75     }
76   fprintf (ERRSINK, "error *** ");
77   va_start (ap, sz);
78   vfprintf (ERRSINK, sz, ap);
79   va_end (ap);
80   fprintf (ERRSINK, "\n");
81   fflush (ERRSINK);
82 }
83
84 static int 
85 underflow (void)
86 {
87   linelen = fread (linebuf, 1, sizeof (linebuf), yyin);
88   if (linelen <= 0)
89     return EOF;
90   linepos = 0;
91   return linebuf[linepos++];
92 }
93
94 static int INLINE 
95 ygetc (void)
96 {
97   if (linepos < linelen)
98     return linebuf[linepos++];
99   else
100     return underflow ();
101 };
102
103 static int INLINE 
104 yungetc (int c)
105 {
106   linebuf[--linepos] = c;
107   return 0;
108 }
109
110 #define GETC()          ygetc()
111 #define UNGETC(_a)      yungetc(_a)
112
113 //#define GETC()                fgetc(yyin);
114 //#define UNGETC(_a)    ungetc(_a, yyin)
115 #define ISL(_a)         (isalnum(_a) || _a == '_')
116 #define ISALNUM(_a)     isalnum(_a)
117 #define ISHEX(_a)       isxdigit(_a)
118
119 static char *
120 stringLiteral (void)
121 {
122   static char line[1000];
123   int ch;
124   char *str = line;
125
126   *str++ = '\"';
127   /* put into the buffer till we hit the */
128   /* first \" */
129   while (1)
130     {
131
132       ch = GETC ();
133       if (!ch)
134         break;                  /* end of input */
135       /* if it is a \ then everything allowed */
136       if (ch == '\\')
137         {
138           *str++ = ch;          /* backslash in place */
139           *str++ = GETC ();     /* following char in place */
140           continue;             /* carry on */
141         }
142
143       /* if new line we have a new line break */
144       if (ch == '\n')
145         break;
146
147       /* if this is a quote then we have work to do */
148       /* find the next non whitespace character     */
149       /* if that is a double quote then carry on    */
150       if (ch == '\"')
151         {
152
153           while ((ch = GETC ()) && isspace (ch));
154           if (!ch)
155             break;
156           if (ch != '\"')
157             {
158               UNGETC (ch);
159               break;
160             }
161
162           continue;
163         }
164       *str++ = ch;
165     }
166   *str++ = '\"';
167   *str = '\0';
168   return line;
169 }
170
171 static void 
172 discard_comments (int type)
173 {
174   int c;
175   if (type == '*')
176     {
177       do
178         {
179           c = GETC ();
180           if (c == '*')
181             {
182               c = GETC ();
183               if (c == '/')
184                 return;
185             }
186           else if (c == EOF)
187             return;
188         }
189       while (1);
190     }
191   else if (type == '/')
192     {
193       do
194         {
195           c = GETC ();
196         }
197       while (c != '\n' && c != EOF);
198     }
199   else
200     {
201       assert (0);
202     }
203 }
204
205 /* will return 1 if the string is a part
206    of a target specific keyword */
207 static INLINE int 
208 isTargetKeyword (const char *s)
209 {
210   int i;
211
212   if (port->keywords == NULL)
213     return 0;
214   for (i = 0; port->keywords[i]; i++)
215     {
216       if (strcmp (port->keywords[i], s) == 0)
217         return 1;
218     }
219
220   return 0;
221 }
222
223 static INLINE int 
224 check_token (const char *sz)
225 {
226   const struct reserved_words *p;
227   p = is_reserved_word (sz, strlen (sz));
228   if (p)
229     {
230       if (!p->is_special || isTargetKeyword (sz))
231         return p->token;
232     }
233
234   /* check if it is in the typedef table */
235   if (findSym (TypedefTab, NULL, sz))
236     {
237       strcpy (yylval.yychar, sz);
238       return TYPE_NAME;
239     }
240   else
241     {
242       strcpy (yylval.yychar, sz);
243       return IDENTIFIER;
244     }
245 }
246
247 static void 
248 handle_pragma (void)
249 {
250   char line[128], *p;
251   int c;
252
253   c = GETC ();
254   while (c == '\t' || c == ' ')
255     c = GETC ();
256   p = line;
257   while (!isspace (c))
258     {
259       *p++ = c;
260       c = GETC ();
261     }
262   *p = '\0';
263   if (line[0] == '\0')
264     error ("Missing argument to pragma");
265   else
266     {
267       /* First give the port a chance */
268       if (port->process_pragma && !port->process_pragma (line))
269         return;
270       /* PENDING: all the SDCC shared pragmas */
271       /* Nothing handled it */
272       error ("Unrecognised #pragma %s", line);
273     }
274 }
275
276 static void 
277 handle_line (void)
278 {
279   int c;
280   char line[128], *p;
281
282   c = GETC ();
283   while (c == '\t' || c == ' ')
284     c = GETC ();
285   p = line;
286   while (isdigit (c))
287     {
288       *p++ = c;
289       c = GETC ();
290     }
291   *p = '\0';
292   if (line[0] == '\0')
293     error ("Error in number in #line");
294   /* This is weird but cpp seems to add an extra three to the line no */
295   yylineno = atoi (line) - 3;
296   lineno = yylineno;
297   /* Fetch the filename if there is one */
298   while (c == '\t' || c == ' ')
299     c = GETC ();
300   if (c == '\"')
301     {
302       p = line;
303       c = GETC ();
304       while (c != '\"' && c != EOF && c != '\n')
305         {
306           *p++ = c;
307           c = GETC ();
308         }
309       if (c == '\"')
310         {
311           *p = '\0';
312           currFname = Safe_strdup (line);
313         }
314       filename = currFname;
315     }
316 }
317
318 static INLINE void 
319 invalid_directive (void)
320 {
321   error ("Invalid directive");
322 }
323
324 static INLINE int 
325 check_newline (void)
326 {
327   int c;
328   yylineno++;
329   lineno = yylineno;
330
331   /* Skip any leading white space */
332   c = GETC ();
333   while (c == '\t' || c == ' ')
334     c = GETC ();
335   /* Were only interested in #something */
336   if (c != '#')
337     return c;
338   c = GETC ();
339   while (c == '\t' || c == ' ')
340     c = GETC ();
341   /* The text in the stream is the type of directive */
342   switch (c)
343     {
344     case 'l':
345       /* Start of line? */
346       if (GETC () == 'i' && GETC () == 'n' && GETC () == 'e')
347         {
348           c = GETC ();
349           if (c == '\t' || c == ' ')
350             handle_line ();
351           else
352             invalid_directive ();
353         }
354       else
355         invalid_directive ();
356       break;
357     case 'p':
358       /* Start of pragma? */
359       if (GETC () == 'r' && GETC () == 'a' && GETC () == 'g' &&
360           GETC () == 'm' && GETC () == 'a')
361         {
362           c = GETC ();
363           if (c == '\t' || c == ' ')
364             handle_pragma ();
365           else
366             invalid_directive ();
367         }
368       else
369         invalid_directive ();
370       break;
371     default:
372       invalid_directive ();
373     }
374   /* Discard from here until the start of the next line */
375   while (c != '\n' && c != EOF)
376     c = GETC ();
377   return c;
378 }
379
380 static int 
381 skip_whitespace (int c)
382 {
383   while (1)
384     {
385       switch (c)
386         {
387         case ' ':
388         case '\t':
389         case '\f':
390         case '\v':
391         case '\b':
392         case '\r':
393           c = GETC ();
394           break;
395         case '\n':
396           c = check_newline ();
397         default:
398           return c;
399         }
400     }
401 }
402
403 void 
404 yyerror (const char *s)
405 {
406   if (end_of_file)
407     error ("%s at end of of input", s);
408   else if (yytext[0] == '\0')
409     error ("%s at null character", s);
410   else if (yytext[0] == '"')
411     error ("%s before string constant", s);
412   else if (yytext[0] == '\'')
413     error ("%s before character constant", s);
414   else
415     error ("%s before %s", s, yytext);
416 }
417
418 static int 
419 _yylex (void)
420 {
421   int c;
422   static char line[128];
423   char *p;
424
425   yytext = line;
426
427   c = GETC ();
428   while (1)
429     {
430       switch (c)
431         {
432         case ' ':
433         case '\t':
434         case '\f':
435         case '\v':
436         case '\b':
437           /* Skip whitespace */
438           c = GETC ();
439           break;
440         case '\r':
441         case '\n':
442           c = skip_whitespace (c);
443           break;
444         case '#':
445           UNGETC (c);
446           c = check_newline ();
447           break;
448         default:
449           goto past_ws;
450         }
451     }
452
453 past_ws:
454   /* Handle comments first */
455   if (c == '/')
456     {
457       int c2 = GETC ();
458       if (c2 == '*' || c2 == '/')
459         {
460           discard_comments (c2);
461           c = GETC ();
462         }
463       else
464         UNGETC (c2);
465     }
466   switch (c)
467     {
468     case EOF:
469       end_of_file = TRUE;
470       line[0] = '\0';
471       return 0;
472     case 'a':
473     case 'b':
474     case 'c':
475     case 'd':
476     case 'e':
477     case 'f':
478     case 'g':
479     case 'h':
480     case 'i':
481     case 'j':
482     case 'k':
483     case 'l':
484     case 'm':
485     case 'n':
486     case 'o':
487     case 'p':
488     case 'q':
489     case 'r':
490     case 's':
491     case 't':
492     case 'u':
493     case 'v':
494     case 'w':
495     case 'x':
496     case 'y':
497     case 'z':
498     case 'A':
499     case 'B':
500     case 'C':
501     case 'D':
502     case 'E':
503     case 'F':
504     case 'G':
505     case 'H':
506     case 'I':
507     case 'J':
508     case 'K':
509     case 'L':
510     case 'M':
511     case 'N':
512     case 'O':
513     case 'P':
514     case 'Q':
515     case 'R':
516     case 'S':
517     case 'T':
518     case 'U':
519     case 'V':
520     case 'W':
521     case 'X':
522     case 'Y':
523     case 'Z':
524     case '_':
525       /* Start of a token.  Parse. */
526       p = line;
527       *p++ = c;
528       c = GETC ();
529       while (ISL (c))
530         {
531           *p++ = c;
532           c = GETC ();
533         }
534       *p = '\0';
535       UNGETC (c);
536       return check_token (line);
537     case '0':
538     case '1':
539     case '2':
540     case '3':
541     case '4':
542     case '5':
543     case '6':
544     case '7':
545     case '8':
546     case '9':
547       p = line;
548       *p++ = c;
549       c = GETC ();
550       if (c == 'x' || c == 'X')
551         {
552           *p++ = c;
553           c = GETC ();
554         }
555       while (ISHEX (c))
556         {
557           *p++ = c;
558           c = GETC ();
559         }
560       if (c == 'U' || c == 'u' || c == 'L' || c == 'l')
561         {
562           *p++ = c;
563           c = GETC ();
564         }
565       if (c == 'U' || c == 'u' || c == 'L' || c == 'l')
566         {
567           *p++ = c;
568           c = GETC ();
569         }
570       *p = '\0';
571       UNGETC (c);
572       yylval.val = constVal (line);
573       return CONSTANT;
574     case '\"':
575       /* A string */
576       p = stringLiteral ();
577       yylval.val = strVal (p);
578       return (STRING_LITERAL);
579     case '\'':
580       /* Possible formats:
581          ['\n', '\\', '\'', '\"'...]
582          ['a'...]
583        */
584       p = line;
585       *p++ = c;
586       c = GETC ();
587       if (c == '\\')
588         {
589           *p++ = c;
590           c = GETC ();
591           /* Fall through */
592         }
593       *p++ = c;
594       c = GETC ();
595       *p++ = c;
596       *p = '\0';
597       if (c != '\'')
598         {
599           error ("Unrecognised character constant %s", line);
600         }
601       yylval.val = charVal (line);
602       return CONSTANT;
603     case '=':
604     case '&':
605     case '!':
606     case '-':
607     case '+':
608     case '*':
609     case '/':
610     case '%':
611     case '<':
612     case '>':
613     case '^':
614     case '|':
615       {
616         /* Cases which can be compounds */
617         /* The types and classes of composites are:
618            >>= <<=
619            += -= *= /= %= &= ^= |=
620            >> << ++ --
621            && ||
622            <= >= == !=
623            ->
624            So a composite started by char 'x' can be:
625            1. Followed by itself then an equals
626            2. Followed by itself
627            3. Followed by an equals
628            4. Be a '->'
629            5. Be by itself
630          */
631         int next = GETC ();
632         /* Class 1 and 2 */
633         if (next == c)
634           {
635             next = GETC ();
636             /* Class 1 */
637             if (next == '=')
638               {
639                 switch (c)
640                   {
641                   case '>':     // >>=
642
643                     yylval.yyint = RIGHT_ASSIGN;
644                     return RIGHT_ASSIGN;
645                   case '<':     // <<=
646
647                     yylval.yyint = LEFT_ASSIGN;
648                     return LEFT_ASSIGN;
649                   default:
650                     error ("Unrecognised token %c%c=", c, c);
651                   }
652               }
653             else
654               {
655                 /* Push the next char back on and find the class */
656                 UNGETC (next);
657                 /* Case 2 */
658                 switch (c)
659                   {
660                   case '>':     // >>
661
662                     return RIGHT_OP;
663                   case '<':     // <<
664
665                     return LEFT_OP;
666                   case '+':
667                     return INC_OP;
668                   case '-':
669                     return DEC_OP;
670                   case '&':
671                     return AND_OP;
672                   case '|':
673                     return OR_OP;
674                   case '=':
675                     return EQ_OP;
676                   default:
677                     error ("Unrecognised token %c%c", c, c);
678                   }
679               }
680           }
681         /* Case 3 */
682         else if (next == '=')
683           {
684             int result = 0;
685             switch (c)
686               {
687               case '+':
688                 result = ADD_ASSIGN;
689                 break;
690               case '-':
691                 result = SUB_ASSIGN;
692                 break;
693               case '*':
694                 result = MUL_ASSIGN;
695                 break;
696               case '/':
697                 result = DIV_ASSIGN;
698                 break;
699               case '%':
700                 result = MOD_ASSIGN;
701                 break;
702               case '&':
703                 result = AND_ASSIGN;
704                 break;
705               case '^':
706                 result = XOR_ASSIGN;
707                 break;
708               case '|':
709                 result = OR_ASSIGN;
710                 break;
711               case '<':
712                 result = LE_OP;
713                 break;
714               case '>':
715                 result = GE_OP;
716                 break;
717               case '!':
718                 result = NE_OP;
719                 break;
720               default:
721                 error ("Unrecognised token %c=", c);
722               }
723             if (result)
724               {
725                 yylval.yyint = result;
726                 return result;
727               }
728           }
729         /* Case 4 */
730         else if (c == '-' && next == '>')
731           {
732             return PTR_OP;
733           }
734         /* Case 5 */
735         else
736           {
737             UNGETC (next);
738             return c;
739           }
740         break;
741       }
742     case '{':
743       NestLevel++;
744       return c;
745     case '}':
746       NestLevel--;
747       return c;
748     case '.':
749       c = GETC ();
750       if (c == '.')
751         {
752           c = GETC ();
753           if (c == '.')
754             {
755               return VAR_ARGS;
756             }
757         }
758       UNGETC (c);
759       return '.';
760     case '[':
761     case ']':
762       return c;
763     case ',':
764     case ':':
765     case '(':
766     case ')':
767     case '~':
768     case '?':
769     case ';':
770       /* Special characters that cant be part of a composite */
771       return c;
772     default:
773       error ("Unhandled character %c", c);
774     }
775   return 0;
776 }
777
778 #define ENTRY(_a)       case (_a): printf(#_a); break;
779
780 int 
781 yylex (void)
782 {
783   int ret = _yylex ();
784 #if DUMP_OUTPUT
785   static int lastpos = 0;
786   char tmp;
787
788   printf ("Returning ");
789   switch (ret)
790     {
791       /* Wrapper */
792       ENTRY (IDENTIFIER);
793       ENTRY (TYPE_NAME);
794       ENTRY (CONSTANT);
795       ENTRY (STRING_LITERAL);
796       ENTRY (SIZEOF);
797       ENTRY (PTR_OP);
798       ENTRY (INC_OP);
799       ENTRY (DEC_OP);
800       ENTRY (LEFT_OP);
801       ENTRY (RIGHT_OP);
802       ENTRY (LE_OP);
803       ENTRY (GE_OP);
804       ENTRY (EQ_OP);
805       ENTRY (NE_OP);
806       ENTRY (AND_OP);
807       ENTRY (OR_OP);
808       ENTRY (MUL_ASSIGN);
809       ENTRY (DIV_ASSIGN);
810       ENTRY (MOD_ASSIGN);
811       ENTRY (ADD_ASSIGN);
812       ENTRY (SUB_ASSIGN);
813       ENTRY (LEFT_ASSIGN);
814       ENTRY (RIGHT_ASSIGN);
815       ENTRY (AND_ASSIGN);
816       ENTRY (XOR_ASSIGN);
817       ENTRY (OR_ASSIGN);
818       ENTRY (TYPEDEF);
819       ENTRY (EXTERN);
820       ENTRY (STATIC);
821       ENTRY (AUTO);
822       ENTRY (REGISTER);
823       ENTRY (CODE);
824       ENTRY (EEPROM);
825       ENTRY (INTERRUPT);
826       ENTRY (SFR);
827       ENTRY (AT);
828       ENTRY (SBIT);
829       ENTRY (REENTRANT);
830       ENTRY (USING);
831       ENTRY (XDATA);
832       ENTRY (DATA);
833       ENTRY (IDATA);
834       ENTRY (PDATA);
835       ENTRY (VAR_ARGS);
836       ENTRY (CRITICAL);
837       ENTRY (NONBANKED);
838       ENTRY (BANKED);
839       ENTRY (CHAR);
840       ENTRY (SHORT);
841       ENTRY (INT);
842       ENTRY (LONG);
843       ENTRY (SIGNED);
844       ENTRY (UNSIGNED);
845       ENTRY (FLOAT);
846       ENTRY (DOUBLE);
847       ENTRY (CONST);
848       ENTRY (VOLATILE);
849       ENTRY (VOID);
850       ENTRY (BIT);
851       ENTRY (STRUCT);
852       ENTRY (UNION);
853       ENTRY (ENUM);
854       ENTRY (ELIPSIS);
855       ENTRY (RANGE);
856       ENTRY (FAR);
857       ENTRY (_XDATA);
858       ENTRY (_CODE);
859       ENTRY (_GENERIC);
860       ENTRY (_NEAR);
861       ENTRY (_PDATA);
862       ENTRY (_IDATA);
863       ENTRY (_EEPROM);
864       ENTRY (CASE);
865       ENTRY (DEFAULT);
866       ENTRY (IF);
867       ENTRY (ELSE);
868       ENTRY (SWITCH);
869       ENTRY (WHILE);
870       ENTRY (DO);
871       ENTRY (FOR);
872       ENTRY (GOTO);
873       ENTRY (CONTINUE);
874       ENTRY (BREAK);
875       ENTRY (RETURN);
876       ENTRY (INLINEASM);
877       ENTRY (IFX);
878       ENTRY (ADDRESS_OF);
879       ENTRY (GET_VALUE_AT_ADDRESS);
880       ENTRY (SPIL);
881       ENTRY (UNSPIL);
882       ENTRY (GETHBIT);
883       ENTRY (BITWISEAND);
884       ENTRY (UNARYMINUS);
885       ENTRY (IPUSH);
886       ENTRY (IPOP);
887       ENTRY (PCALL);
888       ENTRY (ENDFUNCTION);
889       ENTRY (JUMPTABLE);
890       ENTRY (RRC);
891       ENTRY (RLC);
892       ENTRY (CAST);
893       ENTRY (CALL);
894       ENTRY (PARAM);
895       ENTRY (NULLOP);
896       ENTRY (BLOCK);
897       ENTRY (LABEL);
898       ENTRY (RECEIVE);
899       ENTRY (SEND);
900     default:
901       printf ("default: %c", ret);
902     }
903   tmp = linebuf[linepos];
904   linebuf[linepos] = '\0';
905   printf (" for %s (%u bytes)\n", linebuf + lastpos, linepos - lastpos);
906   linebuf[linepos] = tmp;
907   lastpos = linepos;
908   fflush (stdout);
909 #endif
910   return ret;
911 }
912
913 #define TEST(_a)        (_a) ? (void)0 : printf("Test %s failed\n", #_a);
914
915 int 
916 altlex_testparse (const char *input)
917 {
918   /* Fiddle with the read-ahead buffer to insert ourselves */
919   strcpy (linebuf, input);
920   linelen = strlen (linebuf) + 1;
921   linepos = 0;
922
923   return yylex ();
924 }
925
926 int 
927 altlex_testchar (const char *input)
928 {
929   value *val;
930   if (altlex_testparse (input) != CONSTANT)
931     return -2;
932   val = yylval.val;
933   if (val->type->class != SPECIFIER)
934     return -3;
935   if (SPEC_NOUN (val->type) != V_CHAR)
936     return -4;
937   if (SPEC_SCLS (val->type) != S_LITERAL)
938     return -5;
939   return SPEC_CVAL (val->type).v_int;
940 }
941
942 int 
943 altlex_testnum (const char *input)
944 {
945   value *val;
946   if (altlex_testparse (input) != CONSTANT)
947     return -2;
948   val = yylval.val;
949   if (val->type->class != SPECIFIER)
950     return -3;
951   if (SPEC_NOUN (val->type) != V_INT)
952     return -4;
953   if (SPEC_SCLS (val->type) != S_LITERAL)
954     return -5;
955   if (SPEC_USIGN (val->type))
956     return SPEC_CVAL (val->type).v_uint;
957   else
958     return SPEC_CVAL (val->type).v_int;
959 }
960
961 int 
962 altlex_runtests (void)
963 {
964   /* These conditions are ripped directly from SDCC.lex */
965   /* First check the parsing of the basic tokens */
966   TEST (altlex_testparse (">>=") == RIGHT_ASSIGN);
967   TEST (altlex_testparse ("<<=") == LEFT_ASSIGN);
968   TEST (altlex_testparse ("+=") == ADD_ASSIGN);
969   TEST (altlex_testparse ("-=") == SUB_ASSIGN);
970   TEST (altlex_testparse ("*=") == MUL_ASSIGN);
971   TEST (altlex_testparse ("/=") == DIV_ASSIGN);
972   TEST (altlex_testparse ("%=") == MOD_ASSIGN);
973   TEST (altlex_testparse ("&=") == AND_ASSIGN);
974   TEST (altlex_testparse ("^=") == XOR_ASSIGN);
975   TEST (altlex_testparse ("|=") == OR_ASSIGN);
976   TEST (altlex_testparse (">>") == RIGHT_OP);
977   TEST (altlex_testparse ("<<") == LEFT_OP);
978   TEST (altlex_testparse ("++") == INC_OP);
979   TEST (altlex_testparse ("--") == DEC_OP);
980   TEST (altlex_testparse ("->") == PTR_OP);
981   TEST (altlex_testparse ("&&") == AND_OP);
982   TEST (altlex_testparse ("||") == OR_OP);
983   TEST (altlex_testparse ("<=") == LE_OP);
984   TEST (altlex_testparse (">=") == GE_OP);
985   TEST (altlex_testparse ("==") == EQ_OP);
986   TEST (altlex_testparse ("!=") == NE_OP);
987   TEST (altlex_testparse (";") == ';');
988   TEST (altlex_testparse ("{") == '{');
989   TEST (altlex_testparse ("}") == '}');
990   TEST (altlex_testparse (",") == ',');
991   TEST (altlex_testparse (":") == ':');
992   TEST (altlex_testparse ("=") == '=');
993   TEST (altlex_testparse ("(") == '(');
994   TEST (altlex_testparse (")") == ')');
995   TEST (altlex_testparse ("[") == '[');
996   TEST (altlex_testparse ("]") == ']');
997   TEST (altlex_testparse (".") == '.');
998   TEST (altlex_testparse ("&") == '&');
999   TEST (altlex_testparse ("!") == '!');
1000   TEST (altlex_testparse ("~") == '~');
1001   TEST (altlex_testparse ("-") == '-');
1002   TEST (altlex_testparse ("+") == '+');
1003   TEST (altlex_testparse ("*") == '*');
1004   TEST (altlex_testparse ("/") == '/');
1005   TEST (altlex_testparse ("%") == '%');
1006   TEST (altlex_testparse ("<") == '<');
1007   TEST (altlex_testparse (">") == '>');
1008   TEST (altlex_testparse ("^") == '^');
1009   TEST (altlex_testparse ("|") == '|');
1010   TEST (altlex_testparse ("?") == '?');
1011
1012   /* Now some character constants */
1013   TEST (altlex_testchar ("'1'") == '1');
1014   TEST (altlex_testchar ("'a'") == 'a');
1015   TEST (altlex_testchar ("'A'") == 'A');
1016   TEST (altlex_testchar ("'z'") == 'z');
1017   TEST (altlex_testchar ("'Z'") == 'Z');
1018   TEST (altlex_testchar ("'\n'") == '\n');
1019   TEST (altlex_testchar ("'\\\\'") == '\\');
1020   TEST (altlex_testchar ("'\\''") == '\'');
1021
1022   /* And some numbers */
1023   TEST (altlex_testnum ("0") == 0);
1024   TEST (altlex_testnum ("1") == 1);
1025   TEST (altlex_testnum ("075") == 075);
1026   TEST (altlex_testnum ("0xfeed") == 0xfeed);
1027   TEST (altlex_testnum ("0xFEED") == 0xFEED);
1028   TEST (altlex_testnum ("0x00005678") == 0x5678);
1029
1030   /* Keywords */
1031   TEST (altlex_testparse ("auto") == AUTO);
1032   TEST (altlex_testparse ("break") == BREAK);
1033   TEST (altlex_testparse ("case") == CASE);
1034   TEST (altlex_testparse ("char") == CHAR);
1035   TEST (altlex_testparse ("const") == CONST);
1036   TEST (altlex_testparse ("continue") == CONTINUE);
1037   TEST (altlex_testparse ("default") == DEFAULT);
1038   TEST (altlex_testparse ("do") == DO);
1039   /* Prints a warning */
1040   //    TEST(altlex_testparse("double") == FLOAT);
1041   TEST (altlex_testparse ("else") == ELSE);
1042   TEST (altlex_testparse ("enum") == ENUM);
1043   TEST (altlex_testparse ("extern") == EXTERN);
1044   TEST (altlex_testparse ("float") == FLOAT);
1045   TEST (altlex_testparse ("for") == FOR);
1046   TEST (altlex_testparse ("goto") == GOTO);
1047   TEST (altlex_testparse ("if") == IF);
1048   TEST (altlex_testparse ("int") == INT);
1049   TEST (altlex_testparse ("interrupt") == INTERRUPT);
1050   TEST (altlex_testparse ("long") == LONG);
1051   TEST (altlex_testparse ("register") == REGISTER);
1052   TEST (altlex_testparse ("return") == RETURN);
1053   TEST (altlex_testparse ("short") == SHORT);
1054   TEST (altlex_testparse ("signed") == SIGNED);
1055   TEST (altlex_testparse ("sizeof") == SIZEOF);
1056   TEST (altlex_testparse ("static") == STATIC);
1057   TEST (altlex_testparse ("struct") == STRUCT);
1058   TEST (altlex_testparse ("switch") == SWITCH);
1059   TEST (altlex_testparse ("typedef") == TYPEDEF);
1060   TEST (altlex_testparse ("union") == UNION);
1061   TEST (altlex_testparse ("unsigned") == UNSIGNED);
1062   TEST (altlex_testparse ("void") == VOID);
1063   TEST (altlex_testparse ("volatile") == VOLATILE);
1064   TEST (altlex_testparse ("while") == WHILE);
1065   TEST (altlex_testparse ("...") == VAR_ARGS);
1066
1067 #if 0
1068   /* Platform specific keywords */
1069   TEST (altlex_testparse ("sram") ==)
1070   {
1071     count ();
1072     TKEYWORD (XDATA);
1073   }
1074   TEST (altlex_testparse ("using") ==)
1075   {
1076     count ();
1077     TKEYWORD (USING);
1078   }
1079   TEST (altlex_testparse ("near") ==)
1080   {
1081     count ();
1082     TKEYWORD (DATA);
1083   }
1084   TEST (altlex_testparse ("at") ==)
1085   {
1086     count ();
1087     TKEYWORD (AT);
1088   }
1089   TEST (altlex_testparse ("bit") ==)
1090   {
1091     count ();
1092     TKEYWORD (BIT);
1093   }
1094   TEST (altlex_testparse ("code") ==)
1095   {
1096     count ();
1097     TKEYWORD (CODE);
1098   }
1099   TEST (altlex_testparse ("critical") ==)
1100   {
1101     count ();
1102     TKEYWORD (CRITICAL);
1103   }
1104   TEST (altlex_testparse ("data") ==)
1105   {
1106     count ();
1107     TKEYWORD (DATA);
1108   }
1109   TEST (altlex_testparse ("far") ==)
1110   {
1111     count ();
1112     TKEYWORD (XDATA);
1113   }
1114   TEST (altlex_testparse ("eeprom") ==)
1115   {
1116     count ();
1117     TKEYWORD (EEPROM);
1118   }
1119   TEST (altlex_testparse ("flash") ==)
1120   {
1121     count ();
1122     TKEYWORD (CODE);
1123   }
1124   TEST (altlex_testparse ("idata") ==)
1125   {
1126     count ();
1127     TKEYWORD (IDATA);
1128   }
1129   TEST (altlex_testparse ("nonbanked") ==)
1130   {
1131     count ();
1132     TKEYWORD (NONBANKED);
1133   }
1134   TEST (altlex_testparse ("banked") ==)
1135   {
1136     count ();
1137     TKEYWORD (BANKED);
1138   }
1139   TEST (altlex_testparse ("pdata") ==)
1140   {
1141     count ();
1142     TKEYWORD (PDATA);
1143   }
1144   TEST (altlex_testparse ("reentrant") ==)
1145   {
1146     count ();
1147     TKEYWORD (REENTRANT);
1148   }
1149   TEST (altlex_testparse ("sfr") ==)
1150   {
1151     count ();
1152     TKEYWORD (SFR);
1153   }
1154   TEST (altlex_testparse ("sbit") ==)
1155   {
1156     count ();
1157     TKEYWORD (SBIT);
1158   }
1159   TEST (altlex_testparse ("xdata") ==)
1160   {
1161     count ();
1162     TKEYWORD (XDATA);
1163   }
1164   TEST (altlex_testparse ("_data") ==)
1165   {
1166     count ();
1167     TKEYWORD (_NEAR);
1168   }
1169   TEST (altlex_testparse ("_code") ==)
1170   {
1171     count ();
1172     TKEYWORD (_CODE);
1173   }
1174   TEST (altlex_testparse ("_eeprom") ==)
1175   {
1176     count ();
1177     TKEYWORD (_EEPROM);
1178   }
1179   TEST (altlex_testparse ("_flash") ==)
1180   {
1181     count ();
1182     TKEYWORD (_CODE);
1183   }
1184   TEST (altlex_testparse ("_generic") ==)
1185   {
1186     count ();
1187     TKEYWORD (_GENERIC);
1188   }
1189   TEST (altlex_testparse ("_near") ==)
1190   {
1191     count ();
1192     TKEYWORD (_NEAR);
1193   }
1194   TEST (altlex_testparse ("_sram") ==)
1195   {
1196     count ();
1197     TKEYWORD (_XDATA);
1198   }
1199   TEST (altlex_testparse ("_xdata") ==)
1200   {
1201     count ();
1202     TKEYWORD (_XDATA);
1203   }
1204   TEST (altlex_testparse ("_pdata") ==)
1205   {
1206     count ();
1207     TKEYWORD (_PDATA);
1208   }
1209   TEST (altlex_testparse ("_idata") ==)
1210   {
1211     count ();
1212     TKEYWORD (_IDATA);
1213   }
1214 #endif
1215
1216   return 0;
1217 }