SpiderScript - For loop, #if'd out experimental code
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / parse.c
index 5622123..3ad4081 100644 (file)
@@ -36,6 +36,11 @@ tAST_Node    *Parse_GetIdent(tParser *Parser);
 
 void   SyntaxAssert(tParser *Parser, int Have, int Want);
 
+#define TODO(Parser, message...) do {\
+       fprintf(stderr, "TODO: "message);\
+       longjmp(Parser->JmpTarget, -1);\
+}while(0)
+
 // === CODE ===
 /**
  * \brief Parse a buffer into a syntax tree
@@ -43,7 +48,7 @@ void  SyntaxAssert(tParser *Parser, int Have, int Want);
 tAST_Script    *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
 {
        tParser parser = {0};
-       tParser *Parser = &parser;      //< Keeps code consitent
+       tParser *Parser = &parser;      //< Keeps code consistent
        tAST_Script     *ret;
        tAST_Node       *mainCode;
        char    *name;
@@ -64,12 +69,14 @@ tAST_Script *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
        ret = AST_NewScript();
        mainCode = AST_NewCodeBlock();
        
+       // Give us an error fallback
        if( setjmp( parser.JmpTarget ) != 0 )
        {
                AST_FreeNode( mainCode );
                return NULL;
        }
        
+       // Parse the file!
        while(Parser->Token != TOK_EOF)
        {
                switch( GetToken(Parser) )
@@ -103,7 +110,7 @@ tAST_Script *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
                // Define a function
                case TOK_RWD_FUNCTION:
                        if( !Variant->bDyamicTyped ) {
-                               fprintf(stderr, "ERROR: Attempt to create a dynamic function\n");
+                               fprintf(stderr, "ERROR: Dynamic functions are invalid in static mode\n");
                                longjmp(Parser->JmpTarget, -1);
                        }
                        type = SS_DATATYPE_DYNAMIC;
@@ -148,7 +155,7 @@ tAST_Script *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
        fcn = AST_AppendFunction( ret, "" );
        AST_SetFunctionCode( fcn, mainCode );
        
-       printf("---- %p parsed as SpiderScript ----\n", Buffer);
+       //printf("---- %p parsed as SpiderScript ----\n", Buffer);
        
        return ret;
 }
@@ -159,7 +166,12 @@ tAST_Script        *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
 {
        tAST_Node       *ret;
-       SyntaxAssert(Parser, GetToken(Parser), TOK_BRACE_OPEN );
+       
+       // Check if we are being called for a one-liner
+       if( GetToken(Parser) != TOK_BRACE_OPEN ) {
+               PutBack(Parser);
+               return Parse_DoBlockLine(Parser);
+       }
        
        ret = AST_NewCodeBlock();
        
@@ -182,17 +194,61 @@ tAST_Node *Parse_DoBlockLine(tParser *Parser)
        
        switch(LookAhead(Parser))
        {
+       // Empty statement
+       case TOK_SEMICOLON:
+               GetToken(Parser);
+               return NULL;
        
        // Return from a method
        case TOK_RWD_RETURN:
                //printf("return\n");
                GetToken(Parser);
-               ret = AST_NewUniOp(NODETYPE_RETURN, Parse_DoExpr0(Parser));
+               ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
                break;
        
        // Control Statements
-       //case TOK_RWD_IF:
-       //      break;
+       case TOK_RWD_IF:
+               {
+               tAST_Node       *cond, *true, *false = NULL;
+               GetToken(Parser);       // eat the if
+               SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
+               cond = Parse_DoExpr0(Parser);   // Get condition
+               SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
+               true = Parse_DoCodeBlock(Parser);
+               if( LookAhead(Parser) == TOK_RWD_ELSE ) {
+                       GetToken(Parser);
+                       false = Parse_DoCodeBlock(Parser);
+               }
+               ret = AST_NewIf(Parser, cond, true, false);
+               }
+               return ret;
+       case TOK_RWD_FOR:
+               {
+               tAST_Node       *init=NULL, *cond=NULL, *inc=NULL, *code;
+               GetToken(Parser);       // Eat 'for'
+               SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
+               
+               if(LookAhead(Parser) != TOK_SEMICOLON)
+                       init = Parse_DoExpr0(Parser);
+               
+               SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
+               if(LookAhead(Parser) != TOK_SEMICOLON)
+                       cond = Parse_DoExpr0(Parser);
+               
+               SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
+               if(LookAhead(Parser) != TOK_SEMICOLON)
+                       inc = Parse_DoExpr0(Parser);
+               
+               SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
+               
+               code = Parse_DoCodeBlock(Parser);
+               ret = AST_NewLoop(Parser, init, 0, cond, inc, code);
+               }
+               return ret;
+       case TOK_RWD_DO:
+       case TOK_RWD_WHILE:
+               TODO(Parser, "Implement do and while\n");
+               break;
        
        // Define Variables
        case TOKEN_GROUP_TYPES:
@@ -238,7 +294,7 @@ tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
        memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
        name[Parser->TokenLen-1] = 0;
        // Define the variable
-       ret = AST_NewDefineVar(Type, name);
+       ret = AST_NewDefineVar(Parser, Type, name);
        // Handle arrays
        while( LookAhead(Parser) == TOK_SQUARE_OPEN )
        {
@@ -261,16 +317,16 @@ tAST_Node *Parse_DoExpr0(tParser *Parser)
        {
        case TOK_ASSIGN:
                GetToken(Parser);               // Eat Token
-               ret = AST_NewAssign(NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
+               ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
                break;
        #if 0
        case TOK_DIV_EQU:
                GetToken(Parser);               // Eat Token
-               ret = AST_NewAssign(NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
+               ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
                break;
        case TOK_MULT_EQU:
                GetToken(Parser);               // Eat Token
-               ret = AST_NewAssign(NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
+               ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
                break;
        #endif
        default:
@@ -292,13 +348,13 @@ tAST_Node *Parse_DoExpr1(tParser *Parser)
        switch(GetToken(Parser))
        {
        case TOK_LOGICAND:
-               ret = AST_NewBinOp(NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
                break;
        case TOK_LOGICOR:
-               ret = AST_NewBinOp(NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
                break;
        case TOK_LOGICXOR:
-               ret = AST_NewBinOp(NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
                break;
        default:
                PutBack(Parser);
@@ -318,13 +374,13 @@ tAST_Node *Parse_DoExpr2(tParser *Parser)
        switch(GetToken(Parser))
        {
        case TOK_EQUALS:
-               ret = AST_NewBinOp(NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
                break;
        case TOK_LT:
-               ret = AST_NewBinOp(NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
                break;
        case TOK_GT:
-               ret = AST_NewBinOp(NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
                break;
        default:
                PutBack(Parser);
@@ -344,13 +400,13 @@ tAST_Node *Parse_DoExpr3(tParser *Parser)
        switch(GetToken(Parser))
        {
        case TOK_OR:
-               ret = AST_NewBinOp(NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
                break;
        case TOK_AND:
-               ret = AST_NewBinOp(NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
                break;
        case TOK_XOR:
-               ret = AST_NewBinOp(NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
                break;
        default:
                PutBack(Parser);
@@ -369,10 +425,10 @@ tAST_Node *Parse_DoExpr4(tParser *Parser)
        switch(GetToken(Parser))
        {
        case TOK_SHL:
-               ret = AST_NewBinOp(NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
                break;
        case TOK_SHR:
-               ret = AST_NewBinOp(NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
                break;
        default:
                PutBack(Parser);
@@ -392,10 +448,10 @@ tAST_Node *Parse_DoExpr5(tParser *Parser)
        switch(GetToken(Parser))
        {
        case TOK_PLUS:
-               ret = AST_NewBinOp(NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
                break;
        case TOK_MINUS:
-               ret = AST_NewBinOp(NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
                break;
        default:
                PutBack(Parser);
@@ -415,10 +471,10 @@ tAST_Node *Parse_DoExpr6(tParser *Parser)
        switch(GetToken(Parser))
        {
        case TOK_MUL:
-               ret = AST_NewBinOp(NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
                break;
        case TOK_DIV:
-               ret = AST_NewBinOp(NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
                break;
        default:
                PutBack(Parser);
@@ -440,12 +496,23 @@ tAST_Node *Parse_DoParen(tParser *Parser)
        if(LookAhead(Parser) == TOK_PAREN_OPEN)
        {
                tAST_Node       *ret;
+                int    type;
                GetToken(Parser);
                
                // TODO: Handle casts here
-               
-               ret = Parse_DoExpr0(Parser);
-               SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
+               switch(LookAhead(Parser))
+               {
+               case TOKEN_GROUP_TYPES:
+                       GetToken(Parser);
+                       TOKEN_GET_DATATYPE(type, Parser->Token);
+                       SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
+                       ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
+                       break;
+               default:                
+                       ret = Parse_DoExpr0(Parser);
+                       SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
+                       break;
+               }
                return ret;
        }
        else
@@ -483,9 +550,35 @@ tAST_Node *Parse_DoValue(tParser *Parser)
 tAST_Node *Parse_GetString(tParser *Parser)
 {
        tAST_Node       *ret;
+        int    i, j;
        GetToken( Parser );
-       // TODO: Parse Escape Codes
-       ret = AST_NewString( Parser->TokenStr+1, Parser->TokenLen-2 );
+       
+       {
+               char    data[ Parser->TokenLen - 2 ];
+               j = 0;
+               
+               for( i = 1; i < Parser->TokenLen - 1; i++ )
+               {
+                       if( Parser->TokenStr[i] == '\\' ) {
+                               i ++;
+                               switch( Parser->TokenStr[i] )
+                               {
+                               case 'n':       data[j++] = '\n';       break;
+                               case 'r':       data[j++] = '\r';       break;
+                               default:
+                                       // TODO: Octal Codes
+                                       // TODO: Error/Warning?
+                                       break;
+                               }
+                       }
+                       else {
+                               data[j++] = Parser->TokenStr[i];
+                       }
+               }
+               
+               // TODO: Parse Escape Codes
+               ret = AST_NewString( Parser, data, j );
+       }
        return ret;
 }
 
@@ -494,10 +587,50 @@ tAST_Node *Parse_GetString(tParser *Parser)
  */
 tAST_Node *Parse_GetNumeric(tParser *Parser)
 {
-       uint64_t        value;
+       uint64_t        value = 0;
+       char    *pos;
        GetToken( Parser );
-       value = atoi( Parser->TokenStr );
-       return AST_NewInteger( value );
+       pos = Parser->TokenStr;
+       //printf("pos = %p, *pos = %c\n", pos, *pos);
+               
+       if( *pos == '0' )
+       {
+               pos ++;
+               if(*pos == 'x') {
+                       pos ++;
+                       for( ;; pos++)
+                       {
+                               value *= 16;
+                               if( '0' <= *pos && *pos <= '9' ) {
+                                       value += *pos - '0';
+                                       continue;
+                               }
+                               if( 'A' <= *pos && *pos <= 'F' ) {
+                                       value += *pos - 'A' + 10;
+                                       continue;
+                               }
+                               if( 'a' <= *pos && *pos <= 'f' ) {
+                                       value += *pos - 'a' + 10;
+                                       continue;
+                               }
+                               break;
+                       }
+               }
+               else {
+                       while( '0' <= *pos && *pos <= '7' ) {
+                               value = value*8 + *pos - '0';
+                               pos ++;
+                       }
+               }
+       }
+       else {
+               while( '0' <= *pos && *pos <= '9' ) {
+                       value = value*10 + *pos - '0';
+                       pos ++;
+               }
+       }
+       
+       return AST_NewInteger( Parser, value );
 }
 
 /**
@@ -511,7 +644,7 @@ tAST_Node *Parse_GetVariable(tParser *Parser)
                char    name[Parser->TokenLen];
                memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
                name[Parser->TokenLen-1] = 0;
-               ret = AST_NewVariable( name );
+               ret = AST_NewVariable( Parser, name );
                #if DEBUG >= 2
                printf("Parse_GetVariable: name = '%s'\n", name);
                #endif
@@ -520,7 +653,7 @@ tAST_Node *Parse_GetVariable(tParser *Parser)
        while( LookAhead(Parser) == TOK_SQUARE_OPEN )
        {
                GetToken(Parser);
-               ret = AST_NewBinOp(NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
+               ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
                SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
        }
        return ret;
@@ -550,7 +683,7 @@ tAST_Node *Parse_GetIdent(tParser *Parser)
                printf("Parse_GetIdent: Calling '%s'\n", name);
                #endif
                // Function Call
-               ret = AST_NewFunctionCall( name );
+               ret = AST_NewFunctionCall( Parser, name );
                // Read arguments
                if( GetToken(Parser) != TOK_PAREN_CLOSE )
                {
@@ -573,7 +706,7 @@ tAST_Node *Parse_GetIdent(tParser *Parser)
                printf("Parse_GetIdent: Referencing '%s'\n", name);
                #endif
                PutBack(Parser);
-               ret = AST_NewConstant( name );
+               ret = AST_NewConstant( Parser, name );
        }
        
        free(name);

UCC git Repository :: git.ucc.asn.au