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);
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 consitent
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();
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: Attempt to create a dynamic function\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();
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))
198 // Return from a method
200 //printf("return\n");
202 ret = AST_NewUniOp(NODETYPE_RETURN, Parse_DoExpr0(Parser));
205 // Control Statements
208 tAST_Node *cond, *true, *false = NULL;
209 GetToken(Parser); // eat the if
210 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
211 cond = Parse_DoExpr0(Parser); // Get condition
212 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
213 true = Parse_DoCodeBlock(Parser);
214 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
216 false = Parse_DoCodeBlock(Parser);
218 ret = AST_NewIf(cond, true, false);
224 TODO(Parser, "Implement if, for, do and while\n");
228 case TOKEN_GROUP_TYPES:
232 switch(GetToken(Parser))
234 case TOK_RWD_INTEGER: type = SS_DATATYPE_INTEGER; break;
235 case TOK_RWD_OBJECT: type = SS_DATATYPE_OBJECT; break;
236 case TOK_RWD_REAL: type = SS_DATATYPE_REAL; break;
237 case TOK_RWD_STRING: type = SS_DATATYPE_STRING; break;
240 SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
242 ret = Parse_GetVarDef(Parser, type);
249 ret = Parse_DoExpr0(Parser);
253 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
258 * \brief Get a variable definition
260 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
262 char name[Parser->TokenLen];
265 SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
267 // copy the name (trimming the $)
268 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
269 name[Parser->TokenLen-1] = 0;
270 // Define the variable
271 ret = AST_NewDefineVar(Type, name);
273 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
276 AST_AppendNode(ret, Parse_DoExpr0(Parser));
277 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
283 * \brief Assignment Operations
285 tAST_Node *Parse_DoExpr0(tParser *Parser)
287 tAST_Node *ret = Parse_DoExpr1(Parser);
290 switch(LookAhead(Parser))
293 GetToken(Parser); // Eat Token
294 ret = AST_NewAssign(NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
298 GetToken(Parser); // Eat Token
299 ret = AST_NewAssign(NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
302 GetToken(Parser); // Eat Token
303 ret = AST_NewAssign(NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
308 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
316 * \brief Logical/Boolean Operators
318 tAST_Node *Parse_DoExpr1(tParser *Parser)
320 tAST_Node *ret = Parse_DoExpr2(Parser);
322 switch(GetToken(Parser))
325 ret = AST_NewBinOp(NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
328 ret = AST_NewBinOp(NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
331 ret = AST_NewBinOp(NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
340 // --------------------
341 // Expression 2 - Comparison Operators
342 // --------------------
343 tAST_Node *Parse_DoExpr2(tParser *Parser)
345 tAST_Node *ret = Parse_DoExpr3(Parser);
348 switch(GetToken(Parser))
351 ret = AST_NewBinOp(NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
354 ret = AST_NewBinOp(NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
357 ret = AST_NewBinOp(NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
367 * \brief Bitwise Operations
369 tAST_Node *Parse_DoExpr3(tParser *Parser)
371 tAST_Node *ret = Parse_DoExpr4(Parser);
374 switch(GetToken(Parser))
377 ret = AST_NewBinOp(NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
380 ret = AST_NewBinOp(NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
383 ret = AST_NewBinOp(NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
392 // --------------------
393 // Expression 4 - Shifts
394 // --------------------
395 tAST_Node *Parse_DoExpr4(tParser *Parser)
397 tAST_Node *ret = Parse_DoExpr5(Parser);
399 switch(GetToken(Parser))
402 ret = AST_NewBinOp(NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
405 ret = AST_NewBinOp(NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
415 // --------------------
416 // Expression 5 - Arithmatic
417 // --------------------
418 tAST_Node *Parse_DoExpr5(tParser *Parser)
420 tAST_Node *ret = Parse_DoExpr6(Parser);
422 switch(GetToken(Parser))
425 ret = AST_NewBinOp(NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
428 ret = AST_NewBinOp(NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
438 // --------------------
439 // Expression 6 - Multiplcation & Division
440 // --------------------
441 tAST_Node *Parse_DoExpr6(tParser *Parser)
443 tAST_Node *ret = Parse_DoParen(Parser);
445 switch(GetToken(Parser))
448 ret = AST_NewBinOp(NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
451 ret = AST_NewBinOp(NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
462 // --------------------
463 // 2nd Last Expression - Parens
464 // --------------------
465 tAST_Node *Parse_DoParen(tParser *Parser)
468 printf("Parse_DoParen: (Parser=%p)\n", Parser);
470 if(LookAhead(Parser) == TOK_PAREN_OPEN)
475 // TODO: Handle casts here
477 ret = Parse_DoExpr0(Parser);
478 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
482 return Parse_DoValue(Parser);
485 // --------------------
486 // Last Expression - Value
487 // --------------------
488 tAST_Node *Parse_DoValue(tParser *Parser)
490 int tok = LookAhead(Parser);
493 printf("Parse_DoValue: tok = %i\n", tok);
498 case TOK_STR: return Parse_GetString(Parser);
499 case TOK_INTEGER: return Parse_GetNumeric(Parser);
500 case TOK_IDENT: return Parse_GetIdent(Parser);
501 case TOK_VARIABLE: return Parse_GetVariable(Parser);
504 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
505 csaTOKEN_NAMES[tok], Parser->CurLine);
506 longjmp( Parser->JmpTarget, -1 );
511 * \brief Get a string
513 tAST_Node *Parse_GetString(tParser *Parser)
517 // TODO: Parse Escape Codes
518 ret = AST_NewString( Parser->TokenStr+1, Parser->TokenLen-2 );
523 * \brief Get a numeric value
525 tAST_Node *Parse_GetNumeric(tParser *Parser)
529 value = atoi( Parser->TokenStr );
530 return AST_NewInteger( value );
534 * \brief Get a variable
536 tAST_Node *Parse_GetVariable(tParser *Parser)
539 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
541 char name[Parser->TokenLen];
542 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
543 name[Parser->TokenLen-1] = 0;
544 ret = AST_NewVariable( name );
546 printf("Parse_GetVariable: name = '%s'\n", name);
549 // Handle array references
550 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
553 ret = AST_NewBinOp(NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
554 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
560 * \brief Get an identifier (constand or function call)
562 tAST_Node *Parse_GetIdent(tParser *Parser)
566 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
567 name = strndup( Parser->TokenStr, Parser->TokenLen );
570 while( GetToken(Parser) == TOK_SCOPE )
577 if( GetToken(Parser) == TOK_PAREN_OPEN )
580 printf("Parse_GetIdent: Calling '%s'\n", name);
583 ret = AST_NewFunctionCall( name );
585 if( GetToken(Parser) != TOK_PAREN_CLOSE )
590 printf(" Parse_GetIdent: Argument\n");
592 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
593 } while(GetToken(Parser) == TOK_COMMA);
594 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
596 printf(" Parse_GetIdent: All arguments parsed\n");
603 printf("Parse_GetIdent: Referencing '%s'\n", name);
606 ret = AST_NewConstant( name );
614 * \brief Check for an error
616 void SyntaxAssert(tParser *Parser, int Have, int Want)
619 fprintf(stderr, "ERROR: SyntaxAssert Failed, Expected %s(%i), got %s(%i) on line %i\n",
620 csaTOKEN_NAMES[Want], Want, csaTOKEN_NAMES[Have], Have, Parser->CurLine);
621 longjmp(Parser->JmpTarget, -1);