001 #include "Lexer.HC";
002 #define AST_UNOP 1
003 #define AST_BINOP 2
004 #define AST_KEYWORD 3
005 #define AST_ASSIGN 4
006 #define AST_STR 5
007 #define AST_VAR 6
008 #define AST_ARRAY 7
009 #define AST_CASCADE 8
010 #define AST_BLOCK 9
011 #define AST_CHR 10
012 #define AST_NUM 11
013 #define AST_SYMBOL 12
014 #define AST_CASCADE_HEAD 13 //str points to cascade head
015 #define AST_RETURN 14
016 #define AST_SELF 15
017 #define AST_SUPER 16
018 class CAST:CQue {
019   CQue args;
020   I64 type;
021   union {
022     U8 op_name[STR_LEN];
023     U8 name[STR_LEN];
024   };
025   union {
026     F64 num;
027     U8 *str;
028     CQue body;
029   };
030 };
031 class CName:CQue {
032   U8 name[STR_LEN];
033 };
034 class CMethod {
035   U8 name[STR_LEN];
036   I64 arity;
037   CQue args; //CName
038   CQue temps;
039   CQue body; //CAST
040 };
041 extern CAST *ParseAst(CLexer *l);
042 extern CAST *ParseCascade(CLexer *l);
043 CAST *ParseLiteral(CLexer *l) {
044   CAST *ret,*item;
045   if(l->tok=='(') {
046     Lex(l);
047     ret=ParseCascade(l);
048     if(l->tok!=')')
049       LexExcept(l,"Expeted a niggerfuckin ')' nigger.");
050     Lex(l);
051     return ret;
052   }
053   if(l->tok=='#') {
054     if(Lex(l)=='(') {
055       ret=CAlloc(sizeof CAST);
056       ret->type=AST_ARRAY;
057       QueInit(&ret->body);
058       QueInit(ret);
059       Lex(l);
060       do {
061         if(l->tok==')')
062           break;
063         if(!l->tok)
064           LexExcept(l,"Unexpected end of input you fuckin goatballer.");
065         item=ParseAst(l);
066         if(!item)
067           LexExcept(l,"Expected a motherfuckin array item.");
068         QueIns(item,ret->body.last);
069       } while(TRUE);
070       Lex(l);
071     } else if(l->tok==TOK_NAME) {
072       ret=CAlloc(sizeof CAST);
073       ret->type=AST_SYMBOL;
074       QueInit(&ret->args);
075       QueInit(ret);
076       StrCpy(ret->name,l->str);
077       Lex(l);
078       return ret;
079     } else if(!l->tok)
080       LexExcept(l,"Erection's over;Unexpected end of input.");
081   } else if(l->tok=='[') {
082     ret=CAlloc(sizeof CAST);
083     ret->type=AST_BLOCK;
084     QueInit(&ret->args);
085     QueInit(&ret->body);
086     QueInit(ret);
087 //Arguemnts Nigstrodamus
088     Lex(l);
089     if(l->tok==':') {
090       while(l->tok!='|') {
091         if(l->tok==':') {
092           if(Lex(l)!=TOK_NAME) {
093             LexExcept(l,"Put away you 50 inch nigger shlong and give me and argument.");
094           }
095           item=CAlloc(sizeof CAST);
096           item->type=AST_VAR;
097           StrCpy(item->name,l->str);
098           QueInit(&item->args);
099           QueInit(item);
100           QueIns(item,ret->args.last);
101           Lex(l);
102         } else
103           LexExcept(l,"Nigger please,expected a ':'");
104       }
105       Lex(l);
106     }
107     while(l->tok!=']') {
108       item=ParseAst(l);
109       if(!item)
110         LexExcept(l,"Are you fucking kidding me? I need an expression here.");
111       QueIns(item,ret->body.last);
112       if(l->tok=='.')
113         Lex(l);
114     }
115     Lex(l);
116     item=ret->args.next;
117     while(item!=&ret->args) {
118       item=item->next;
119     }
120     return ret;
121   } else if(l->tok==TOK_STR) {
122     item=CAlloc(sizeof CAST);
123     item->type=AST_STR;
124     item->str=StrNew(l->str);
125     QueInit(&item->args);
126     QueInit(item);
127     Lex(l);
128     return item;
129   } else if(l->tok==TOK_NAME) {
130     item=CAlloc(sizeof CAST);
131     if(!StrCmp(l->str,"self")) {
132       item->type=AST_SELF;
133       goto np;
134     } else if(!StrCmp(l->str,"super")) {
135       item->type=AST_SUPER;
136       goto np;
137     }
138     item->type=AST_VAR;
139     StrCpy(item->name,l->str);
140 np:
141     QueInit(&item->args);
142     QueInit(item);
143     Lex(l);
144     return item;    
145   } else if(l->tok==TOK_CHR) {
146     item=CAlloc(sizeof CAST);
147     item->type=AST_CHR;
148     item->name[0]=l->chr;
149     item->name[1]=0;
150     QueInit(&item->args);
151     QueInit(item);
152     Lex(l);
153     return item;    
154   } else if(l->tok==TOK_NUM) {
155     item=CAlloc(sizeof CAST);
156     item->type=AST_NUM;
157     item->num=l->num;
158     QueInit(&item->args);
159     QueInit(item);
160     Lex(l);
161     return item;    
162   }
163   LexExcept(l,"Unexpected token here nigga.");
164 }
165 CAST *ParseUnop(CLexer *l,CAST *left=NULL) {
166   if(!left) left=ParseLiteral(l);
167   CAST *ret;
168   CLexer backup;
169   I64 old_pos,old_ch;
170   if(!left) return NULL;
171 again:
172   if(l->tok==TOK_NAME) {
173     MemCpy(&backup,l,sizeof CLexer);
174     if(Lex(l)==':') {
175       MemCpy(l,&backup,sizeof CLexer);
176       return left;
177     }
178     ret=CAlloc(sizeof CAST);
179     ret->type=AST_UNOP;
180     QueInit(&ret->args);
181     QueInit(ret);
182     QueIns(left,&ret->args);
183     StrCpy(ret->name,backup.str);
184     left=ret;
185     goto again;
186   }
187   return left;
188 }
189 CAST *ParseBinop(CLexer *l,CAST *left=NULL) {
190   CAST *right,*ret;
191   if(!left) left=ParseUnop(l);
192   if(!left) return NULL;
193   I64 idx;
194 again:
195   if(l->tok!=TOK_NAME) {
196     for(idx=0;l->tok.u8[idx];idx++) {
197       if(!IsOperatorChr(l->tok.u8[idx])) 
198         goto fail;
199     }
200     ret=CAlloc(sizeof CAST);
201     ret->type=AST_BINOP;
202     QueInit(&ret->args);
203     QueInit(ret);
204     QueIns(left,ret->args.last);
205     StrCpy(ret->name,&l->tok);
206     if(!idx) goto fail;
207     Lex(l);
208 
209     right=ParseUnop(l);
210     if(!right)
211       LexExcept(l,"Binop needs 2 fucking operands nigga.");
212     QueIns(right,ret->args.last);
213     left=ret;
214     goto again;
215   }
216 fail:
217   return left;
218 }
219 CAST *ParseKeyword(CLexer *l,CAST *left=NULL) {
220   if(!left) left=ParseBinop(l);
221   CAST *ret=NULL,*right;
222   CLexer backup;
223   U8 buf[STR_LEN],str2[STR_LEN];
224   buf[0]=0;
225   if(!left) return NULL;
226 again:
227   if(l->tok==TOK_NAME) {
228     MemCpy(&backup,l,sizeof CLexer);
229     StrCpy(str2,l->str);
230     if(Lex(l)!=':') {
231       MemCpy(l,&backup,sizeof CLexer);
232       return left;
233     }
234     CatPrint(buf,"%s:",str2);
235     if(!ret) {
236       ret=CAlloc(sizeof CAST);
237       ret->type=AST_KEYWORD;
238       QueInit(&ret->args);
239       QueInit(ret);
240       QueIns(left,ret->args.last);
241     }
242     Lex(l);
243     right=ParseBinop(l);
244     if(!right)
245       LexExcept(l,"Where the fuck is my operand");
246     QueIns(right,ret->args.last);
247     goto again;
248   }
249   if(!StrLen(buf))
250     return left;
251   StrCpy(ret->name,buf);
252   return ret;
253 }
254 CAST *ParseCascade(CLexer *l) {
255   CAST *left=ParseKeyword(l),*ret=NULL,*item,*alias;
256   if(!left) return left;
257   while(l->tok==';') {
258     if(!ret) {
259       ret=CAlloc(sizeof CAST);
260       ret->type=AST_CASCADE;
261       QueInit(&ret->args);
262       QueInit(ret);
263       QueIns(left,ret->args.last);
264     }
265     Lex(l);
266     alias=CAlloc(sizeof CAST);
267     alias->type=AST_CASCADE_HEAD;
268     alias->str=left;
269     item=ParseKeyword(l,alias);
270     if(alias!=item) {
271       QueIns(item,ret->args.last);
272     } else {
273       item=ParseUnop(l,alias);
274       if(alias!=item) {
275         QueIns(item,ret->args.last);
276       } else
277         LexExcept(l,"Expected a fuckin cascade operation nigga.");
278     }
279   }
280   if(!ret) return left;
281   return ret;
282 }
283 CAST *ParseAst(CLexer *l) {
284   CLexer backup;
285   CAST *var,*right,*assign;
286   U8 assign_to[STR_LEN];
287   if(l->tok==TOK_NAME) {
288     StrCpy(assign_to,l->str);
289     MemCpy(&backup,l,sizeof CLexer);
290     if(Lex(l)=='_') {
291       var=CAlloc(sizeof CAST);
292       QueInit(var);
293       var->type=AST_VAR;
294       StrCpy(var->name,assign_to);
295       if(right=ParseCascade(l)) {
296         assign=CAlloc(sizeof CAST);
297         QueInit(assign);
298         QueInit(&assign->args);
299         QueIns(var,assign->args.last);
300         QueIns(right,assign->args.last);
301         return assign;
302       } else 
303         LexExcept("I want something to asign to '%s' nigga.",assign_to);
304     } else
305       MemCpy(l,&backup,sizeof CLexer);
306   }
307   if(l->tok=='^') {
308     Lex(l);
309     right=ParseCascade(l);
310     if(!right)
311       LexExcept(l,"Nigger toads fiegning 4 a nigger return.");
312     assign=CAlloc(sizeof CAST);
313     assign->type=AST_RETURN;
314     QueInit(assign);
315     QueInit(&assign->args);
316     QueIns(right,assign->args.last);    
317     return assign;
318   }
319   return ParseCascade(l);
320 }
321 CMethod *ParseMethod(CLexer *l) {
322   CMethod *m=CAlloc(sizeof CMethod);
323   CName *name,*head;
324   CAST *ast;
325   I64 idx;
326   QueInit(&m->args);
327   QueInit(&m->body);
328   QueInit(&m->temps);
329   while(TRUE) {
330     if(l->tok=='|')
331       break;
332     if(l->tok==TOK_NAME) {
333       CatPrint(m->name,"%s",l->str);
334       if(Lex(l)==':') {
335         CatPrint(m->name,":"); 
336         Lex(l);
337         if(l->tok!=TOK_NAME)
338           LexExcept(l,"I expected a name nigga.");
339         m->arity++;
340         name=CAlloc(sizeof CName);
341         StrCpy(name->name,l->str);
342         QueIns(name,m->args.last);
343         Lex(l);
344       } else if(m->arity>1) {
345         LexExcept(l,"I expected a ':' asswipe.");
346       } else {// is unop
347         if(Lex(l)!='|') 
348           LexExcept(l,"This is an unop nigga");
349         else
350           break;
351       }
352     } else {
353       for(idx=0;l->tok.u8[idx];idx++) {
354         if(!IsOperatorChr(l->tok.u8[idx])) 
355           LexExcept(l,"Expected a operator/method name here nigga.");
356       }
357       if(Lex(l)==TOK_NAME) {
358         name=CAlloc(sizeof CName);
359         StrCpy(name->name,l->str);
360         QueIns(name,m->args.last);
361         m->arity++;
362         if(Lex(l)!='|')
363           LexExcept(l,"Expected a fuckin '|'.");
364         break;
365       } else
366         LexExcept(l,"I niggin need uh argument name nigga.");
367     }
368   }
369   Lex(l);
370   while(TRUE) {
371     if(l->tok==TOK_NAME) {
372       name=CAlloc(sizeof CName);
373       StrCpy(name->name,l->str);
374       QueIns(name,m->temps.last);
375       Lex(l);
376     } else if(l->tok=='|') {
377       Lex(l);
378       break;
379     } else
380       LexExcept(l,"Go stupid and give me a fucking temporary name.");
381   }
382   while(l->tok) {
383     if(ast=ParseAst(l)) {
384       QueIns(ast,m->body.last);
385       while(l->tok=='.')
386         Lex(l);
387     } else
388       LexExcept(l,"Expected a niggerlicious statement.");
389   }
390   return m;
391 }
392 U0 DumpAst(CAST *s) {
393   CAST *cur,*head;
394 "$ID,2$";
395   switch(s->type) {
396     case AST_ARRAY:
397         "ARRAY\n";
398         head=&s->body;
399         for(cur=head->next;cur!=head;cur=cur->next)
400           DumpAst(cur);
401         break;
402     start:
403       case AST_RETURN:
404         "RETURN\n";
405         break;
406       case AST_CASCADE:
407         "CASCADE\n";
408         break;
409       case AST_UNOP:
410         "UNOP:%s\n",s->name;
411         break;
412       case AST_BINOP:
413         "BINOP:%s\n",s->name;
414         break;
415       case AST_KEYWORD:
416         "KW:%s\n",s->name;
417         break;
418       case AST_BLOCK:
419         "BLOCK\n";
420         break;
421       case AST_ASSIGN:
422         "_\n";
423         break;
424     end:
425       head=&s->args;
426       for(cur=head->next;cur!=head;cur=cur->next) {
427         DumpAst(cur);
428       }
429       if(s->type==AST_BLOCK) {
430         head=&s->body;
431         for(cur=head->next;cur!=head;cur=cur->next)
432           DumpAst(cur);
433       }
434       break;
435     case AST_SELF:
436       "SELF\n";
437       break;
438     case AST_SUPER:
439       "SUPER\n";
440       break;
441     case AST_STR:
442       "STR:\"%Q\"\n",s->str;
443       break;
444     case AST_VAR:
445       "VAR:%s\n",s->name;
446       break;
447     case AST_SYMBOL:
448       "SYM:%s\n",s->name;
449       break;
450     case AST_CHR:
451       "CHR:%s\n",s->name;
452       break;
453 //#define AST_CASCADE 8
454     case AST_NUM:
455       "NUM:%n\n",s->num;
456       break;
457   }
458 "$ID,-2$";
459 }
460 CLexer *l=LexerNew("123.4 + 456.789 +(3 + 4) add: 100 sqrt to: 1");
461 Lex(l);
462 DumpAst(ParseAst(l));
463 CLexer *l=LexerNew("^ (#Window new) + 2 ; open ; addButton: 'hi' ");
464 Lex(l);
465 DumpAst(ParseAst(l));
466 
467 CLexer *l=LexerNew("Method: a|b c|
468   a ifTrue: [ ^ 'poop' ] .
469   ^ a+b+s -self Method: super
470 ");
471 Lex(l);
472 CMethod *m=ParseMethod(l);
473 DumpAst(m->body.next);
474 DumpAst(m->body.last);