X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibspiderscript.so_src%2Fparse.c;h=0b4819800ef21659c88395a59cf3d3a2e36c8eb2;hb=270e5fe88b0666021a7a6393334db7feeb8245f8;hp=5622123e71cc0f9ca7691347e43eda272d9af765;hpb=86f49ede5038704ac4f12eab9794e9a8110a4985;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libspiderscript.so_src/parse.c b/Usermode/Libraries/libspiderscript.so_src/parse.c index 5622123e..0b481980 100644 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ b/Usermode/Libraries/libspiderscript.so_src/parse.c @@ -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,62 @@ 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 +295,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 +318,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 +349,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 +375,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 +401,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 +426,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 +449,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 +472,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 +497,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 +551,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 +588,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 +645,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,18 +654,18 @@ 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; } /** - * \brief Get an identifier (constand or function call) + * \brief Get an identifier (constant or function call) */ tAST_Node *Parse_GetIdent(tParser *Parser) { - tAST_Node *ret; + tAST_Node *ret = NULL; char *name; SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT ); name = strndup( Parser->TokenStr, Parser->TokenLen ); @@ -539,7 +673,9 @@ tAST_Node *Parse_GetIdent(tParser *Parser) #if 0 while( GetToken(Parser) == TOK_SCOPE ) { - ret = AST_New + ret = AST_NewScopeDereference( Parser, ret, name ); + SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT ); + name = strndup( Parser->TokenStr, Parser->TokenLen ); } PutBack(Parser); #endif @@ -550,7 +686,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 ) { @@ -568,12 +704,12 @@ tAST_Node *Parse_GetIdent(tParser *Parser) } } else { - // Runtime Constant + // Runtime Constant / Variable (When implemented) #if DEBUG >= 2 printf("Parse_GetIdent: Referencing '%s'\n", name); #endif PutBack(Parser); - ret = AST_NewConstant( name ); + ret = AST_NewConstant( Parser, name ); } free(name);