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_NOTEQUALS, ret, _next(Parser));
588 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, _next(Parser));
591 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, _next(Parser));
594 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, _next(Parser));
597 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, _next(Parser));
610 * \brief Bitwise Operations
612 tAST_Node *Parse_DoExpr3(tParser *Parser)
614 #define _next Parse_DoExpr4
615 tAST_Node *ret = _next(Parser);
621 switch(GetToken(Parser))
624 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, _next(Parser));
627 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, _next(Parser));
630 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, _next(Parser));
642 // --------------------
643 // Expression 4 - Shifts
644 // --------------------
645 tAST_Node *Parse_DoExpr4(tParser *Parser)
647 #define _next Parse_DoExpr5
648 tAST_Node *ret = _next(Parser);
653 switch(GetToken(Parser))
656 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, _next(Parser));
659 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, _next(Parser));
672 // --------------------
673 // Expression 5 - Arithmatic
674 // --------------------
675 tAST_Node *Parse_DoExpr5(tParser *Parser)
677 #define _next Parse_DoExpr6
678 tAST_Node *ret = _next(Parser);
681 // While loop is added to ensure that the evaluation order ends up as
683 // E.g. a + b + c + d ends up as (((a + b) + c) + d) for casting
686 switch(GetToken(Parser))
689 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, _next(Parser));
692 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
705 // --------------------
706 // Expression 6 - Multiplcation & Division
707 // --------------------
708 tAST_Node *Parse_DoExpr6(tParser *Parser)
710 #define _next Parse_DoExpr7
711 tAST_Node *ret = _next(Parser);
716 switch(GetToken(Parser))
719 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
722 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
735 // --------------------
736 // Expression 7 - Right Unary Operations
737 // --------------------
738 tAST_Node *Parse_DoExpr7(tParser *Parser)
740 tAST_Node *ret = Parse_DoExpr8(Parser);
742 switch(GetToken(Parser))
745 ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
748 ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
757 // --------------------
758 // Expression 8 - Left Unary Operations
759 // --------------------
760 tAST_Node *Parse_DoExpr8(tParser *Parser)
762 switch(GetToken(Parser))
765 return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
767 return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
769 return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
771 return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
773 return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
776 return Parse_DoParen(Parser);
780 // --------------------
781 // 2nd Last Expression - Parens
782 // --------------------
783 tAST_Node *Parse_DoParen(tParser *Parser)
786 printf("Parse_DoParen: (Parser=%p)\n", Parser);
788 if(LookAhead(Parser) == TOK_PAREN_OPEN)
794 // TODO: Handle casts here
795 switch(LookAhead(Parser))
797 case TOKEN_GROUP_TYPES:
799 TOKEN_GET_DATATYPE(type, Parser->Token);
800 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
801 ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
804 ret = Parse_DoExpr0(Parser);
805 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
811 return Parse_DoValue(Parser);
814 // --------------------
815 // Last Expression - Value
816 // --------------------
817 tAST_Node *Parse_DoValue(tParser *Parser)
819 int tok = LookAhead(Parser);
822 printf("Parse_DoValue: tok = %i\n", tok);
828 return Parse_GetString(Parser);
830 return Parse_GetNumeric(Parser);
834 return AST_NewReal( Parser, atof(Parser->TokenStr) );
837 return Parse_GetIdent(Parser, 0);
839 return Parse_GetVariable(Parser);
842 return AST_NewNop(Parser); // NODETYPE_NOP returns NULL
845 return Parse_GetIdent(Parser, 1);
848 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
849 csaTOKEN_NAMES[tok], Parser->CurLine);
850 longjmp( Parser->JmpTarget, -1 );
855 * \brief Get a string
857 tAST_Node *Parse_GetString(tParser *Parser)
864 char data[ Parser->TokenLen - 2 ];
867 for( i = 1; i < Parser->TokenLen - 1; i++ )
869 if( Parser->TokenStr[i] == '\\' ) {
871 switch( Parser->TokenStr[i] )
873 case 'n': data[j++] = '\n'; break;
874 case 'r': data[j++] = '\r'; break;
877 // TODO: Error/Warning?
882 data[j++] = Parser->TokenStr[i];
886 // TODO: Parse Escape Codes
887 ret = AST_NewString( Parser, data, j );
893 * \brief Get a numeric value
895 tAST_Node *Parse_GetNumeric(tParser *Parser)
899 SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
900 pos = Parser->TokenStr;
901 //printf("pos = %p, *pos = %c\n", pos, *pos);
911 if( '0' <= *pos && *pos <= '9' ) {
915 if( 'A' <= *pos && *pos <= 'F' ) {
916 value += *pos - 'A' + 10;
919 if( 'a' <= *pos && *pos <= 'f' ) {
920 value += *pos - 'a' + 10;
927 while( '0' <= *pos && *pos <= '7' ) {
928 value = value*8 + *pos - '0';
934 while( '0' <= *pos && *pos <= '9' ) {
935 value = value*10 + *pos - '0';
940 return AST_NewInteger( Parser, value );
944 * \brief Get a variable
946 tAST_Node *Parse_GetVariable(tParser *Parser)
949 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
951 char name[Parser->TokenLen];
952 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
953 name[Parser->TokenLen-1] = 0;
954 ret = AST_NewVariable( Parser, name );
956 printf("Parse_GetVariable: name = '%s'\n", name);
962 if( Parser->Token == TOK_SQUARE_OPEN )
964 ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
965 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
968 if( Parser->Token == TOK_ELEMENT )
970 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
972 if( LookAhead(Parser) == TOK_PAREN_OPEN )
974 char name[Parser->TokenLen+1];
975 memcpy(name, Parser->TokenStr, Parser->TokenLen);
976 name[Parser->TokenLen] = 0;
977 ret = AST_NewMethodCall(Parser, ret, name);
978 GetToken(Parser); // Eat the '('
980 if( GetToken(Parser) != TOK_PAREN_CLOSE )
984 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
985 } while(GetToken(Parser) == TOK_COMMA);
986 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
993 char name[Parser->TokenLen];
994 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
995 name[Parser->TokenLen-1] = 0;
996 ret = AST_NewClassElement(Parser, ret, name);
1008 * \brief Get an identifier (constant or function call)
1010 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
1012 tAST_Node *ret = NULL;
1014 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
1015 name = strndup( Parser->TokenStr, Parser->TokenLen );
1018 if( GetToken(Parser) == TOK_SCOPE )
1020 ret = AST_NewScopeDereference( Parser, name, Parse_GetIdent(Parser, bObjectCreate) );
1027 if( GetToken(Parser) == TOK_PAREN_OPEN )
1030 printf("Parse_GetIdent: Calling '%s'\n", name);
1034 ret = AST_NewCreateObject( Parser, name );
1036 ret = AST_NewFunctionCall( Parser, name );
1038 if( GetToken(Parser) != TOK_PAREN_CLOSE )
1043 printf(" Parse_GetIdent: Argument\n");
1045 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
1046 } while(GetToken(Parser) == TOK_COMMA);
1047 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
1049 printf(" Parse_GetIdent: All arguments parsed\n");
1055 // Runtime Constant / Variable (When implemented)
1057 printf("Parse_GetIdent: Referencing '%s'\n", name);
1060 if( bObjectCreate ) // Void constructor (TODO: Should this be an error?)
1061 ret = AST_NewCreateObject( Parser, name );
1063 ret = AST_NewConstant( Parser, name );
1071 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...)
1074 va_start(args, Message);
1075 fprintf(stderr, "%s:%i: error: ", Parser->Filename, Parser->CurLine);
1076 vfprintf(stderr, Message, args);
1077 fprintf(stderr, "\n");
1081 //longjmp(Parser->JmpTarget, -1);
1082 Parser->ErrorHit = 1;