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

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