2 * Acess2 - SpiderScript
9 #include <spiderscript.h>
10 #define WANT_TOKEN_STRINGS 1
17 tAST_Script *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const char *Filename);
18 void *Parse_FunctionDefinition(tAST_Script *Script, tSpiderVariant *Variant, tParser *Parser, int Type);
19 tAST_Node *Parse_DoCodeBlock(tParser *Parser);
20 tAST_Node *Parse_DoBlockLine(tParser *Parser);
21 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type);
23 tAST_Node *Parse_DoExpr0(tParser *Parser); // Assignment
24 tAST_Node *Parse_DoExpr1(tParser *Parser); // Boolean Operators
25 tAST_Node *Parse_DoExpr2(tParser *Parser); // Comparison Operators
26 tAST_Node *Parse_DoExpr3(tParser *Parser); // Bitwise Operators
27 tAST_Node *Parse_DoExpr4(tParser *Parser); // Bit Shifts
28 tAST_Node *Parse_DoExpr5(tParser *Parser); // Arithmatic
29 tAST_Node *Parse_DoExpr6(tParser *Parser); // Mult & Div
30 tAST_Node *Parse_DoExpr7(tParser *Parser); // Right Unary Operations
31 tAST_Node *Parse_DoExpr8(tParser *Parser); // Left Unary Operations
33 tAST_Node *Parse_DoParen(tParser *Parser); // Parenthesis (Always Last)
34 tAST_Node *Parse_DoValue(tParser *Parser); // Values
36 tAST_Node *Parse_GetString(tParser *Parser);
37 tAST_Node *Parse_GetNumeric(tParser *Parser);
38 tAST_Node *Parse_GetVariable(tParser *Parser);
39 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate);
41 void SyntaxAssert(tParser *Parser, int Have, int Want);
42 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...);
44 #define SyntaxAssert(_parser, _have, _want) do { \
45 if( (_have) != (_want) ) { \
46 SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n", \
47 csaTOKEN_NAMES[_have], _have, csaTOKEN_NAMES[_want], _want); \
52 #define TODO(Parser, message...) do {\
53 fprintf(stderr, "TODO: "message);\
54 longjmp(Parser->JmpTarget, -1);\
59 * \brief Parse a buffer into a syntax tree
61 tAST_Script *Parse_Buffer(tSpiderVariant *Variant, const char *Buffer, const char *Filename)
64 tParser *Parser = &parser; //< Keeps code consistent
66 tAST_Node *mainCode, *node;
71 printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer);
75 parser.LastToken = -1;
76 parser.NextToken = -1;
78 parser.BufStart = Buffer;
79 parser.CurPos = Buffer;
80 parser.Filename = Filename;
83 ret = AST_NewScript();
84 mainCode = AST_NewCodeBlock(&parser);
86 // Give us an error fallback
87 if( setjmp( parser.JmpTarget ) != 0 )
89 AST_FreeNode( mainCode );
91 for(fcn = ret->Functions; fcn; )
94 tAST_Function *nextFcn;
95 AST_FreeNode( fcn->Code );
96 for(var = fcn->Arguments; var;)
98 tAST_Node *nextVar = var->NextSibling;
112 while(Parser->Token != TOK_EOF)
114 switch( GetToken(Parser) )
119 // Typed variables/functions
120 case TOKEN_GROUP_TYPES:
121 TOKEN_GET_DATATYPE(type, Parser->Token);
123 switch(GetToken(Parser))
125 // Define a function (pass on to the other function definition code)
128 if( Parse_FunctionDefinition(ret, Variant, Parser, type) == NULL )
129 longjmp(Parser->JmpTarget, -1);
133 node = Parse_GetVarDef(Parser, type);
134 if(!node) longjmp(Parser->JmpTarget, -1);
136 AST_AppendNode( mainCode, node );
137 // Can't use SyntaxAssert because that returns
138 if(GetToken(Parser) != TOK_SEMICOLON) {
139 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_SEMICOLON",
140 csaTOKEN_NAMES[Parser->Token]);
141 longjmp(Parser->JmpTarget, -1);
145 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
146 csaTOKEN_NAMES[Parser->Token]);
152 case TOK_RWD_FUNCTION:
153 if( !Variant->bDyamicTyped ) {
154 SyntaxError(Parser, 1, "Dynamic functions are invalid in static mode");
155 longjmp(Parser->JmpTarget, -1);
158 type = SS_DATATYPE_DYNAMIC;
160 if( Parse_FunctionDefinition(ret, Variant, Parser, SS_DATATYPE_DYNAMIC) == NULL )
161 longjmp(Parser->JmpTarget, -1);
165 // Ordinary Statement
168 node = Parse_DoBlockLine(Parser);
169 if(!node) longjmp(Parser->JmpTarget, -1);
170 AST_AppendNode( mainCode, node );
174 // Jump to error handler on error
176 longjmp(Parser->JmpTarget, -1);
179 fcn = AST_AppendFunction( ret, "", SS_DATATYPE_INTEGER );
180 AST_SetFunctionCode( fcn, mainCode );
182 //printf("---- %p parsed as SpiderScript ----\n", Buffer);
187 void *Parse_FunctionDefinition(tAST_Script *Script, tSpiderVariant *Variant, tParser *Parser, int Type)
193 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
195 name = strndup( Parser->TokenStr, Parser->TokenLen );
196 fcn = AST_AppendFunction( Script, name, Type );
198 printf("DefFCN %s\n", name);
203 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
204 if( LookAhead(Parser) != TOK_PAREN_CLOSE )
207 type = SS_DATATYPE_DYNAMIC;
209 // Non dynamic typed variants must use data types
210 if( !Variant->bDyamicTyped ) {
211 TOKEN_GET_DATATYPE(type, Parser->Token);
214 AST_AppendFunctionArg(fcn, Parse_GetVarDef(Parser, type));
215 } while(GetToken(Parser) == TOK_COMMA);
219 SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
221 AST_SetFunctionCode( fcn, Parse_DoCodeBlock(Parser) );
227 * \brief Parse a block of code surrounded by { }
229 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
233 // Check if we are being called for a one-liner
234 if( GetToken(Parser) != TOK_BRACE_OPEN ) {
236 return Parse_DoBlockLine(Parser);
239 ret = AST_NewCodeBlock(Parser);
241 while( LookAhead(Parser) != TOK_BRACE_CLOSE )
243 tAST_Node *node = Parse_DoBlockLine(Parser);
248 AST_AppendNode( ret, node );
250 GetToken(Parser); // Omnomnom
255 * \brief Parse a line in a block
257 tAST_Node *Parse_DoBlockLine(tParser *Parser)
261 //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
263 switch(LookAhead(Parser))
267 return Parse_DoCodeBlock(Parser);
274 // Return from a method
277 ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
280 // Control Statements
283 tAST_Node *cond, *true, *false = NULL;
284 GetToken(Parser); // eat the if
285 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
286 cond = Parse_DoExpr0(Parser); // Get condition
287 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
288 true = Parse_DoCodeBlock(Parser);
289 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
291 false = Parse_DoCodeBlock(Parser);
294 false = AST_NewNop(Parser);
295 ret = AST_NewIf(Parser, cond, true, false);
301 tAST_Node *init=NULL, *cond=NULL, *inc=NULL, *code;
302 GetToken(Parser); // Eat 'for'
303 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
305 if(LookAhead(Parser) != TOK_SEMICOLON)
306 init = Parse_DoExpr0(Parser);
308 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
310 if(LookAhead(Parser) != TOK_SEMICOLON)
311 cond = Parse_DoExpr0(Parser);
313 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
315 if(LookAhead(Parser) != TOK_PAREN_CLOSE)
316 inc = Parse_DoExpr0(Parser);
318 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
320 code = Parse_DoCodeBlock(Parser);
321 ret = AST_NewLoop(Parser, init, 0, cond, inc, code);
327 tAST_Node *code, *cond;
328 GetToken(Parser); // Eat 'do'
329 code = Parse_DoCodeBlock(Parser);
330 SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
331 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
332 cond = Parse_DoExpr0(Parser);
333 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
334 ret = AST_NewLoop(Parser, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code);
339 tAST_Node *code, *cond;
340 GetToken(Parser); // Eat 'while'
341 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
342 cond = Parse_DoExpr0(Parser);
343 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
344 code = Parse_DoCodeBlock(Parser);
345 ret = AST_NewLoop(Parser, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
350 case TOKEN_GROUP_TYPES:
354 TOKEN_GET_DATATYPE(type, Parser->Token);
356 SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
358 ret = Parse_GetVarDef(Parser, type);
365 ret = Parse_DoExpr0(Parser);
369 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
374 * \brief Get a variable definition
376 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
378 char name[Parser->TokenLen];
381 SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
383 // copy the name (trimming the $)
384 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
385 name[Parser->TokenLen-1] = 0;
386 // Define the variable
387 ret = AST_NewDefineVar(Parser, Type, name);
389 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
393 node = Parse_DoExpr0(Parser);
398 AST_AppendNode(ret, node);
399 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
402 if( LookAhead(Parser) == TOK_ASSIGN )
405 ret->DefVar.InitialValue = Parse_DoExpr0(Parser);
406 if(!ret->DefVar.InitialValue) {
416 * \brief Assignment Operations
418 tAST_Node *Parse_DoExpr0(tParser *Parser)
420 #define _next Parse_DoExpr1
421 tAST_Node *ret = _next(Parser);
427 switch(GetToken(Parser))
430 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, _next(Parser));
433 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
436 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
438 case TOK_ASSIGN_PLUS:
439 ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, _next(Parser));
441 case TOK_ASSIGN_MINUS:
442 ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
446 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
458 * \brief Logical/Boolean Operators
460 tAST_Node *Parse_DoExpr1(tParser *Parser)
462 #define _next Parse_DoExpr2
463 tAST_Node *ret = _next(Parser);
468 switch(GetToken(Parser))
471 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, _next(Parser));
474 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, _next(Parser));
477 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, _next(Parser));
489 // --------------------
490 // Expression 2 - Comparison Operators
491 // --------------------
492 tAST_Node *Parse_DoExpr2(tParser *Parser)
494 #define _next Parse_DoExpr3
495 tAST_Node *ret = _next(Parser);
501 switch(GetToken(Parser))
504 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, _next(Parser));
507 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, _next(Parser));
510 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, _next(Parser));
513 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, _next(Parser));
516 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, _next(Parser));
529 * \brief Bitwise Operations
531 tAST_Node *Parse_DoExpr3(tParser *Parser)
533 #define _next Parse_DoExpr4
534 tAST_Node *ret = _next(Parser);
540 switch(GetToken(Parser))
543 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, _next(Parser));
546 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, _next(Parser));
549 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, _next(Parser));
561 // --------------------
562 // Expression 4 - Shifts
563 // --------------------
564 tAST_Node *Parse_DoExpr4(tParser *Parser)
566 #define _next Parse_DoExpr5
567 tAST_Node *ret = _next(Parser);
572 switch(GetToken(Parser))
575 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, _next(Parser));
578 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, _next(Parser));
591 // --------------------
592 // Expression 5 - Arithmatic
593 // --------------------
594 tAST_Node *Parse_DoExpr5(tParser *Parser)
596 #define _next Parse_DoExpr6
597 tAST_Node *ret = _next(Parser);
600 // While loop is added to ensure that the evaluation order ends up as
602 // E.g. a + b + c + d ends up as (((a + b) + c) + d) for casting
605 switch(GetToken(Parser))
608 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, _next(Parser));
611 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
624 // --------------------
625 // Expression 6 - Multiplcation & Division
626 // --------------------
627 tAST_Node *Parse_DoExpr6(tParser *Parser)
629 #define _next Parse_DoExpr7
630 tAST_Node *ret = _next(Parser);
635 switch(GetToken(Parser))
638 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
641 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
654 // --------------------
655 // Expression 7 - Right Unary Operations
656 // --------------------
657 tAST_Node *Parse_DoExpr7(tParser *Parser)
659 tAST_Node *ret = Parse_DoExpr8(Parser);
661 switch(GetToken(Parser))
664 ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
667 ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
676 // --------------------
677 // Expression 8 - Left Unary Operations
678 // --------------------
679 tAST_Node *Parse_DoExpr8(tParser *Parser)
681 switch(GetToken(Parser))
684 return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
686 return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
688 return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
690 return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
692 return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
695 return Parse_DoParen(Parser);
699 // --------------------
700 // 2nd Last Expression - Parens
701 // --------------------
702 tAST_Node *Parse_DoParen(tParser *Parser)
705 printf("Parse_DoParen: (Parser=%p)\n", Parser);
707 if(LookAhead(Parser) == TOK_PAREN_OPEN)
713 // TODO: Handle casts here
714 switch(LookAhead(Parser))
716 case TOKEN_GROUP_TYPES:
718 TOKEN_GET_DATATYPE(type, Parser->Token);
719 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
720 ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
723 ret = Parse_DoExpr0(Parser);
724 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
730 return Parse_DoValue(Parser);
733 // --------------------
734 // Last Expression - Value
735 // --------------------
736 tAST_Node *Parse_DoValue(tParser *Parser)
738 int tok = LookAhead(Parser);
741 printf("Parse_DoValue: tok = %i\n", tok);
747 return Parse_GetString(Parser);
749 return Parse_GetNumeric(Parser);
753 return AST_NewReal( Parser, atof(Parser->TokenStr) );
755 case TOK_IDENT: return Parse_GetIdent(Parser, 0);
756 case TOK_VARIABLE: return Parse_GetVariable(Parser);
758 GetToken(Parser); // Omnomnom
759 return Parse_GetIdent(Parser, 1);
762 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
763 csaTOKEN_NAMES[tok], Parser->CurLine);
764 longjmp( Parser->JmpTarget, -1 );
769 * \brief Get a string
771 tAST_Node *Parse_GetString(tParser *Parser)
778 char data[ Parser->TokenLen - 2 ];
781 for( i = 1; i < Parser->TokenLen - 1; i++ )
783 if( Parser->TokenStr[i] == '\\' ) {
785 switch( Parser->TokenStr[i] )
787 case 'n': data[j++] = '\n'; break;
788 case 'r': data[j++] = '\r'; break;
791 // TODO: Error/Warning?
796 data[j++] = Parser->TokenStr[i];
800 // TODO: Parse Escape Codes
801 ret = AST_NewString( Parser, data, j );
807 * \brief Get a numeric value
809 tAST_Node *Parse_GetNumeric(tParser *Parser)
813 SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
814 pos = Parser->TokenStr;
815 //printf("pos = %p, *pos = %c\n", pos, *pos);
825 if( '0' <= *pos && *pos <= '9' ) {
829 if( 'A' <= *pos && *pos <= 'F' ) {
830 value += *pos - 'A' + 10;
833 if( 'a' <= *pos && *pos <= 'f' ) {
834 value += *pos - 'a' + 10;
841 while( '0' <= *pos && *pos <= '7' ) {
842 value = value*8 + *pos - '0';
848 while( '0' <= *pos && *pos <= '9' ) {
849 value = value*10 + *pos - '0';
854 return AST_NewInteger( Parser, value );
858 * \brief Get a variable
860 tAST_Node *Parse_GetVariable(tParser *Parser)
863 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
865 char name[Parser->TokenLen];
866 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
867 name[Parser->TokenLen-1] = 0;
868 ret = AST_NewVariable( Parser, name );
870 printf("Parse_GetVariable: name = '%s'\n", name);
876 if( Parser->Token == TOK_SQUARE_OPEN )
878 ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
879 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
882 if( Parser->Token == TOK_ELEMENT )
884 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
886 if( LookAhead(Parser) == TOK_PAREN_OPEN )
888 char name[Parser->TokenLen+1];
889 memcpy(name, Parser->TokenStr, Parser->TokenLen);
890 name[Parser->TokenLen] = 0;
891 ret = AST_NewMethodCall(Parser, ret, name);
892 GetToken(Parser); // Eat the '('
894 if( GetToken(Parser) != TOK_PAREN_CLOSE )
898 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
899 } while(GetToken(Parser) == TOK_COMMA);
900 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
907 char name[Parser->TokenLen];
908 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
909 name[Parser->TokenLen-1] = 0;
910 ret = AST_NewClassElement(Parser, ret, name);
922 * \brief Get an identifier (constant or function call)
924 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
926 tAST_Node *ret = NULL;
928 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
929 name = strndup( Parser->TokenStr, Parser->TokenLen );
932 if( GetToken(Parser) == TOK_SCOPE )
934 ret = AST_NewScopeDereference( Parser, Parse_GetIdent(Parser, bObjectCreate), name );
941 if( GetToken(Parser) == TOK_PAREN_OPEN )
944 printf("Parse_GetIdent: Calling '%s'\n", name);
948 ret = AST_NewCreateObject( Parser, name );
950 ret = AST_NewFunctionCall( Parser, name );
952 if( GetToken(Parser) != TOK_PAREN_CLOSE )
957 printf(" Parse_GetIdent: Argument\n");
959 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
960 } while(GetToken(Parser) == TOK_COMMA);
961 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
963 printf(" Parse_GetIdent: All arguments parsed\n");
969 // Runtime Constant / Variable (When implemented)
971 printf("Parse_GetIdent: Referencing '%s'\n", name);
974 if( bObjectCreate ) // Void constructor (TODO: Should this be an error?)
975 ret = AST_NewCreateObject( Parser, name );
977 ret = AST_NewConstant( Parser, name );
985 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...)
988 va_start(args, Message);
989 fprintf(stderr, "%s:%i: error: ", Parser->Filename, Parser->CurLine);
990 vfprintf(stderr, Message, args);
991 fprintf(stderr, "\n");
995 //longjmp(Parser->JmpTarget, -1);
996 Parser->ErrorHit = 1;