Fixed behavior of VTerm when driver is set at runtime
[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 #include "tokens.h"
10 #include "ast.h"
11
12 // === PROTOTYPES ===
13 tAST_Script     *Parse_Buffer(tSpiderVariant *Variant, char *Buffer);
14 tAST_Node       *Parse_DoCodeBlock(tParser *Parser);
15 tAST_Node       *Parse_DoExpr(tParser *Parser);
16
17 tAST_Node       *Parse_DoExpr0(tParser *Parser);        // Assignment
18 tAST_Node       *Parse_DoExpr1(tParser *Parser);        // Boolean Operators
19 tAST_Node       *Parse_DoExpr2(tParser *Parser);        // Comparison Operators
20 tAST_Node       *Parse_DoExpr3(tParser *Parser);        // Bitwise Operators
21 tAST_Node       *Parse_DoExpr4(tParser *Parser);        // Bit Shifts
22 tAST_Node       *Parse_DoExpr5(tParser *Parser);        // Arithmatic
23 tAST_Node       *Parse_DoExpr6(tParser *Parser);        // Mult & Div
24
25 tAST_Node       *Parse_DoParen(tParser *Parser);        // Parenthesis (Always Last)
26 tAST_Node       *Parse_DoValue(tParser *Parser);        // Values
27
28 tAST_Node       *Parse_GetString(tParser *Parser);
29 tAST_Node       *Parse_GetNumeric(tParser *Parser);
30 tAST_Node       *Parse_GetVariable(tParser *Parser);
31 tAST_Node       *Parse_GetIdent(tParser *Parser);
32
33 void    SyntaxAssert(int Have, int Want);
34
35 // === CODE ===
36 /**
37  * \brief Parse a buffer into a syntax tree
38  */
39 tAST_Script     *Parse_Buffer(tSpiderVariant *Variant, char *Buffer)
40 {
41         tParser parser = {0};
42         tParser *Parser = &parser;      //< Keeps code consitent
43         tAST_Script     *ret;
44         tAST_Node       *mainCode;
45         char    *name;
46         tAST_Function   *fcn;
47         
48         // Initialise parser
49         parser.BufStart = Buffer;
50         parser.CurPos = Buffer;
51         
52         ret = AST_NewScript();
53         mainCode = AST_NewCodeBlock();
54         
55         for(;;)
56         {
57                 switch( GetToken(Parser) )
58                 {
59                 case TOK_RWD_FUNCTION:                  
60                         // Define a function
61                         SyntaxAssert( GetToken(Parser), TOK_IDENT );
62                         name = strndup( Parser->TokenStr, Parser->TokenLen );
63                         fcn = AST_AppendFunction( ret, name );
64                         free(name);
65                         
66                         SyntaxAssert( GetToken(Parser), TOK_PAREN_OPEN );
67                         // TODO: Arguments
68                         SyntaxAssert( GetToken(Parser), TOK_PAREN_CLOSE );
69                         
70                         AST_SetFunctionCode( fcn, Parse_DoCodeBlock(Parser) );
71                         break;
72                 
73                 default:
74                         PutBack(&parser);
75                         AST_AppendNode( mainCode, Parse_DoExpr(Parser) );
76                         break;
77                 }
78         }
79         
80         fcn = AST_AppendFunction( ret, "" );
81         AST_SetFunctionCode( fcn, mainCode );
82         
83         return ret;
84 }
85
86 /**
87  * \brief Parse a block of code surrounded by { }
88  */
89 tAST_Node *Parse_DoCodeBlock(tParser *Parser)
90 {
91         tAST_Node       *ret;
92         SyntaxAssert( GetToken(Parser), TOK_BRACE_OPEN );
93         
94         ret = AST_NewCodeBlock();
95         
96         while( GetToken(Parser) != TOK_BRACE_CLOSE )
97         {
98                 AST_AppendNode( ret, Parse_DoExpr(Parser) );
99                 SyntaxAssert( GetToken(Parser), TOK_SEMICOLON );
100         }
101         return ret;
102 }
103
104 /**
105  * \brief Parse an expression
106  */
107 tAST_Node *Parse_DoExpr(tParser *Parser)
108 {
109         return Parse_DoExpr0(Parser);
110 }
111
112 /**
113  * \brief Assignment Operations
114  */
115 tAST_Node *Parse_DoExpr0(tParser *Parser)
116 {
117         tAST_Node       *ret = Parse_DoExpr1(Parser);
118
119         // Check Assignment
120         switch(LookAhead(Parser))
121         {
122         case TOK_ASSIGN:
123                 GetToken(Parser);               // Eat Token
124                 ret = AST_NewAssign(NODETYPE_NOP, ret, Parse_DoExpr0(Parser));
125                 break;
126         #if 0
127         case TOK_DIV_EQU:
128                 GetToken(Parser);               // Eat Token
129                 ret = AST_NewAssignOp(ret, NODETYPE_DIVIDE, DoExpr0(Parser));
130                 break;
131         case TOK_MULT_EQU:
132                 GetToken(Parser);               // Eat Token
133                 ret = AST_NewAssignOp(ret, NODETYPE_MULTIPLY, DoExpr0(Parser));
134                 break;
135         #endif
136         default:        break;
137         }
138         return ret;
139 }
140
141 /**
142  * \brief Logical/Boolean Operators
143  */
144 tAST_Node *Parse_DoExpr1(tParser *Parser)
145 {
146         tAST_Node       *ret = Parse_DoExpr2(Parser);
147         
148         switch(GetToken(Parser))
149         {
150         case TOK_LOGICAND:
151                 ret = AST_NewBinOp(NODETYPE_LOGICALAND, ret, Parse_DoExpr1(Parser));
152                 break;
153         case TOK_LOGICOR:
154                 ret = AST_NewBinOp(NODETYPE_LOGICALOR, ret, Parse_DoExpr1(Parser));
155                 break;
156         case TOK_LOGICXOR:
157                 ret = AST_NewBinOp(NODETYPE_LOGICALXOR, ret, Parse_DoExpr1(Parser));
158                 break;
159         default:
160                 PutBack(Parser);
161                 break;
162         }
163         return ret;
164 }
165
166 // --------------------
167 // Expression 2 - Comparison Operators
168 // --------------------
169 tAST_Node *Parse_DoExpr2(tParser *Parser)
170 {
171         tAST_Node       *ret = Parse_DoExpr3(Parser);
172
173         // Check token
174         switch(GetToken(Parser))
175         {
176         case TOK_EQUALS:
177                 ret = AST_NewBinOp(NODETYPE_EQUALS, ret, Parse_DoExpr2(Parser));
178                 break;
179         case TOK_LT:
180                 ret = AST_NewBinOp(NODETYPE_LESSTHAN, ret, Parse_DoExpr2(Parser));
181                 break;
182         case TOK_GT:
183                 ret = AST_NewBinOp(NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser));
184                 break;
185         default:
186                 PutBack(Parser);
187                 break;
188         }
189         return ret;
190 }
191
192 /**
193  * \brief Bitwise Operations
194  */
195 tAST_Node *Parse_DoExpr3(tParser *Parser)
196 {
197         tAST_Node       *ret = Parse_DoExpr4(Parser);
198
199         // Check Token
200         switch(GetToken(Parser))
201         {
202         case TOK_OR:
203                 ret = AST_NewBinOp(NODETYPE_BWOR, ret, Parse_DoExpr3(Parser));
204                 break;
205         case TOK_AND:
206                 ret = AST_NewBinOp(NODETYPE_BWAND, ret, Parse_DoExpr3(Parser));
207                 break;
208         case TOK_XOR:
209                 ret = AST_NewBinOp(NODETYPE_BWXOR, ret, Parse_DoExpr3(Parser));
210                 break;
211         default:
212                 PutBack(Parser);
213                 break;
214         }
215         return ret;
216 }
217
218 // --------------------
219 // Expression 4 - Shifts
220 // --------------------
221 tAST_Node *Parse_DoExpr4(tParser *Parser)
222 {
223         tAST_Node *ret = Parse_DoExpr5(Parser);
224
225         switch(GetToken(Parser))
226         {
227         case TOK_SHL:
228                 ret = AST_NewBinOp(NODETYPE_BITSHIFTLEFT, ret, Parse_DoExpr5(Parser));
229                 break;
230         case TOK_SHR:
231                 ret = AST_NewBinOp(NODETYPE_BITSHIFTRIGHT, ret, Parse_DoExpr5(Parser));
232                 break;
233         default:
234                 PutBack(Parser);
235                 break;
236         }
237
238         return ret;
239 }
240
241 // --------------------
242 // Expression 5 - Arithmatic
243 // --------------------
244 tAST_Node *Parse_DoExpr5(tParser *Parser)
245 {
246         tAST_Node *ret = Parse_DoExpr6(Parser);
247
248         switch(GetToken(Parser))
249         {
250         case TOK_PLUS:
251                 ret = AST_NewBinOp(NODETYPE_ADD, ret, Parse_DoExpr5(Parser));
252                 break;
253         case TOK_MINUS:
254                 ret = AST_NewBinOp(NODETYPE_SUBTRACT, ret, Parse_DoExpr5(Parser));
255                 break;
256         default:
257                 PutBack(Parser);
258                 break;
259         }
260
261         return ret;
262 }
263
264 // --------------------
265 // Expression 6 - Multiplcation & Division
266 // --------------------
267 tAST_Node *Parse_DoExpr6(tParser *Parser)
268 {
269         tAST_Node *ret = Parse_DoParen(Parser);
270
271         switch(GetToken(Parser))
272         {
273         case TOK_MUL:
274                 ret = AST_NewBinOp(NODETYPE_MULTIPLY, ret, Parse_DoExpr6(Parser));
275                 break;
276         case TOK_DIV:
277                 ret = AST_NewBinOp(NODETYPE_DIVIDE, ret, Parse_DoExpr6(Parser));
278                 break;
279         default:
280                 PutBack(Parser);
281                 break;
282         }
283
284         return ret;
285 }
286
287
288 // --------------------
289 // 2nd Last Expression - Parens
290 // --------------------
291 tAST_Node *Parse_DoParen(tParser *Parser)
292 {
293         if(LookAhead(Parser) == TOK_PAREN_OPEN)
294         {
295                 tAST_Node       *ret;
296                 GetToken(Parser);
297                 ret = Parse_DoExpr0(Parser);
298                 SyntaxAssert(GetToken(Parser), TOK_PAREN_CLOSE);
299                 return ret;
300         }
301         else
302                 return Parse_DoValue(Parser);
303 }
304
305 // --------------------
306 // Last Expression - Value
307 // --------------------
308 tAST_Node *Parse_DoValue(tParser *Parser)
309 {
310          int    tok = LookAhead(Parser);
311
312         switch(tok)
313         {
314         case TOK_STR:   return Parse_GetString(Parser);
315         case TOK_INTEGER:       return Parse_GetNumeric(Parser);
316         case TOK_IDENT: return Parse_GetIdent(Parser);
317         case TOK_VARIABLE:      return Parse_GetVariable(Parser);
318
319         default:
320                 //ParseError2( tok, TOK_T_VALUE );
321                 return NULL;
322         }
323 }
324
325 /**
326  * \brief Get a string
327  */
328 tAST_Node *Parse_GetString(tParser *Parser)
329 {
330         tAST_Node       *ret;
331         GetToken( Parser );
332         // TODO: Parse Escape Codes
333         ret = AST_NewString( Parser->TokenStr+1, Parser->TokenLen-2 );
334         return ret;
335 }
336
337 /**
338  * \brief Get a numeric value
339  */
340 tAST_Node *Parse_GetNumeric(tParser *Parser)
341 {
342         uint64_t        value;
343         GetToken( Parser );
344         value = atoi( Parser->TokenStr );
345         return AST_NewInteger( value );
346 }
347
348 /**
349  * \brief Get a variable
350  */
351 tAST_Node *Parse_GetVariable(tParser *Parser)
352 {
353         char    *name;
354         tAST_Node       *ret;
355         SyntaxAssert( GetToken(Parser), TOK_VARIABLE );
356         name = strndup( Parser->TokenStr+1, Parser->TokenLen-1 );
357         ret = AST_NewVariable( name );
358         free(name);
359         return ret;
360 }
361
362 /**
363  * \brief Get an identifier (constand or function call)
364  */
365 tAST_Node *Parse_GetIdent(tParser *Parser)
366 {
367         tAST_Node       *ret;
368         char    *name;
369         SyntaxAssert( GetToken(Parser), TOK_IDENT );
370         name = strndup( Parser->TokenStr, Parser->TokenLen );
371         
372         if( GetToken(Parser) == TOK_PAREN_OPEN )
373         {
374                 // Function Call
375                 ret = AST_NewFunctionCall( name );
376                 // Read arguments
377                 if( GetToken(Parser) != TOK_PAREN_CLOSE )
378                 {
379                         PutBack(Parser);
380                         do {
381                                 AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) );
382                         } while(GetToken(Parser) == TOK_COMMA);
383                         SyntaxAssert( Parser->Token, TOK_PAREN_CLOSE );
384                 }
385         }
386         else {
387                 // Runtime Constant
388                 PutBack(Parser);
389                 ret = AST_NewConstant( name );
390         }
391         
392         free(name);
393         return ret;
394 }
395
396 /**
397  * \brief Check for an error
398  */
399 void SyntaxAssert(int Have, int Want)
400 {
401         if(Have != Want) {
402                 fprintf(stderr, "ERROR: Expected %i, got %i\n", Want, Have);
403                 //longjmp(jmpTarget, 1);
404                 return;
405         }
406 }
407

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