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 // hackery to do reference counting
81 parser.Filename = malloc(sizeof(int)+strlen(Filename)+1);
82 strcpy(parser.Filename + sizeof(int), Filename);
83 *(int*)(parser.Filename) = 0; // Set reference count
84 parser.Filename += sizeof(int); // Move filename
87 ret = AST_NewScript();
88 mainCode = AST_NewCodeBlock(&parser);
90 // Give us an error fallback
91 if( setjmp( parser.JmpTarget ) != 0 )
93 AST_FreeNode( mainCode );
95 for(fcn = ret->Functions; fcn; )
98 tAST_Function *nextFcn;
99 AST_FreeNode( fcn->Code );
100 for(var = fcn->Arguments; var;)
102 tAST_Node *nextVar = var->NextSibling;
116 while(Parser->Token != TOK_EOF)
118 switch( GetToken(Parser) )
123 // Typed variables/functions
124 case TOKEN_GROUP_TYPES:
125 TOKEN_GET_DATATYPE(type, Parser->Token);
127 switch(GetToken(Parser))
129 // Define a function (pass on to the other function definition code)
132 if( Parse_FunctionDefinition(ret, Variant, Parser, type) == NULL )
133 longjmp(Parser->JmpTarget, -1);
137 node = Parse_GetVarDef(Parser, type);
138 if(!node) longjmp(Parser->JmpTarget, -1);
140 AST_AppendNode( mainCode, node );
141 // Can't use SyntaxAssert because that returns
142 if(GetToken(Parser) != TOK_SEMICOLON) {
143 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_SEMICOLON",
144 csaTOKEN_NAMES[Parser->Token]);
145 longjmp(Parser->JmpTarget, -1);
149 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
150 csaTOKEN_NAMES[Parser->Token]);
156 case TOK_RWD_FUNCTION:
157 if( !Variant->bDyamicTyped ) {
158 SyntaxError(Parser, 1, "Dynamic functions are invalid in static mode");
159 longjmp(Parser->JmpTarget, -1);
162 type = SS_DATATYPE_DYNAMIC;
164 if( Parse_FunctionDefinition(ret, Variant, Parser, SS_DATATYPE_DYNAMIC) == NULL )
165 longjmp(Parser->JmpTarget, -1);
169 // Ordinary Statement
172 node = Parse_DoBlockLine(Parser);
173 if(!node) longjmp(Parser->JmpTarget, -1);
174 AST_AppendNode( mainCode, node );
178 // Jump to error handler on error
180 longjmp(Parser->JmpTarget, -1);
183 fcn = AST_AppendFunction( ret, "", SS_DATATYPE_INTEGER );
184 AST_SetFunctionCode( fcn, mainCode );
186 //printf("---- %p parsed as SpiderScript ----\n", Buffer);
191 void *Parse_FunctionDefinition(tAST_Script *Script, tSpiderVariant *Variant, tParser *Parser, int Type)
197 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
199 name = strndup( Parser->TokenStr, Parser->TokenLen );
200 fcn = AST_AppendFunction( Script, name, Type );
202 printf("DefFCN %s\n", name);
207 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
208 if( LookAhead(Parser) != TOK_PAREN_CLOSE )
211 type = SS_DATATYPE_DYNAMIC;
213 // Non dynamic typed variants must use data types
214 if( !Variant->bDyamicTyped ) {
215 TOKEN_GET_DATATYPE(type, Parser->Token);
218 AST_AppendFunctionArg(fcn, Parse_GetVarDef(Parser, type));
219 } while(GetToken(Parser) == TOK_COMMA);
223 SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
225 AST_SetFunctionCode( fcn, Parse_DoCodeBlock(Parser) );
231 * \brief Parse a block of code surrounded by { }
233 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
237 // Check if we are being called for a one-liner
238 if( GetToken(Parser) != TOK_BRACE_OPEN ) {
240 return Parse_DoBlockLine(Parser);
243 ret = AST_NewCodeBlock(Parser);
245 while( LookAhead(Parser) != TOK_BRACE_CLOSE )
247 tAST_Node *node = Parse_DoBlockLine(Parser);
252 AST_AppendNode( ret, node );
254 GetToken(Parser); // Omnomnom
259 * \brief Parse a line in a block
261 tAST_Node *Parse_DoBlockLine(tParser *Parser)
265 //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
267 switch(LookAhead(Parser))
271 return Parse_DoCodeBlock(Parser);
278 // Return from a method
281 ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
284 // Control Statements
287 tAST_Node *cond, *true, *false = NULL;
288 GetToken(Parser); // eat the if
289 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
290 cond = Parse_DoExpr0(Parser); // Get condition
291 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
292 true = Parse_DoCodeBlock(Parser);
293 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
295 false = Parse_DoCodeBlock(Parser);
298 false = AST_NewNop(Parser);
299 ret = AST_NewIf(Parser, cond, true, false);
305 tAST_Node *init=NULL, *cond=NULL, *inc=NULL, *code;
306 GetToken(Parser); // Eat 'for'
307 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
309 if(LookAhead(Parser) != TOK_SEMICOLON)
310 init = Parse_DoExpr0(Parser);
312 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
314 if(LookAhead(Parser) != TOK_SEMICOLON)
315 cond = Parse_DoExpr0(Parser);
317 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
319 if(LookAhead(Parser) != TOK_PAREN_CLOSE)
320 inc = Parse_DoExpr0(Parser);
322 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
324 code = Parse_DoCodeBlock(Parser);
325 ret = AST_NewLoop(Parser, init, 0, cond, inc, code);
331 tAST_Node *code, *cond;
332 GetToken(Parser); // Eat 'do'
333 code = Parse_DoCodeBlock(Parser);
334 SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
335 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
336 cond = Parse_DoExpr0(Parser);
337 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
338 ret = AST_NewLoop(Parser, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code);
343 tAST_Node *code, *cond;
344 GetToken(Parser); // Eat 'while'
345 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
346 cond = Parse_DoExpr0(Parser);
347 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
348 code = Parse_DoCodeBlock(Parser);
349 ret = AST_NewLoop(Parser, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
354 case TOKEN_GROUP_TYPES:
358 TOKEN_GET_DATATYPE(type, Parser->Token);
360 SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
362 ret = Parse_GetVarDef(Parser, type);
369 ret = Parse_DoExpr0(Parser);
373 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
378 * \brief Get a variable definition
380 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
382 char name[Parser->TokenLen];
385 SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
387 // copy the name (trimming the $)
388 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
389 name[Parser->TokenLen-1] = 0;
390 // Define the variable
391 ret = AST_NewDefineVar(Parser, Type, name);
393 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
397 node = Parse_DoExpr0(Parser);
402 AST_AppendNode(ret, node);
403 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
406 if( LookAhead(Parser) == TOK_ASSIGN )
409 ret->DefVar.InitialValue = Parse_DoExpr0(Parser);
410 if(!ret->DefVar.InitialValue) {
420 * \brief Assignment Operations
422 tAST_Node *Parse_DoExpr0(tParser *Parser)
424 #define _next Parse_DoExpr1
425 tAST_Node *ret = _next(Parser);
431 switch(GetToken(Parser))
434 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, _next(Parser));
437 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
440 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
442 case TOK_ASSIGN_PLUS:
443 ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, _next(Parser));
445 case TOK_ASSIGN_MINUS:
446 ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
450 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
462 * \brief Logical/Boolean Operators
464 tAST_Node *Parse_DoExpr1(tParser *Parser)
466 #define _next Parse_DoExpr2
467 tAST_Node *ret = _next(Parser);
472 switch(GetToken(Parser))
475 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, _next(Parser));
478 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, _next(Parser));
481 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, _next(Parser));
493 // --------------------
494 // Expression 2 - Comparison Operators
495 // --------------------
496 tAST_Node *Parse_DoExpr2(tParser *Parser)
498 #define _next Parse_DoExpr3
499 tAST_Node *ret = _next(Parser);
505 switch(GetToken(Parser))
508 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, _next(Parser));
511 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, _next(Parser));
514 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, _next(Parser));
517 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, _next(Parser));
520 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, _next(Parser));
533 * \brief Bitwise Operations
535 tAST_Node *Parse_DoExpr3(tParser *Parser)
537 #define _next Parse_DoExpr4
538 tAST_Node *ret = _next(Parser);
544 switch(GetToken(Parser))
547 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, _next(Parser));
550 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, _next(Parser));
553 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, _next(Parser));
565 // --------------------
566 // Expression 4 - Shifts
567 // --------------------
568 tAST_Node *Parse_DoExpr4(tParser *Parser)
570 #define _next Parse_DoExpr5
571 tAST_Node *ret = _next(Parser);
576 switch(GetToken(Parser))
579 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, _next(Parser));
582 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, _next(Parser));
595 // --------------------
596 // Expression 5 - Arithmatic
597 // --------------------
598 tAST_Node *Parse_DoExpr5(tParser *Parser)
600 #define _next Parse_DoExpr6
601 tAST_Node *ret = _next(Parser);
604 // While loop is added to ensure that the evaluation order ends up as
606 // E.g. a + b + c + d ends up as (((a + b) + c) + d) for casting
609 switch(GetToken(Parser))
612 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, _next(Parser));
615 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
628 // --------------------
629 // Expression 6 - Multiplcation & Division
630 // --------------------
631 tAST_Node *Parse_DoExpr6(tParser *Parser)
633 #define _next Parse_DoExpr7
634 tAST_Node *ret = _next(Parser);
639 switch(GetToken(Parser))
642 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
645 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
658 // --------------------
659 // Expression 7 - Right Unary Operations
660 // --------------------
661 tAST_Node *Parse_DoExpr7(tParser *Parser)
663 tAST_Node *ret = Parse_DoExpr8(Parser);
665 switch(GetToken(Parser))
668 ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
671 ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
680 // --------------------
681 // Expression 8 - Left Unary Operations
682 // --------------------
683 tAST_Node *Parse_DoExpr8(tParser *Parser)
685 switch(GetToken(Parser))
688 return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
690 return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
692 return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
694 return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
696 return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
699 return Parse_DoParen(Parser);
703 // --------------------
704 // 2nd Last Expression - Parens
705 // --------------------
706 tAST_Node *Parse_DoParen(tParser *Parser)
709 printf("Parse_DoParen: (Parser=%p)\n", Parser);
711 if(LookAhead(Parser) == TOK_PAREN_OPEN)
717 // TODO: Handle casts here
718 switch(LookAhead(Parser))
720 case TOKEN_GROUP_TYPES:
722 TOKEN_GET_DATATYPE(type, Parser->Token);
723 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
724 ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
727 ret = Parse_DoExpr0(Parser);
728 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
734 return Parse_DoValue(Parser);
737 // --------------------
738 // Last Expression - Value
739 // --------------------
740 tAST_Node *Parse_DoValue(tParser *Parser)
742 int tok = LookAhead(Parser);
745 printf("Parse_DoValue: tok = %i\n", tok);
751 return Parse_GetString(Parser);
753 return Parse_GetNumeric(Parser);
757 return AST_NewReal( Parser, atof(Parser->TokenStr) );
759 case TOK_IDENT: return Parse_GetIdent(Parser, 0);
760 case TOK_VARIABLE: return Parse_GetVariable(Parser);
762 GetToken(Parser); // Omnomnom
763 return Parse_GetIdent(Parser, 1);
766 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
767 csaTOKEN_NAMES[tok], Parser->CurLine);
768 longjmp( Parser->JmpTarget, -1 );
773 * \brief Get a string
775 tAST_Node *Parse_GetString(tParser *Parser)
782 char data[ Parser->TokenLen - 2 ];
785 for( i = 1; i < Parser->TokenLen - 1; i++ )
787 if( Parser->TokenStr[i] == '\\' ) {
789 switch( Parser->TokenStr[i] )
791 case 'n': data[j++] = '\n'; break;
792 case 'r': data[j++] = '\r'; break;
795 // TODO: Error/Warning?
800 data[j++] = Parser->TokenStr[i];
804 // TODO: Parse Escape Codes
805 ret = AST_NewString( Parser, data, j );
811 * \brief Get a numeric value
813 tAST_Node *Parse_GetNumeric(tParser *Parser)
817 SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
818 pos = Parser->TokenStr;
819 //printf("pos = %p, *pos = %c\n", pos, *pos);
829 if( '0' <= *pos && *pos <= '9' ) {
833 if( 'A' <= *pos && *pos <= 'F' ) {
834 value += *pos - 'A' + 10;
837 if( 'a' <= *pos && *pos <= 'f' ) {
838 value += *pos - 'a' + 10;
845 while( '0' <= *pos && *pos <= '7' ) {
846 value = value*8 + *pos - '0';
852 while( '0' <= *pos && *pos <= '9' ) {
853 value = value*10 + *pos - '0';
858 return AST_NewInteger( Parser, value );
862 * \brief Get a variable
864 tAST_Node *Parse_GetVariable(tParser *Parser)
867 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
869 char name[Parser->TokenLen];
870 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
871 name[Parser->TokenLen-1] = 0;
872 ret = AST_NewVariable( Parser, name );
874 printf("Parse_GetVariable: name = '%s'\n", name);
880 if( Parser->Token == TOK_SQUARE_OPEN )
882 ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
883 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
886 if( Parser->Token == TOK_ELEMENT )
888 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
890 if( LookAhead(Parser) == TOK_PAREN_OPEN )
892 char name[Parser->TokenLen+1];
893 memcpy(name, Parser->TokenStr, Parser->TokenLen);
894 name[Parser->TokenLen] = 0;
895 ret = AST_NewMethodCall(Parser, ret, name);
896 GetToken(Parser); // Eat the '('
898 if( GetToken(Parser) != TOK_PAREN_CLOSE )
902 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
903 } while(GetToken(Parser) == TOK_COMMA);
904 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
911 char name[Parser->TokenLen];
912 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
913 name[Parser->TokenLen-1] = 0;
914 ret = AST_NewClassElement(Parser, ret, name);
926 * \brief Get an identifier (constant or function call)
928 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
930 tAST_Node *ret = NULL;
932 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
933 name = strndup( Parser->TokenStr, Parser->TokenLen );
936 if( GetToken(Parser) == TOK_SCOPE )
938 ret = AST_NewScopeDereference( Parser, name, Parse_GetIdent(Parser, bObjectCreate) );
945 if( GetToken(Parser) == TOK_PAREN_OPEN )
948 printf("Parse_GetIdent: Calling '%s'\n", name);
952 ret = AST_NewCreateObject( Parser, name );
954 ret = AST_NewFunctionCall( Parser, name );
956 if( GetToken(Parser) != TOK_PAREN_CLOSE )
961 printf(" Parse_GetIdent: Argument\n");
963 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
964 } while(GetToken(Parser) == TOK_COMMA);
965 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
967 printf(" Parse_GetIdent: All arguments parsed\n");
973 // Runtime Constant / Variable (When implemented)
975 printf("Parse_GetIdent: Referencing '%s'\n", name);
978 if( bObjectCreate ) // Void constructor (TODO: Should this be an error?)
979 ret = AST_NewCreateObject( Parser, name );
981 ret = AST_NewConstant( Parser, name );
989 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...)
992 va_start(args, Message);
993 fprintf(stderr, "%s:%i: error: ", Parser->Filename, Parser->CurLine);
994 vfprintf(stderr, Message, args);
995 fprintf(stderr, "\n");
999 //longjmp(Parser->JmpTarget, -1);
1000 Parser->ErrorHit = 1;