Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[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 mylineno;
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       strncpyz (yylval.yychar, sz, sizeof(yylval.yychar));
238       return TYPE_NAME;
239     }
240   else
241     {
242       strncpyz (yylval.yychar, sz, sizeof(yylval.yychar));
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   mylineno = atoi (line) - 3;
296   lineno = mylineno;
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   mylineno++;
329   lineno = mylineno;
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 (FIXED16X16);
847       ENTRY (DOUBLE);
848       ENTRY (CONST);
849       ENTRY (VOLATILE);
850       ENTRY (VOID);
851       ENTRY (BIT);
852       ENTRY (STRUCT);
853       ENTRY (UNION);
854       ENTRY (ENUM);
855       ENTRY (ELIPSIS);
856       ENTRY (RANGE);
857       ENTRY (FAR);
858       ENTRY (_XDATA);
859       ENTRY (_CODE);
860       ENTRY (_GENERIC);
861       ENTRY (_NEAR);
862       ENTRY (_PDATA);
863       ENTRY (_IDATA);
864       ENTRY (_EEPROM);
865       ENTRY (CASE);
866       ENTRY (DEFAULT);
867       ENTRY (IF);
868       ENTRY (ELSE);
869       ENTRY (SWITCH);
870       ENTRY (WHILE);
871       ENTRY (DO);
872       ENTRY (FOR);
873       ENTRY (GOTO);
874       ENTRY (CONTINUE);
875       ENTRY (BREAK);
876       ENTRY (RETURN);
877       ENTRY (INLINEASM);
878       ENTRY (IFX);
879       ENTRY (ADDRESS_OF);
880       ENTRY (GET_VALUE_AT_ADDRESS);
881       ENTRY (SPIL);
882       ENTRY (UNSPIL);
883       ENTRY (GETHBIT);
884       ENTRY (BITWISEAND);
885       ENTRY (UNARYMINUS);
886       ENTRY (IPUSH);
887       ENTRY (IPOP);
888       ENTRY (PCALL);
889       ENTRY (ENDFUNCTION);
890       ENTRY (JUMPTABLE);
891       ENTRY (RRC);
892       ENTRY (RLC);
893       ENTRY (CAST);
894       ENTRY (CALL);
895       ENTRY (PARAM);
896       ENTRY (NULLOP);
897       ENTRY (BLOCK);
898       ENTRY (LABEL);
899       ENTRY (RECEIVE);
900       ENTRY (SEND);
901     default:
902       printf ("default: %c", ret);
903     }
904   tmp = linebuf[linepos];
905   linebuf[linepos] = '\0';
906   printf (" for %s (%u bytes)\n", linebuf + lastpos, linepos - lastpos);
907   linebuf[linepos] = tmp;
908   lastpos = linepos;
909   fflush (stdout);
910 #endif
911   return ret;
912 }
913
914 #define TEST(_a)        (_a) ? (void)0 : printf("Test %s failed\n", #_a);
915
916 int 
917 altlex_testparse (const char *input)
918 {
919   /* Fiddle with the read-ahead buffer to insert ourselves */
920   strncpyz (linebuf, input, sizeof(linebuf));
921   linelen = strlen (linebuf) + 1;
922   linepos = 0;
923
924   return yylex ();
925 }
926
927 int 
928 altlex_testchar (const char *input)
929 {
930   value *val;
931   if (altlex_testparse (input) != CONSTANT)
932     return -2;
933   val = yylval.val;
934   if (val->type->class != SPECIFIER)
935     return -3;
936   if (SPEC_NOUN (val->type) != V_CHAR)
937     return -4;
938   if (SPEC_SCLS (val->type) != S_LITERAL)
939     return -5;
940   return SPEC_CVAL (val->type).v_int;
941 }
942
943 int 
944 altlex_testnum (const char *input)
945 {
946   value *val;
947   if (altlex_testparse (input) != CONSTANT)
948     return -2;
949   val = yylval.val;
950   if (val->type->class != SPECIFIER)
951     return -3;
952   if (SPEC_NOUN (val->type) != V_INT)
953     return -4;
954   if (SPEC_SCLS (val->type) != S_LITERAL)
955     return -5;
956   if (SPEC_USIGN (val->type))
957     return SPEC_CVAL (val->type).v_uint;
958   else
959     return SPEC_CVAL (val->type).v_int;
960 }
961
962 int 
963 altlex_runtests (void)
964 {
965   /* These conditions are ripped directly from SDCC.lex */
966   /* First check the parsing of the basic tokens */
967   TEST (altlex_testparse (">>=") == RIGHT_ASSIGN);
968   TEST (altlex_testparse ("<<=") == LEFT_ASSIGN);
969   TEST (altlex_testparse ("+=") == ADD_ASSIGN);
970   TEST (altlex_testparse ("-=") == SUB_ASSIGN);
971   TEST (altlex_testparse ("*=") == MUL_ASSIGN);
972   TEST (altlex_testparse ("/=") == DIV_ASSIGN);
973   TEST (altlex_testparse ("%=") == MOD_ASSIGN);
974   TEST (altlex_testparse ("&=") == AND_ASSIGN);
975   TEST (altlex_testparse ("^=") == XOR_ASSIGN);
976   TEST (altlex_testparse ("|=") == OR_ASSIGN);
977   TEST (altlex_testparse (">>") == RIGHT_OP);
978   TEST (altlex_testparse ("<<") == LEFT_OP);
979   TEST (altlex_testparse ("++") == INC_OP);
980   TEST (altlex_testparse ("--") == DEC_OP);
981   TEST (altlex_testparse ("->") == PTR_OP);
982   TEST (altlex_testparse ("&&") == AND_OP);
983   TEST (altlex_testparse ("||") == OR_OP);
984   TEST (altlex_testparse ("<=") == LE_OP);
985   TEST (altlex_testparse (">=") == GE_OP);
986   TEST (altlex_testparse ("==") == EQ_OP);
987   TEST (altlex_testparse ("!=") == NE_OP);
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   TEST (altlex_testparse ("?") == '?');
1012
1013   /* Now some character constants */
1014   TEST (altlex_testchar ("'1'") == '1');
1015   TEST (altlex_testchar ("'a'") == 'a');
1016   TEST (altlex_testchar ("'A'") == 'A');
1017   TEST (altlex_testchar ("'z'") == 'z');
1018   TEST (altlex_testchar ("'Z'") == 'Z');
1019   TEST (altlex_testchar ("'\n'") == '\n');
1020   TEST (altlex_testchar ("'\\\\'") == '\\');
1021   TEST (altlex_testchar ("'\\''") == '\'');
1022
1023   /* And some numbers */
1024   TEST (altlex_testnum ("0") == 0);
1025   TEST (altlex_testnum ("1") == 1);
1026   TEST (altlex_testnum ("075") == 075);
1027   TEST (altlex_testnum ("0xfeed") == 0xfeed);
1028   TEST (altlex_testnum ("0xFEED") == 0xFEED);
1029   TEST (altlex_testnum ("0x00005678") == 0x5678);
1030
1031   /* Keywords */
1032   TEST (altlex_testparse ("auto") == AUTO);
1033   TEST (altlex_testparse ("break") == BREAK);
1034   TEST (altlex_testparse ("case") == CASE);
1035   TEST (altlex_testparse ("char") == CHAR);
1036   TEST (altlex_testparse ("const") == CONST);
1037   TEST (altlex_testparse ("continue") == CONTINUE);
1038   TEST (altlex_testparse ("default") == DEFAULT);
1039   TEST (altlex_testparse ("do") == DO);
1040   /* Prints a warning */
1041   //    TEST(altlex_testparse("double") == FLOAT);
1042   TEST (altlex_testparse ("else") == ELSE);
1043   TEST (altlex_testparse ("enum") == ENUM);
1044   TEST (altlex_testparse ("extern") == EXTERN);
1045   TEST (altlex_testparse ("float") == FLOAT);
1046   TEST (altlex_testparse ("fixed16x16") == FIXED16X16);
1047   TEST (altlex_testparse ("for") == FOR);
1048   TEST (altlex_testparse ("goto") == GOTO);
1049   TEST (altlex_testparse ("if") == IF);
1050   TEST (altlex_testparse ("int") == INT);
1051   TEST (altlex_testparse ("interrupt") == INTERRUPT);
1052   TEST (altlex_testparse ("long") == LONG);
1053   TEST (altlex_testparse ("register") == REGISTER);
1054   TEST (altlex_testparse ("return") == RETURN);
1055   TEST (altlex_testparse ("short") == SHORT);
1056   TEST (altlex_testparse ("signed") == SIGNED);
1057   TEST (altlex_testparse ("sizeof") == SIZEOF);
1058   TEST (altlex_testparse ("static") == STATIC);
1059   TEST (altlex_testparse ("struct") == STRUCT);
1060   TEST (altlex_testparse ("switch") == SWITCH);
1061   TEST (altlex_testparse ("typedef") == TYPEDEF);
1062   TEST (altlex_testparse ("union") == UNION);
1063   TEST (altlex_testparse ("unsigned") == UNSIGNED);
1064   TEST (altlex_testparse ("void") == VOID);
1065   TEST (altlex_testparse ("volatile") == VOLATILE);
1066   TEST (altlex_testparse ("while") == WHILE);
1067   TEST (altlex_testparse ("...") == VAR_ARGS);
1068
1069 #if 0
1070   /* Platform specific keywords */
1071   TEST (altlex_testparse ("sram") ==)
1072   {
1073     count ();
1074     TKEYWORD (XDATA);
1075   }
1076   TEST (altlex_testparse ("using") ==)
1077   {
1078     count ();
1079     TKEYWORD (USING);
1080   }
1081   TEST (altlex_testparse ("near") ==)
1082   {
1083     count ();
1084     TKEYWORD (DATA);
1085   }
1086   TEST (altlex_testparse ("at") ==)
1087   {
1088     count ();
1089     TKEYWORD (AT);
1090   }
1091   TEST (altlex_testparse ("bit") ==)
1092   {
1093     count ();
1094     TKEYWORD (BIT);
1095   }
1096   TEST (altlex_testparse ("code") ==)
1097   {
1098     count ();
1099     TKEYWORD (CODE);
1100   }
1101   TEST (altlex_testparse ("critical") ==)
1102   {
1103     count ();
1104     TKEYWORD (CRITICAL);
1105   }
1106   TEST (altlex_testparse ("data") ==)
1107   {
1108     count ();
1109     TKEYWORD (DATA);
1110   }
1111   TEST (altlex_testparse ("far") ==)
1112   {
1113     count ();
1114     TKEYWORD (XDATA);
1115   }
1116   TEST (altlex_testparse ("eeprom") ==)
1117   {
1118     count ();
1119     TKEYWORD (EEPROM);
1120   }
1121   TEST (altlex_testparse ("flash") ==)
1122   {
1123     count ();
1124     TKEYWORD (CODE);
1125   }
1126   TEST (altlex_testparse ("idata") ==)
1127   {
1128     count ();
1129     TKEYWORD (IDATA);
1130   }
1131   TEST (altlex_testparse ("nonbanked") ==)
1132   {
1133     count ();
1134     TKEYWORD (NONBANKED);
1135   }
1136   TEST (altlex_testparse ("banked") ==)
1137   {
1138     count ();
1139     TKEYWORD (BANKED);
1140   }
1141   TEST (altlex_testparse ("pdata") ==)
1142   {
1143     count ();
1144     TKEYWORD (PDATA);
1145   }
1146   TEST (altlex_testparse ("reentrant") ==)
1147   {
1148     count ();
1149     TKEYWORD (REENTRANT);
1150   }
1151   TEST (altlex_testparse ("sfr") ==)
1152   {
1153     count ();
1154     TKEYWORD (SFR);
1155   }
1156   TEST (altlex_testparse ("sbit") ==)
1157   {
1158     count ();
1159     TKEYWORD (SBIT);
1160   }
1161   TEST (altlex_testparse ("xdata") ==)
1162   {
1163     count ();
1164     TKEYWORD (XDATA);
1165   }
1166   TEST (altlex_testparse ("_data") ==)
1167   {
1168     count ();
1169     TKEYWORD (_NEAR);
1170   }
1171   TEST (altlex_testparse ("_code") ==)
1172   {
1173     count ();
1174     TKEYWORD (_CODE);
1175   }
1176   TEST (altlex_testparse ("_eeprom") ==)
1177   {
1178     count ();
1179     TKEYWORD (_EEPROM);
1180   }
1181   TEST (altlex_testparse ("_flash") ==)
1182   {
1183     count ();
1184     TKEYWORD (_CODE);
1185   }
1186   TEST (altlex_testparse ("_generic") ==)
1187   {
1188     count ();
1189     TKEYWORD (_GENERIC);
1190   }
1191   TEST (altlex_testparse ("_near") ==)
1192   {
1193     count ();
1194     TKEYWORD (_NEAR);
1195   }
1196   TEST (altlex_testparse ("_sram") ==)
1197   {
1198     count ();
1199     TKEYWORD (_XDATA);
1200   }
1201   TEST (altlex_testparse ("_xdata") ==)
1202   {
1203     count ();
1204     TKEYWORD (_XDATA);
1205   }
1206   TEST (altlex_testparse ("_pdata") ==)
1207   {
1208     count ();
1209     TKEYWORD (_PDATA);
1210   }
1211   TEST (altlex_testparse ("_idata") ==)
1212   {
1213     count ();
1214     TKEYWORD (_IDATA);
1215   }
1216 #endif
1217
1218   return 0;
1219 }