907c7291ac38d1dad04d2725b51478678b423f07
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / parse.c
1 /*
2  * Acess2 - SpiderScript
3  * - Parser
4  */
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <spiderscript.h>
9 #define WANT_TOKEN_STRINGS      1
10 #include "tokens.h"
11 #include "ast.h"
12
13 #define DEBUG   0
14
15 // === PROTOTYPES ===
16 tAST_Script     *Parse_Buffer(tSpiderVariant *Variant, char *Buffer);
17 tAST_Node       *Parse_DoCodeBlock(tParser *Parser);
18 tAST_Node       *Parse_DoBlockLine(tParser *Parser);
19 tAST_Node       *Parse_GetVarDef(tParser *Parser, int Type);
20
21 tAST_Node       *Parse_DoExpr0(tParser *Parser);        // Assignment
22 tAST_Node       *Parse_DoExpr1(tParser *Parser);        // Boolean Operators
23 tAST_Node       *Parse_DoExpr2(tParser *Parser);        // Comparison Operators
24 tAST_Node       *Parse_DoExpr3(tParser *Parser);        // Bitwise Operators
25 tAST_Node       *Parse_DoExpr4(tParser *Parser);        // Bit Shifts
26 tAST_Node       *Parse_DoExpr5(tParser *Parser);        // Arithmatic
27 tAST_Node       *Parse_DoExpr6(tParser *Parser);        // Mult & Div
28
29 tAST_Node       *Parse_DoParen(tParser *Parser);        // Parenthesis (Always Last)
30 tAST_Node       *Parse_DoValue(tParser *Parser);        // Values
31
32 tAST_Node       *Parse_GetString(tParser *Parser);
33 tAST_Node       *Parse_GetNumeric(tParser *Parser);
34 tAST_Node       *Parse_GetVariable(tParser *Parser);
35 tAST_Node       *Parse_GetIdent(tParser *Parser, int bObjectCreate);
36
37 void    SyntaxAssert(tParser *Parser, int Have, int Want);
38
39 #define TODO(Parser, message...) do {\
40         fprintf(stderr, "TODO: "message);\
41         longjmp(Parser->JmpTarget, -1);\
42 }while(0)
43
44 // === CODE ===
45 /**
46  * \brief Parse a buffer into a syntax tree
47  */
48 tAST_Script     *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
49 {
50         tParser parser = {0};
51         tParser *Parser = &parser;      //< Keeps code consistent
52         tAST_Script     *ret;
53         tAST_Node       *mainCode;
54         char    *name;
55         tAST_Function   *fcn;
56          int    type;
57         
58         #if DEBUG >= 2
59         printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer);
60         #endif
61         
62         // Initialise parser
63         parser.LastToken = -1;
64         parser.NextToken = -1;
65         parser.CurLine = 1;
66         parser.BufStart = Buffer;
67         parser.CurPos = Buffer;
68         
69         ret = AST_NewScript();
70         mainCode = AST_NewCodeBlock(&parser);
71         
72         // Give us an error fallback
73         if( setjmp( parser.JmpTarget ) != 0 )
74         {
75                 AST_FreeNode( mainCode );
76                 return NULL;
77         }
78         
79         // Parse the file!
80         while(Parser->Token != TOK_EOF)
81         {
82                 switch( GetToken(Parser) )
83                 {
84                 case TOK_EOF:
85                         break;
86                 
87                 // Typed variables/functions
88                 case TOKEN_GROUP_TYPES:
89                         {
90                          int    tok, type;
91                         TOKEN_GET_DATATYPE(type, Parser->Token);
92                         
93                         tok = GetToken(Parser);
94                         // Define a function (pass on to the other function definition code)
95                         if( tok == TOK_IDENT ) {
96                                 goto defFcn;
97                         }
98                         // Define a variable
99                         else if( tok == TOK_VARIABLE ) {
100                                 AST_AppendNode( mainCode, Parse_GetVarDef(Parser, type) );
101                                 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
102                         }
103                         else {
104                                 fprintf(stderr, "ERROR: Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
105                                         csaTOKEN_NAMES[tok]);
106                         }
107                         }
108                         break;
109                 
110                 // Define a function
111                 case TOK_RWD_FUNCTION:
112                         if( !Variant->bDyamicTyped ) {
113                                 fprintf(stderr, "ERROR: Dynamic functions are invalid in static mode\n");
114                                 longjmp(Parser->JmpTarget, -1);
115                         }
116                         type = SS_DATATYPE_DYNAMIC;
117                         SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
118                 defFcn:
119                         name = strndup( Parser->TokenStr, Parser->TokenLen );
120                         fcn = AST_AppendFunction( ret, name );
121                         #if DEBUG
122                         printf("DefFCN %s\n", name);
123                         #endif
124                         free(name);
125                         
126                         // Get arguments
127                         SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
128                         if( LookAhead(Parser) != TOK_PAREN_CLOSE )
129                         {
130                                 do {
131                                         type = SS_DATATYPE_DYNAMIC;
132                                         GetToken(Parser);
133                                         // Non dynamic typed variants must use data types
134                                         if( !Variant->bDyamicTyped ) {
135                                                 TOKEN_GET_DATATYPE(type, Parser->Token);
136                                                 GetToken(Parser);
137                                         }
138                                         AST_AppendFunctionArg(fcn, Parse_GetVarDef(Parser, type)); 
139                                 }       while(GetToken(Parser) == TOK_COMMA);
140                         }
141                         else
142                                 GetToken(Parser);
143                         SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
144                         
145                         AST_SetFunctionCode( fcn, Parse_DoCodeBlock(Parser) );
146                         break;
147                 
148                 default:
149                         PutBack(Parser);
150                         AST_AppendNode( mainCode, Parse_DoBlockLine(Parser) );
151                         break;
152                 }
153         }
154         
155         fcn = AST_AppendFunction( ret, "" );
156         AST_SetFunctionCode( fcn, mainCode );
157         
158         //printf("---- %p parsed as SpiderScript ----\n", Buffer);
159         
160         return ret;
161 }
162
163 /**
164  * \brief Parse a block of code surrounded by { }
165  */
166 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
167 {
168         tAST_Node       *ret;
169         
170         // Check if we are being called for a one-liner
171         if( GetToken(Parser) != TOK_BRACE_OPEN ) {
172                 PutBack(Parser);
173                 return Parse_DoBlockLine(Parser);
174         }
175         
176         ret = AST_NewCodeBlock(Parser);
177         
178         while( LookAhead(Parser) != TOK_BRACE_CLOSE )
179         {
180                 AST_AppendNode( ret, Parse_DoBlockLine(Parser) );
181         }
182         GetToken(Parser);       // Omnomnom
183         return ret;
184 }
185
186 /**
187  * \brief Parse a line in a block
188  */
189 tAST_Node *Parse_DoBlockLine(tParser *Parser)
190 {
191         tAST_Node       *ret;
192         
193         //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
194         
195         switch(LookAhead(Parser))
196         {
197         // Empty statement
198         case TOK_SEMICOLON:
199                 GetToken(Parser);
200                 return NULL;
201         
202         // Return from a method
203         case TOK_RWD_RETURN:
204                 GetToken(Parser);
205                 ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
206                 break;
207         
208         // Control Statements
209         case TOK_RWD_IF:
210                 {
211                 tAST_Node       *cond, *true, *false = NULL;
212                 GetToken(Parser);       // eat the if
213                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
214                 cond = Parse_DoExpr0(Parser);   // Get condition
215                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
216                 true = Parse_DoCodeBlock(Parser);
217                 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
218                         GetToken(Parser);
219                         false = Parse_DoCodeBlock(Parser);
220                 }
221                 ret = AST_NewIf(Parser, cond, true, false);
222                 }
223                 return ret;
224         
225         case TOK_RWD_FOR:
226                 {
227                 tAST_Node       *init=NULL, *cond=NULL, *inc=NULL, *code;
228                 GetToken(Parser);       // Eat 'for'
229                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
230                 
231                 if(LookAhead(Parser) != TOK_SEMICOLON)
232                         init = Parse_DoExpr0(Parser);
233                 
234                 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
235                 
236                 if(LookAhead(Parser) != TOK_SEMICOLON)
237                         cond = Parse_DoExpr0(Parser);
238                 
239                 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
240                 
241                 if(LookAhead(Parser) != TOK_PAREN_CLOSE)
242                         inc = Parse_DoExpr0(Parser);
243                 
244                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
245                 
246                 code = Parse_DoCodeBlock(Parser);
247                 ret = AST_NewLoop(Parser, init, 0, cond, inc, code);
248                 }
249                 return ret;
250         
251         case TOK_RWD_DO:
252         case TOK_RWD_WHILE:
253                 TODO(Parser, "Implement do and while\n");
254                 break;
255         
256         // Define Variables
257         case TOKEN_GROUP_TYPES:
258                 {
259                          int    type;
260                         
261                         switch(GetToken(Parser))
262                         {
263                         case TOK_RWD_INTEGER:   type = SS_DATATYPE_INTEGER;     break;
264                         case TOK_RWD_OBJECT:    type = SS_DATATYPE_OBJECT;      break;
265                         case TOK_RWD_REAL:      type = SS_DATATYPE_REAL;        break;
266                         case TOK_RWD_STRING:    type = SS_DATATYPE_STRING;      break;
267                         }
268                         
269                         SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
270                         
271                         ret = Parse_GetVarDef(Parser, type);
272                 }
273                 break;
274         
275         // Default
276         default:
277                 //printf("exp0\n");
278                 ret = Parse_DoExpr0(Parser);
279                 break;
280         }
281         
282         SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
283         return ret;
284 }
285
286 /**
287  * \brief Get a variable definition
288  */
289 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
290 {
291         char    name[Parser->TokenLen];
292         tAST_Node       *ret;
293         
294         SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
295         
296         // copy the name (trimming the $)
297         memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
298         name[Parser->TokenLen-1] = 0;
299         // Define the variable
300         ret = AST_NewDefineVar(Parser, Type, name);
301         // Handle arrays
302         while( LookAhead(Parser) == TOK_SQUARE_OPEN )
303         {
304                 GetToken(Parser);
305                 AST_AppendNode(ret, Parse_DoExpr0(Parser));
306                 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
307         }
308         return ret;
309 }
310
311 /**
312  * \brief Assignment Operations
313  */
314 tAST_Node *Parse_DoExpr0(tParser *Parser)
315 {
316         tAST_Node       *ret = Parse_DoExpr1(Parser);
317
318         // Check Assignment
319         switch(LookAhead(Parser))
320         {
321         case TOK_ASSIGN:
322                 GetToken(Parser);               // Eat Token
323                 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
324                 break;
325         case TOK_ASSIGN_DIV:
326                 GetToken(Parser);               // Eat Token
327                 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
328                 break;
329         case TOK_ASSIGN_MUL:
330                 GetToken(Parser);               // Eat Token
331                 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
332                 break;
333         case TOK_ASSIGN_PLUS:
334                 GetToken(Parser);               // Eat Token
335                 ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, Parse_DoExpr0(Parser));
336                 break;
337         case TOK_ASSIGN_MINUS:
338                 GetToken(Parser);               // Eat Token
339                 ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr0(Parser));
340                 break;
341         default:
342                 #if DEBUG >= 2
343                 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
344                 #endif
345                 break;
346         }
347         return ret;
348 }
349
350 /**
351  * \brief Logical/Boolean Operators
352  */
353 tAST_Node *Parse_DoExpr1(tParser *Parser)
354 {
355         tAST_Node       *ret = Parse_DoExpr2(Parser);
356         
357         switch(GetToken(Parser))
358         {
359         case TOK_LOGICAND:
360                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
361                 break;
362         case TOK_LOGICOR:
363                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
364                 break;
365         case TOK_LOGICXOR:
366                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
367                 break;
368         default:
369                 PutBack(Parser);
370                 break;
371         }
372         return ret;
373 }
374
375 // --------------------
376 // Expression 2 - Comparison Operators
377 // --------------------
378 tAST_Node *Parse_DoExpr2(tParser *Parser)
379 {
380         tAST_Node       *ret = Parse_DoExpr3(Parser);
381
382         // Check token
383         switch(GetToken(Parser))
384         {
385         case TOK_EQUALS:
386                 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
387                 break;
388         case TOK_LT:
389                 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
390                 break;
391         case TOK_GT:
392                 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
393                 break;
394         default:
395                 PutBack(Parser);
396                 break;
397         }
398         return ret;
399 }
400
401 /**
402  * \brief Bitwise Operations
403  */
404 tAST_Node *Parse_DoExpr3(tParser *Parser)
405 {
406         tAST_Node       *ret = Parse_DoExpr4(Parser);
407
408         // Check Token
409         switch(GetToken(Parser))
410         {
411         case TOK_OR:
412                 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
413                 break;
414         case TOK_AND:
415                 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
416                 break;
417         case TOK_XOR:
418                 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
419                 break;
420         default:
421                 PutBack(Parser);
422                 break;
423         }
424         return ret;
425 }
426
427 // --------------------
428 // Expression 4 - Shifts
429 // --------------------
430 tAST_Node *Parse_DoExpr4(tParser *Parser)
431 {
432         tAST_Node *ret = Parse_DoExpr5(Parser);
433
434         switch(GetToken(Parser))
435         {
436         case TOK_SHL:
437                 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
438                 break;
439         case TOK_SHR:
440                 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
441                 break;
442         default:
443                 PutBack(Parser);
444                 break;
445         }
446
447         return ret;
448 }
449
450 // --------------------
451 // Expression 5 - Arithmatic
452 // --------------------
453 tAST_Node *Parse_DoExpr5(tParser *Parser)
454 {
455         tAST_Node *ret = Parse_DoExpr6(Parser);
456
457         switch(GetToken(Parser))
458         {
459         case TOK_PLUS:
460                 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
461                 break;
462         case TOK_MINUS:
463                 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
464                 break;
465         default:
466                 PutBack(Parser);
467                 break;
468         }
469
470         return ret;
471 }
472
473 // --------------------
474 // Expression 6 - Multiplcation & Division
475 // --------------------
476 tAST_Node *Parse_DoExpr6(tParser *Parser)
477 {
478         tAST_Node *ret = Parse_DoParen(Parser);
479
480         switch(GetToken(Parser))
481         {
482         case TOK_MUL:
483                 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
484                 break;
485         case TOK_DIV:
486                 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
487                 break;
488         default:
489                 PutBack(Parser);
490                 break;
491         }
492
493         return ret;
494 }
495
496
497 // --------------------
498 // 2nd Last Expression - Parens
499 // --------------------
500 tAST_Node *Parse_DoParen(tParser *Parser)
501 {
502         #if DEBUG >= 2
503         printf("Parse_DoParen: (Parser=%p)\n", Parser);
504         #endif
505         if(LookAhead(Parser) == TOK_PAREN_OPEN)
506         {
507                 tAST_Node       *ret;
508                  int    type;
509                 GetToken(Parser);
510                 
511                 // TODO: Handle casts here
512                 switch(LookAhead(Parser))
513                 {
514                 case TOKEN_GROUP_TYPES:
515                         GetToken(Parser);
516                         TOKEN_GET_DATATYPE(type, Parser->Token);
517                         SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
518                         ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
519                         break;
520                 default:                
521                         ret = Parse_DoExpr0(Parser);
522                         SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
523                         break;
524                 }
525                 return ret;
526         }
527         else
528                 return Parse_DoValue(Parser);
529 }
530
531 // --------------------
532 // Last Expression - Value
533 // --------------------
534 tAST_Node *Parse_DoValue(tParser *Parser)
535 {
536          int    tok = LookAhead(Parser);
537
538         #if DEBUG >= 2
539         printf("Parse_DoValue: tok = %i\n", tok);
540         #endif
541
542         switch(tok)
543         {
544         case TOK_STR:   return Parse_GetString(Parser);
545         case TOK_INTEGER:       return Parse_GetNumeric(Parser);
546         case TOK_IDENT: return Parse_GetIdent(Parser, 0);
547         case TOK_VARIABLE:      return Parse_GetVariable(Parser);
548         case TOK_RWD_NEW:
549                 GetToken(Parser);       // Omnomnom
550                 return Parse_GetIdent(Parser, 1);
551
552         default:
553                 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
554                         csaTOKEN_NAMES[tok], Parser->CurLine);
555                 longjmp( Parser->JmpTarget, -1 );
556         }
557 }
558
559 /**
560  * \brief Get a string
561  */
562 tAST_Node *Parse_GetString(tParser *Parser)
563 {
564         tAST_Node       *ret;
565          int    i, j;
566         GetToken( Parser );
567         
568         {
569                 char    data[ Parser->TokenLen - 2 ];
570                 j = 0;
571                 
572                 for( i = 1; i < Parser->TokenLen - 1; i++ )
573                 {
574                         if( Parser->TokenStr[i] == '\\' ) {
575                                 i ++;
576                                 switch( Parser->TokenStr[i] )
577                                 {
578                                 case 'n':       data[j++] = '\n';       break;
579                                 case 'r':       data[j++] = '\r';       break;
580                                 default:
581                                         // TODO: Octal Codes
582                                         // TODO: Error/Warning?
583                                         break;
584                                 }
585                         }
586                         else {
587                                 data[j++] = Parser->TokenStr[i];
588                         }
589                 }
590                 
591                 // TODO: Parse Escape Codes
592                 ret = AST_NewString( Parser, data, j );
593         }
594         return ret;
595 }
596
597 /**
598  * \brief Get a numeric value
599  */
600 tAST_Node *Parse_GetNumeric(tParser *Parser)
601 {
602         uint64_t        value = 0;
603         char    *pos;
604         GetToken( Parser );
605         pos = Parser->TokenStr;
606         //printf("pos = %p, *pos = %c\n", pos, *pos);
607                 
608         if( *pos == '0' )
609         {
610                 pos ++;
611                 if(*pos == 'x') {
612                         pos ++;
613                         for( ;; pos++)
614                         {
615                                 value *= 16;
616                                 if( '0' <= *pos && *pos <= '9' ) {
617                                         value += *pos - '0';
618                                         continue;
619                                 }
620                                 if( 'A' <= *pos && *pos <= 'F' ) {
621                                         value += *pos - 'A' + 10;
622                                         continue;
623                                 }
624                                 if( 'a' <= *pos && *pos <= 'f' ) {
625                                         value += *pos - 'a' + 10;
626                                         continue;
627                                 }
628                                 break;
629                         }
630                 }
631                 else {
632                         while( '0' <= *pos && *pos <= '7' ) {
633                                 value = value*8 + *pos - '0';
634                                 pos ++;
635                         }
636                 }
637         }
638         else {
639                 while( '0' <= *pos && *pos <= '9' ) {
640                         value = value*10 + *pos - '0';
641                         pos ++;
642                 }
643         }
644         
645         return AST_NewInteger( Parser, value );
646 }
647
648 /**
649  * \brief Get a variable
650  */
651 tAST_Node *Parse_GetVariable(tParser *Parser)
652 {
653         tAST_Node       *ret;
654         SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
655         {
656                 char    name[Parser->TokenLen];
657                 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
658                 name[Parser->TokenLen-1] = 0;
659                 ret = AST_NewVariable( Parser, name );
660                 #if DEBUG >= 2
661                 printf("Parse_GetVariable: name = '%s'\n", name);
662                 #endif
663         }
664         for(;;)
665         {
666                 GetToken(Parser);
667                 if( Parser->Token == TOK_SQUARE_OPEN )
668                 {
669                         ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
670                         SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
671                         continue ;
672                 }
673                 if( Parser->Token == TOK_ELEMENT )
674                 {
675                         SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
676                         // Method Call
677                         if( LookAhead(Parser) == TOK_PAREN_OPEN )
678                         {
679                                 char    name[Parser->TokenLen+1];
680                                 memcpy(name, Parser->TokenStr, Parser->TokenLen);
681                                 name[Parser->TokenLen] = 0;
682                                 ret = AST_NewMethodCall(Parser, ret, name);
683                                 GetToken(Parser);       // Eat the '('
684                                 // Read arguments
685                                 if( GetToken(Parser) != TOK_PAREN_CLOSE )
686                                 {
687                                         PutBack(Parser);
688                                         do {
689                                                 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
690                                         } while(GetToken(Parser) == TOK_COMMA);
691                                         SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
692                                 }
693                                 
694                         }
695                         // Attribute
696                         else
697                         {
698                                 char    name[Parser->TokenLen];
699                                 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
700                                 name[Parser->TokenLen-1] = 0;
701                                 ret = AST_NewClassElement(Parser, ret, name);
702                         }
703                         continue ;
704                 }
705                 
706                 break ;
707         }
708         PutBack(Parser);
709         return ret;
710 }
711
712 /**
713  * \brief Get an identifier (constant or function call)
714  */
715 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
716 {
717         tAST_Node       *ret = NULL;
718         char    *name;
719         SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
720         name = strndup( Parser->TokenStr, Parser->TokenLen );
721         
722         #if USE_SCOPE_CHAR
723         if( GetToken(Parser) == TOK_SCOPE )
724         {
725                 ret = AST_NewScopeDereference( Parser, Parse_GetIdent(Parser, bObjectCreate), name );
726                 free(name);
727                 return ret;
728         }
729         PutBack(Parser);
730         #endif
731         
732         if( GetToken(Parser) == TOK_PAREN_OPEN )
733         {
734                 #if DEBUG >= 2
735                 printf("Parse_GetIdent: Calling '%s'\n", name);
736                 #endif
737                 // Function Call
738                 if( bObjectCreate )
739                         ret = AST_NewCreateObject( Parser, name );
740                 else
741                         ret = AST_NewFunctionCall( Parser, name );
742                 // Read arguments
743                 if( GetToken(Parser) != TOK_PAREN_CLOSE )
744                 {
745                         PutBack(Parser);
746                         do {
747                                 #if DEBUG >= 2
748                                 printf(" Parse_GetIdent: Argument\n");
749                                 #endif
750                                 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
751                         } while(GetToken(Parser) == TOK_COMMA);
752                         SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
753                         #if DEBUG >= 2
754                         printf(" Parse_GetIdent: All arguments parsed\n");
755                         #endif
756                 }
757         }
758         else
759         {
760                 // Runtime Constant / Variable (When implemented)
761                 #if DEBUG >= 2
762                 printf("Parse_GetIdent: Referencing '%s'\n", name);
763                 #endif
764                 PutBack(Parser);
765                 if( bObjectCreate )     // Void constructor (TODO: Should this be an error?)
766                         ret = AST_NewCreateObject( Parser, name );
767                 else
768                         ret = AST_NewConstant( Parser, name );
769         }
770         
771         free(name);
772         return ret;
773 }
774
775 /**
776  * \brief Check for an error
777  */
778 void SyntaxAssert(tParser *Parser, int Have, int Want)
779 {
780         if(Have != Want) {
781                 fprintf(stderr, "ERROR: SyntaxAssert Failed, Expected %s(%i), got %s(%i) on line %i\n",
782                         csaTOKEN_NAMES[Want], Want, csaTOKEN_NAMES[Have], Have, Parser->CurLine);
783                 longjmp(Parser->JmpTarget, -1);
784         }
785 }
786

UCC git Repository :: git.ucc.asn.au