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

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