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

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