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, tAST_Node *CodeNode);
22 tAST_Node *Parse_DoBlockLine(tParser *Parser, tAST_Node *CodeNode);
23 tAST_Node *Parse_VarDefList(tParser *Parser, tAST_Node *CodeNode, int Type);
24 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type);
26 tAST_Node *Parse_DoExpr0(tParser *Parser); // Assignment
27 tAST_Node *Parse_DoExpr1(tParser *Parser); // Boolean Operators
28 tAST_Node *Parse_DoExpr2(tParser *Parser); // Comparison Operators
29 tAST_Node *Parse_DoExpr3(tParser *Parser); // Bitwise Operators
30 tAST_Node *Parse_DoExpr4(tParser *Parser); // Bit Shifts
31 tAST_Node *Parse_DoExpr5(tParser *Parser); // Arithmatic
32 tAST_Node *Parse_DoExpr6(tParser *Parser); // Mult & Div
33 tAST_Node *Parse_DoExpr7(tParser *Parser); // Right Unary Operations
34 tAST_Node *Parse_DoExpr8(tParser *Parser); // Left Unary Operations
36 tAST_Node *Parse_DoParen(tParser *Parser); // Parenthesis (Always Last)
37 tAST_Node *Parse_DoValue(tParser *Parser); // Values
39 tAST_Node *Parse_GetString(tParser *Parser);
40 tAST_Node *Parse_GetNumeric(tParser *Parser);
41 tAST_Node *Parse_GetVariable(tParser *Parser);
42 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate);
44 void SyntaxAssert(tParser *Parser, int Have, int Want);
45 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...);
48 #define SyntaxAssert(_parser, _have, _want) SyntaxAssertV(_parser, _have, _want, NULL)
49 #define SyntaxAssertV(_parser, _have, _want, _rv) do { \
50 int have = (_have), want = (_want); \
51 if( (have) != (want) ) { \
52 SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n", \
53 csaTOKEN_NAMES[have], have, csaTOKEN_NAMES[want], want); \
59 #define TODO(Parser, message...) do {\
60 fprintf(stderr, "TODO: "message);\
61 longjmp(Parser->JmpTarget, -1);\
66 * \brief Parse a buffer into a syntax tree
68 int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename)
71 tParser *Parser = &parser; //< Keeps code consistent
72 tAST_Node *mainCode, *node;
74 tScript_Function *fcn;
77 printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer);
81 parser.LastToken = -1;
82 parser.NextToken = -1;
84 parser.BufStart = Buffer;
85 parser.CurPos = Buffer;
86 // hackery to do reference counting
87 parser.Filename = malloc(sizeof(int)+strlen(Filename)+1);
88 strcpy(parser.Filename + sizeof(int), Filename);
89 *(int*)(parser.Filename) = 0; // Set reference count
90 parser.Filename += sizeof(int); // Move filename
92 parser.Variant = Script->Variant;
94 mainCode = AST_NewCodeBlock(&parser);
96 // Give us an error fallback
97 if( setjmp( parser.JmpTarget ) != 0 )
99 AST_FreeNode( mainCode );
101 for(fcn = Script->Functions; fcn; )
103 tScript_Function *nextFcn;
105 AST_FreeNode( fcn->ASTFcn );
115 while(Parser->Token != TOK_EOF)
117 switch( GetToken(Parser) )
122 // Typed variables/functions
123 case TOKEN_GROUP_TYPES:
124 TOKEN_GET_DATATYPE(type, Parser->Token);
126 switch(LookAhead(Parser))
128 // Define a function (pass on to the other function definition code)
130 if( Parse_FunctionDefinition(Script, Parser, type) == NULL )
131 longjmp(Parser->JmpTarget, -1);
133 // Define a variable (pass back to _DoBlockLine)
135 node = Parse_VarDefList(Parser, mainCode, type);
136 AST_AppendNode(mainCode, node);
137 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
140 SyntaxError(Parser, 1, "Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
141 csaTOKEN_NAMES[Parser->Token]);
147 case TOK_RWD_FUNCTION:
148 if( !Script->Variant->bDyamicTyped ) {
149 SyntaxError(Parser, 1, "Dynamic functions are invalid in static mode");
150 longjmp(Parser->JmpTarget, -1);
153 type = SS_DATATYPE_DYNAMIC;
155 if( Parse_FunctionDefinition(Script, Parser, SS_DATATYPE_DYNAMIC) == NULL )
156 longjmp(Parser->JmpTarget, -1);
160 // Ordinary Statement
163 node = Parse_DoBlockLine(Parser, mainCode);
164 if(!node) longjmp(Parser->JmpTarget, -1);
165 AST_AppendNode( mainCode, node );
169 // Jump to error handler on error
171 longjmp(Parser->JmpTarget, -1);
174 AST_AppendFunction( Script, "", SS_DATATYPE_INTEGER, NULL, mainCode );
176 //printf("---- %p parsed as SpiderScript ----\n", Buffer);
181 void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type)
185 tAST_Node *first_arg, *last_arg, *code;
187 last_arg = (void*)&first_arg; // HACK
189 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
191 name = strndup( Parser->TokenStr, Parser->TokenLen );
193 printf("DefFCN %s\n", name);
197 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
198 if( LookAhead(Parser) != TOK_PAREN_CLOSE )
201 int type = SS_DATATYPE_DYNAMIC;
203 // Non dynamic typed variants must use data types
204 if( !Script->Variant->bDyamicTyped ) {
205 TOKEN_GET_DATATYPE(type, Parser->Token);
208 last_arg->NextSibling = Parse_GetVarDef(Parser, type);
209 last_arg = last_arg->NextSibling;
210 last_arg->NextSibling = NULL;
211 } while(GetToken(Parser) == TOK_COMMA);
215 SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
217 code = Parse_DoCodeBlock(Parser, NULL);
219 rv = AST_AppendFunction( Script, name, Type, first_arg, code );
221 // Clean up argument definition nodes
224 for( ; first_arg; first_arg = nextarg )
226 nextarg = first_arg->NextSibling;
227 AST_FreeNode(first_arg);
233 return rv == 0 ? (void*)1 : NULL;
237 * \brief Parse a block of code surrounded by { }
239 tAST_Node *Parse_DoCodeBlock(tParser *Parser, tAST_Node *CodeNode)
243 // Check if we are being called for a one-liner
244 if( GetToken(Parser) != TOK_BRACE_OPEN ) {
246 return Parse_DoBlockLine(Parser, CodeNode);
249 ret = AST_NewCodeBlock(Parser);
251 while( LookAhead(Parser) != TOK_BRACE_CLOSE )
253 tAST_Node *node = Parse_DoBlockLine(Parser, ret);
258 AST_AppendNode( ret, node );
260 GetToken(Parser); // Omnomnom
265 * \brief Parse a line in a block
267 tAST_Node *Parse_DoBlockLine(tParser *Parser, tAST_Node *CodeNode)
271 //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
273 switch(LookAhead(Parser))
277 return Parse_DoCodeBlock(Parser, CodeNode);
284 // Return from a method
287 ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
290 // Break / Continue (end a loop / go to next iteration)
291 case TOK_RWD_CONTINUE:
296 tok = GetToken(Parser);
297 // Get the number of nesting levels to break
298 if(LookAhead(Parser) == TOK_IDENT)
301 ident = strndup(Parser->TokenStr, Parser->TokenLen);
306 case TOK_RWD_BREAK: ret = AST_NewBreakout(Parser, NODETYPE_BREAK, ident); break;
307 case TOK_RWD_CONTINUE: ret = AST_NewBreakout(Parser, NODETYPE_CONTINUE, ident); break;
309 SyntaxError(Parser, 1, "BUG Unhandled break/continue (%s)",
310 csaTOKEN_NAMES[tok]);
313 if(ident) free(ident);
317 // Control Statements
320 tAST_Node *cond, *true, *false = NULL;
321 GetToken(Parser); // eat the if
323 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
324 cond = Parse_DoExpr0(Parser); // Get condition
325 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
326 true = Parse_DoCodeBlock(Parser, CodeNode);
327 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
329 false = Parse_DoCodeBlock(Parser, CodeNode);
332 false = AST_NewNop(Parser);
333 ret = AST_NewIf(Parser, cond, true, false);
340 tAST_Node *init=NULL, *cond=NULL, *inc=NULL, *code;
341 GetToken(Parser); // Eat 'for'
343 #if SUPPORT_BREAK_TAGS
344 if(LookAhead(Parser) == TOK_LT)
347 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
348 tag = strndup(Parser->TokenStr, Parser->TokenLen);
349 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
353 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
355 if(LookAhead(Parser) != TOK_SEMICOLON)
356 init = Parse_DoExpr0(Parser);
358 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
360 if(LookAhead(Parser) != TOK_SEMICOLON)
361 cond = Parse_DoExpr0(Parser);
363 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
365 if(LookAhead(Parser) != TOK_PAREN_CLOSE)
366 inc = Parse_DoExpr0(Parser);
368 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
370 code = Parse_DoCodeBlock(Parser, CodeNode);
371 ret = AST_NewLoop(Parser, tag, init, 0, cond, inc, code);
378 const char *tag = "";
379 tAST_Node *code, *cond;
380 GetToken(Parser); // Eat 'do'
382 #if SUPPORT_BREAK_TAGS
383 if(LookAhead(Parser) == TOK_LT)
386 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
387 tag = strndup(Parser->TokenStr, Parser->TokenLen);
388 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
392 code = Parse_DoCodeBlock(Parser, CodeNode);
393 SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
394 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
395 cond = Parse_DoExpr0(Parser);
396 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
397 ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code);
402 const char *tag = "";
403 tAST_Node *code, *cond;
404 GetToken(Parser); // Eat 'while'
406 #if SUPPORT_BREAK_TAGS
407 if(LookAhead(Parser) == TOK_LT)
410 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
411 tag = strndup(Parser->TokenStr, Parser->TokenLen);
412 SyntaxAssert(Parser, GetToken(Parser), TOK_GT);
416 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
417 cond = Parse_DoExpr0(Parser);
418 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
419 code = Parse_DoCodeBlock(Parser, CodeNode);
420 ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
425 case TOKEN_GROUP_TYPES:
429 TOKEN_GET_DATATYPE(type, Parser->Token);
430 ret = Parse_VarDefList(Parser, CodeNode, type);
437 ret = Parse_DoExpr0(Parser);
441 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
445 tAST_Node *Parse_VarDefList(tParser *Parser, tAST_Node *CodeNode, int Type)
451 if(ret) AST_AppendNode( CodeNode, ret );
452 SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
454 ret = Parse_GetVarDef(Parser, Type);
455 if(!ret) longjmp(Parser->JmpTarget, -1);
456 } while(GetToken(Parser) == TOK_COMMA);
457 PutBack(Parser); // Semicolon is checked by caller
463 * \brief Get a variable definition
465 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
467 char name[Parser->TokenLen];
471 SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
473 // copy the name (trimming the $)
474 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
475 name[Parser->TokenLen-1] = 0;
477 // Define the variable
478 ret = AST_NewDefineVar(Parser, Type, name);
481 if( LookAhead(Parser) == TOK_SQUARE_OPEN )
484 if( LookAhead(Parser) != TOK_SQUARE_CLOSE )
486 ret->DefVar.InitialValue = AST_NewFunctionCall(Parser, "array");
487 AST_AppendFunctionCallArg(ret->DefVar.InitialValue, Parse_DoExpr0(Parser));
489 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
493 while( LookAhead(Parser) == TOK_SQUARE_OPEN )
496 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
500 // Maul the type to denote the dereference level
501 if( Parser->Variant->bDyamicTyped ) {
502 ret->DefVar.DataType = SS_DATATYPE_ARRAY;
505 ret->DefVar.DataType |= (level << 16);
509 if( LookAhead(Parser) == TOK_ASSIGN )
511 if( ret->DefVar.InitialValue )
513 SyntaxError(Parser, 1, "Cannot assign and set array size at the same time");
516 ret->DefVar.InitialValue = Parse_DoExpr0(Parser);
517 if(!ret->DefVar.InitialValue) {
522 else if( ret->DefVar.InitialValue )
524 AST_AppendFunctionCallArg(ret->DefVar.InitialValue, AST_NewInteger(Parser, ret->DefVar.DataType));
531 * \brief Assignment Operations
533 tAST_Node *Parse_DoExpr0(tParser *Parser)
535 #define _next Parse_DoExpr1
536 tAST_Node *ret = _next(Parser);
542 switch(GetToken(Parser))
545 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, _next(Parser));
548 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
551 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
553 case TOK_ASSIGN_PLUS:
554 ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, _next(Parser));
556 case TOK_ASSIGN_MINUS:
557 ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
561 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
573 * \brief Logical/Boolean Operators
575 tAST_Node *Parse_DoExpr1(tParser *Parser)
577 #define _next Parse_DoExpr2
578 tAST_Node *ret = _next(Parser);
583 switch(GetToken(Parser))
586 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, _next(Parser));
589 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, _next(Parser));
592 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, _next(Parser));
604 // --------------------
605 // Expression 2 - Comparison Operators
606 // --------------------
607 tAST_Node *Parse_DoExpr2(tParser *Parser)
609 #define _next Parse_DoExpr3
610 tAST_Node *ret = _next(Parser);
616 switch(GetToken(Parser))
619 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, _next(Parser));
622 ret = AST_NewBinOp(Parser, NODETYPE_NOTEQUALS, ret, _next(Parser));
625 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, _next(Parser));
628 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, _next(Parser));
631 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, _next(Parser));
634 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, _next(Parser));
647 * \brief Bitwise Operations
649 tAST_Node *Parse_DoExpr3(tParser *Parser)
651 #define _next Parse_DoExpr4
652 tAST_Node *ret = _next(Parser);
658 switch(GetToken(Parser))
661 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, _next(Parser));
664 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, _next(Parser));
667 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, _next(Parser));
679 // --------------------
680 // Expression 4 - Shifts
681 // --------------------
682 tAST_Node *Parse_DoExpr4(tParser *Parser)
684 #define _next Parse_DoExpr5
685 tAST_Node *ret = _next(Parser);
690 switch(GetToken(Parser))
693 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, _next(Parser));
696 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, _next(Parser));
709 // --------------------
710 // Expression 5 - Arithmatic
711 // --------------------
712 tAST_Node *Parse_DoExpr5(tParser *Parser)
714 #define _next Parse_DoExpr6
715 tAST_Node *ret = _next(Parser);
718 // While loop is added to ensure that the evaluation order ends up as
720 // E.g. a + b + c + d ends up as (((a + b) + c) + d) for casting
723 switch(GetToken(Parser))
726 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, _next(Parser));
729 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, _next(Parser));
742 // --------------------
743 // Expression 6 - Multiplcation & Division
744 // --------------------
745 tAST_Node *Parse_DoExpr6(tParser *Parser)
747 #define _next Parse_DoExpr7
748 tAST_Node *ret = _next(Parser);
753 switch(GetToken(Parser))
756 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, _next(Parser));
759 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, _next(Parser));
772 // --------------------
773 // Expression 7 - Right Unary Operations
774 // --------------------
775 tAST_Node *Parse_DoExpr7(tParser *Parser)
777 tAST_Node *ret = Parse_DoExpr8(Parser);
779 switch(GetToken(Parser))
782 ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
785 ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
794 // --------------------
795 // Expression 8 - Left Unary Operations
796 // --------------------
797 tAST_Node *Parse_DoExpr8(tParser *Parser)
799 switch(GetToken(Parser))
802 return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
804 return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
806 return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
808 return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
810 return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
813 return Parse_DoParen(Parser);
817 // --------------------
818 // 2nd Last Expression - Parens
819 // --------------------
820 tAST_Node *Parse_DoParen(tParser *Parser)
823 printf("Parse_DoParen: (Parser=%p)\n", Parser);
825 if(LookAhead(Parser) == TOK_PAREN_OPEN)
831 // TODO: Handle casts here
832 switch(LookAhead(Parser))
834 case TOKEN_GROUP_TYPES:
836 TOKEN_GET_DATATYPE(type, Parser->Token);
837 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
838 ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
841 ret = Parse_DoExpr0(Parser);
842 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
848 return Parse_DoValue(Parser);
851 // --------------------
852 // Last Expression - Value
853 // --------------------
854 tAST_Node *Parse_DoValue(tParser *Parser)
856 int tok = LookAhead(Parser);
859 printf("Parse_DoValue: tok = %i\n", tok);
865 return Parse_GetString(Parser);
867 return Parse_GetNumeric(Parser);
871 return AST_NewReal( Parser, atof(Parser->TokenStr) );
874 return Parse_GetIdent(Parser, 0);
876 return Parse_GetVariable(Parser);
879 return AST_NewNull(Parser); // nODETYPE_NOP returns NULL
882 return Parse_GetIdent(Parser, 1);
885 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
886 csaTOKEN_NAMES[tok], Parser->CurLine);
887 longjmp( Parser->JmpTarget, -1 );
892 * \brief Get a string
894 tAST_Node *Parse_GetString(tParser *Parser)
901 char data[ Parser->TokenLen - 2 ];
904 for( i = 1; i < Parser->TokenLen - 1; i++ )
906 if( Parser->TokenStr[i] == '\\' ) {
908 switch( Parser->TokenStr[i] )
910 case 'n': data[j++] = '\n'; break;
911 case 'r': data[j++] = '\r'; break;
914 // TODO: Error/Warning?
919 data[j++] = Parser->TokenStr[i];
923 // TODO: Parse Escape Codes
924 ret = AST_NewString( Parser, data, j );
930 * \brief Get a numeric value
932 tAST_Node *Parse_GetNumeric(tParser *Parser)
936 SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
937 pos = Parser->TokenStr;
938 //printf("pos = %p, *pos = %c\n", pos, *pos);
948 if( '0' <= *pos && *pos <= '9' ) {
952 if( 'A' <= *pos && *pos <= 'F' ) {
953 value += *pos - 'A' + 10;
956 if( 'a' <= *pos && *pos <= 'f' ) {
957 value += *pos - 'a' + 10;
964 while( '0' <= *pos && *pos <= '7' ) {
965 value = value*8 + *pos - '0';
971 while( '0' <= *pos && *pos <= '9' ) {
972 value = value*10 + *pos - '0';
977 return AST_NewInteger( Parser, value );
981 * \brief Get a variable
983 tAST_Node *Parse_GetVariable(tParser *Parser)
986 SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
988 char name[Parser->TokenLen];
989 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
990 name[Parser->TokenLen-1] = 0;
991 ret = AST_NewVariable( Parser, name );
993 printf("Parse_GetVariable: name = '%s'\n", name);
999 if( Parser->Token == TOK_SQUARE_OPEN )
1001 ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
1002 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
1005 if( Parser->Token == TOK_ELEMENT )
1007 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
1009 if( LookAhead(Parser) == TOK_PAREN_OPEN )
1011 char name[Parser->TokenLen+1];
1012 memcpy(name, Parser->TokenStr, Parser->TokenLen);
1013 name[Parser->TokenLen] = 0;
1014 ret = AST_NewMethodCall(Parser, ret, name);
1015 GetToken(Parser); // Eat the '('
1017 if( GetToken(Parser) != TOK_PAREN_CLOSE )
1021 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
1022 } while(GetToken(Parser) == TOK_COMMA);
1023 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
1030 char name[Parser->TokenLen];
1031 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
1032 name[Parser->TokenLen-1] = 0;
1033 ret = AST_NewClassElement(Parser, ret, name);
1045 * \brief Get an identifier (constant or function call)
1047 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
1049 tAST_Node *ret = NULL;
1051 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
1052 name = strndup( Parser->TokenStr, Parser->TokenLen );
1055 if( GetToken(Parser) == TOK_SCOPE )
1057 ret = AST_NewScopeDereference( Parser, name, Parse_GetIdent(Parser, bObjectCreate) );
1064 if( GetToken(Parser) == TOK_PAREN_OPEN )
1067 printf("Parse_GetIdent: Calling '%s'\n", name);
1071 ret = AST_NewCreateObject( Parser, name );
1073 ret = AST_NewFunctionCall( Parser, name );
1075 if( GetToken(Parser) != TOK_PAREN_CLOSE )
1080 printf(" Parse_GetIdent: Argument\n");
1082 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
1083 } while(GetToken(Parser) == TOK_COMMA);
1084 SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
1086 printf(" Parse_GetIdent: All arguments parsed\n");
1092 // Runtime Constant / Variable (When implemented)
1094 printf("Parse_GetIdent: Referencing '%s'\n", name);
1097 if( bObjectCreate ) // Void constructor (TODO: Should this be an error?)
1098 ret = AST_NewCreateObject( Parser, name );
1100 ret = AST_NewConstant( Parser, name );
1108 void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...)
1111 va_start(args, Message);
1112 fprintf(stderr, "%s:%i: error: ", Parser->Filename, Parser->CurLine);
1113 vfprintf(stderr, Message, args);
1114 fprintf(stderr, "\n");
1118 //longjmp(Parser->JmpTarget, -1);
1119 Parser->ErrorHit = 1;
1123 void SyntaxAssert(tParser *Parser, int Have, int Want)
1127 SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n",
1128 csaTOKEN_NAMES[Have], Have, csaTOKEN_NAMES[Want], Want);