added '*=' token
[swftools.git] / lib / as3 / tokenizer.lex
index 7a17622..0da86e9 100644 (file)
@@ -1,4 +1,28 @@
+/* tokenizer.lex
+
+   Routines for compiling Flash2 AVM2 ABC Actionscript
+
+   Extension module for the rfxswf library.
+   Part of the swftools package.
+
+   Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 %{
+
+
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -50,10 +74,23 @@ void syntaxerror(const char*format, ...)
     va_start(arglist, format);
     vsprintf(buf, format, arglist);
     va_end(arglist);
-    fprintf(stderr, "%s:%d:%d: error: %s\n", current_filename, current_line, current_column, buf);
+    fprintf(stderr, "%s:%d:%d: error: %s\n", current_filename_short, current_line, current_column, buf);
     fflush(stderr);
     exit(1);
 }
+void warning(const char*format, ...)
+{
+    char buf[1024];
+    int l;
+    va_list arglist;
+    if(!verbose)
+       return;
+    va_start(arglist, format);
+    vsprintf(buf, format, arglist);
+    va_end(arglist);
+    fprintf(stderr, "%s:%d:%d: warning: %s\n", current_filename_short, current_line, current_column, buf);
+    fflush(stderr);
+}
 
 
 #ifndef YY_CURRENT_BUFFER
@@ -92,6 +129,22 @@ void handleInclude(char*text, int len, char quotes)
     //BEGIN(INITIAL); keep context
 }
 
+static void handleString(char*s, int len)
+{
+    if(s[0]=='"') {
+        if(s[len-1]!='"') syntaxerror("String doesn't end with '\"'");
+        s++;len-=2;
+    }
+    else if(s[0]=='\'') {
+        if(s[len-1]!='\'') syntaxerror("String doesn't end with '\"'");
+        s++;len-=2;
+    }
+    else syntaxerror("String incorrectly terminated");
+    s[len] = 0;
+    avm2_lval.string = s;
+}
+
+
 char start_of_expression;
 
 static inline int m(int type)
@@ -121,9 +174,10 @@ static inline int handlenumber()
     char is_float=0;
     for(t=0;t<yyleng;t++) {
         if(yytext[t]=='.') {
+            if(is_float)
+                syntaxerror("Invalid number");
             is_float=1;
-        } 
-        if(!strchr("0123456789", yytext[t])) {
+        } else if(!strchr("-0123456789", yytext[t])) {
             syntaxerror("Invalid number");
         }
     }
@@ -131,31 +185,39 @@ static inline int handlenumber()
         avm2_lval.number_float = atof(s);
         return T_FLOAT;
     } 
-    int l=0;
-    if(yytext[0]=='-')
-        l++;
+    char l = (yytext[0]=='-');
 
-    char*max = l?"2147483648":"4294967296";
-    if(yyleng>10)
+    char*max = l?"1073741824":"2147483647";
+    if(yyleng-l>10)
         syntaxerror("integer overflow");
-    if(yyleng==10) {
+    if(yyleng-l==10) {
         int t;
         for(t=0;t<yyleng-l;t++) {
             if(yytext[l+t]>max[t])
-                syntaxerror("integer overflow");
+                syntaxerror("integer overflow %s > %s", s+l,max);
             else if(yytext[l+t]<max[t])
                 break;
         }
     }
     if(yytext[0]=='-') {
-        avm2_lval.number_int = atoi(s);
-        return T_INT;
+        int v = atoi(s);
+        avm2_lval.number_int = v;
+        if(v>-128)
+            return T_BYTE;
+        else if(v>=-32768)
+            return T_SHORT;
+        else
+            return T_INT;
     } else {
-        unsigned int v = atoi(s);
+        unsigned int v = 0;
+        for(t=0;t<yyleng;t++) {
+            v*=10;
+            v+=yytext[t]-'0';
+        }
         avm2_lval.number_uint = v;
-        if(v<256)
+        if(v<128)
             return T_BYTE;
-        else if(v<0x80000000)
+        else if(v<32768)
             return T_SHORT;
         else
             return T_UINT;
@@ -178,7 +240,7 @@ NUMBER       -?[0-9]+(\.[0-9]*)?
 
 STRING   ["](\\[\x00-\xff]|[^\\"\n])*["]|['](\\[\x00-\xff]|[^\\'\n])*[']
 S       [ \n\r\t]
-MULTILINE_COMMENT [/][*]([*][^/]|[^*]|[\x00-\x31])*[*]+[/]
+MULTILINE_COMMENT [/][*]+([*][^/]|[^/*]|[^*][/]|[\x00-\x1f])*[*]+[/]
 SINGLELINE_COMMENT \/\/[^\n]*\n
 REGEXP   [/]([^/\n]|\\[/])*[/][a-zA-Z]*
 %%
@@ -190,7 +252,7 @@ REGEXP   [/]([^/\n]|\\[/])*[/][a-zA-Z]*
 
 ^include{S}+{STRING}{S}*/\n    {c();handleInclude(yytext, yyleng, 1);}
 ^include{S}+[^" \t\r\n][\x20-\xff]*{S}*/\n    {c();handleInclude(yytext, yyleng, 0);}
-{STRING}                     {c(); BEGIN(INITIAL);return m(T_STRING);}
+{STRING}                     {c(); BEGIN(INITIAL);handleString(yytext, yyleng);return T_STRING;}
 
 <BEGINNING,REGEXPOK>{
 {REGEXP}                     {c(); BEGIN(INITIAL);return m(T_REGEXP);} 
@@ -201,48 +263,72 @@ REGEXP   [/]([^/\n]|\\[/])*[/][a-zA-Z]*
 
 {NUMBER}                     {c(); BEGIN(INITIAL);return handlenumber();}
 
-[>][=]                       {return m(T_GE);}
-[<][=]                       {return m(T_LE);}
-[-][-]                       {BEGIN(INITIAL);return m(T_MINUSMINUS);}
-[+][+]                       {BEGIN(INITIAL);return m(T_PLUSPLUS);}
-==                           {BEGIN(REGEXPOK);return m(T_EQEQ);}
-\.\.                         {return m(T_DOTDOT);}
-\.                           {return m('.');}
-::                           {return m(T_COLONCOLON);}
-:                            {return m(':');}
-implements                   {return m(KW_IMPLEMENTS);}
-interface                    {return m(KW_INTERFACE);}
-namespace                    {return m(KW_NAMESPACE);}
-protected                    {return m(KW_PROTECTED);}
-override                     {return m(KW_OVERRIDE);}
-internal                     {return m(KW_INTERNAL);}
-function                     {return m(KW_FUNCTION);}
-package                      {return m(KW_PACKAGE);}
-private                      {return m(KW_PRIVATE);}
-Boolean                      {return m(KW_BOOLEAN);}
-dynamic                      {return m(KW_DYNAMIC);}
-extends                      {return m(KW_EXTENDS);}
-public                       {return m(KW_PUBLIC);}
-native                       {return m(KW_NATIVE);}
-static                       {return m(KW_STATIC);}
-import                       {return m(KW_IMPORT);}
-Number                       {return m(KW_NUMBER);}
-class                        {return m(KW_CLASS);}
-const                        {return m(KW_CONST);}
-final                        {return m(KW_FINAL);}
-False                        {return m(KW_FALSE);}
-True                         {return m(KW_TRUE);}
-uint                         {return m(KW_UINT);}
-null                         {return m(KW_NULL);}
-use                          {return m(KW_USE);}
-int                          {return m(KW_INT);}
-new                          {return m(KW_NEW);}
-get                          {return m(KW_GET);}
-for                          {return m(KW_FOR);}
-set                          {return m(KW_SET);}
-var                          {return m(KW_VAR);}
-is                           {return m(KW_IS) ;}
-as                           {return m(KW_AS);}
+3rr0r                        {/* for debugging: generates a tokenizer-level error */
+                              syntaxerror("3rr0r");}
+
+[&][&]                       {c();BEGIN(REGEXPOK);return m(T_ANDAND);}
+[|][|]                       {c();BEGIN(REGEXPOK);return m(T_OROR);}
+[!][=]                       {c();BEGIN(REGEXPOK);return m(T_NE);}
+[=][=][=]                    {c();BEGIN(REGEXPOK);return m(T_EQEQEQ);}
+[=][=]                       {c();BEGIN(REGEXPOK);return m(T_EQEQ);}
+[>][=]                       {c();return m(T_GE);}
+[<][=]                       {c();return m(T_LE);}
+[-][-]                       {c();BEGIN(INITIAL);return m(T_MINUSMINUS);}
+[+][+]                       {c();BEGIN(INITIAL);return m(T_PLUSPLUS);}
+[+][=]                       {c();return m(T_PLUSBY);}
+[-][=]                       {c();return m(T_MINUSBY);}
+[/][=]                       {c();return m(T_DIVBY);}
+[%][=]                       {c();return m(T_MODBY);}
+[*][=]                       {c();return m(T_MULBY);}
+[>][>][=]                    {c();return m(T_SHRBY);}
+[<][<][=]                    {c();return m(T_SHLBY);}
+[>][>][>][=]                 {c();return m(T_USHRBY);}
+[<][<]                       {c();return m(T_SHL);}
+[>][>][>]                    {c();return m(T_USHR);}
+[>][>]                       {c();return m(T_SHR);}
+\.\.\.                       {c();return m(T_DOTDOTDOT);}
+\.\.                         {c();return m(T_DOTDOT);}
+\.                           {c();return m('.');}
+::                           {c();return m(T_COLONCOLON);}
+:                            {c();return m(':');}
+implements                   {c();return m(KW_IMPLEMENTS);}
+interface                    {c();return m(KW_INTERFACE);}
+namespace                    {c();return m(KW_NAMESPACE);}
+protected                    {c();return m(KW_PROTECTED);}
+override                     {c();return m(KW_OVERRIDE);}
+internal                     {c();return m(KW_INTERNAL);}
+function                     {c();return m(KW_FUNCTION);}
+package                      {c();return m(KW_PACKAGE);}
+private                      {c();return m(KW_PRIVATE);}
+Boolean                      {c();return m(KW_BOOLEAN);}
+dynamic                      {c();return m(KW_DYNAMIC);}
+extends                      {c();return m(KW_EXTENDS);}
+return                       {c();return m(KW_RETURN);}
+public                       {c();return m(KW_PUBLIC);}
+native                       {c();return m(KW_NATIVE);}
+static                       {c();return m(KW_STATIC);}
+import                       {c();return m(KW_IMPORT);}
+Number                       {c();return m(KW_NUMBER);}
+while                        {c();return m(KW_WHILE);}
+class                        {c();return m(KW_CLASS);}
+const                        {c();return m(KW_CONST);}
+final                        {c();return m(KW_FINAL);}
+false                        {c();return m(KW_FALSE);}
+break                        {c();return m(KW_BREAK);}
+true                         {c();return m(KW_TRUE);}
+uint                         {c();return m(KW_UINT);}
+null                         {c();return m(KW_NULL);}
+else                         {c();return m(KW_ELSE);}
+use                          {c();return m(KW_USE);}
+int                          {c();return m(KW_INT);}
+new                          {c();return m(KW_NEW);}
+get                          {c();return m(KW_GET);}
+for                          {c();return m(KW_FOR);}
+set                          {c();return m(KW_SET);}
+var                          {c();return m(KW_VAR);}
+is                           {c();return m(KW_IS) ;}
+if                           {c();return m(KW_IF) ;}
+as                           {c();return m(KW_AS);}
 {NAME}                       {c();BEGIN(INITIAL);return m(T_IDENTIFIER);}
 
 [+-\/*^~@$!%&\(=\[\]\{\}|?:;,.<>] {c();BEGIN(REGEXPOK);return m(yytext[0]);}
@@ -324,6 +410,7 @@ char*token2string(token_t*t)
     else if(nr==KW_TRUE)       return "True";
     else if(nr==KW_UINT)       return "uint";
     else if(nr==KW_NULL)       return "null";
+    else if(nr==KW_ELSE)       return "else";
     else if(nr==KW_USE)        return "use";
     else if(nr==KW_INT)        return "int";
     else if(nr==KW_NEW)        return "new";