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);
41 * \brief Parse a buffer into a syntax tree
43 tAST_Script *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
46 tParser *Parser = &parser; //< Keeps code consitent
54 printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer);
58 parser.LastToken = -1;
59 parser.NextToken = -1;
61 parser.BufStart = Buffer;
62 parser.CurPos = Buffer;
64 ret = AST_NewScript();
65 mainCode = AST_NewCodeBlock();
67 if( setjmp( parser.JmpTarget ) != 0 )
69 AST_FreeNode( mainCode );
73 while(Parser->Token != TOK_EOF)
75 switch( GetToken(Parser) )
80 // Typed variables/functions
81 case TOKEN_GROUP_TYPES:
84 TOKEN_GET_DATATYPE(type, Parser->Token);
86 tok = GetToken(Parser);
87 // Define a function (pass on to the other function definition code)
88 if( tok == TOK_IDENT ) {
92 else if( tok == TOK_VARIABLE ) {
93 AST_AppendNode( mainCode, Parse_GetVarDef(Parser, type) );
94 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
97 fprintf(stderr, "ERROR: Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
104 case TOK_RWD_FUNCTION:
105 if( !Variant->bDyamicTyped ) {
106 fprintf(stderr, "ERROR: Attempt to create a dynamic function\n");
107 longjmp(Parser->JmpTarget, -1);
109 type = SS_DATATYPE_DYNAMIC;
110 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
112 name = strndup( Parser->TokenStr, Parser->TokenLen );
113 fcn = AST_AppendFunction( ret, name );
115 printf("DefFCN %s\n", name);
120 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
121 if( LookAhead(Parser) != TOK_PAREN_CLOSE )
124 type = SS_DATATYPE_DYNAMIC;
126 // Non dynamic typed variants must use data types
127 if( !Variant->bDyamicTyped ) {
128 TOKEN_GET_DATATYPE(type, Parser->Token);
131 AST_AppendFunctionArg(fcn, Parse_GetVarDef(Parser, type));
132 } while(GetToken(Parser) == TOK_COMMA);
136 SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
138 AST_SetFunctionCode( fcn, Parse_DoCodeBlock(Parser) );
143 AST_AppendNode( mainCode, Parse_DoBlockLine(Parser) );
148 fcn = AST_AppendFunction( ret, "" );
149 AST_SetFunctionCode( fcn, mainCode );
151 printf("---- %p parsed as SpiderScript ----\n", Buffer);
157 * \brief Parse a block of code surrounded by { }
159 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
162 SyntaxAssert(Parser, GetToken(Parser), TOK_BRACE_OPEN );
164 ret = AST_NewCodeBlock();
166 while( LookAhead(Parser) != TOK_BRACE_CLOSE )
168 AST_AppendNode( ret, Parse_DoBlockLine(Parser) );
170 GetToken(Parser); // Omnomnom
175 * \brief Parse a line in a block
177 tAST_Node *Parse_DoBlockLine(tParser *Parser)
181 //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
183 switch(LookAhead(Parser))
186 // Return from a method
188 //printf("return\n");
190 ret = AST_NewUniOp(NODETYPE_RETURN, Parse_DoExpr0(Parser));
193 // Control Statements
198 case TOKEN_GROUP_TYPES:
202 switch(GetToken(Parser))
204 case TOK_RWD_INTEGER: type = SS_DATATYPE_INTEGER; break;
205 case TOK_RWD_OBJECT: type = SS_DATATYPE_OBJECT; break;
206 case TOK_RWD_REAL: type = SS_DATATYPE_REAL; break;
207 case TOK_RWD_STRING: type = SS_DATATYPE_STRING; break;
210 SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
212 ret = Parse_GetVarDef(Parser, type);
219 ret = Parse_DoExpr0(Parser);
223 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
228 * \brief Get a variable definition
230 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
232 char name[Parser->TokenLen];
235 SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
237 // copy the name (trimming the $)
238 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
239 name[Parser->TokenLen-1] = 0;
240 // Define the variable
241 ret = AST_NewDefineVar(Type, name);
243 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
246 AST_AppendNode(ret, Parse_DoExpr0(Parser));
247 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
253 * \brief Assignment Operations
255 tAST_Node *Parse_DoExpr0(tParser *Parser)
257 tAST_Node *ret = Parse_DoExpr1(Parser);
260 switch(LookAhead(Parser))
263 GetToken(Parser); // Eat Token
264 ret = AST_NewAssign(NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
268 GetToken(Parser); // Eat Token
269 ret = AST_NewAssign(NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
272 GetToken(Parser); // Eat Token
273 ret = AST_NewAssign(NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
278 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
286 * \brief Logical/Boolean Operators
288 tAST_Node *Parse_DoExpr1(tParser *Parser)
290 tAST_Node *ret = Parse_DoExpr2(Parser);
292 switch(GetToken(Parser))
295 ret = AST_NewBinOp(NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
298 ret = AST_NewBinOp(NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
301 ret = AST_NewBinOp(NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
310 // --------------------
311 // Expression 2 - Comparison Operators
312 // --------------------
313 tAST_Node *Parse_DoExpr2(tParser *Parser)
315 tAST_Node *ret = Parse_DoExpr3(Parser);
318 switch(GetToken(Parser))
321 ret = AST_NewBinOp(NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
324 ret = AST_NewBinOp(NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
327 ret = AST_NewBinOp(NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
337 * \brief Bitwise Operations
339 tAST_Node *Parse_DoExpr3(tParser *Parser)
341 tAST_Node *ret = Parse_DoExpr4(Parser);
344 switch(GetToken(Parser))
347 ret = AST_NewBinOp(NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
350 ret = AST_NewBinOp(NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
353 ret = AST_NewBinOp(NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
362 // --------------------
363 // Expression 4 - Shifts
364 // --------------------
365 tAST_Node *Parse_DoExpr4(tParser *Parser)
367 tAST_Node *ret = Parse_DoExpr5(Parser);
369 switch(GetToken(Parser))
372 ret = AST_NewBinOp(NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
375 ret = AST_NewBinOp(NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
385 // --------------------
386 // Expression 5 - Arithmatic
387 // --------------------
388 tAST_Node *Parse_DoExpr5(tParser *Parser)
390 tAST_Node *ret = Parse_DoExpr6(Parser);
392 switch(GetToken(Parser))
395 ret = AST_NewBinOp(NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
398 ret = AST_NewBinOp(NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
408 // --------------------
409 // Expression 6 - Multiplcation & Division
410 // --------------------
411 tAST_Node *Parse_DoExpr6(tParser *Parser)
413 tAST_Node *ret = Parse_DoParen(Parser);
415 switch(GetToken(Parser))
418 ret = AST_NewBinOp(NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
421 ret = AST_NewBinOp(NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
432 // --------------------
433 // 2nd Last Expression - Parens
434 // --------------------
435 tAST_Node *Parse_DoParen(tParser *Parser)
438 printf("Parse_DoParen: (Parser=%p)\n", Parser);
440 if(LookAhead(Parser) == TOK_PAREN_OPEN)
445 // TODO: Handle casts here
447 ret = Parse_DoExpr0(Parser);
448 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
452 return Parse_DoValue(Parser);
455 // --------------------
456 // Last Expression - Value
457 // --------------------
458 tAST_Node *Parse_DoValue(tParser *Parser)
460 int tok = LookAhead(Parser);
463 printf("Parse_DoValue: tok = %i\n", tok);
468 case TOK_STR: return Parse_GetString(Parser);
469 case TOK_INTEGER: return Parse_GetNumeric(Parser);
470 case TOK_IDENT: return Parse_GetIdent(Parser);
471 case TOK_VARIABLE: return Parse_GetVariable(Parser);
474 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
475 csaTOKEN_NAMES[tok], Parser->CurLine);
476 longjmp( Parser->JmpTarget, -1 );
481 * \brief Get a string
483 tAST_Node *Parse_GetString(tParser *Parser)
487 // TODO: Parse Escape Codes
488 ret = AST_NewString( Parser->TokenStr+1, Parser->TokenLen-2 );
493 * \brief Get a numeric value
495 tAST_Node *Parse_GetNumeric(tParser *Parser)
499 value = atoi( Parser->TokenStr );
500 return AST_NewInteger( value );
504 * \brief Get a variable
506 tAST_Node *Parse_GetVariable(tParser *Parser)
509 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
511 char name[Parser->TokenLen];
512 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
513 name[Parser->TokenLen-1] = 0;
514 ret = AST_NewVariable( name );
516 printf("Parse_GetVariable: name = '%s'\n", name);
519 // Handle array references
520 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
523 ret = AST_NewBinOp(NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
524 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
530 * \brief Get an identifier (constand or function call)
532 tAST_Node *Parse_GetIdent(tParser *Parser)
536 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
537 name = strndup( Parser->TokenStr, Parser->TokenLen );
540 while( GetToken(Parser) == TOK_SCOPE )
547 if( GetToken(Parser) == TOK_PAREN_OPEN )
550 printf("Parse_GetIdent: Calling '%s'\n", name);
553 ret = AST_NewFunctionCall( name );
555 if( GetToken(Parser) != TOK_PAREN_CLOSE )
560 printf(" Parse_GetIdent: Argument\n");
562 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
563 } while(GetToken(Parser) == TOK_COMMA);
564 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
566 printf(" Parse_GetIdent: All arguments parsed\n");
573 printf("Parse_GetIdent: Referencing '%s'\n", name);
576 ret = AST_NewConstant( name );
584 * \brief Check for an error
586 void SyntaxAssert(tParser *Parser, int Have, int Want)
589 fprintf(stderr, "ERROR: SyntaxAssert Failed, Expected %s(%i), got %s(%i) on line %i\n",
590 csaTOKEN_NAMES[Want], Want, csaTOKEN_NAMES[Have], Have, Parser->CurLine);
591 longjmp(Parser->JmpTarget, -1);