31dabadec76970f62cb93e2efdf64f3d100990a6
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / parse.c
1 /*
2  * Acess2 - SpiderScript
3  * - Parser
4  */
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <spiderscript.h>
9 #define WANT_TOKEN_STRINGS      1
10 #include "tokens.h"
11 #include "ast.h"
12
13 #define DEBUG   0
14
15 // === PROTOTYPES ===
16 tAST_Script     *Parse_Buffer(tSpiderVariant *Variant, char *Buffer);
17 tAST_Node       *Parse_DoCodeBlock(tParser *Parser);
18 tAST_Node       *Parse_DoBlockLine(tParser *Parser);
19 tAST_Node       *Parse_GetVarDef(tParser *Parser, int Type);
20
21 tAST_Node       *Parse_DoExpr0(tParser *Parser);        // Assignment
22 tAST_Node       *Parse_DoExpr1(tParser *Parser);        // Boolean Operators
23 tAST_Node       *Parse_DoExpr2(tParser *Parser);        // Comparison Operators
24 tAST_Node       *Parse_DoExpr3(tParser *Parser);        // Bitwise Operators
25 tAST_Node       *Parse_DoExpr4(tParser *Parser);        // Bit Shifts
26 tAST_Node       *Parse_DoExpr5(tParser *Parser);        // Arithmatic
27 tAST_Node       *Parse_DoExpr6(tParser *Parser);        // Mult & Div
28
29 tAST_Node       *Parse_DoParen(tParser *Parser);        // Parenthesis (Always Last)
30 tAST_Node       *Parse_DoValue(tParser *Parser);        // Values
31
32 tAST_Node       *Parse_GetString(tParser *Parser);
33 tAST_Node       *Parse_GetNumeric(tParser *Parser);
34 tAST_Node       *Parse_GetVariable(tParser *Parser);
35 tAST_Node       *Parse_GetIdent(tParser *Parser);
36
37 void    SyntaxAssert(tParser *Parser, int Have, int Want);
38
39 // === CODE ===
40 /**
41  * \brief Parse a buffer into a syntax tree
42  */
43 tAST_Script     *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
44 {
45         tParser parser = {0};
46         tParser *Parser = &parser;      //< Keeps code consitent
47         tAST_Script     *ret;
48         tAST_Node       *mainCode;
49         char    *name;
50         tAST_Function   *fcn;
51          int    type;
52         
53         #if DEBUG >= 2
54         printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer);
55         #endif
56         
57         // Initialise parser
58         parser.LastToken = -1;
59         parser.NextToken = -1;
60         parser.CurLine = 1;
61         parser.BufStart = Buffer;
62         parser.CurPos = Buffer;
63         
64         ret = AST_NewScript();
65         mainCode = AST_NewCodeBlock();
66         
67         if( setjmp( parser.JmpTarget ) != 0 )
68         {
69                 AST_FreeNode( mainCode );
70                 return NULL;
71         }
72         
73         while(Parser->Token != TOK_EOF)
74         {
75                 switch( GetToken(Parser) )
76                 {
77                 case TOK_EOF:
78                         break;
79                 
80                 // Typed variables/functions
81                 case TOKEN_GROUP_TYPES:
82                         {
83                          int    tok, type;
84                         TOKEN_GET_DATATYPE(type, Parser->Token);
85                         
86                         tok = GetToken(Parser);
87                         // Define a function (pass on to the other function definition code)
88                         if( tok == TOK_IDENT ) {
89                                 goto defFcn;
90                         }
91                         // Define a variable
92                         else if( tok == TOK_VARIABLE ) {
93                                 AST_AppendNode( mainCode, Parse_GetVarDef(Parser, type) );
94                                 SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON);
95                         }
96                         else {
97                                 fprintf(stderr, "ERROR: Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n",
98                                         csaTOKEN_NAMES[tok]);
99                         }
100                         }
101                         break;
102                 
103                 // Define a function
104                 case TOK_RWD_FUNCTION:
105                         if( !Variant->bDyamicTyped ) {
106                                 fprintf(stderr, "ERROR: Attempt to create a dynamic function\n");
107                                 longjmp(Parser->JmpTarget, -1);
108                         }
109                         type = SS_DATATYPE_DYNAMIC;
110                         SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
111                 defFcn:
112                         name = strndup( Parser->TokenStr, Parser->TokenLen );
113                         fcn = AST_AppendFunction( ret, name );
114                         #if DEBUG
115                         printf("DefFCN %s\n", name);
116                         #endif
117                         free(name);
118                         
119                         // Get arguments
120                         SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN );
121                         if( LookAhead(Parser) != TOK_PAREN_CLOSE )
122                         {
123                                 do {
124                                         type = SS_DATATYPE_DYNAMIC;
125                                         GetToken(Parser);
126                                         // Non dynamic typed variants must use data types
127                                         if( !Variant->bDyamicTyped ) {
128                                                 TOKEN_GET_DATATYPE(type, Parser->Token);
129                                                 GetToken(Parser);
130                                         }
131                                         AST_AppendFunctionArg(fcn, Parse_GetVarDef(Parser, type)); 
132                                 }       while(GetToken(Parser) == TOK_COMMA);
133                         }
134                         else
135                                 GetToken(Parser);
136                         SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE );
137                         
138                         AST_SetFunctionCode( fcn, Parse_DoCodeBlock(Parser) );
139                         break;
140                 
141                 default:
142                         PutBack(Parser);
143                         AST_AppendNode( mainCode, Parse_DoBlockLine(Parser) );
144                         break;
145                 }
146         }
147         
148         fcn = AST_AppendFunction( ret, "" );
149         AST_SetFunctionCode( fcn, mainCode );
150         
151         printf("---- %p parsed as SpiderScript ----\n", Buffer);
152         
153         return ret;
154 }
155
156 /**
157  * \brief Parse a block of code surrounded by { }
158  */
159 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
160 {
161         tAST_Node       *ret;
162         SyntaxAssert(Parser, GetToken(Parser), TOK_BRACE_OPEN );
163         
164         ret = AST_NewCodeBlock();
165         
166         while( LookAhead(Parser) != TOK_BRACE_CLOSE )
167         {
168                 AST_AppendNode( ret, Parse_DoBlockLine(Parser) );
169         }
170         GetToken(Parser);       // Omnomnom
171         return ret;
172 }
173
174 /**
175  * \brief Parse a line in a block
176  */
177 tAST_Node *Parse_DoBlockLine(tParser *Parser)
178 {
179         tAST_Node       *ret;
180         
181         //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine);
182         
183         switch(LookAhead(Parser))
184         {
185         
186         // Return from a method
187         case TOK_RWD_RETURN:
188                 //printf("return\n");
189                 GetToken(Parser);
190                 ret = AST_NewUniOp(NODETYPE_RETURN, Parse_DoExpr0(Parser));
191                 break;
192         
193         // Define Variables
194         case TOK_RWD_OBJECT:
195         case TOK_RWD_STRING:
196         case TOK_RWD_REAL:
197         case TOK_RWD_INTEGER:
198                 {
199                          int    type;
200                         
201                         switch(GetToken(Parser))
202                         {
203                         case TOK_RWD_INTEGER:   type = SS_DATATYPE_INTEGER;     break;
204                         case TOK_RWD_OBJECT:    type = SS_DATATYPE_OBJECT;      break;
205                         case TOK_RWD_REAL:      type = SS_DATATYPE_REAL;        break;
206                         case TOK_RWD_STRING:    type = SS_DATATYPE_STRING;      break;
207                         }
208                         
209                         SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE);
210                         
211                         ret = Parse_GetVarDef(Parser, type);
212                 }
213                 break;
214         
215         // Default
216         default:
217                 //printf("exp0\n");
218                 ret = Parse_DoExpr0(Parser);
219                 break;
220         }
221         
222         SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON );
223         return ret;
224 }
225
226 /**
227  * \brief Get a variable definition
228  */
229 tAST_Node *Parse_GetVarDef(tParser *Parser, int Type)
230 {
231         char    name[Parser->TokenLen];
232         tAST_Node       *ret;
233         
234         SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE);
235         
236         // copy the name (trimming the $)
237         memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
238         name[Parser->TokenLen-1] = 0;
239         // Define the variable
240         ret = AST_NewDefineVar(Type, name);
241         // Handle arrays
242         while( LookAhead(Parser) == TOK_SQUARE_OPEN )
243         {
244                 GetToken(Parser);
245                 AST_AppendNode(ret, Parse_DoExpr0(Parser));
246                 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
247         }
248         return ret;
249 }
250
251 /**
252  * \brief Assignment Operations
253  */
254 tAST_Node *Parse_DoExpr0(tParser *Parser)
255 {
256         tAST_Node       *ret = Parse_DoExpr1(Parser);
257
258         // Check Assignment
259         switch(LookAhead(Parser))
260         {
261         case TOK_ASSIGN:
262                 GetToken(Parser);               // Eat Token
263                 ret = AST_NewAssign(NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
264                 break;
265         #if 0
266         case TOK_DIV_EQU:
267                 GetToken(Parser);               // Eat Token
268                 ret = AST_NewAssign(NODETYPE_DIVIDE, ret, Parse_DoExpr0(Parser));
269                 break;
270         case TOK_MULT_EQU:
271                 GetToken(Parser);               // Eat Token
272                 ret = AST_NewAssign(NODETYPE_MULTIPLY, ret, Parse_DoExpr0(Parser));
273                 break;
274         #endif
275         default:
276                 #if DEBUG >= 2
277                 printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token);
278                 #endif
279                 break;
280         }
281         return ret;
282 }
283
284 /**
285  * \brief Logical/Boolean Operators
286  */
287 tAST_Node *Parse_DoExpr1(tParser *Parser)
288 {
289         tAST_Node       *ret = Parse_DoExpr2(Parser);
290         
291         switch(GetToken(Parser))
292         {
293         case TOK_LOGICAND:
294                 ret = AST_NewBinOp(NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
295                 break;
296         case TOK_LOGICOR:
297                 ret = AST_NewBinOp(NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
298                 break;
299         case TOK_LOGICXOR:
300                 ret = AST_NewBinOp(NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
301                 break;
302         default:
303                 PutBack(Parser);
304                 break;
305         }
306         return ret;
307 }
308
309 // --------------------
310 // Expression 2 - Comparison Operators
311 // --------------------
312 tAST_Node *Parse_DoExpr2(tParser *Parser)
313 {
314         tAST_Node       *ret = Parse_DoExpr3(Parser);
315
316         // Check token
317         switch(GetToken(Parser))
318         {
319         case TOK_EQUALS:
320                 ret = AST_NewBinOp(NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
321                 break;
322         case TOK_LT:
323                 ret = AST_NewBinOp(NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
324                 break;
325         case TOK_GT:
326                 ret = AST_NewBinOp(NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
327                 break;
328         default:
329                 PutBack(Parser);
330                 break;
331         }
332         return ret;
333 }
334
335 /**
336  * \brief Bitwise Operations
337  */
338 tAST_Node *Parse_DoExpr3(tParser *Parser)
339 {
340         tAST_Node       *ret = Parse_DoExpr4(Parser);
341
342         // Check Token
343         switch(GetToken(Parser))
344         {
345         case TOK_OR:
346                 ret = AST_NewBinOp(NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
347                 break;
348         case TOK_AND:
349                 ret = AST_NewBinOp(NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
350                 break;
351         case TOK_XOR:
352                 ret = AST_NewBinOp(NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
353                 break;
354         default:
355                 PutBack(Parser);
356                 break;
357         }
358         return ret;
359 }
360
361 // --------------------
362 // Expression 4 - Shifts
363 // --------------------
364 tAST_Node *Parse_DoExpr4(tParser *Parser)
365 {
366         tAST_Node *ret = Parse_DoExpr5(Parser);
367
368         switch(GetToken(Parser))
369         {
370         case TOK_SHL:
371                 ret = AST_NewBinOp(NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
372                 break;
373         case TOK_SHR:
374                 ret = AST_NewBinOp(NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
375                 break;
376         default:
377                 PutBack(Parser);
378                 break;
379         }
380
381         return ret;
382 }
383
384 // --------------------
385 // Expression 5 - Arithmatic
386 // --------------------
387 tAST_Node *Parse_DoExpr5(tParser *Parser)
388 {
389         tAST_Node *ret = Parse_DoExpr6(Parser);
390
391         switch(GetToken(Parser))
392         {
393         case TOK_PLUS:
394                 ret = AST_NewBinOp(NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
395                 break;
396         case TOK_MINUS:
397                 ret = AST_NewBinOp(NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
398                 break;
399         default:
400                 PutBack(Parser);
401                 break;
402         }
403
404         return ret;
405 }
406
407 // --------------------
408 // Expression 6 - Multiplcation & Division
409 // --------------------
410 tAST_Node *Parse_DoExpr6(tParser *Parser)
411 {
412         tAST_Node *ret = Parse_DoParen(Parser);
413
414         switch(GetToken(Parser))
415         {
416         case TOK_MUL:
417                 ret = AST_NewBinOp(NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
418                 break;
419         case TOK_DIV:
420                 ret = AST_NewBinOp(NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
421                 break;
422         default:
423                 PutBack(Parser);
424                 break;
425         }
426
427         return ret;
428 }
429
430
431 // --------------------
432 // 2nd Last Expression - Parens
433 // --------------------
434 tAST_Node *Parse_DoParen(tParser *Parser)
435 {
436         #if DEBUG >= 2
437         printf("Parse_DoParen: (Parser=%p)\n", Parser);
438         #endif
439         if(LookAhead(Parser) == TOK_PAREN_OPEN)
440         {
441                 tAST_Node       *ret;
442                 GetToken(Parser);
443                 
444                 // TODO: Handle casts here
445                 
446                 ret = Parse_DoExpr0(Parser);
447                 SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE);
448                 return ret;
449         }
450         else
451                 return Parse_DoValue(Parser);
452 }
453
454 // --------------------
455 // Last Expression - Value
456 // --------------------
457 tAST_Node *Parse_DoValue(tParser *Parser)
458 {
459          int    tok = LookAhead(Parser);
460
461         #if DEBUG >= 2
462         printf("Parse_DoValue: tok = %i\n", tok);
463         #endif
464
465         switch(tok)
466         {
467         case TOK_STR:   return Parse_GetString(Parser);
468         case TOK_INTEGER:       return Parse_GetNumeric(Parser);
469         case TOK_IDENT: return Parse_GetIdent(Parser);
470         case TOK_VARIABLE:      return Parse_GetVariable(Parser);
471
472         default:
473                 fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n",
474                         csaTOKEN_NAMES[tok], Parser->CurLine);
475                 longjmp( Parser->JmpTarget, -1 );
476         }
477 }
478
479 /**
480  * \brief Get a string
481  */
482 tAST_Node *Parse_GetString(tParser *Parser)
483 {
484         tAST_Node       *ret;
485         GetToken( Parser );
486         // TODO: Parse Escape Codes
487         ret = AST_NewString( Parser->TokenStr+1, Parser->TokenLen-2 );
488         return ret;
489 }
490
491 /**
492  * \brief Get a numeric value
493  */
494 tAST_Node *Parse_GetNumeric(tParser *Parser)
495 {
496         uint64_t        value;
497         GetToken( Parser );
498         value = atoi( Parser->TokenStr );
499         return AST_NewInteger( value );
500 }
501
502 /**
503  * \brief Get a variable
504  */
505 tAST_Node *Parse_GetVariable(tParser *Parser)
506 {
507         tAST_Node       *ret;
508         SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE );
509         {
510                 char    name[Parser->TokenLen];
511                 memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1);
512                 name[Parser->TokenLen-1] = 0;
513                 ret = AST_NewVariable( name );
514                 #if DEBUG >= 2
515                 printf("Parse_GetVariable: name = '%s'\n", name);
516                 #endif
517         }
518         // Handle array references
519         while( LookAhead(Parser) == TOK_SQUARE_OPEN )
520         {
521                 GetToken(Parser);
522                 ret = AST_NewBinOp(NODETYPE_INDEX, ret, Parse_DoExpr0(Parser));
523                 SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE);
524         }
525         return ret;
526 }
527
528 /**
529  * \brief Get an identifier (constand or function call)
530  */
531 tAST_Node *Parse_GetIdent(tParser *Parser)
532 {
533         tAST_Node       *ret;
534         char    *name;
535         SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT );
536         name = strndup( Parser->TokenStr, Parser->TokenLen );
537         
538         #if 0
539         while( GetToken(Parser) == TOK_SCOPE )
540         {
541                 ret = AST_New
542         }
543         PutBack(Parser);
544         #endif
545         
546         if( GetToken(Parser) == TOK_PAREN_OPEN )
547         {
548                 #if DEBUG >= 2
549                 printf("Parse_GetIdent: Calling '%s'\n", name);
550                 #endif
551                 // Function Call
552                 ret = AST_NewFunctionCall( name );
553                 // Read arguments
554                 if( GetToken(Parser) != TOK_PAREN_CLOSE )
555                 {
556                         PutBack(Parser);
557                         do {
558                                 #if DEBUG >= 2
559                                 printf(" Parse_GetIdent: Argument\n");
560                                 #endif
561                                 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
562                         } while(GetToken(Parser) == TOK_COMMA);
563                         SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE );
564                         #if DEBUG >= 2
565                         printf(" Parse_GetIdent: All arguments parsed\n");
566                         #endif
567                 }
568         }
569         else {
570                 // Runtime Constant
571                 #if DEBUG >= 2
572                 printf("Parse_GetIdent: Referencing '%s'\n", name);
573                 #endif
574                 PutBack(Parser);
575                 ret = AST_NewConstant( name );
576         }
577         
578         free(name);
579         return ret;
580 }
581
582 /**
583  * \brief Check for an error
584  */
585 void SyntaxAssert(tParser *Parser, int Have, int Want)
586 {
587         if(Have != Want) {
588                 fprintf(stderr, "ERROR: SyntaxAssert Failed, Expected %s(%i), got %s(%i) on line %i\n",
589                         csaTOKEN_NAMES[Want], Want, csaTOKEN_NAMES[Have], Have, Parser->CurLine);
590                 longjmp(Parser->JmpTarget, -1);
591         }
592 }
593

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