2 * Acess2 - SpiderScript
8 #include <spiderscript.h>
9 #define WANT_TOKEN_STRINGS 1
16 tAST_Script *Parse_Buffer(tSpiderVariant *Variant, char *Buffer);
17 tAST_Node *Parse_DoCodeBlock(tParser *Parser);
18 tAST_Node *Parse_DoBlockLine(tParser *Parser);
19 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type);
21 tAST_Node *Parse_DoExpr0(tParser *Parser); // Assignment
22 tAST_Node *Parse_DoExpr1(tParser *Parser); // Boolean Operators
23 tAST_Node *Parse_DoExpr2(tParser *Parser); // Comparison Operators
24 tAST_Node *Parse_DoExpr3(tParser *Parser); // Bitwise Operators
25 tAST_Node *Parse_DoExpr4(tParser *Parser); // Bit Shifts
26 tAST_Node *Parse_DoExpr5(tParser *Parser); // Arithmatic
27 tAST_Node *Parse_DoExpr6(tParser *Parser); // Mult & Div
29 tAST_Node *Parse_DoParen(tParser *Parser); // Parenthesis (Always Last)
30 tAST_Node *Parse_DoValue(tParser *Parser); // Values
32 tAST_Node *Parse_GetString(tParser *Parser);
33 tAST_Node *Parse_GetNumeric(tParser *Parser);
34 tAST_Node *Parse_GetVariable(tParser *Parser);
35 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate);
37 void SyntaxAssert(tParser *Parser, int Have, int Want);
39 #define TODO(Parser, message...) do {\
40 fprintf(stderr, "TODO: "message);\
41 longjmp(Parser->JmpTarget, -1);\
46 * \brief Parse a buffer into a syntax tree
48 tAST_Script *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
51 tParser *Parser = &parser; //< Keeps code consistent
59 printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer);
63 parser.LastToken = -1;
64 parser.NextToken = -1;
66 parser.BufStart = Buffer;
67 parser.CurPos = Buffer;
69 ret = AST_NewScript();
70 mainCode = AST_NewCodeBlock(&parser);
72 // Give us an error fallback
73 if( setjmp( parser.JmpTarget ) != 0 )
75 AST_FreeNode( mainCode );
80 while(Parser->Token != TOK_EOF)
82 switch( GetToken(Parser) )
87 // Typed variables/functions
88 case TOKEN_GROUP_TYPES:
91 TOKEN_GET_DATATYPE(type, Parser->Token);
93 tok = GetToken(Parser);
94 // Define a function (pass on to the other function definition code)
95 if( tok == TOK_IDENT ) {
99 else if( tok == TOK_VARIABLE ) {
100 AST_AppendNode( mainCode, Parse_GetVarDef(Parser, type) );
101 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
104 fprintf(stderr, "ERROR: Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
105 csaTOKEN_NAMES[tok]);
111 case TOK_RWD_FUNCTION:
112 if( !Variant->bDyamicTyped ) {
113 fprintf(stderr, "ERROR: Dynamic functions are invalid in static mode\n");
114 longjmp(Parser->JmpTarget, -1);
116 type = SS_DATATYPE_DYNAMIC;
117 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
119 name = strndup( Parser->TokenStr, Parser->TokenLen );
120 fcn = AST_AppendFunction( ret, name );
122 printf("DefFCN %s\n", name);
127 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
128 if( LookAhead(Parser) != TOK_PAREN_CLOSE )
131 type = SS_DATATYPE_DYNAMIC;
133 // Non dynamic typed variants must use data types
134 if( !Variant->bDyamicTyped ) {
135 TOKEN_GET_DATATYPE(type, Parser->Token);
138 AST_AppendFunctionArg(fcn, Parse_GetVarDef(Parser, type));
139 } while(GetToken(Parser) == TOK_COMMA);
143 SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
145 AST_SetFunctionCode( fcn, Parse_DoCodeBlock(Parser) );
150 AST_AppendNode( mainCode, Parse_DoBlockLine(Parser) );
155 fcn = AST_AppendFunction( ret, "" );
156 AST_SetFunctionCode( fcn, mainCode );
158 //printf("---- %p parsed as SpiderScript ----\n", Buffer);
164 * \brief Parse a block of code surrounded by { }
166 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
170 // Check if we are being called for a one-liner
171 if( GetToken(Parser) != TOK_BRACE_OPEN ) {
173 return Parse_DoBlockLine(Parser);
176 ret = AST_NewCodeBlock(Parser);
178 while( LookAhead(Parser) != TOK_BRACE_CLOSE )
180 AST_AppendNode( ret, Parse_DoBlockLine(Parser) );
182 GetToken(Parser); // Omnomnom
187 * \brief Parse a line in a block
189 tAST_Node *Parse_DoBlockLine(tParser *Parser)
193 //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
195 switch(LookAhead(Parser))
202 // Return from a method
205 ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
208 // Control Statements
211 tAST_Node *cond, *true, *false = NULL;
212 GetToken(Parser); // eat the if
213 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
214 cond = Parse_DoExpr0(Parser); // Get condition
215 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
216 true = Parse_DoCodeBlock(Parser);
217 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
219 false = Parse_DoCodeBlock(Parser);
221 ret = AST_NewIf(Parser, cond, true, false);
227 tAST_Node *init=NULL, *cond=NULL, *inc=NULL, *code;
228 GetToken(Parser); // Eat 'for'
229 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
231 if(LookAhead(Parser) != TOK_SEMICOLON)
232 init = Parse_DoExpr0(Parser);
234 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
236 if(LookAhead(Parser) != TOK_SEMICOLON)
237 cond = Parse_DoExpr0(Parser);
239 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
241 if(LookAhead(Parser) != TOK_PAREN_CLOSE)
242 inc = Parse_DoExpr0(Parser);
244 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
246 code = Parse_DoCodeBlock(Parser);
247 ret = AST_NewLoop(Parser, init, 0, cond, inc, code);
253 TODO(Parser, "Implement do and while\n");
257 case TOKEN_GROUP_TYPES:
261 switch(GetToken(Parser))
263 case TOK_RWD_INTEGER: type = SS_DATATYPE_INTEGER; break;
264 case TOK_RWD_OBJECT: type = SS_DATATYPE_OBJECT; break;
265 case TOK_RWD_REAL: type = SS_DATATYPE_REAL; break;
266 case TOK_RWD_STRING: type = SS_DATATYPE_STRING; break;
269 SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
271 ret = Parse_GetVarDef(Parser, type);
278 ret = Parse_DoExpr0(Parser);
282 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
287 * \brief Get a variable definition
289 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
291 char name[Parser->TokenLen];
294 SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
296 // copy the name (trimming the $)
297 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
298 name[Parser->TokenLen-1] = 0;
299 // Define the variable
300 ret = AST_NewDefineVar(Parser, Type, name);
302 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
305 AST_AppendNode(ret, Parse_DoExpr0(Parser));
306 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
312 * \brief Assignment Operations
314 tAST_Node *Parse_DoExpr0(tParser *Parser)
316 tAST_Node *ret = Parse_DoExpr1(Parser);
319 switch(LookAhead(Parser))
322 GetToken(Parser); // Eat Token
323 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
326 GetToken(Parser); // Eat Token
327 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
330 GetToken(Parser); // Eat Token
331 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
333 case TOK_ASSIGN_PLUS:
334 GetToken(Parser); // Eat Token
335 ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, Parse_DoExpr0(Parser));
337 case TOK_ASSIGN_MINUS:
338 GetToken(Parser); // Eat Token
339 ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr0(Parser));
343 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
351 * \brief Logical/Boolean Operators
353 tAST_Node *Parse_DoExpr1(tParser *Parser)
355 tAST_Node *ret = Parse_DoExpr2(Parser);
357 switch(GetToken(Parser))
360 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
363 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
366 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
375 // --------------------
376 // Expression 2 - Comparison Operators
377 // --------------------
378 tAST_Node *Parse_DoExpr2(tParser *Parser)
380 tAST_Node *ret = Parse_DoExpr3(Parser);
383 switch(GetToken(Parser))
386 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
389 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
392 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
402 * \brief Bitwise Operations
404 tAST_Node *Parse_DoExpr3(tParser *Parser)
406 tAST_Node *ret = Parse_DoExpr4(Parser);
409 switch(GetToken(Parser))
412 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
415 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
418 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
427 // --------------------
428 // Expression 4 - Shifts
429 // --------------------
430 tAST_Node *Parse_DoExpr4(tParser *Parser)
432 tAST_Node *ret = Parse_DoExpr5(Parser);
434 switch(GetToken(Parser))
437 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
440 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
450 // --------------------
451 // Expression 5 - Arithmatic
452 // --------------------
453 tAST_Node *Parse_DoExpr5(tParser *Parser)
455 tAST_Node *ret = Parse_DoExpr6(Parser);
457 switch(GetToken(Parser))
460 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
463 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
473 // --------------------
474 // Expression 6 - Multiplcation & Division
475 // --------------------
476 tAST_Node *Parse_DoExpr6(tParser *Parser)
478 tAST_Node *ret = Parse_DoParen(Parser);
480 switch(GetToken(Parser))
483 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
486 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
497 // --------------------
498 // 2nd Last Expression - Parens
499 // --------------------
500 tAST_Node *Parse_DoParen(tParser *Parser)
503 printf("Parse_DoParen: (Parser=%p)\n", Parser);
505 if(LookAhead(Parser) == TOK_PAREN_OPEN)
511 // TODO: Handle casts here
512 switch(LookAhead(Parser))
514 case TOKEN_GROUP_TYPES:
516 TOKEN_GET_DATATYPE(type, Parser->Token);
517 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
518 ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
521 ret = Parse_DoExpr0(Parser);
522 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
528 return Parse_DoValue(Parser);
531 // --------------------
532 // Last Expression - Value
533 // --------------------
534 tAST_Node *Parse_DoValue(tParser *Parser)
536 int tok = LookAhead(Parser);
539 printf("Parse_DoValue: tok = %i\n", tok);
544 case TOK_STR: return Parse_GetString(Parser);
545 case TOK_INTEGER: return Parse_GetNumeric(Parser);
546 case TOK_IDENT: return Parse_GetIdent(Parser, 0);
547 case TOK_VARIABLE: return Parse_GetVariable(Parser);
549 GetToken(Parser); // Omnomnom
550 return Parse_GetIdent(Parser, 1);
553 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
554 csaTOKEN_NAMES[tok], Parser->CurLine);
555 longjmp( Parser->JmpTarget, -1 );
560 * \brief Get a string
562 tAST_Node *Parse_GetString(tParser *Parser)
569 char data[ Parser->TokenLen - 2 ];
572 for( i = 1; i < Parser->TokenLen - 1; i++ )
574 if( Parser->TokenStr[i] == '\\' ) {
576 switch( Parser->TokenStr[i] )
578 case 'n': data[j++] = '\n'; break;
579 case 'r': data[j++] = '\r'; break;
582 // TODO: Error/Warning?
587 data[j++] = Parser->TokenStr[i];
591 // TODO: Parse Escape Codes
592 ret = AST_NewString( Parser, data, j );
598 * \brief Get a numeric value
600 tAST_Node *Parse_GetNumeric(tParser *Parser)
605 pos = Parser->TokenStr;
606 //printf("pos = %p, *pos = %c\n", pos, *pos);
616 if( '0' <= *pos && *pos <= '9' ) {
620 if( 'A' <= *pos && *pos <= 'F' ) {
621 value += *pos - 'A' + 10;
624 if( 'a' <= *pos && *pos <= 'f' ) {
625 value += *pos - 'a' + 10;
632 while( '0' <= *pos && *pos <= '7' ) {
633 value = value*8 + *pos - '0';
639 while( '0' <= *pos && *pos <= '9' ) {
640 value = value*10 + *pos - '0';
645 return AST_NewInteger( Parser, value );
649 * \brief Get a variable
651 tAST_Node *Parse_GetVariable(tParser *Parser)
654 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
656 char name[Parser->TokenLen];
657 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
658 name[Parser->TokenLen-1] = 0;
659 ret = AST_NewVariable( Parser, name );
661 printf("Parse_GetVariable: name = '%s'\n", name);
667 if( Parser->Token == TOK_SQUARE_OPEN )
669 ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
670 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
673 if( Parser->Token == TOK_ELEMENT )
675 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
677 if( LookAhead(Parser) == TOK_PAREN_OPEN )
679 char name[Parser->TokenLen+1];
680 memcpy(name, Parser->TokenStr, Parser->TokenLen);
681 name[Parser->TokenLen] = 0;
682 ret = AST_NewMethodCall(Parser, ret, name);
683 GetToken(Parser); // Eat the '('
685 if( GetToken(Parser) != TOK_PAREN_CLOSE )
689 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
690 } while(GetToken(Parser) == TOK_COMMA);
691 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
698 char name[Parser->TokenLen];
699 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
700 name[Parser->TokenLen-1] = 0;
701 ret = AST_NewClassElement(Parser, ret, name);
713 * \brief Get an identifier (constant or function call)
715 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
717 tAST_Node *ret = NULL;
719 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
720 name = strndup( Parser->TokenStr, Parser->TokenLen );
723 if( GetToken(Parser) == TOK_SCOPE )
725 ret = AST_NewScopeDereference( Parser, Parse_GetIdent(Parser, bObjectCreate), name );
732 if( GetToken(Parser) == TOK_PAREN_OPEN )
735 printf("Parse_GetIdent: Calling '%s'\n", name);
739 ret = AST_NewCreateObject( Parser, name );
741 ret = AST_NewFunctionCall( Parser, name );
743 if( GetToken(Parser) != TOK_PAREN_CLOSE )
748 printf(" Parse_GetIdent: Argument\n");
750 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
751 } while(GetToken(Parser) == TOK_COMMA);
752 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
754 printf(" Parse_GetIdent: All arguments parsed\n");
760 // Runtime Constant / Variable (When implemented)
762 printf("Parse_GetIdent: Referencing '%s'\n", name);
765 if( bObjectCreate ) // Void constructor (TODO: Should this be an error?)
766 ret = AST_NewCreateObject( Parser, name );
768 ret = AST_NewConstant( Parser, name );
776 * \brief Check for an error
778 void SyntaxAssert(tParser *Parser, int Have, int Want)
781 fprintf(stderr, "ERROR: SyntaxAssert Failed, Expected %s(%i), got %s(%i) on line %i\n",
782 csaTOKEN_NAMES[Want], Want, csaTOKEN_NAMES[Have], Have, Parser->CurLine);
783 longjmp(Parser->JmpTarget, -1);