2 * Acess2 - SpiderScript
9 #include <spiderscript.h>
10 #define WANT_TOKEN_STRINGS 1
16 #define SUPPORT_BREAK_TAGS 1
19 int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename);
20 void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type);
21 tAST_Node *Parse_DoCodeBlock(tParser *Parser);
22 tAST_Node *Parse_DoBlockLine(tParser *Parser);
23 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type);
25 tAST_Node *Parse_DoExpr0(tParser *Parser); // Assignment
26 tAST_Node *Parse_DoExpr1(tParser *Parser); // Boolean Operators
27 tAST_Node *Parse_DoExpr2(tParser *Parser); // Comparison Operators
28 tAST_Node *Parse_DoExpr3(tParser *Parser); // Bitwise Operators
29 tAST_Node *Parse_DoExpr4(tParser *Parser); // Bit Shifts
30 tAST_Node *Parse_DoExpr5(tParser *Parser); // Arithmatic
31 tAST_Node *Parse_DoExpr6(tParser *Parser); // Mult & Div
32 tAST_Node *Parse_DoExpr7(tParser *Parser); // Right Unary Operations
33 tAST_Node *Parse_DoExpr8(tParser *Parser); // Left Unary Operations
35 tAST_Node *Parse_DoParen(tParser *Parser); // Parenthesis (Always Last)
36 tAST_Node *Parse_DoValue(tParser *Parser); // Values
38 tAST_Node *Parse_GetString(tParser *Parser);
39 tAST_Node *Parse_GetNumeric(tParser *Parser);
40 tAST_Node *Parse_GetVariable(tParser *Parser);
41 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate);
43 void SyntaxAssert(tParser *Parser, int Have, int Want);
44 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...);
46 #define SyntaxAssert(_parser, _have, _want) do { \
47 int have = (_have), want = (_want); \
48 if( (have) != (want) ) { \
49 SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n", \
50 csaTOKEN_NAMES[have], have, csaTOKEN_NAMES[want], want); \
55 #define TODO(Parser, message...) do {\
56 fprintf(stderr, "TODO: "message);\
57 longjmp(Parser->JmpTarget, -1);\
62 * \brief Parse a buffer into a syntax tree
64 int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename)
67 tParser *Parser = &parser; //< Keeps code consistent
68 tAST_Node *mainCode, *node;
70 tScript_Function *fcn;
73 printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer);
77 parser.LastToken = -1;
78 parser.NextToken = -1;
80 parser.BufStart = Buffer;
81 parser.CurPos = Buffer;
82 // hackery to do reference counting
83 parser.Filename = malloc(sizeof(int)+strlen(Filename)+1);
84 strcpy(parser.Filename + sizeof(int), Filename);
85 *(int*)(parser.Filename) = 0; // Set reference count
86 parser.Filename += sizeof(int); // Move filename
88 parser.Variant = Script->Variant;
90 mainCode = AST_NewCodeBlock(&parser);
92 // Give us an error fallback
93 if( setjmp( parser.JmpTarget ) != 0 )
95 AST_FreeNode( mainCode );
97 for(fcn = Script->Functions; fcn; )
99 tScript_Function *nextFcn;
101 AST_FreeNode( fcn->ASTFcn );
111 while(Parser->Token != TOK_EOF)
113 switch( GetToken(Parser) )
118 // Typed variables/functions
119 case TOKEN_GROUP_TYPES:
120 TOKEN_GET_DATATYPE(type, Parser->Token);
122 switch(GetToken(Parser))
124 // Define a function (pass on to the other function definition code)
127 if( Parse_FunctionDefinition(Script, Parser, type) == NULL )
128 longjmp(Parser->JmpTarget, -1);
132 node = Parse_GetVarDef(Parser, type);
133 if(!node) longjmp(Parser->JmpTarget, -1);
135 AST_AppendNode( mainCode, node );
136 // Can't use SyntaxAssert because that returns
137 if(GetToken(Parser) != TOK_SEMICOLON) {
138 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_SEMICOLON",
139 csaTOKEN_NAMES[Parser->Token]);
140 longjmp(Parser->JmpTarget, -1);
144 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
145 csaTOKEN_NAMES[Parser->Token]);
151 case TOK_RWD_FUNCTION:
152 if( !Script->Variant->bDyamicTyped ) {
153 SyntaxError(Parser, 1, "Dynamic functions are invalid in static mode");
154 longjmp(Parser->JmpTarget, -1);
157 type = SS_DATATYPE_DYNAMIC;
159 if( Parse_FunctionDefinition(Script, Parser, SS_DATATYPE_DYNAMIC) == NULL )
160 longjmp(Parser->JmpTarget, -1);
164 // Ordinary Statement
167 node = Parse_DoBlockLine(Parser);
168 if(!node) longjmp(Parser->JmpTarget, -1);
169 AST_AppendNode( mainCode, node );
173 // Jump to error handler on error
175 longjmp(Parser->JmpTarget, -1);
178 AST_AppendFunction( Script, "", SS_DATATYPE_INTEGER, NULL, mainCode );
180 //printf("---- %p parsed as SpiderScript ----\n", Buffer);
185 void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type)
189 tAST_Node *first_arg, *last_arg, *code;
191 last_arg = (void*)&first_arg; // HACK
193 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
195 name = strndup( Parser->TokenStr, Parser->TokenLen );
197 printf("DefFCN %s\n", name);
201 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
202 if( LookAhead(Parser) != TOK_PAREN_CLOSE )
205 int type = SS_DATATYPE_DYNAMIC;
207 // Non dynamic typed variants must use data types
208 if( !Script->Variant->bDyamicTyped ) {
209 TOKEN_GET_DATATYPE(type, Parser->Token);
212 last_arg->NextSibling = Parse_GetVarDef(Parser, type);
213 last_arg = last_arg->NextSibling;
214 last_arg->NextSibling = NULL;
215 } while(GetToken(Parser) == TOK_COMMA);
219 SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
221 code = Parse_DoCodeBlock(Parser);
223 rv = AST_AppendFunction( Script, name, Type, first_arg, code );
225 // Clean up argument definition nodes
228 for( ; first_arg; first_arg = nextarg )
230 nextarg = first_arg->NextSibling;
231 AST_FreeNode(first_arg);
237 return rv == 0 ? (void*)1 : NULL;
241 * \brief Parse a block of code surrounded by { }
243 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
247 // Check if we are being called for a one-liner
248 if( GetToken(Parser) != TOK_BRACE_OPEN ) {
250 return Parse_DoBlockLine(Parser);
253 ret = AST_NewCodeBlock(Parser);
255 while( LookAhead(Parser) != TOK_BRACE_CLOSE )
257 tAST_Node *node = Parse_DoBlockLine(Parser);
262 AST_AppendNode( ret, node );
264 GetToken(Parser); // Omnomnom
269 * \brief Parse a line in a block
271 tAST_Node *Parse_DoBlockLine(tParser *Parser)
275 //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
277 switch(LookAhead(Parser))
281 return Parse_DoCodeBlock(Parser);
288 // Return from a method
291 ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
294 // Break / Continue (end a loop / go to next iteration)
295 case TOK_RWD_CONTINUE:
300 tok = GetToken(Parser);
301 // Get the number of nesting levels to break
302 if(LookAhead(Parser) == TOK_IDENT)
305 ident = strndup(Parser->TokenStr, Parser->TokenLen);
310 case TOK_RWD_BREAK: ret = AST_NewBreakout(Parser, NODETYPE_BREAK, ident); break;
311 case TOK_RWD_CONTINUE: ret = AST_NewBreakout(Parser, NODETYPE_CONTINUE, ident); break;
313 SyntaxError(Parser, 1, "BUG Unhandled break/continue (%s)",
314 csaTOKEN_NAMES[tok]);
317 if(ident) free(ident);
321 // Control Statements
324 tAST_Node *cond, *true, *false = NULL;
325 GetToken(Parser); // eat the if
327 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
328 cond = Parse_DoExpr0(Parser); // Get condition
329 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
330 true = Parse_DoCodeBlock(Parser);
331 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
333 false = Parse_DoCodeBlock(Parser);
336 false = AST_NewNop(Parser);
337 ret = AST_NewIf(Parser, cond, true, false);
344 tAST_Node *init=NULL, *cond=NULL, *inc=NULL, *code;
345 GetToken(Parser); // Eat 'for'
347 #if SUPPORT_BREAK_TAGS
348 if(LookAhead(Parser) == TOK_LT)
351 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
352 tag = strndup(Parser->TokenStr, Parser->TokenLen);
353 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
357 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
359 if(LookAhead(Parser) != TOK_SEMICOLON)
360 init = Parse_DoExpr0(Parser);
362 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
364 if(LookAhead(Parser) != TOK_SEMICOLON)
365 cond = Parse_DoExpr0(Parser);
367 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
369 if(LookAhead(Parser) != TOK_PAREN_CLOSE)
370 inc = Parse_DoExpr0(Parser);
372 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
374 code = Parse_DoCodeBlock(Parser);
375 ret = AST_NewLoop(Parser, tag, init, 0, cond, inc, code);
382 const char *tag = "";
383 tAST_Node *code, *cond;
384 GetToken(Parser); // Eat 'do'
386 #if SUPPORT_BREAK_TAGS
387 if(LookAhead(Parser) == TOK_LT)
390 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
391 tag = strndup(Parser->TokenStr, Parser->TokenLen);
392 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
396 code = Parse_DoCodeBlock(Parser);
397 SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
398 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
399 cond = Parse_DoExpr0(Parser);
400 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
401 ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code);
406 const char *tag = "";
407 tAST_Node *code, *cond;
408 GetToken(Parser); // Eat 'while'
410 #if SUPPORT_BREAK_TAGS
411 if(LookAhead(Parser) == TOK_LT)
414 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
415 tag = strndup(Parser->TokenStr, Parser->TokenLen);
416 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
420 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
421 cond = Parse_DoExpr0(Parser);
422 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
423 code = Parse_DoCodeBlock(Parser);
424 ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
429 case TOKEN_GROUP_TYPES:
433 TOKEN_GET_DATATYPE(type, Parser->Token);
435 SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
437 ret = Parse_GetVarDef(Parser, type);
444 ret = Parse_DoExpr0(Parser);
448 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
453 * \brief Get a variable definition
455 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
457 char name[Parser->TokenLen];
461 SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
463 // copy the name (trimming the $)
464 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
465 name[Parser->TokenLen-1] = 0;
467 // Define the variable
468 ret = AST_NewDefineVar(Parser, Type, name);
471 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
475 node = Parse_DoExpr0(Parser);
480 AST_AppendNode(ret, node);
481 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
485 // Maul the type to denote the dereference level
486 if( Parser->Variant->bDyamicTyped ) {
487 ret->DefVar.DataType = SS_DATATYPE_ARRAY;
490 ret->DefVar.DataType |= (level << 16);
494 if( LookAhead(Parser) == TOK_ASSIGN )
497 ret->DefVar.InitialValue = Parse_DoExpr0(Parser);
498 if(!ret->DefVar.InitialValue) {
508 * \brief Assignment Operations
510 tAST_Node *Parse_DoExpr0(tParser *Parser)
512 #define _next Parse_DoExpr1
513 tAST_Node *ret = _next(Parser);
519 switch(GetToken(Parser))
522 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, _next(Parser));
525 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
528 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
530 case TOK_ASSIGN_PLUS:
531 ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, _next(Parser));
533 case TOK_ASSIGN_MINUS:
534 ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
538 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
550 * \brief Logical/Boolean Operators
552 tAST_Node *Parse_DoExpr1(tParser *Parser)
554 #define _next Parse_DoExpr2
555 tAST_Node *ret = _next(Parser);
560 switch(GetToken(Parser))
563 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, _next(Parser));
566 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, _next(Parser));
569 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, _next(Parser));
581 // --------------------
582 // Expression 2 - Comparison Operators
583 // --------------------
584 tAST_Node *Parse_DoExpr2(tParser *Parser)
586 #define _next Parse_DoExpr3
587 tAST_Node *ret = _next(Parser);
593 switch(GetToken(Parser))
596 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, _next(Parser));
599 ret = AST_NewBinOp(Parser, NODETYPE_NOTEQUALS, ret, _next(Parser));
602 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, _next(Parser));
605 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, _next(Parser));
608 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, _next(Parser));
611 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, _next(Parser));
624 * \brief Bitwise Operations
626 tAST_Node *Parse_DoExpr3(tParser *Parser)
628 #define _next Parse_DoExpr4
629 tAST_Node *ret = _next(Parser);
635 switch(GetToken(Parser))
638 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, _next(Parser));
641 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, _next(Parser));
644 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, _next(Parser));
656 // --------------------
657 // Expression 4 - Shifts
658 // --------------------
659 tAST_Node *Parse_DoExpr4(tParser *Parser)
661 #define _next Parse_DoExpr5
662 tAST_Node *ret = _next(Parser);
667 switch(GetToken(Parser))
670 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, _next(Parser));
673 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, _next(Parser));
686 // --------------------
687 // Expression 5 - Arithmatic
688 // --------------------
689 tAST_Node *Parse_DoExpr5(tParser *Parser)
691 #define _next Parse_DoExpr6
692 tAST_Node *ret = _next(Parser);
695 // While loop is added to ensure that the evaluation order ends up as
697 // E.g. a + b + c + d ends up as (((a + b) + c) + d) for casting
700 switch(GetToken(Parser))
703 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, _next(Parser));
706 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
719 // --------------------
720 // Expression 6 - Multiplcation & Division
721 // --------------------
722 tAST_Node *Parse_DoExpr6(tParser *Parser)
724 #define _next Parse_DoExpr7
725 tAST_Node *ret = _next(Parser);
730 switch(GetToken(Parser))
733 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
736 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
749 // --------------------
750 // Expression 7 - Right Unary Operations
751 // --------------------
752 tAST_Node *Parse_DoExpr7(tParser *Parser)
754 tAST_Node *ret = Parse_DoExpr8(Parser);
756 switch(GetToken(Parser))
759 ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
762 ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
771 // --------------------
772 // Expression 8 - Left Unary Operations
773 // --------------------
774 tAST_Node *Parse_DoExpr8(tParser *Parser)
776 switch(GetToken(Parser))
779 return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
781 return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
783 return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
785 return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
787 return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
790 return Parse_DoParen(Parser);
794 // --------------------
795 // 2nd Last Expression - Parens
796 // --------------------
797 tAST_Node *Parse_DoParen(tParser *Parser)
800 printf("Parse_DoParen: (Parser=%p)\n", Parser);
802 if(LookAhead(Parser) == TOK_PAREN_OPEN)
808 // TODO: Handle casts here
809 switch(LookAhead(Parser))
811 case TOKEN_GROUP_TYPES:
813 TOKEN_GET_DATATYPE(type, Parser->Token);
814 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
815 ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
818 ret = Parse_DoExpr0(Parser);
819 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
825 return Parse_DoValue(Parser);
828 // --------------------
829 // Last Expression - Value
830 // --------------------
831 tAST_Node *Parse_DoValue(tParser *Parser)
833 int tok = LookAhead(Parser);
836 printf("Parse_DoValue: tok = %i\n", tok);
842 return Parse_GetString(Parser);
844 return Parse_GetNumeric(Parser);
848 return AST_NewReal( Parser, atof(Parser->TokenStr) );
851 return Parse_GetIdent(Parser, 0);
853 return Parse_GetVariable(Parser);
856 return AST_NewNull(Parser); // nODETYPE_NOP returns NULL
859 return Parse_GetIdent(Parser, 1);
862 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
863 csaTOKEN_NAMES[tok], Parser->CurLine);
864 longjmp( Parser->JmpTarget, -1 );
869 * \brief Get a string
871 tAST_Node *Parse_GetString(tParser *Parser)
878 char data[ Parser->TokenLen - 2 ];
881 for( i = 1; i < Parser->TokenLen - 1; i++ )
883 if( Parser->TokenStr[i] == '\\' ) {
885 switch( Parser->TokenStr[i] )
887 case 'n': data[j++] = '\n'; break;
888 case 'r': data[j++] = '\r'; break;
891 // TODO: Error/Warning?
896 data[j++] = Parser->TokenStr[i];
900 // TODO: Parse Escape Codes
901 ret = AST_NewString( Parser, data, j );
907 * \brief Get a numeric value
909 tAST_Node *Parse_GetNumeric(tParser *Parser)
913 SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
914 pos = Parser->TokenStr;
915 //printf("pos = %p, *pos = %c\n", pos, *pos);
925 if( '0' <= *pos && *pos <= '9' ) {
929 if( 'A' <= *pos && *pos <= 'F' ) {
930 value += *pos - 'A' + 10;
933 if( 'a' <= *pos && *pos <= 'f' ) {
934 value += *pos - 'a' + 10;
941 while( '0' <= *pos && *pos <= '7' ) {
942 value = value*8 + *pos - '0';
948 while( '0' <= *pos && *pos <= '9' ) {
949 value = value*10 + *pos - '0';
954 return AST_NewInteger( Parser, value );
958 * \brief Get a variable
960 tAST_Node *Parse_GetVariable(tParser *Parser)
963 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
965 char name[Parser->TokenLen];
966 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
967 name[Parser->TokenLen-1] = 0;
968 ret = AST_NewVariable( Parser, name );
970 printf("Parse_GetVariable: name = '%s'\n", name);
976 if( Parser->Token == TOK_SQUARE_OPEN )
978 ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
979 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
982 if( Parser->Token == TOK_ELEMENT )
984 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
986 if( LookAhead(Parser) == TOK_PAREN_OPEN )
988 char name[Parser->TokenLen+1];
989 memcpy(name, Parser->TokenStr, Parser->TokenLen);
990 name[Parser->TokenLen] = 0;
991 ret = AST_NewMethodCall(Parser, ret, name);
992 GetToken(Parser); // Eat the '('
994 if( GetToken(Parser) != TOK_PAREN_CLOSE )
998 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
999 } while(GetToken(Parser) == TOK_COMMA);
1000 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
1007 char name[Parser->TokenLen];
1008 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
1009 name[Parser->TokenLen-1] = 0;
1010 ret = AST_NewClassElement(Parser, ret, name);
1022 * \brief Get an identifier (constant or function call)
1024 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
1026 tAST_Node *ret = NULL;
1028 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
1029 name = strndup( Parser->TokenStr, Parser->TokenLen );
1032 if( GetToken(Parser) == TOK_SCOPE )
1034 ret = AST_NewScopeDereference( Parser, name, Parse_GetIdent(Parser, bObjectCreate) );
1041 if( GetToken(Parser) == TOK_PAREN_OPEN )
1044 printf("Parse_GetIdent: Calling '%s'\n", name);
1048 ret = AST_NewCreateObject( Parser, name );
1050 ret = AST_NewFunctionCall( Parser, name );
1052 if( GetToken(Parser) != TOK_PAREN_CLOSE )
1057 printf(" Parse_GetIdent: Argument\n");
1059 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
1060 } while(GetToken(Parser) == TOK_COMMA);
1061 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
1063 printf(" Parse_GetIdent: All arguments parsed\n");
1069 // Runtime Constant / Variable (When implemented)
1071 printf("Parse_GetIdent: Referencing '%s'\n", name);
1074 if( bObjectCreate ) // Void constructor (TODO: Should this be an error?)
1075 ret = AST_NewCreateObject( Parser, name );
1077 ret = AST_NewConstant( Parser, name );
1085 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...)
1088 va_start(args, Message);
1089 fprintf(stderr, "%s:%i: error: ", Parser->Filename, Parser->CurLine);
1090 vfprintf(stderr, Message, args);
1091 fprintf(stderr, "\n");
1095 //longjmp(Parser->JmpTarget, -1);
1096 Parser->ErrorHit = 1;