fixed small dumping issue
[swftools.git] / lib / as3 / tokenizer.lex
1 /* tokenizer.lex
2
3    Routines for compiling Flash2 AVM2 ABC Actionscript
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
9  
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
23 %{
24
25
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include "../utf8.h"
31 #include "tokenizer.h"
32 #include "files.h"
33
34 int as3_verbosity = 1;
35 void as3_error(const char*format, ...)
36 {
37     char buf[1024];
38     int l;
39     va_list arglist;
40     if(as3_verbosity<0)
41         exit(1);
42     va_start(arglist, format);
43     vsprintf(buf, format, arglist);
44     va_end(arglist);
45     fprintf(stderr, "%s:%d:%d: error: %s\n", current_filename_short, current_line, current_column, buf);
46     fflush(stderr);
47     exit(1);
48 }
49 void as3_warning(const char*format, ...)
50 {
51     char buf[1024];
52     int l;
53     va_list arglist;
54     if(as3_verbosity<1)
55         return;
56     va_start(arglist, format);
57     vsprintf(buf, format, arglist);
58     va_end(arglist);
59     fprintf(stderr, "%s:%d:%d: warning: %s\n", current_filename_short, current_line, current_column, buf);
60     fflush(stderr);
61 }
62 void as3_softwarning(const char*format, ...)
63 {
64     char buf[1024];
65     int l;
66     va_list arglist;
67     if(as3_verbosity<2)
68         return;
69     va_start(arglist, format);
70     vsprintf(buf, format, arglist);
71     va_end(arglist);
72     fprintf(stderr, "%s:%d:%d: warning: %s\n", current_filename_short, current_line, current_column, buf);
73     fflush(stderr);
74 }
75 static void dbg(const char*format, ...)
76 {
77     char buf[1024];
78     int l;
79     va_list arglist;
80     if(as3_verbosity<3)
81         return;
82     va_start(arglist, format);
83     vsprintf(buf, format, arglist);
84     va_end(arglist);
85     l = strlen(buf);
86     while(l && buf[l-1]=='\n') {
87         buf[l-1] = 0;
88         l--;
89     }
90     printf("(tokenizer) ");
91     printf("%s\n", buf);
92     fflush(stdout);
93 }
94
95
96
97 #ifndef YY_CURRENT_BUFFER
98 #define YY_CURRENT_BUFFER yy_current_buffer
99 #endif
100
101 void handleInclude(char*text, int len, char quotes)
102 {
103     char*filename = 0;
104     if(quotes) {
105         char*p1 = strchr(text, '"');
106         char*p2 = strrchr(text, '"');
107         if(!p1 || !p2 || p1==p2) {
108             syntaxerror("Invalid include in line %d\n", current_line);
109         }
110         *p2 = 0;
111         filename = strdup(p1+1);
112     } else {
113         int i1=0,i2=len;
114         // find start
115         while(!strchr(" \n\r\t", text[i1])) i1++;
116         // strip
117         while(strchr(" \n\r\t", text[i1])) i1++;
118         while(strchr(" \n\r\t", text[i2-1])) i2--;
119         if(i2!=len) text[i2]=0;
120         filename = strdup(&text[i1]);
121     }
122     
123     char*fullfilename = enter_file(filename, YY_CURRENT_BUFFER);
124     yyin = fopen(fullfilename, "rb");
125     if (!yyin) {
126         syntaxerror("Couldn't open include file \"%s\"\n", fullfilename);
127     }
128
129     yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
130     //BEGIN(INITIAL); keep context
131 }
132
133 static int do_unescape(const char*s, const char*end, char*n) 
134 {
135     char*o = n;
136     int len=0;
137     while(s<end) {
138         if(*s!='\\') {
139             if(o) o[len] = *s;len++;
140             s++;
141             continue;
142         }
143         s++; //skip past '\'
144         if(s==end) syntaxerror("invalid \\ at end of string");
145
146         /* handle the various line endings (mac, dos, unix) */
147         if(*s=='\r') { 
148             s++; 
149             if(s==end) break;
150             if(*s=='\n') 
151                 s++;
152             continue;
153         }
154         if(*s=='\n')  {
155             s++;
156             continue;
157         }
158         switch(*s) {
159             case '\\': if(o) o[len] = '\\';s++;len++; break;
160             case '"': if(o) o[len] = '"';s++;len++; break;
161             case '\'': if(o) o[len] = '\'';s++;len++; break;
162             case 'b': if(o) o[len] = '\b';s++;len++; break;
163             case 'f': if(o) o[len] = '\f';s++;len++; break;
164             case 'n': if(o) o[len] = '\n';s++;len++; break;
165             case 'r': if(o) o[len] = '\r';s++;len++; break;
166             case 't': if(o) o[len] = '\t';s++;len++; break;
167             case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': {
168                 unsigned int num=0;
169                 int nr = 0;
170                 while(strchr("01234567", *s) && nr<3 && s<end) {
171                     num <<= 3;
172                     num |= *s-'0';
173                     nr++;
174                     s++;
175                 }
176                 if(num>256) 
177                     syntaxerror("octal number out of range (0-255): %d", num);
178                 if(o) o[len] = num;len++;
179                 continue;
180             }
181             case 'x': case 'u': {
182                 int max=2;
183                 char bracket = 0;
184                 char unicode = 0;
185                 if(*s == 'u') {
186                     max = 6;
187                     unicode = 1;
188                 }
189                 s++;
190                 if(s==end) syntaxerror("invalid \\u or \\x at end of string");
191                 if(*s == '{')  {
192                     s++;
193                     if(s==end) syntaxerror("invalid \\u{ at end of string");
194                     bracket=1;
195                 }
196                 unsigned int num=0;
197                 int nr = 0;
198                 while(strchr("0123456789abcdefABCDEF", *s) && (bracket || nr < max) && s<end) {
199                     num <<= 4;
200                     if(*s>='0' && *s<='9') num |= *s - '0';
201                     if(*s>='a' && *s<='f') num |= *s - 'a' + 10;
202                     if(*s>='A' && *s<='F') num |= *s - 'A' + 10;
203                     nr++;
204                     s++;
205                 }
206                 if(bracket) {
207                     if(*s=='}' && s<end) {
208                         s++;
209                     } else {
210                         syntaxerror("missing terminating '}'");
211                     }
212                 }
213                 if(unicode) {
214                     char*utf8 = getUTF8(num);
215                     while(*utf8) {
216                         if(o) o[len] = *utf8;utf8++;len++;
217                     }
218                 } else {
219                     if(num>256) 
220                         syntaxerror("byte out of range (0-255): %d", num);
221                     if(o) o[len] = num;len++;
222                 }
223                 break;
224             }
225             default:
226                 syntaxerror("unknown escape sequence: \"\\%c\"", *s);
227         }
228     }
229     if(o) o[len]=0;
230     return len;
231 }
232
233 static string_t string_unescape(const char*in, int l)
234 {
235     const char*s = in;
236     const char*end = &in[l];
237
238     int len = do_unescape(s, end, 0);
239     char*n = (char*)malloc(len+1);
240     do_unescape(s, end, n);
241     string_t out = string_new(n, len);
242     return out; 
243 }
244
245 static void handleString(char*s, int len)
246 {
247     if(s[0]=='"') {
248         if(s[len-1]!='"') syntaxerror("String doesn't end with '\"'");
249         s++;len-=2;
250     }
251     else if(s[0]=='\'') {
252         if(s[len-1]!='\'') syntaxerror("String doesn't end with '\"'");
253         s++;len-=2;
254     }
255     else syntaxerror("String incorrectly terminated");
256
257     
258     avm2_lval.str = string_unescape(s, len);
259 }
260
261
262 char start_of_expression;
263
264 static inline int mkid(int type)
265 {
266     char*s = malloc(yyleng+1);
267     memcpy(s, yytext, yyleng);
268     s[yyleng]=0;
269     avm2_lval.id = s;
270     return type;
271 }
272
273 static inline int m(int type)
274 {
275     avm2_lval.token = type;
276     return type;
277 }
278
279
280 static char numberbuf[64];
281 static char*nrbuf()
282 {
283     if(yyleng>sizeof(numberbuf)-1)
284         syntaxerror("decimal number overflow");
285     char*s = numberbuf;
286     memcpy(s, yytext, yyleng);
287     s[yyleng]=0;
288     return s;
289 }
290
291 static inline int setint(int v)
292 {
293     avm2_lval.number_int = v;
294     if(v>-128)
295         return T_BYTE;
296     else if(v>=-32768)
297         return T_SHORT;
298     else
299         return T_INT;
300 }
301 static inline int setuint(unsigned int v)
302 {
303     avm2_lval.number_uint = v;
304     if(v<128)
305         return T_BYTE;
306     else if(v<32768)
307         return T_SHORT;
308     else
309         return T_UINT;
310 }
311 static inline int setfloat(double v)
312 {
313     avm2_lval.number_float = v;
314     return T_FLOAT;
315 }
316
317 static inline int handlefloat()
318 {
319     char*s = nrbuf();
320     avm2_lval.number_float = atof(s);
321     return T_FLOAT;
322 }
323
324 static inline int handleint()
325 {
326     char*s = nrbuf();
327     char l = (yytext[0]=='-');
328
329     char*max = l?"1073741824":"2147483647";
330     if(yyleng-l>10) {
331         as3_warning("integer overflow: %s (converted to Number)", s);
332         return handlefloat();
333     }
334     if(yyleng-l==10) {
335         int t;
336         for(t=0;t<yyleng-l;t++) {
337             if(yytext[l+t]>max[t]) {
338                 as3_warning("integer overflow: %s (converted to Number)", s);
339                 return handlefloat();
340             }
341             else if(yytext[l+t]<max[t])
342                 break;
343         }
344     }
345     if(yytext[0]=='-') {
346         int v = atoi(s);
347         return setint(v);
348     } else {
349         unsigned int v = 0;
350         int t;
351         for(t=0;t<yyleng;t++) {
352             v*=10;
353             v+=yytext[t]-'0';
354         }
355         return setuint(v);
356     }
357 }
358
359 static inline int handlehexfloat()
360 {
361     char l = (yytext[0]=='-')+2;
362     double d=0;
363     char dot=0;
364     double base=1;
365     int t;
366     for(t=l;t<yyleng;t++) {
367         char c = yytext[t];
368         if(c=='.') {
369             dot=1;
370             continue;
371         }
372         if(!dot) {
373             d*=16;
374         } else {
375             base*=1/16.0;
376         }
377         if(c>='0' && c<='9')
378             d+=(c&15)*base;
379         else if((c>='a' && c<='f') || (c>='A' && c<='F'))
380             d+=((c&0x0f)+9)*base;
381     }
382     return setfloat(d);
383 }
384 static inline int handlehex()
385 {
386     char l = (yytext[0]=='-')+2;
387     int len = yyleng;
388
389     if(len-l>8) {
390         char*s = nrbuf();
391         syntaxerror("integer overflow %s", s);
392     }
393
394     int t;
395     unsigned int v = 0;
396     for(t=l;t<len;t++) {
397         v<<=4;
398         char c = yytext[t];
399         if(c>='0' && c<='9')
400             v|=(c&15);
401         else if((c>='a' && c<='f') || (c>='A' && c<='F'))
402             v|=(c&0x0f)+9;
403     }
404     if(l && v>1073741824) {
405         char*s = nrbuf();
406         as3_warning("signed integer overflow: %s (converted to Number)", s);
407         return setfloat(v);
408     }
409     if(!l && v>2147483647) {
410         char*s = nrbuf();
411         as3_warning("unsigned integer overflow: %s (converted to Number)", s);
412         return setfloat(v);
413     }
414
415     if(l==3) {
416         return setint(-(int)v);
417     } else {
418         return setuint(v);
419     }
420 }
421
422 void handleLabel(char*text, int len)
423 {
424     int t;
425     for(t=len-1;t>=0;--t) {
426         if(text[t]!=' ' &&
427            text[t]!=':')
428             break;
429     }
430     char*s = malloc(t+1);
431     memcpy(s, yytext, t);
432     s[t]=0;
433     avm2_lval.id = s;
434 }
435
436 static int handleregexp()
437 {
438     char*s = malloc(yyleng);
439     int len=yyleng-1;
440     memcpy(s, yytext+1, len);
441     s[len] = 0;
442     int t;
443     for(t=len;t>=0;--t) {
444         if(s[t]=='/') {
445             s[t] = 0;
446             break;
447         }
448     }
449     avm2_lval.regexp.pattern = s;
450     if(t==len) {
451         avm2_lval.regexp.options = 0;
452     } else {
453         avm2_lval.regexp.options = s+t+1;
454     }
455     return T_REGEXP;
456 }
457
458 void initialize_scanner();
459 #define YY_USER_INIT initialize_scanner();
460
461 /* count the number of lines+columns consumed by this token */
462 static inline void l() {
463     int t;
464     for(t=0;t<yyleng;t++) {
465         if(yytext[t]=='\n') {
466             current_line++;
467             current_column=0;
468         } else {
469             current_column++;
470         }
471     }
472 }
473 /* count the number of columns consumed by this token */
474 static inline void c() {
475     current_column+=yyleng;
476 }
477
478 //Boolean                      {c();return m(KW_BOOLEAN);}
479 //int                          {c();return m(KW_INT);}
480 //uint                         {c();return m(KW_UINT);}
481 //Number                       {c();return m(KW_NUMBER);}
482
483
484 %}
485
486 %s REGEXPOK
487 %s BEGINNING
488
489 NAME     [a-zA-Z_][a-zA-Z0-9_\\]*
490 _        [^a-zA-Z0-9_\\]
491
492 HEXINT    0x[a-zA-Z0-9]+
493 HEXFLOAT  0x[a-zA-Z0-9]*\.[a-zA-Z0-9]*
494 INT       [0-9]+
495 FLOAT     [0-9]+(\.[0-9]*)?|\.[0-9]+
496
497 HEXWITHSIGN [+-]?({HEXINT})
498 HEXFLOATWITHSIGN [+-]?({HEXFLOAT})
499 INTWITHSIGN [+-]?({INT})
500 FLOATWITHSIGN [+-]?({FLOAT})
501
502 STRING   ["](\\[\x00-\xff]|[^\\"\n])*["]|['](\\[\x00-\xff]|[^\\'\n])*[']
503 S        [ \n\r\t]
504 MULTILINE_COMMENT [/][*]+([*][^/]|[^/*]|[^*][/]|[\x00-\x1f])*[*]+[/]
505 SINGLELINE_COMMENT \/\/[^\n]*\n
506 REGEXP   [/]([^/\n]|\\[/])*[/][a-zA-Z]*
507 %%
508
509
510 {SINGLELINE_COMMENT}         {l(); /* single line comment */}
511 {MULTILINE_COMMENT}          {l(); /* multi line comment */}
512 [/][*]                       {syntaxerror("syntax error: unterminated comment", yytext);}
513
514 ^include{S}+{STRING}{S}*/\n    {l();handleInclude(yytext, yyleng, 1);}
515 ^include{S}+[^" \t\r\n][\x20-\xff]*{S}*/\n    {l();handleInclude(yytext, yyleng, 0);}
516 {STRING}                     {l(); BEGIN(INITIAL);handleString(yytext, yyleng);return T_STRING;}
517
518 <BEGINNING,REGEXPOK>{
519 {REGEXP}                     {c(); BEGIN(INITIAL);return handleregexp();} 
520 {HEXWITHSIGN}                {c(); BEGIN(INITIAL);return handlehex();}
521 {HEXFLOATWITHSIGN}                {c(); BEGIN(INITIAL);return handlehexfloat();}
522 {INTWITHSIGN}                {c(); BEGIN(INITIAL);return handleint();}
523 {FLOATWITHSIGN}              {c(); BEGIN(INITIAL);return handlefloat();}
524 }
525
526 \xef\xbb\xbf                 {/* utf 8 bom */}
527 {S}                          {l();}
528
529 {HEXINT}                     {c(); BEGIN(INITIAL);return handlehex();}
530 {HEXFLOAT}                   {c(); BEGIN(INITIAL);return handlehexfloat();}
531 {INT}                        {c(); BEGIN(INITIAL);return handleint();}
532 {FLOAT}                      {c(); BEGIN(INITIAL);return handlefloat();}
533
534 3rr0r                        {/* for debugging: generates a tokenizer-level error */
535                               syntaxerror("3rr0r");}
536
537 {NAME}{S}*:{S}*for/{_}        {l();handleLabel(yytext, yyleng-3);return T_FOR;}
538 {NAME}{S}*:{S}*do/{_}         {l();handleLabel(yytext, yyleng-2);return T_DO;}
539 {NAME}{S}*:{S}*while/{_}      {l();handleLabel(yytext, yyleng-5);return T_WHILE;}
540 {NAME}{S}*:{S}*switch/{_}     {l();handleLabel(yytext, yyleng-6);return T_SWITCH;}
541 for                          {c();avm2_lval.id="";return T_FOR;}
542 do                           {c();avm2_lval.id="";return T_DO;}
543 while                        {c();avm2_lval.id="";return T_WHILE;}
544 switch                       {c();avm2_lval.id="";return T_SWITCH;}
545
546 [&][&]                       {c();BEGIN(REGEXPOK);return m(T_ANDAND);}
547 [|][|]                       {c();BEGIN(REGEXPOK);return m(T_OROR);}
548 [!][=]                       {c();BEGIN(REGEXPOK);return m(T_NE);}
549 [!][=][=]                    {c();BEGIN(REGEXPOK);return m(T_NEE);}
550 [=][=][=]                    {c();BEGIN(REGEXPOK);return m(T_EQEQEQ);}
551 [=][=]                       {c();BEGIN(REGEXPOK);return m(T_EQEQ);}
552 [>][=]                       {c();return m(T_GE);}
553 [<][=]                       {c();return m(T_LE);}
554 [-][-]                       {c();BEGIN(INITIAL);return m(T_MINUSMINUS);}
555 [+][+]                       {c();BEGIN(INITIAL);return m(T_PLUSPLUS);}
556 [+][=]                       {c();return m(T_PLUSBY);}
557 [-][=]                       {c();return m(T_MINUSBY);}
558 [/][=]                       {c();return m(T_DIVBY);}
559 [%][=]                       {c();return m(T_MODBY);}
560 [*][=]                       {c();return m(T_MULBY);}
561 [|][=]                       {c();return m(T_ORBY);}
562 [>][>][=]                    {c();return m(T_SHRBY);}
563 [<][<][=]                    {c();return m(T_SHLBY);}
564 [>][>][>][=]                 {c();return m(T_USHRBY);}
565 [<][<]                       {c();return m(T_SHL);}
566 [>][>][>]                    {c();return m(T_USHR);}
567 [>][>]                       {c();return m(T_SHR);}
568 \.\.\.                       {c();return m(T_DOTDOTDOT);}
569 \.\.                         {c();return m(T_DOTDOT);}
570 \.                           {c();return m('.');}
571 ::                           {c();return m(T_COLONCOLON);}
572 :                            {c();return m(':');}
573 instanceof                   {c();return m(KW_INSTANCEOF);}
574 implements                   {c();return m(KW_IMPLEMENTS);}
575 interface                    {c();return m(KW_INTERFACE);}
576 namespace                    {c();return m(KW_NAMESPACE);}
577 protected                    {c();return m(KW_PROTECTED);}
578 undefined                    {c();return m(KW_UNDEFINED);}
579 continue                     {c();return m(KW_CONTINUE);}
580 override                     {c();return m(KW_OVERRIDE);}
581 internal                     {c();return m(KW_INTERNAL);}
582 function                     {c();return m(KW_FUNCTION);}
583 finally                      {c();return m(KW_FINALLY);}
584 default                      {c();return m(KW_DEFAULT);}
585 package                      {c();return m(KW_PACKAGE);}
586 private                      {c();return m(KW_PRIVATE);}
587 dynamic                      {c();return m(KW_DYNAMIC);}
588 extends                      {c();return m(KW_EXTENDS);}
589 delete                       {c();return m(KW_DELETE);}
590 return                       {c();return m(KW_RETURN);}
591 public                       {c();return m(KW_PUBLIC);}
592 native                       {c();return m(KW_NATIVE);}
593 static                       {c();return m(KW_STATIC);}
594 import                       {c();return m(KW_IMPORT);}
595 typeof                       {c();return m(KW_TYPEOF);}
596 throw                        {c();return m(KW_THROW);}
597 class                        {c();return m(KW_CLASS);}
598 const                        {c();return m(KW_CONST);}
599 catch                        {c();return m(KW_CATCH);}
600 final                        {c();return m(KW_FINAL);}
601 false                        {c();return m(KW_FALSE);}
602 break                        {c();return m(KW_BREAK);}
603 super                        {c();return m(KW_SUPER);}
604 each                         {c();return m(KW_EACH);}
605 void                         {c();return m(KW_VOID);}
606 true                         {c();return m(KW_TRUE);}
607 null                         {c();return m(KW_NULL);}
608 else                         {c();return m(KW_ELSE);}
609 case                         {c();return m(KW_CASE);}
610 with                         {c();return m(KW_WITH);}
611 use                          {c();return m(KW_USE);}
612 new                          {c();return m(KW_NEW);}
613 get                          {c();return m(KW_GET);}
614 set                          {c();return m(KW_SET);}
615 var                          {c();return m(KW_VAR);}
616 try                          {c();return m(KW_TRY);}
617 is                           {c();return m(KW_IS) ;}
618 in                           {c();return m(KW_IN) ;}
619 if                           {c();return m(KW_IF) ;}
620 as                           {c();return m(KW_AS);}
621 {NAME}                       {c();BEGIN(INITIAL);return mkid(T_IDENTIFIER);}
622
623 [+-\/*^~@$!%&\(=\[\]\{\}|?:;,<>] {c();BEGIN(REGEXPOK);return m(yytext[0]);}
624 [\)\]]                           {c();BEGIN(INITIAL);return m(yytext[0]);}
625
626 .                            {char c1=yytext[0];
627                               char buf[128];
628                               buf[0] = yytext[0];
629                               int t;
630                               for(t=1;t<128;t++) {
631                                   char c = buf[t]=input();
632                                   if(c=='\n' || c==EOF)  {
633                                       buf[t] = 0;
634                                       break;
635                                   }
636                               }
637                               if(c1>='0' && c1<='9')
638                                   syntaxerror("syntax error: %s (identifiers must not start with a digit)");
639                               else
640                                   syntaxerror("syntax error: %s", buf);
641                               printf("\n");
642                               exit(1);
643                               yyterminate();
644                              }
645 <<EOF>>                      {l();
646                               void*b = leave_file();
647                               if (!b) {
648                                  yyterminate();
649                                  yy_delete_buffer(YY_CURRENT_BUFFER);
650                                  return m(T_EOF);
651                               } else {
652                                   yy_delete_buffer(YY_CURRENT_BUFFER);
653                                   yy_switch_to_buffer(b);
654                               }
655                              }
656
657 %%
658
659 int yywrap()
660 {
661     return 1;
662 }
663
664 static char mbuf[256];
665 char*token2string(enum yytokentype nr, YYSTYPE v)
666 {
667     if(nr==T_STRING)     return "<string>";
668     else if(nr==T_INT)     return "<int>";
669     else if(nr==T_UINT)     return "<uint>";
670     else if(nr==T_BYTE)     return "<byte>";
671     else if(nr==T_FLOAT)     return "<float>";
672     else if(nr==T_REGEXP)     return "REGEXP";
673     else if(nr==T_EOF)        return "***END***";
674     else if(nr==T_GE)         return ">=";
675     else if(nr==T_LE)         return "<=";
676     else if(nr==T_MINUSMINUS) return "--";
677     else if(nr==T_PLUSPLUS)   return "++";
678     else if(nr==KW_IMPLEMENTS) return "implements";
679     else if(nr==KW_INTERFACE)  return "interface";
680     else if(nr==KW_NAMESPACE)  return "namespace";
681     else if(nr==KW_PROTECTED)  return "protected";
682     else if(nr==KW_OVERRIDE)   return "override";
683     else if(nr==KW_INTERNAL)   return "internal";
684     else if(nr==KW_FUNCTION)   return "function";
685     else if(nr==KW_PACKAGE)    return "package";
686     else if(nr==KW_PRIVATE)    return "private";
687     else if(nr==KW_BOOLEAN)    return "Boolean";
688     else if(nr==KW_DYNAMIC)    return "dynamic";
689     else if(nr==KW_EXTENDS)    return "extends";
690     else if(nr==KW_PUBLIC)     return "public";
691     else if(nr==KW_NATIVE)     return "native";
692     else if(nr==KW_STATIC)     return "static";
693     else if(nr==KW_IMPORT)     return "import";
694     else if(nr==KW_NUMBER)     return "number";
695     else if(nr==KW_CLASS)      return "class";
696     else if(nr==KW_CONST)      return "const";
697     else if(nr==KW_FINAL)      return "final";
698     else if(nr==KW_FALSE)      return "False";
699     else if(nr==KW_TRUE)       return "True";
700     else if(nr==KW_UINT)       return "uint";
701     else if(nr==KW_NULL)       return "null";
702     else if(nr==KW_ELSE)       return "else";
703     else if(nr==KW_USE)        return "use";
704     else if(nr==KW_INT)        return "int";
705     else if(nr==KW_NEW)        return "new";
706     else if(nr==KW_GET)        return "get";
707     else if(nr==KW_SET)        return "set";
708     else if(nr==KW_VAR)        return "var";
709     else if(nr==KW_IS)         return "is";
710     else if(nr==KW_AS)         return "as";
711     else if(nr==T_IDENTIFIER)  return "ID";
712     else {
713         sprintf(mbuf, "%d", nr);
714         return mbuf;
715     }
716 }
717
718 void initialize_scanner()
719 {
720     BEGIN(BEGINNING);
721 }
722