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
89 mainCode = AST_NewCodeBlock(&parser);
91 // Give us an error fallback
92 if( setjmp( parser.JmpTarget ) != 0 )
94 AST_FreeNode( mainCode );
96 for(fcn = Script->Functions; fcn; )
98 tScript_Function *nextFcn;
100 AST_FreeNode( fcn->ASTFcn );
110 while(Parser->Token != TOK_EOF)
112 switch( GetToken(Parser) )
117 // Typed variables/functions
118 case TOKEN_GROUP_TYPES:
119 TOKEN_GET_DATATYPE(type, Parser->Token);
121 switch(GetToken(Parser))
123 // Define a function (pass on to the other function definition code)
126 if( Parse_FunctionDefinition(Script, Parser, type) == NULL )
127 longjmp(Parser->JmpTarget, -1);
131 node = Parse_GetVarDef(Parser, type);
132 if(!node) longjmp(Parser->JmpTarget, -1);
134 AST_AppendNode( mainCode, node );
135 // Can't use SyntaxAssert because that returns
136 if(GetToken(Parser) != TOK_SEMICOLON) {
137 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_SEMICOLON",
138 csaTOKEN_NAMES[Parser->Token]);
139 longjmp(Parser->JmpTarget, -1);
143 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
144 csaTOKEN_NAMES[Parser->Token]);
150 case TOK_RWD_FUNCTION:
151 if( !Script->Variant->bDyamicTyped ) {
152 SyntaxError(Parser, 1, "Dynamic functions are invalid in static mode");
153 longjmp(Parser->JmpTarget, -1);
156 type = SS_DATATYPE_DYNAMIC;
158 if( Parse_FunctionDefinition(Script, Parser, SS_DATATYPE_DYNAMIC) == NULL )
159 longjmp(Parser->JmpTarget, -1);
163 // Ordinary Statement
166 node = Parse_DoBlockLine(Parser);
167 if(!node) longjmp(Parser->JmpTarget, -1);
168 AST_AppendNode( mainCode, node );
172 // Jump to error handler on error
174 longjmp(Parser->JmpTarget, -1);
177 AST_AppendFunction( Script, "", SS_DATATYPE_INTEGER, NULL, mainCode );
179 //printf("---- %p parsed as SpiderScript ----\n", Buffer);
184 void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type)
188 tAST_Node *first_arg, *last_arg, *code;
190 last_arg = (void*)&first_arg; // HACK
192 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
194 name = strndup( Parser->TokenStr, Parser->TokenLen );
196 printf("DefFCN %s\n", name);
200 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
201 if( LookAhead(Parser) != TOK_PAREN_CLOSE )
204 int type = SS_DATATYPE_DYNAMIC;
206 // Non dynamic typed variants must use data types
207 if( !Script->Variant->bDyamicTyped ) {
208 TOKEN_GET_DATATYPE(type, Parser->Token);
211 last_arg->NextSibling = Parse_GetVarDef(Parser, type);
212 last_arg = last_arg->NextSibling;
213 last_arg->NextSibling = NULL;
214 } while(GetToken(Parser) == TOK_COMMA);
218 SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
220 code = Parse_DoCodeBlock(Parser);
222 rv = AST_AppendFunction( Script, name, Type, first_arg, code );
224 // Clean up argument definition nodes
227 for( ; first_arg; first_arg = nextarg )
229 nextarg = first_arg->NextSibling;
230 AST_FreeNode(first_arg);
236 return rv == 0 ? (void*)1 : NULL;
240 * \brief Parse a block of code surrounded by { }
242 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
246 // Check if we are being called for a one-liner
247 if( GetToken(Parser) != TOK_BRACE_OPEN ) {
249 return Parse_DoBlockLine(Parser);
252 ret = AST_NewCodeBlock(Parser);
254 while( LookAhead(Parser) != TOK_BRACE_CLOSE )
256 tAST_Node *node = Parse_DoBlockLine(Parser);
261 AST_AppendNode( ret, node );
263 GetToken(Parser); // Omnomnom
268 * \brief Parse a line in a block
270 tAST_Node *Parse_DoBlockLine(tParser *Parser)
274 //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
276 switch(LookAhead(Parser))
280 return Parse_DoCodeBlock(Parser);
287 // Return from a method
290 ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
293 // Break / Continue (end a loop / go to next iteration)
294 case TOK_RWD_CONTINUE:
299 tok = GetToken(Parser);
300 // Get the number of nesting levels to break
301 if(LookAhead(Parser) == TOK_IDENT)
304 ident = strndup(Parser->TokenStr, Parser->TokenLen);
309 case TOK_RWD_BREAK: ret = AST_NewBreakout(Parser, NODETYPE_BREAK, ident); break;
310 case TOK_RWD_CONTINUE: ret = AST_NewBreakout(Parser, NODETYPE_CONTINUE, ident); break;
312 SyntaxError(Parser, 1, "BUG Unhandled break/continue (%s)",
313 csaTOKEN_NAMES[tok]);
316 if(ident) free(ident);
320 // Control Statements
323 tAST_Node *cond, *true, *false = NULL;
324 GetToken(Parser); // eat the if
326 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
327 cond = Parse_DoExpr0(Parser); // Get condition
328 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
329 true = Parse_DoCodeBlock(Parser);
330 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
332 false = Parse_DoCodeBlock(Parser);
335 false = AST_NewNop(Parser);
336 ret = AST_NewIf(Parser, cond, true, false);
343 tAST_Node *init=NULL, *cond=NULL, *inc=NULL, *code;
344 GetToken(Parser); // Eat 'for'
346 #if SUPPORT_BREAK_TAGS
347 if(LookAhead(Parser) == TOK_LT)
350 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
351 tag = strndup(Parser->TokenStr, Parser->TokenLen);
352 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
356 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
358 if(LookAhead(Parser) != TOK_SEMICOLON)
359 init = Parse_DoExpr0(Parser);
361 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
363 if(LookAhead(Parser) != TOK_SEMICOLON)
364 cond = Parse_DoExpr0(Parser);
366 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
368 if(LookAhead(Parser) != TOK_PAREN_CLOSE)
369 inc = Parse_DoExpr0(Parser);
371 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
373 code = Parse_DoCodeBlock(Parser);
374 ret = AST_NewLoop(Parser, tag, init, 0, cond, inc, code);
381 const char *tag = "";
382 tAST_Node *code, *cond;
383 GetToken(Parser); // Eat 'do'
385 #if SUPPORT_BREAK_TAGS
386 if(LookAhead(Parser) == TOK_LT)
389 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
390 tag = strndup(Parser->TokenStr, Parser->TokenLen);
391 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
395 code = Parse_DoCodeBlock(Parser);
396 SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
397 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
398 cond = Parse_DoExpr0(Parser);
399 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
400 ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code);
405 const char *tag = "";
406 tAST_Node *code, *cond;
407 GetToken(Parser); // Eat 'while'
409 #if SUPPORT_BREAK_TAGS
410 if(LookAhead(Parser) == TOK_LT)
413 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
414 tag = strndup(Parser->TokenStr, Parser->TokenLen);
415 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
419 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
420 cond = Parse_DoExpr0(Parser);
421 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
422 code = Parse_DoCodeBlock(Parser);
423 ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
428 case TOKEN_GROUP_TYPES:
432 TOKEN_GET_DATATYPE(type, Parser->Token);
434 SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
436 ret = Parse_GetVarDef(Parser, type);
443 ret = Parse_DoExpr0(Parser);
447 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
452 * \brief Get a variable definition
454 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
456 char name[Parser->TokenLen];
459 SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
461 // copy the name (trimming the $)
462 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
463 name[Parser->TokenLen-1] = 0;
464 // Define the variable
465 ret = AST_NewDefineVar(Parser, Type, name);
467 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
471 node = Parse_DoExpr0(Parser);
476 AST_AppendNode(ret, node);
477 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
480 if( LookAhead(Parser) == TOK_ASSIGN )
483 ret->DefVar.InitialValue = Parse_DoExpr0(Parser);
484 if(!ret->DefVar.InitialValue) {
494 * \brief Assignment Operations
496 tAST_Node *Parse_DoExpr0(tParser *Parser)
498 #define _next Parse_DoExpr1
499 tAST_Node *ret = _next(Parser);
505 switch(GetToken(Parser))
508 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, _next(Parser));
511 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
514 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
516 case TOK_ASSIGN_PLUS:
517 ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, _next(Parser));
519 case TOK_ASSIGN_MINUS:
520 ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
524 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
536 * \brief Logical/Boolean Operators
538 tAST_Node *Parse_DoExpr1(tParser *Parser)
540 #define _next Parse_DoExpr2
541 tAST_Node *ret = _next(Parser);
546 switch(GetToken(Parser))
549 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, _next(Parser));
552 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, _next(Parser));
555 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, _next(Parser));
567 // --------------------
568 // Expression 2 - Comparison Operators
569 // --------------------
570 tAST_Node *Parse_DoExpr2(tParser *Parser)
572 #define _next Parse_DoExpr3
573 tAST_Node *ret = _next(Parser);
579 switch(GetToken(Parser))
582 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, _next(Parser));
585 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, _next(Parser));
588 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, _next(Parser));
591 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, _next(Parser));
594 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, _next(Parser));
607 * \brief Bitwise Operations
609 tAST_Node *Parse_DoExpr3(tParser *Parser)
611 #define _next Parse_DoExpr4
612 tAST_Node *ret = _next(Parser);
618 switch(GetToken(Parser))
621 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, _next(Parser));
624 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, _next(Parser));
627 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, _next(Parser));
639 // --------------------
640 // Expression 4 - Shifts
641 // --------------------
642 tAST_Node *Parse_DoExpr4(tParser *Parser)
644 #define _next Parse_DoExpr5
645 tAST_Node *ret = _next(Parser);
650 switch(GetToken(Parser))
653 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, _next(Parser));
656 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, _next(Parser));
669 // --------------------
670 // Expression 5 - Arithmatic
671 // --------------------
672 tAST_Node *Parse_DoExpr5(tParser *Parser)
674 #define _next Parse_DoExpr6
675 tAST_Node *ret = _next(Parser);
678 // While loop is added to ensure that the evaluation order ends up as
680 // E.g. a + b + c + d ends up as (((a + b) + c) + d) for casting
683 switch(GetToken(Parser))
686 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, _next(Parser));
689 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
702 // --------------------
703 // Expression 6 - Multiplcation & Division
704 // --------------------
705 tAST_Node *Parse_DoExpr6(tParser *Parser)
707 #define _next Parse_DoExpr7
708 tAST_Node *ret = _next(Parser);
713 switch(GetToken(Parser))
716 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
719 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
732 // --------------------
733 // Expression 7 - Right Unary Operations
734 // --------------------
735 tAST_Node *Parse_DoExpr7(tParser *Parser)
737 tAST_Node *ret = Parse_DoExpr8(Parser);
739 switch(GetToken(Parser))
742 ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
745 ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
754 // --------------------
755 // Expression 8 - Left Unary Operations
756 // --------------------
757 tAST_Node *Parse_DoExpr8(tParser *Parser)
759 switch(GetToken(Parser))
762 return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
764 return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
766 return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
768 return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
770 return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
773 return Parse_DoParen(Parser);
777 // --------------------
778 // 2nd Last Expression - Parens
779 // --------------------
780 tAST_Node *Parse_DoParen(tParser *Parser)
783 printf("Parse_DoParen: (Parser=%p)\n", Parser);
785 if(LookAhead(Parser) == TOK_PAREN_OPEN)
791 // TODO: Handle casts here
792 switch(LookAhead(Parser))
794 case TOKEN_GROUP_TYPES:
796 TOKEN_GET_DATATYPE(type, Parser->Token);
797 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
798 ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
801 ret = Parse_DoExpr0(Parser);
802 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
808 return Parse_DoValue(Parser);
811 // --------------------
812 // Last Expression - Value
813 // --------------------
814 tAST_Node *Parse_DoValue(tParser *Parser)
816 int tok = LookAhead(Parser);
819 printf("Parse_DoValue: tok = %i\n", tok);
825 return Parse_GetString(Parser);
827 return Parse_GetNumeric(Parser);
831 return AST_NewReal( Parser, atof(Parser->TokenStr) );
834 return Parse_GetIdent(Parser, 0);
836 return Parse_GetVariable(Parser);
839 return AST_NewNop(Parser); // NODETYPE_NOP returns NULL
842 return Parse_GetIdent(Parser, 1);
845 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
846 csaTOKEN_NAMES[tok], Parser->CurLine);
847 longjmp( Parser->JmpTarget, -1 );
852 * \brief Get a string
854 tAST_Node *Parse_GetString(tParser *Parser)
861 char data[ Parser->TokenLen - 2 ];
864 for( i = 1; i < Parser->TokenLen - 1; i++ )
866 if( Parser->TokenStr[i] == '\\' ) {
868 switch( Parser->TokenStr[i] )
870 case 'n': data[j++] = '\n'; break;
871 case 'r': data[j++] = '\r'; break;
874 // TODO: Error/Warning?
879 data[j++] = Parser->TokenStr[i];
883 // TODO: Parse Escape Codes
884 ret = AST_NewString( Parser, data, j );
890 * \brief Get a numeric value
892 tAST_Node *Parse_GetNumeric(tParser *Parser)
896 SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
897 pos = Parser->TokenStr;
898 //printf("pos = %p, *pos = %c\n", pos, *pos);
908 if( '0' <= *pos && *pos <= '9' ) {
912 if( 'A' <= *pos && *pos <= 'F' ) {
913 value += *pos - 'A' + 10;
916 if( 'a' <= *pos && *pos <= 'f' ) {
917 value += *pos - 'a' + 10;
924 while( '0' <= *pos && *pos <= '7' ) {
925 value = value*8 + *pos - '0';
931 while( '0' <= *pos && *pos <= '9' ) {
932 value = value*10 + *pos - '0';
937 return AST_NewInteger( Parser, value );
941 * \brief Get a variable
943 tAST_Node *Parse_GetVariable(tParser *Parser)
946 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
948 char name[Parser->TokenLen];
949 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
950 name[Parser->TokenLen-1] = 0;
951 ret = AST_NewVariable( Parser, name );
953 printf("Parse_GetVariable: name = '%s'\n", name);
959 if( Parser->Token == TOK_SQUARE_OPEN )
961 ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
962 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
965 if( Parser->Token == TOK_ELEMENT )
967 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
969 if( LookAhead(Parser) == TOK_PAREN_OPEN )
971 char name[Parser->TokenLen+1];
972 memcpy(name, Parser->TokenStr, Parser->TokenLen);
973 name[Parser->TokenLen] = 0;
974 ret = AST_NewMethodCall(Parser, ret, name);
975 GetToken(Parser); // Eat the '('
977 if( GetToken(Parser) != TOK_PAREN_CLOSE )
981 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
982 } while(GetToken(Parser) == TOK_COMMA);
983 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
990 char name[Parser->TokenLen];
991 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
992 name[Parser->TokenLen-1] = 0;
993 ret = AST_NewClassElement(Parser, ret, name);
1005 * \brief Get an identifier (constant or function call)
1007 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
1009 tAST_Node *ret = NULL;
1011 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
1012 name = strndup( Parser->TokenStr, Parser->TokenLen );
1015 if( GetToken(Parser) == TOK_SCOPE )
1017 ret = AST_NewScopeDereference( Parser, name, Parse_GetIdent(Parser, bObjectCreate) );
1024 if( GetToken(Parser) == TOK_PAREN_OPEN )
1027 printf("Parse_GetIdent: Calling '%s'\n", name);
1031 ret = AST_NewCreateObject( Parser, name );
1033 ret = AST_NewFunctionCall( Parser, name );
1035 if( GetToken(Parser) != TOK_PAREN_CLOSE )
1040 printf(" Parse_GetIdent: Argument\n");
1042 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
1043 } while(GetToken(Parser) == TOK_COMMA);
1044 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
1046 printf(" Parse_GetIdent: All arguments parsed\n");
1052 // Runtime Constant / Variable (When implemented)
1054 printf("Parse_GetIdent: Referencing '%s'\n", name);
1057 if( bObjectCreate ) // Void constructor (TODO: Should this be an error?)
1058 ret = AST_NewCreateObject( Parser, name );
1060 ret = AST_NewConstant( Parser, name );
1068 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...)
1071 va_start(args, Message);
1072 fprintf(stderr, "%s:%i: error: ", Parser->Filename, Parser->CurLine);
1073 vfprintf(stderr, Message, args);
1074 fprintf(stderr, "\n");
1078 //longjmp(Parser->JmpTarget, -1);
1079 Parser->ErrorHit = 1;