0b4819800ef21659c88395a59cf3d3a2e36c8eb2
[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);
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();
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();
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                 if(LookAhead(Parser) != TOK_SEMICOLON)
236                         cond = Parse_DoExpr0(Parser);
237                 
238                 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
239                 if(LookAhead(Parser) != TOK_SEMICOLON)
240                         inc = Parse_DoExpr0(Parser);
241                 
242                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
243                 
244                 code = Parse_DoCodeBlock(Parser);
245                 ret = AST_NewLoop(Parser, init, 0, cond, inc, code);
246                 }
247                 return ret;
248         
249         case TOK_RWD_DO:
250         case TOK_RWD_WHILE:
251                 TODO(Parser, "Implement do and while\n");
252                 break;
253         
254         // Define Variables
255         case TOKEN_GROUP_TYPES:
256                 {
257                          int    type;
258                         
259                         switch(GetToken(Parser))
260                         {
261                         case TOK_RWD_INTEGER:   type = SS_DATATYPE_INTEGER;     break;
262                         case TOK_RWD_OBJECT:    type = SS_DATATYPE_OBJECT;      break;
263                         case TOK_RWD_REAL:      type = SS_DATATYPE_REAL;        break;
264                         case TOK_RWD_STRING:    type = SS_DATATYPE_STRING;      break;
265                         }
266                         
267                         SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
268                         
269                         ret = Parse_GetVarDef(Parser, type);
270                 }
271                 break;
272         
273         // Default
274         default:
275                 //printf("exp0\n");
276                 ret = Parse_DoExpr0(Parser);
277                 break;
278         }
279         
280         SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
281         return ret;
282 }
283
284 /**
285  * \brief Get a variable definition
286  */
287 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
288 {
289         char    name[Parser->TokenLen];
290         tAST_Node       *ret;
291         
292         SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
293         
294         // copy the name (trimming the $)
295         memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
296         name[Parser->TokenLen-1] = 0;
297         // Define the variable
298         ret = AST_NewDefineVar(Parser, Type, name);
299         // Handle arrays
300         while( LookAhead(Parser) == TOK_SQUARE_OPEN )
301         {
302                 GetToken(Parser);
303                 AST_AppendNode(ret, Parse_DoExpr0(Parser));
304                 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
305         }
306         return ret;
307 }
308
309 /**
310  * \brief Assignment Operations
311  */
312 tAST_Node *Parse_DoExpr0(tParser *Parser)
313 {
314         tAST_Node       *ret = Parse_DoExpr1(Parser);
315
316         // Check Assignment
317         switch(LookAhead(Parser))
318         {
319         case TOK_ASSIGN:
320                 GetToken(Parser);               // Eat Token
321                 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
322                 break;
323         #if 0
324         case TOK_DIV_EQU:
325                 GetToken(Parser);               // Eat Token
326                 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
327                 break;
328         case TOK_MULT_EQU:
329                 GetToken(Parser);               // Eat Token
330                 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
331                 break;
332         #endif
333         default:
334                 #if DEBUG >= 2
335                 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
336                 #endif
337                 break;
338         }
339         return ret;
340 }
341
342 /**
343  * \brief Logical/Boolean Operators
344  */
345 tAST_Node *Parse_DoExpr1(tParser *Parser)
346 {
347         tAST_Node       *ret = Parse_DoExpr2(Parser);
348         
349         switch(GetToken(Parser))
350         {
351         case TOK_LOGICAND:
352                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
353                 break;
354         case TOK_LOGICOR:
355                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
356                 break;
357         case TOK_LOGICXOR:
358                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
359                 break;
360         default:
361                 PutBack(Parser);
362                 break;
363         }
364         return ret;
365 }
366
367 // --------------------
368 // Expression 2 - Comparison Operators
369 // --------------------
370 tAST_Node *Parse_DoExpr2(tParser *Parser)
371 {
372         tAST_Node       *ret = Parse_DoExpr3(Parser);
373
374         // Check token
375         switch(GetToken(Parser))
376         {
377         case TOK_EQUALS:
378                 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
379                 break;
380         case TOK_LT:
381                 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
382                 break;
383         case TOK_GT:
384                 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
385                 break;
386         default:
387                 PutBack(Parser);
388                 break;
389         }
390         return ret;
391 }
392
393 /**
394  * \brief Bitwise Operations
395  */
396 tAST_Node *Parse_DoExpr3(tParser *Parser)
397 {
398         tAST_Node       *ret = Parse_DoExpr4(Parser);
399
400         // Check Token
401         switch(GetToken(Parser))
402         {
403         case TOK_OR:
404                 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
405                 break;
406         case TOK_AND:
407                 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
408                 break;
409         case TOK_XOR:
410                 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
411                 break;
412         default:
413                 PutBack(Parser);
414                 break;
415         }
416         return ret;
417 }
418
419 // --------------------
420 // Expression 4 - Shifts
421 // --------------------
422 tAST_Node *Parse_DoExpr4(tParser *Parser)
423 {
424         tAST_Node *ret = Parse_DoExpr5(Parser);
425
426         switch(GetToken(Parser))
427         {
428         case TOK_SHL:
429                 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
430                 break;
431         case TOK_SHR:
432                 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
433                 break;
434         default:
435                 PutBack(Parser);
436                 break;
437         }
438
439         return ret;
440 }
441
442 // --------------------
443 // Expression 5 - Arithmatic
444 // --------------------
445 tAST_Node *Parse_DoExpr5(tParser *Parser)
446 {
447         tAST_Node *ret = Parse_DoExpr6(Parser);
448
449         switch(GetToken(Parser))
450         {
451         case TOK_PLUS:
452                 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
453                 break;
454         case TOK_MINUS:
455                 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
456                 break;
457         default:
458                 PutBack(Parser);
459                 break;
460         }
461
462         return ret;
463 }
464
465 // --------------------
466 // Expression 6 - Multiplcation & Division
467 // --------------------
468 tAST_Node *Parse_DoExpr6(tParser *Parser)
469 {
470         tAST_Node *ret = Parse_DoParen(Parser);
471
472         switch(GetToken(Parser))
473         {
474         case TOK_MUL:
475                 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
476                 break;
477         case TOK_DIV:
478                 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
479                 break;
480         default:
481                 PutBack(Parser);
482                 break;
483         }
484
485         return ret;
486 }
487
488
489 // --------------------
490 // 2nd Last Expression - Parens
491 // --------------------
492 tAST_Node *Parse_DoParen(tParser *Parser)
493 {
494         #if DEBUG >= 2
495         printf("Parse_DoParen: (Parser=%p)\n", Parser);
496         #endif
497         if(LookAhead(Parser) == TOK_PAREN_OPEN)
498         {
499                 tAST_Node       *ret;
500                  int    type;
501                 GetToken(Parser);
502                 
503                 // TODO: Handle casts here
504                 switch(LookAhead(Parser))
505                 {
506                 case TOKEN_GROUP_TYPES:
507                         GetToken(Parser);
508                         TOKEN_GET_DATATYPE(type, Parser->Token);
509                         SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
510                         ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
511                         break;
512                 default:                
513                         ret = Parse_DoExpr0(Parser);
514                         SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
515                         break;
516                 }
517                 return ret;
518         }
519         else
520                 return Parse_DoValue(Parser);
521 }
522
523 // --------------------
524 // Last Expression - Value
525 // --------------------
526 tAST_Node *Parse_DoValue(tParser *Parser)
527 {
528          int    tok = LookAhead(Parser);
529
530         #if DEBUG >= 2
531         printf("Parse_DoValue: tok = %i\n", tok);
532         #endif
533
534         switch(tok)
535         {
536         case TOK_STR:   return Parse_GetString(Parser);
537         case TOK_INTEGER:       return Parse_GetNumeric(Parser);
538         case TOK_IDENT: return Parse_GetIdent(Parser);
539         case TOK_VARIABLE:      return Parse_GetVariable(Parser);
540
541         default:
542                 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
543                         csaTOKEN_NAMES[tok], Parser->CurLine);
544                 longjmp( Parser->JmpTarget, -1 );
545         }
546 }
547
548 /**
549  * \brief Get a string
550  */
551 tAST_Node *Parse_GetString(tParser *Parser)
552 {
553         tAST_Node       *ret;
554          int    i, j;
555         GetToken( Parser );
556         
557         {
558                 char    data[ Parser->TokenLen - 2 ];
559                 j = 0;
560                 
561                 for( i = 1; i < Parser->TokenLen - 1; i++ )
562                 {
563                         if( Parser->TokenStr[i] == '\\' ) {
564                                 i ++;
565                                 switch( Parser->TokenStr[i] )
566                                 {
567                                 case 'n':       data[j++] = '\n';       break;
568                                 case 'r':       data[j++] = '\r';       break;
569                                 default:
570                                         // TODO: Octal Codes
571                                         // TODO: Error/Warning?
572                                         break;
573                                 }
574                         }
575                         else {
576                                 data[j++] = Parser->TokenStr[i];
577                         }
578                 }
579                 
580                 // TODO: Parse Escape Codes
581                 ret = AST_NewString( Parser, data, j );
582         }
583         return ret;
584 }
585
586 /**
587  * \brief Get a numeric value
588  */
589 tAST_Node *Parse_GetNumeric(tParser *Parser)
590 {
591         uint64_t        value = 0;
592         char    *pos;
593         GetToken( Parser );
594         pos = Parser->TokenStr;
595         //printf("pos = %p, *pos = %c\n", pos, *pos);
596                 
597         if( *pos == '0' )
598         {
599                 pos ++;
600                 if(*pos == 'x') {
601                         pos ++;
602                         for( ;; pos++)
603                         {
604                                 value *= 16;
605                                 if( '0' <= *pos && *pos <= '9' ) {
606                                         value += *pos - '0';
607                                         continue;
608                                 }
609                                 if( 'A' <= *pos && *pos <= 'F' ) {
610                                         value += *pos - 'A' + 10;
611                                         continue;
612                                 }
613                                 if( 'a' <= *pos && *pos <= 'f' ) {
614                                         value += *pos - 'a' + 10;
615                                         continue;
616                                 }
617                                 break;
618                         }
619                 }
620                 else {
621                         while( '0' <= *pos && *pos <= '7' ) {
622                                 value = value*8 + *pos - '0';
623                                 pos ++;
624                         }
625                 }
626         }
627         else {
628                 while( '0' <= *pos && *pos <= '9' ) {
629                         value = value*10 + *pos - '0';
630                         pos ++;
631                 }
632         }
633         
634         return AST_NewInteger( Parser, value );
635 }
636
637 /**
638  * \brief Get a variable
639  */
640 tAST_Node *Parse_GetVariable(tParser *Parser)
641 {
642         tAST_Node       *ret;
643         SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
644         {
645                 char    name[Parser->TokenLen];
646                 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
647                 name[Parser->TokenLen-1] = 0;
648                 ret = AST_NewVariable( Parser, name );
649                 #if DEBUG >= 2
650                 printf("Parse_GetVariable: name = '%s'\n", name);
651                 #endif
652         }
653         // Handle array references
654         while( LookAhead(Parser) == TOK_SQUARE_OPEN )
655         {
656                 GetToken(Parser);
657                 ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
658                 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
659         }
660         return ret;
661 }
662
663 /**
664  * \brief Get an identifier (constant or function call)
665  */
666 tAST_Node *Parse_GetIdent(tParser *Parser)
667 {
668         tAST_Node       *ret = NULL;
669         char    *name;
670         SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
671         name = strndup( Parser->TokenStr, Parser->TokenLen );
672         
673         #if 0
674         while( GetToken(Parser) == TOK_SCOPE )
675         {
676                 ret = AST_NewScopeDereference( Parser, ret, name );
677                 SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
678                 name = strndup( Parser->TokenStr, Parser->TokenLen );
679         }
680         PutBack(Parser);
681         #endif
682         
683         if( GetToken(Parser) == TOK_PAREN_OPEN )
684         {
685                 #if DEBUG >= 2
686                 printf("Parse_GetIdent: Calling '%s'\n", name);
687                 #endif
688                 // Function Call
689                 ret = AST_NewFunctionCall( Parser, name );
690                 // Read arguments
691                 if( GetToken(Parser) != TOK_PAREN_CLOSE )
692                 {
693                         PutBack(Parser);
694                         do {
695                                 #if DEBUG >= 2
696                                 printf(" Parse_GetIdent: Argument\n");
697                                 #endif
698                                 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
699                         } while(GetToken(Parser) == TOK_COMMA);
700                         SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
701                         #if DEBUG >= 2
702                         printf(" Parse_GetIdent: All arguments parsed\n");
703                         #endif
704                 }
705         }
706         else {
707                 // Runtime Constant / Variable (When implemented)
708                 #if DEBUG >= 2
709                 printf("Parse_GetIdent: Referencing '%s'\n", name);
710                 #endif
711                 PutBack(Parser);
712                 ret = AST_NewConstant( Parser, name );
713         }
714         
715         free(name);
716         return ret;
717 }
718
719 /**
720  * \brief Check for an error
721  */
722 void SyntaxAssert(tParser *Parser, int Have, int Want)
723 {
724         if(Have != Want) {
725                 fprintf(stderr, "ERROR: SyntaxAssert Failed, Expected %s(%i), got %s(%i) on line %i\n",
726                         csaTOKEN_NAMES[Want], Want, csaTOKEN_NAMES[Have], Have, Parser->CurLine);
727                 longjmp(Parser->JmpTarget, -1);
728         }
729 }
730

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