SpiderScript - Moar fixes, mostly speedups (caching values and lookups)
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / parse.c
index 3ac6fa8..c3a6824 100644 (file)
@@ -25,6 +25,8 @@ tAST_Node     *Parse_DoExpr3(tParser *Parser);        // Bitwise Operators
 tAST_Node      *Parse_DoExpr4(tParser *Parser);        // Bit Shifts
 tAST_Node      *Parse_DoExpr5(tParser *Parser);        // Arithmatic
 tAST_Node      *Parse_DoExpr6(tParser *Parser);        // Mult & Div
+tAST_Node      *Parse_DoExpr7(tParser *Parser);        // Right Unary Operations
+tAST_Node      *Parse_DoExpr8(tParser *Parser);        // Left Unary Operations
 
 tAST_Node      *Parse_DoParen(tParser *Parser);        // Parenthesis (Always Last)
 tAST_Node      *Parse_DoValue(tParser *Parser);        // Values
@@ -32,7 +34,7 @@ tAST_Node     *Parse_DoValue(tParser *Parser);        // Values
 tAST_Node      *Parse_GetString(tParser *Parser);
 tAST_Node      *Parse_GetNumeric(tParser *Parser);
 tAST_Node      *Parse_GetVariable(tParser *Parser);
-tAST_Node      *Parse_GetIdent(tParser *Parser);
+tAST_Node      *Parse_GetIdent(tParser *Parser, int bObjectCreate);
 
 void   SyntaxAssert(tParser *Parser, int Have, int Want);
 
@@ -48,7 +50,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;
@@ -67,7 +69,7 @@ tAST_Script   *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
        parser.CurPos = Buffer;
        
        ret = AST_NewScript();
-       mainCode = AST_NewCodeBlock();
+       mainCode = AST_NewCodeBlock(&parser);
        
        // Give us an error fallback
        if( setjmp( parser.JmpTarget ) != 0 )
@@ -173,7 +175,7 @@ tAST_Node *Parse_DoCodeBlock(tParser *Parser)
                return Parse_DoBlockLine(Parser);
        }
        
-       ret = AST_NewCodeBlock();
+       ret = AST_NewCodeBlock(Parser);
        
        while( LookAhead(Parser) != TOK_BRACE_CLOSE )
        {
@@ -194,10 +196,13 @@ 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(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
                break;
@@ -215,27 +220,68 @@ tAST_Node *Parse_DoBlockLine(tParser *Parser)
                        GetToken(Parser);
                        false = Parse_DoCodeBlock(Parser);
                }
+               else
+                       false = AST_NewNop(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_PAREN_CLOSE)
+                       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 if, for, do and while\n");
+               {
+               tAST_Node       *code, *cond;
+               GetToken(Parser);       // Eat 'do'
+               code = Parse_DoCodeBlock(Parser);
+               SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
+               SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
+               cond = Parse_DoExpr0(Parser);
+               SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
+               ret = AST_NewLoop(Parser, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code);
+               }
                break;
+       case TOK_RWD_WHILE:
+               {
+               tAST_Node       *code, *cond;
+               GetToken(Parser);       // Eat 'while'
+               SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
+               cond = Parse_DoExpr0(Parser);
+               SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
+               code = Parse_DoCodeBlock(Parser);
+               ret = AST_NewLoop(Parser, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
+               }
+               return ret;
        
        // Define Variables
        case TOKEN_GROUP_TYPES:
                {
                         int    type;
-                       
-                       switch(GetToken(Parser))
-                       {
-                       case TOK_RWD_INTEGER:   type = SS_DATATYPE_INTEGER;     break;
-                       case TOK_RWD_OBJECT:    type = SS_DATATYPE_OBJECT;      break;
-                       case TOK_RWD_REAL:      type = SS_DATATYPE_REAL;        break;
-                       case TOK_RWD_STRING:    type = SS_DATATYPE_STRING;      break;
-                       }
+                       GetToken(Parser);
+                       TOKEN_GET_DATATYPE(type, Parser->Token);
                        
                        SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
                        
@@ -293,16 +339,22 @@ tAST_Node *Parse_DoExpr0(tParser *Parser)
                GetToken(Parser);               // Eat Token
                ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
                break;
-       #if 0
-       case TOK_DIV_EQU:
+       case TOK_ASSIGN_DIV:
                GetToken(Parser);               // Eat Token
                ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
                break;
-       case TOK_MULT_EQU:
+       case TOK_ASSIGN_MUL:
                GetToken(Parser);               // Eat Token
                ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
                break;
-       #endif
+       case TOK_ASSIGN_PLUS:
+               GetToken(Parser);               // Eat Token
+               ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, Parse_DoExpr0(Parser));
+               break;
+       case TOK_ASSIGN_MINUS:
+               GetToken(Parser);               // Eat Token
+               ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr0(Parser));
+               break;
        default:
                #if DEBUG >= 2
                printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
@@ -356,6 +408,12 @@ tAST_Node *Parse_DoExpr2(tParser *Parser)
        case TOK_GT:
                ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
                break;
+       case TOK_LTE:
+               ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, Parse_DoExpr2(Parser));
+               break;
+       case TOK_GTE:
+               ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, Parse_DoExpr2(Parser));
+               break;
        default:
                PutBack(Parser);
                break;
@@ -440,7 +498,7 @@ tAST_Node *Parse_DoExpr5(tParser *Parser)
 // --------------------
 tAST_Node *Parse_DoExpr6(tParser *Parser)
 {
-       tAST_Node *ret = Parse_DoParen(Parser);
+       tAST_Node *ret = Parse_DoExpr7(Parser);
 
        switch(GetToken(Parser))
        {
@@ -458,6 +516,46 @@ tAST_Node *Parse_DoExpr6(tParser *Parser)
        return ret;
 }
 
+// Right Unary Operations
+tAST_Node *Parse_DoExpr7(tParser *Parser)
+{
+       tAST_Node *ret = Parse_DoExpr8(Parser);
+       
+       switch(GetToken(Parser))
+       {
+       case TOK_INCREMENT:
+               ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
+               break;
+       case TOK_DECREMENT:
+               ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
+               break;
+       default:
+               PutBack(Parser);
+               break;
+       }
+       return ret;
+}
+
+// Left Unary Operations
+tAST_Node *Parse_DoExpr8(tParser *Parser)
+{
+       switch(GetToken(Parser))
+       {
+       case TOK_INCREMENT:
+               return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
+       case TOK_DECREMENT:
+               return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
+       case TOK_MINUS:
+               return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
+       case TOK_LOGICNOT:
+               return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
+       case TOK_BWNOT:
+               return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
+       default:
+               PutBack(Parser);
+               return Parse_DoParen(Parser);
+       }
+}
 
 // --------------------
 // 2nd Last Expression - Parens
@@ -506,10 +604,20 @@ tAST_Node *Parse_DoValue(tParser *Parser)
 
        switch(tok)
        {
-       case TOK_STR:   return Parse_GetString(Parser);
-       case TOK_INTEGER:       return Parse_GetNumeric(Parser);
-       case TOK_IDENT: return Parse_GetIdent(Parser);
+       case TOK_STR:
+               return Parse_GetString(Parser);
+       case TOK_INTEGER:
+               return Parse_GetNumeric(Parser);
+       
+       case TOK_REAL:
+               GetToken(Parser);
+               return AST_NewReal( Parser, atof(Parser->TokenStr) );
+       
+       case TOK_IDENT: return Parse_GetIdent(Parser, 0);
        case TOK_VARIABLE:      return Parse_GetVariable(Parser);
+       case TOK_RWD_NEW:
+               GetToken(Parser);       // Omnomnom
+               return Parse_GetIdent(Parser, 1);
 
        default:
                fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
@@ -563,7 +671,7 @@ tAST_Node *Parse_GetNumeric(tParser *Parser)
 {
        uint64_t        value = 0;
        char    *pos;
-       GetToken( Parser );
+       SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
        pos = Parser->TokenStr;
        //printf("pos = %p, *pos = %c\n", pos, *pos);
                
@@ -623,30 +731,70 @@ tAST_Node *Parse_GetVariable(tParser *Parser)
                printf("Parse_GetVariable: name = '%s'\n", name);
                #endif
        }
-       // Handle array references
-       while( LookAhead(Parser) == TOK_SQUARE_OPEN )
+       for(;;)
        {
                GetToken(Parser);
-               ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
-               SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
+               if( Parser->Token == TOK_SQUARE_OPEN )
+               {
+                       ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
+                       SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
+                       continue ;
+               }
+               if( Parser->Token == TOK_ELEMENT )
+               {
+                       SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
+                       // Method Call
+                       if( LookAhead(Parser) == TOK_PAREN_OPEN )
+                       {
+                               char    name[Parser->TokenLen+1];
+                               memcpy(name, Parser->TokenStr, Parser->TokenLen);
+                               name[Parser->TokenLen] = 0;
+                               ret = AST_NewMethodCall(Parser, ret, name);
+                               GetToken(Parser);       // Eat the '('
+                               // Read arguments
+                               if( GetToken(Parser) != TOK_PAREN_CLOSE )
+                               {
+                                       PutBack(Parser);
+                                       do {
+                                               AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
+                                       } while(GetToken(Parser) == TOK_COMMA);
+                                       SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
+                               }
+                               
+                       }
+                       // Attribute
+                       else
+                       {
+                               char    name[Parser->TokenLen];
+                               memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
+                               name[Parser->TokenLen-1] = 0;
+                               ret = AST_NewClassElement(Parser, ret, name);
+                       }
+                       continue ;
+               }
+               
+               break ;
        }
+       PutBack(Parser);
        return ret;
 }
 
 /**
- * \brief Get an identifier (constand or function call)
+ * \brief Get an identifier (constant or function call)
  */
-tAST_Node *Parse_GetIdent(tParser *Parser)
+tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
 {
-       tAST_Node       *ret;
+       tAST_Node       *ret = NULL;
        char    *name;
        SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
        name = strndup( Parser->TokenStr, Parser->TokenLen );
        
-       #if 0
-       while( GetToken(Parser) == TOK_SCOPE )
+       #if USE_SCOPE_CHAR
+       if( GetToken(Parser) == TOK_SCOPE )
        {
-               ret = AST_New
+               ret = AST_NewScopeDereference( Parser, Parse_GetIdent(Parser, bObjectCreate), name );
+               free(name);
+               return ret;
        }
        PutBack(Parser);
        #endif
@@ -657,7 +805,10 @@ tAST_Node *Parse_GetIdent(tParser *Parser)
                printf("Parse_GetIdent: Calling '%s'\n", name);
                #endif
                // Function Call
-               ret = AST_NewFunctionCall( Parser, name );
+               if( bObjectCreate )
+                       ret = AST_NewCreateObject( Parser, name );
+               else
+                       ret = AST_NewFunctionCall( Parser, name );
                // Read arguments
                if( GetToken(Parser) != TOK_PAREN_CLOSE )
                {
@@ -674,13 +825,17 @@ tAST_Node *Parse_GetIdent(tParser *Parser)
                        #endif
                }
        }
-       else {
-               // Runtime Constant
+       else
+       {
+               // Runtime Constant / Variable (When implemented)
                #if DEBUG >= 2
                printf("Parse_GetIdent: Referencing '%s'\n", name);
                #endif
                PutBack(Parser);
-               ret = AST_NewConstant( Parser, name );
+               if( bObjectCreate )     // Void constructor (TODO: Should this be an error?)
+                       ret = AST_NewCreateObject( Parser, name );
+               else
+                       ret = AST_NewConstant( Parser, name );
        }
        
        free(name);

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