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

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