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
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);
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;
parser.CurPos = Buffer;
ret = AST_NewScript();
- mainCode = AST_NewCodeBlock();
+ mainCode = AST_NewCodeBlock(&parser);
// Give us an error fallback
if( setjmp( parser.JmpTarget ) != 0 )
// 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;
return Parse_DoBlockLine(Parser);
}
- ret = AST_NewCodeBlock();
+ ret = AST_NewCodeBlock(Parser);
while( LookAhead(Parser) != TOK_BRACE_CLOSE )
{
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;
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);
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);
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;
// --------------------
tAST_Node *Parse_DoExpr6(tParser *Parser)
{
- tAST_Node *ret = Parse_DoParen(Parser);
+ tAST_Node *ret = Parse_DoExpr7(Parser);
switch(GetToken(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
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",
*/
tAST_Node *Parse_GetNumeric(tParser *Parser)
{
- uint64_t value;
- GetToken( Parser );
- value = atoi( Parser->TokenStr );
+ uint64_t value = 0;
+ char *pos;
+ SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
+ 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 );
}
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
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 )
{
#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);