SpiderScript - Bugs, Documentation and a few language features
[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         // New block
200         case TOK_BRACE_OPEN:
201                 return Parse_DoCodeBlock(Parser);
202         
203         // Empty statement
204         case TOK_SEMICOLON:
205                 GetToken(Parser);
206                 return NULL;
207         
208         // Return from a method
209         case TOK_RWD_RETURN:
210                 GetToken(Parser);
211                 ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser));
212                 break;
213         
214         // Control Statements
215         case TOK_RWD_IF:
216                 {
217                 tAST_Node       *cond, *true, *false = NULL;
218                 GetToken(Parser);       // eat the if
219                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
220                 cond = Parse_DoExpr0(Parser);   // Get condition
221                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
222                 true = Parse_DoCodeBlock(Parser);
223                 if( LookAhead(Parser) == TOK_RWD_ELSE ) {
224                         GetToken(Parser);
225                         false = Parse_DoCodeBlock(Parser);
226                 }
227                 else
228                         false = AST_NewNop(Parser);
229                 ret = AST_NewIf(Parser, cond, true, false);
230                 }
231                 return ret;
232         
233         case TOK_RWD_FOR:
234                 {
235                 tAST_Node       *init=NULL, *cond=NULL, *inc=NULL, *code;
236                 GetToken(Parser);       // Eat 'for'
237                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN);
238                 
239                 if(LookAhead(Parser) != TOK_SEMICOLON)
240                         init = Parse_DoExpr0(Parser);
241                 
242                 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
243                 
244                 if(LookAhead(Parser) != TOK_SEMICOLON)
245                         cond = Parse_DoExpr0(Parser);
246                 
247                 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
248                 
249                 if(LookAhead(Parser) != TOK_PAREN_CLOSE)
250                         inc = Parse_DoExpr0(Parser);
251                 
252                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
253                 
254                 code = Parse_DoCodeBlock(Parser);
255                 ret = AST_NewLoop(Parser, init, 0, cond, inc, code);
256                 }
257                 return ret;
258         
259         case TOK_RWD_DO:
260                 {
261                 tAST_Node       *code, *cond;
262                 GetToken(Parser);       // Eat 'do'
263                 code = Parse_DoCodeBlock(Parser);
264                 SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE );
265                 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
266                 cond = Parse_DoExpr0(Parser);
267                 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
268                 ret = AST_NewLoop(Parser, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code);
269                 }
270                 break;
271         case TOK_RWD_WHILE:
272                 {
273                 tAST_Node       *code, *cond;
274                 GetToken(Parser);       // Eat 'while'
275                 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN );
276                 cond = Parse_DoExpr0(Parser);
277                 SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE );
278                 code = Parse_DoCodeBlock(Parser);
279                 ret = AST_NewLoop(Parser, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code);
280                 }
281                 return ret;
282         
283         // Define Variables
284         case TOKEN_GROUP_TYPES:
285                 {
286                          int    type;
287                         GetToken(Parser);
288                         TOKEN_GET_DATATYPE(type, Parser->Token);
289                         
290                         SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
291                         
292                         ret = Parse_GetVarDef(Parser, type);
293                 }
294                 break;
295         
296         // Default
297         default:
298                 //printf("exp0\n");
299                 ret = Parse_DoExpr0(Parser);
300                 break;
301         }
302         
303         SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
304         return ret;
305 }
306
307 /**
308  * \brief Get a variable definition
309  */
310 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
311 {
312         char    name[Parser->TokenLen];
313         tAST_Node       *ret;
314         
315         SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
316         
317         // copy the name (trimming the $)
318         memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
319         name[Parser->TokenLen-1] = 0;
320         // Define the variable
321         ret = AST_NewDefineVar(Parser, Type, name);
322         // Handle arrays
323         while( LookAhead(Parser) == TOK_SQUARE_OPEN )
324         {
325                 GetToken(Parser);
326                 AST_AppendNode(ret, Parse_DoExpr0(Parser));
327                 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
328         }
329         
330         if( LookAhead(Parser) == TOK_ASSIGN )
331         {
332                 GetToken(Parser);
333                 ret->DefVar.InitialValue = Parse_DoExpr0(Parser);
334         }
335         
336         return ret;
337 }
338
339 /**
340  * \brief Assignment Operations
341  */
342 tAST_Node *Parse_DoExpr0(tParser *Parser)
343 {
344         tAST_Node       *ret = Parse_DoExpr1(Parser);
345
346         // Check Assignment
347         switch(LookAhead(Parser))
348         {
349         case TOK_ASSIGN:
350                 GetToken(Parser);               // Eat Token
351                 ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
352                 break;
353         case TOK_ASSIGN_DIV:
354                 GetToken(Parser);               // Eat Token
355                 ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
356                 break;
357         case TOK_ASSIGN_MUL:
358                 GetToken(Parser);               // Eat Token
359                 ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
360                 break;
361         case TOK_ASSIGN_PLUS:
362                 GetToken(Parser);               // Eat Token
363                 ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, Parse_DoExpr0(Parser));
364                 break;
365         case TOK_ASSIGN_MINUS:
366                 GetToken(Parser);               // Eat Token
367                 ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr0(Parser));
368                 break;
369         default:
370                 #if DEBUG >= 2
371                 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
372                 #endif
373                 break;
374         }
375         return ret;
376 }
377
378 /**
379  * \brief Logical/Boolean Operators
380  */
381 tAST_Node *Parse_DoExpr1(tParser *Parser)
382 {
383         tAST_Node       *ret = Parse_DoExpr2(Parser);
384         
385         switch(GetToken(Parser))
386         {
387         case TOK_LOGICAND:
388                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
389                 break;
390         case TOK_LOGICOR:
391                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
392                 break;
393         case TOK_LOGICXOR:
394                 ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
395                 break;
396         default:
397                 PutBack(Parser);
398                 break;
399         }
400         return ret;
401 }
402
403 // --------------------
404 // Expression 2 - Comparison Operators
405 // --------------------
406 tAST_Node *Parse_DoExpr2(tParser *Parser)
407 {
408         tAST_Node       *ret = Parse_DoExpr3(Parser);
409
410         // Check token
411         switch(GetToken(Parser))
412         {
413         case TOK_EQUALS:
414                 ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
415                 break;
416         case TOK_LT:
417                 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
418                 break;
419         case TOK_GT:
420                 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
421                 break;
422         case TOK_LTE:
423                 ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, Parse_DoExpr2(Parser));
424                 break;
425         case TOK_GTE:
426                 ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, Parse_DoExpr2(Parser));
427                 break;
428         default:
429                 PutBack(Parser);
430                 break;
431         }
432         return ret;
433 }
434
435 /**
436  * \brief Bitwise Operations
437  */
438 tAST_Node *Parse_DoExpr3(tParser *Parser)
439 {
440         tAST_Node       *ret = Parse_DoExpr4(Parser);
441
442         // Check Token
443         switch(GetToken(Parser))
444         {
445         case TOK_OR:
446                 ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
447                 break;
448         case TOK_AND:
449                 ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
450                 break;
451         case TOK_XOR:
452                 ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
453                 break;
454         default:
455                 PutBack(Parser);
456                 break;
457         }
458         return ret;
459 }
460
461 // --------------------
462 // Expression 4 - Shifts
463 // --------------------
464 tAST_Node *Parse_DoExpr4(tParser *Parser)
465 {
466         tAST_Node *ret = Parse_DoExpr5(Parser);
467
468         switch(GetToken(Parser))
469         {
470         case TOK_SHL:
471                 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
472                 break;
473         case TOK_SHR:
474                 ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
475                 break;
476         default:
477                 PutBack(Parser);
478                 break;
479         }
480
481         return ret;
482 }
483
484 // --------------------
485 // Expression 5 - Arithmatic
486 // --------------------
487 tAST_Node *Parse_DoExpr5(tParser *Parser)
488 {
489         tAST_Node *ret = Parse_DoExpr6(Parser);
490
491         switch(GetToken(Parser))
492         {
493         case TOK_PLUS:
494                 ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
495                 break;
496         case TOK_MINUS:
497                 ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
498                 break;
499         default:
500                 PutBack(Parser);
501                 break;
502         }
503
504         return ret;
505 }
506
507 // --------------------
508 // Expression 6 - Multiplcation & Division
509 // --------------------
510 tAST_Node *Parse_DoExpr6(tParser *Parser)
511 {
512         tAST_Node *ret = Parse_DoExpr7(Parser);
513
514         switch(GetToken(Parser))
515         {
516         case TOK_MUL:
517                 ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
518                 break;
519         case TOK_DIV:
520                 ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
521                 break;
522         default:
523                 PutBack(Parser);
524                 break;
525         }
526
527         return ret;
528 }
529
530 // Right Unary Operations
531 tAST_Node *Parse_DoExpr7(tParser *Parser)
532 {
533         tAST_Node *ret = Parse_DoExpr8(Parser);
534         
535         switch(GetToken(Parser))
536         {
537         case TOK_INCREMENT:
538                 ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret);
539                 break;
540         case TOK_DECREMENT:
541                 ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret);
542                 break;
543         default:
544                 PutBack(Parser);
545                 break;
546         }
547         return ret;
548 }
549
550 // Left Unary Operations
551 tAST_Node *Parse_DoExpr8(tParser *Parser)
552 {
553         switch(GetToken(Parser))
554         {
555         case TOK_INCREMENT:
556                 return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
557         case TOK_DECREMENT:
558                 return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1));
559         case TOK_MINUS:
560                 return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser));
561         case TOK_LOGICNOT:
562                 return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser));
563         case TOK_BWNOT:
564                 return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser));
565         default:
566                 PutBack(Parser);
567                 return Parse_DoParen(Parser);
568         }
569 }
570
571 // --------------------
572 // 2nd Last Expression - Parens
573 // --------------------
574 tAST_Node *Parse_DoParen(tParser *Parser)
575 {
576         #if DEBUG >= 2
577         printf("Parse_DoParen: (Parser=%p)\n", Parser);
578         #endif
579         if(LookAhead(Parser) == TOK_PAREN_OPEN)
580         {
581                 tAST_Node       *ret;
582                  int    type;
583                 GetToken(Parser);
584                 
585                 // TODO: Handle casts here
586                 switch(LookAhead(Parser))
587                 {
588                 case TOKEN_GROUP_TYPES:
589                         GetToken(Parser);
590                         TOKEN_GET_DATATYPE(type, Parser->Token);
591                         SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
592                         ret = AST_NewCast(Parser, type, Parse_DoParen(Parser));
593                         break;
594                 default:                
595                         ret = Parse_DoExpr0(Parser);
596                         SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
597                         break;
598                 }
599                 return ret;
600         }
601         else
602                 return Parse_DoValue(Parser);
603 }
604
605 // --------------------
606 // Last Expression - Value
607 // --------------------
608 tAST_Node *Parse_DoValue(tParser *Parser)
609 {
610          int    tok = LookAhead(Parser);
611
612         #if DEBUG >= 2
613         printf("Parse_DoValue: tok = %i\n", tok);
614         #endif
615
616         switch(tok)
617         {
618         case TOK_STR:
619                 return Parse_GetString(Parser);
620         case TOK_INTEGER:
621                 return Parse_GetNumeric(Parser);
622         
623         case TOK_REAL:
624                 GetToken(Parser);
625                 return AST_NewReal( Parser, atof(Parser->TokenStr) );
626         
627         case TOK_IDENT: return Parse_GetIdent(Parser, 0);
628         case TOK_VARIABLE:      return Parse_GetVariable(Parser);
629         case TOK_RWD_NEW:
630                 GetToken(Parser);       // Omnomnom
631                 return Parse_GetIdent(Parser, 1);
632
633         default:
634                 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
635                         csaTOKEN_NAMES[tok], Parser->CurLine);
636                 longjmp( Parser->JmpTarget, -1 );
637         }
638 }
639
640 /**
641  * \brief Get a string
642  */
643 tAST_Node *Parse_GetString(tParser *Parser)
644 {
645         tAST_Node       *ret;
646          int    i, j;
647         GetToken( Parser );
648         
649         {
650                 char    data[ Parser->TokenLen - 2 ];
651                 j = 0;
652                 
653                 for( i = 1; i < Parser->TokenLen - 1; i++ )
654                 {
655                         if( Parser->TokenStr[i] == '\\' ) {
656                                 i ++;
657                                 switch( Parser->TokenStr[i] )
658                                 {
659                                 case 'n':       data[j++] = '\n';       break;
660                                 case 'r':       data[j++] = '\r';       break;
661                                 default:
662                                         // TODO: Octal Codes
663                                         // TODO: Error/Warning?
664                                         break;
665                                 }
666                         }
667                         else {
668                                 data[j++] = Parser->TokenStr[i];
669                         }
670                 }
671                 
672                 // TODO: Parse Escape Codes
673                 ret = AST_NewString( Parser, data, j );
674         }
675         return ret;
676 }
677
678 /**
679  * \brief Get a numeric value
680  */
681 tAST_Node *Parse_GetNumeric(tParser *Parser)
682 {
683         uint64_t        value = 0;
684         char    *pos;
685         SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER );
686         pos = Parser->TokenStr;
687         //printf("pos = %p, *pos = %c\n", pos, *pos);
688                 
689         if( *pos == '0' )
690         {
691                 pos ++;
692                 if(*pos == 'x') {
693                         pos ++;
694                         for( ;; pos++)
695                         {
696                                 value *= 16;
697                                 if( '0' <= *pos && *pos <= '9' ) {
698                                         value += *pos - '0';
699                                         continue;
700                                 }
701                                 if( 'A' <= *pos && *pos <= 'F' ) {
702                                         value += *pos - 'A' + 10;
703                                         continue;
704                                 }
705                                 if( 'a' <= *pos && *pos <= 'f' ) {
706                                         value += *pos - 'a' + 10;
707                                         continue;
708                                 }
709                                 break;
710                         }
711                 }
712                 else {
713                         while( '0' <= *pos && *pos <= '7' ) {
714                                 value = value*8 + *pos - '0';
715                                 pos ++;
716                         }
717                 }
718         }
719         else {
720                 while( '0' <= *pos && *pos <= '9' ) {
721                         value = value*10 + *pos - '0';
722                         pos ++;
723                 }
724         }
725         
726         return AST_NewInteger( Parser, value );
727 }
728
729 /**
730  * \brief Get a variable
731  */
732 tAST_Node *Parse_GetVariable(tParser *Parser)
733 {
734         tAST_Node       *ret;
735         SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
736         {
737                 char    name[Parser->TokenLen];
738                 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
739                 name[Parser->TokenLen-1] = 0;
740                 ret = AST_NewVariable( Parser, name );
741                 #if DEBUG >= 2
742                 printf("Parse_GetVariable: name = '%s'\n", name);
743                 #endif
744         }
745         for(;;)
746         {
747                 GetToken(Parser);
748                 if( Parser->Token == TOK_SQUARE_OPEN )
749                 {
750                         ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
751                         SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
752                         continue ;
753                 }
754                 if( Parser->Token == TOK_ELEMENT )
755                 {
756                         SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT);
757                         // Method Call
758                         if( LookAhead(Parser) == TOK_PAREN_OPEN )
759                         {
760                                 char    name[Parser->TokenLen+1];
761                                 memcpy(name, Parser->TokenStr, Parser->TokenLen);
762                                 name[Parser->TokenLen] = 0;
763                                 ret = AST_NewMethodCall(Parser, ret, name);
764                                 GetToken(Parser);       // Eat the '('
765                                 // Read arguments
766                                 if( GetToken(Parser) != TOK_PAREN_CLOSE )
767                                 {
768                                         PutBack(Parser);
769                                         do {
770                                                 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
771                                         } while(GetToken(Parser) == TOK_COMMA);
772                                         SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
773                                 }
774                                 
775                         }
776                         // Attribute
777                         else
778                         {
779                                 char    name[Parser->TokenLen];
780                                 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
781                                 name[Parser->TokenLen-1] = 0;
782                                 ret = AST_NewClassElement(Parser, ret, name);
783                         }
784                         continue ;
785                 }
786                 
787                 break ;
788         }
789         PutBack(Parser);
790         return ret;
791 }
792
793 /**
794  * \brief Get an identifier (constant or function call)
795  */
796 tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate)
797 {
798         tAST_Node       *ret = NULL;
799         char    *name;
800         SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
801         name = strndup( Parser->TokenStr, Parser->TokenLen );
802         
803         #if USE_SCOPE_CHAR
804         if( GetToken(Parser) == TOK_SCOPE )
805         {
806                 ret = AST_NewScopeDereference( Parser, Parse_GetIdent(Parser, bObjectCreate), name );
807                 free(name);
808                 return ret;
809         }
810         PutBack(Parser);
811         #endif
812         
813         if( GetToken(Parser) == TOK_PAREN_OPEN )
814         {
815                 #if DEBUG >= 2
816                 printf("Parse_GetIdent: Calling '%s'\n", name);
817                 #endif
818                 // Function Call
819                 if( bObjectCreate )
820                         ret = AST_NewCreateObject( Parser, name );
821                 else
822                         ret = AST_NewFunctionCall( Parser, name );
823                 // Read arguments
824                 if( GetToken(Parser) != TOK_PAREN_CLOSE )
825                 {
826                         PutBack(Parser);
827                         do {
828                                 #if DEBUG >= 2
829                                 printf(" Parse_GetIdent: Argument\n");
830                                 #endif
831                                 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
832                         } while(GetToken(Parser) == TOK_COMMA);
833                         SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
834                         #if DEBUG >= 2
835                         printf(" Parse_GetIdent: All arguments parsed\n");
836                         #endif
837                 }
838         }
839         else
840         {
841                 // Runtime Constant / Variable (When implemented)
842                 #if DEBUG >= 2
843                 printf("Parse_GetIdent: Referencing '%s'\n", name);
844                 #endif
845                 PutBack(Parser);
846                 if( bObjectCreate )     // Void constructor (TODO: Should this be an error?)
847                         ret = AST_NewCreateObject( Parser, name );
848                 else
849                         ret = AST_NewConstant( Parser, name );
850         }
851         
852         free(name);
853         return ret;
854 }
855
856 /**
857  * \brief Check for an error
858  */
859 void SyntaxAssert(tParser *Parser, int Have, int Want)
860 {
861         if(Have != Want) {
862                 fprintf(stderr, "ERROR: SyntaxAssert Failed, Expected %s(%i), got %s(%i) on line %i\n",
863                         csaTOKEN_NAMES[Want], Want, csaTOKEN_NAMES[Have], Have, Parser->CurLine);
864                 longjmp(Parser->JmpTarget, -1);
865         }
866 }
867

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