OSDN Git Service

wwww
[proj16/16.git] / 16 / v2 / source / VCC / LEXICAL.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 // ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
18 // ³                  The VergeC Compiler version 2.01                   ³\r
19 // ³              Copyright (C)1998 BJ Eirich (aka vecna)                ³\r
20 // ³                           Lexical Parser                            ³\r
21 // ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
22 \r
23 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r
24 // CHANGELOG:\r
25 // <aen, may 16>\r
26 // + ConvHexToDec() was severely screwed (would not return correct values at\r
27 //   *all*; own fault)--fixed\r
28 // <aen, may 14>\r
29 // + fixed some problems with tick mark parsing. didn't like certain chars.\r
30 // <aen, may 9>\r
31 // + fixed floating point exception crash in ConvHexToDec(), which occured\r
32 //   when using very large hex numbers (i think; like $ffffffff). was due to\r
33 //   use of pow()\r
34 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r
35 \r
36 #include <stdio.h>\r
37 #include <stdlib.h>\r
38 #include <string.h>\r
39 #include <math.h>\r
40 #include "compile.h"\r
41 #include "vcc.h"\r
42 #include "vccode.h"\r
43 \r
44 // ================================= Data ====================================\r
45 \r
46 // Character types\r
47 \r
48 #define LETTER 1\r
49 #define DIGIT 2\r
50 #define SPECIAL 3\r
51 \r
52 // ---------------\r
53 \r
54 char token[2000];                 // Token buffer\r
55 int token_nvalue;                 // int value of token if it's type DIGIT\r
56 char token_type;                  // type of current token.\r
57 char token_subtype;               // This is just crap.\r
58 unsigned char chr_table[256];              // Character type table.\r
59 \r
60 int lines, tlines;                // current line number being processed in\r
61 char *source_file;                // the current source file\r
62 \r
63 // ----------------\r
64 \r
65 char *hardfuncs[]=\r
66 {\r
67   // A\r
68   "exit",               "message",              "malloc",\r
69   "free",               "pow",                  "loadimage",\r
70   "copysprite",         "tcopysprite",          "render",\r
71   "showpage",           "entityspawn",          "setplayer",\r
72   "map",                "loadfont",             "playfli",\r
73 \r
74   // B\r
75   "gotoxy",             "printstring",          "loadraw",\r
76   "settile",            "allowconsole",         "scalesprite",\r
77   "processentities",    "updatecontrols",       "unpress",\r
78   "entitymove",         "hline",                "vline",\r
79   "line",               "circle",               "circlefill",   // 30\r
80 \r
81   // C\r
82   "rect",               "rectfill",             "strlen",\r
83   "strcmp",             "cd_stop",              "cd_play",\r
84   "fontwidth",          "fontheight",           "setpixel",\r
85   "getpixel",           "entityonscreen",       "random",\r
86   "gettile",            "hookretrace",          "hooktimer",\r
87 \r
88   // D\r
89   "setresolution",      "setrstring",           "setcliprect",\r
90   "setrenderdest",      "restorerendersettings","partymove",\r
91   "sin",                "cos",                  "tan",\r
92   "readmouse",          "setclip",              "setlucent",\r
93   "wrapblit",           "twrapblit",            "setmousepos",  // 60\r
94 \r
95   // E\r
96   "hookkey",            "playmusic",            "stopmusic",\r
97   "palettemorph",       "fopen",                "fclose",\r
98   "quickread",          "addfollower",          "killfollower",\r
99   "killallfollowers",   "resetfollowers",       "flatpoly",\r
100   "tmappoly",           "cachesound",           "freeallsounds",\r
101 \r
102   // F\r
103   "playsound",          "rotscale",             "mapline",\r
104   "tmapline",           "val",                  "tscalesprite",\r
105   "grabregion",         "log",                  "fseekline",\r
106   "fseekpos",           "fread",                "fgetbyte",\r
107   "fgetword",           "fgetquad",             "fgetline",     // 90\r
108 \r
109   // G\r
110   "fgettoken",          "fwritestring",         "fwrite",\r
111   "frename",            "fdelete",              "fwopen",\r
112   "fwclose",            "memcpy",               "memset",\r
113   "silhouette",         "initmosaictable",      "mosaic",\r
114   "writevars",          "readvars",             "callevent",    // 105\r
115 \r
116   // H\r
117   "asc",                "callscript",           "numforscript",\r
118   "filesize",           "ftell",                "checkcorrupt"\r
119  };\r
120 \r
121 char returntypes[]=\r
122 {\r
123   // A\r
124   0, 0, 1,\r
125   0, 1, 1,\r
126   0, 0, 0,\r
127   0, 1, 0,\r
128   0, 1, 0,\r
129 \r
130   // B\r
131   0, 0, 1,\r
132   0, 0, 0,\r
133   0, 0, 0,\r
134   0, 0, 0,\r
135   0, 0, 0,\r
136 \r
137   // C\r
138   0, 0, 1,\r
139   1, 0, 0,\r
140   1, 1, 0,\r
141   1, 1, 1,\r
142   1, 0, 0,\r
143 \r
144   // D\r
145   0, 0, 0,\r
146   0, 0, 0,\r
147   1, 1, 1,\r
148   0, 0, 0,\r
149   0, 0, 0,\r
150 \r
151   // E\r
152   0, 0, 0,\r
153   0, 1, 0,\r
154   0, 0, 0,\r
155   0, 0, 0,\r
156   0, 1, 0,\r
157 \r
158   // F\r
159   0, 0, 0,\r
160   0, 1, 0,\r
161   0, 0, 0,\r
162   0, 0, 1,\r
163   1, 1, 0,\r
164 \r
165   // G\r
166   0, 0, 0,\r
167   0, 0, 1,\r
168   0, 0, 0,\r
169   0, 1, 0,\r
170   0, 0, 0,\r
171 \r
172   // H\r
173   1, 0, 1,\r
174   1, 1, 0\r
175 };\r
176 \r
177 char *hardvar0[]=\r
178 {\r
179   "xwin",               "ywin",                 "cameratracking",\r
180   "timer",              "up",                   "down",\r
181   "left",               "right",                "b1",\r
182   "b2",                 "b3",                   "b4",\r
183   "screenx",            "screeny",              "player",       // 15\r
184 \r
185   "numentsonscreen",    "tracker",              "mx",\r
186   "my",                 "mb",                   "vctrace",\r
187   "image_width",        "image_height",         "music_volume", // 24\r
188   "vsp",                "lastent",              "last_pressed"\r
189 };\r
190 \r
191 char *hardvar1[]=\r
192 {\r
193   "screen",             "entity.x",             "entity.y",\r
194   "entity.tx",          "entity.ty",            "entity.facing",\r
195   "entity.moving",      "entity.specframe",     "entity.speed",\r
196   "entity.movecode",    "entsonscreen",         "key",\r
197   "layer.hline",        "byte",                 "word",         // 15\r
198 \r
199   "quad",               "pal",                  "sbyte",\r
200   "sword",              "squad"\r
201 };\r
202 \r
203 int funcidx      = 0;\r
204 int varcategory  = 0;\r
205 \r
206 int numhardfuncs = 111;\r
207 int numhardvar0  = 27;\r
208 int numhardvar1  = 20;\r
209 \r
210 // ================================= Code ====================================\r
211 \r
212 int streq(char *a, char *b)\r
213 {\r
214   while (*a)\r
215   {\r
216     if (*a++ != *b++)\r
217       return 0;\r
218   }\r
219   return (*b==0);\r
220 }\r
221 \r
222 char TokenIs(char *str)\r
223   { return streq(str,token); }\r
224 \r
225 void ParseWhitespace(void)\r
226 {\r
227   while (1)\r
228   {\r
229     while (*src<=' ' && *src>2)\r
230       if (!*src++)\r
231         return;\r
232 \r
233     if (src[0]=='/' && src[1]=='/')\r
234     {\r
235       while (*src && (*src != '\n'))\r
236         src++;\r
237       continue;\r
238     }\r
239 \r
240     if (src[0]=='/' && src[1]=='*')\r
241     {\r
242       while (!(src[0]=='*' && src[1]=='/'))\r
243       {\r
244         src++;\r
245         if (!*src)\r
246           return;\r
247         if (*src == 1)\r
248         {\r
249           src++;\r
250           source_file = src;\r
251           while (*src++);\r
252           tlines++;\r
253           continue;\r
254         }\r
255         if (*src==2)\r
256         {\r
257           src++;\r
258           lines = (int) *(int *)src;\r
259           src += 4;\r
260           continue;\r
261         }\r
262       }\r
263       src+=2;\r
264       continue;\r
265     }\r
266 \r
267     if (*src == 1)\r
268     {\r
269       src++;\r
270       source_file = src;\r
271       while (*src++);\r
272       continue;\r
273     }\r
274     if (*src==2)\r
275     {\r
276       src++;\r
277       lines = (int) *(int *)src;\r
278       src += 4;\r
279       tlines++;\r
280       continue;\r
281     }\r
282     break;\r
283   }\r
284 }\r
285 \r
286 int GetStringIdx(char i)\r
287 {\r
288   int j, k=0;\r
289 \r
290   for (j=0; j<i; j++)\r
291   {\r
292     if (funcs[c].argtype[j]==STRING) k++;\r
293  }\r
294  return k;\r
295 }\r
296 \r
297 void CheckLibFunc()\r
298 { int i;\r
299 \r
300   token_nvalue=0;\r
301   token_type=0;\r
302 \r
303   if (TokenIs("if") || TokenIs("else") || TokenIs("for") ||\r
304       TokenIs("while") || TokenIs("switch") || TokenIs("case") ||\r
305       TokenIs("goto"))\r
306   {\r
307     token_type=RESERVED;\r
308     return;\r
309   }\r
310   if (TokenIs("and"))\r
311   {\r
312      token_type=CONTROL;\r
313      token[0]='&'; token[1]='&'; token[2]=0;\r
314      return;\r
315   }\r
316   if (TokenIs("or"))\r
317   {\r
318      token_type=CONTROL;\r
319      token[0]='|'; token[1]='|'; token[2]=0;\r
320      return;\r
321   }\r
322   i=0;\r
323   while (i<numhardfuncs)\r
324   {\r
325     if (!strcmp(hardfuncs[i], token)) break;\r
326     i++;\r
327   }\r
328   if (i<numhardfuncs)\r
329   {\r
330     token_type=FUNCTION;\r
331     token_subtype=op_BFUNC;\r
332     funcidx=i;\r
333   }\r
334   i=0;\r
335   while (i<numhardvar0)\r
336   {\r
337     if (!strcmp(hardvar0[i], token)) break;\r
338     i++;\r
339   }\r
340   if (i<numhardvar0)\r
341   {\r
342     token_type=IDENTIFIER;\r
343     varcategory=op_HVAR0;\r
344     varidx=i;\r
345   }\r
346   i=0;\r
347   while (i<numhardvar1)\r
348   {\r
349     if (!strcmp(hardvar1[i], token)) break;\r
350     i++;\r
351   }\r
352   if (i<numhardvar1)\r
353   {\r
354     token_type=IDENTIFIER;\r
355     varcategory=op_HVAR1;\r
356     varidx=i;\r
357   }\r
358 \r
359   i=0;\r
360   while (i<numfuncs)\r
361   {\r
362     if (!strcmp(funcs[i].fname, token)) break;\r
363     i++;\r
364   }\r
365   if (i<numfuncs)\r
366   {\r
367     token_type=FUNCTION;\r
368     token_subtype=op_UFUNC;\r
369     funcidx=i;\r
370   }\r
371 \r
372   i=0;\r
373   while (i<numvars)\r
374   {\r
375     if (!strcmp(vars[i].vname, token)) break;\r
376     i++;\r
377   }\r
378   if (i<numvars)\r
379   {\r
380     token_type=IDENTIFIER;\r
381     varidx=i;\r
382     varcategory=op_UVAR;\r
383     if (vars[varidx].arraylen>1) varcategory=op_UVARRAY;\r
384   }\r
385   i=0;\r
386   while (i<funcs[c].numlocals)\r
387   {\r
388     if (!strcmp(larg[i], token)) break;\r
389     i++;\r
390   }\r
391   if (i<funcs[c].numlocals)\r
392   {\r
393     token_type=IDENTIFIER;\r
394     varidx=i;\r
395     switch (funcs[c].argtype[varidx])\r
396     {\r
397       case INT: varcategory=op_LVAR; break;\r
398       case STRING: varcategory=op_SLOCAL;\r
399                    varidx=GetStringIdx(varidx);\r
400                    break;\r
401       default: vcerr("um.");\r
402     }\r
403   }\r
404   i=0;\r
405   while (i<numstr)\r
406   {\r
407     if (!strcmp(str[i].vname, token)) break;\r
408     i++;\r
409   }\r
410   if (i<numstr)\r
411   {\r
412     token_type=IDENTIFIER;\r
413     varidx=i;\r
414     varcategory=op_STRING;\r
415     if (str[i].arraylen>1) varcategory=op_SARRAY;\r
416   }\r
417 }\r
418 \r
419 void GetIdentifier(void)\r
420 {\r
421   int i;\r
422 \r
423   i=0;\r
424   while ((chr_table[*src] == LETTER) || (chr_table[*src] == DIGIT))\r
425     token[i++] = *src++;\r
426   token[i]=0;\r
427   strlwr(token);\r
428   CheckLibFunc();\r
429 }\r
430 \r
431 void ConvHexToDec()\r
432 {\r
433   static const char *const hextbl="0123456789abcdef\0";\r
434   static int pow_lut[]={1,16,256,4096,65536,1048576,16777216,268435456};\r
435   int i=0, pos=0, z=0;\r
436   unsigned int j=0;\r
437 \r
438   if (strlen(token)>9)\r
439     vcerr("Hex number exceeds 8 digit maximum.");\r
440 \r
441   strlwr(token);\r
442   i=strlen(token)-1;\r
443   token_nvalue=0;\r
444   for (pos=0; i>0; pos++,i--)\r
445   {\r
446     z=token[i];\r
447     for (j=0; j<16; j++)\r
448       if (hextbl[j]==z) break;\r
449     if (j>=16)\r
450       vcerr("Invalid hex number.");\r
451     token_nvalue += (j * pow_lut[pos]);\r
452   }\r
453 }\r
454 \r
455 void DoTickMarks()\r
456 {\r
457   token_nvalue=token[1];\r
458 }\r
459 \r
460 void GetNumber()\r
461 {\r
462   int i;\r
463 \r
464   if ('\'' == *src)\r
465   {\r
466     token[0]=*src++;\r
467     token[1]=*src++;\r
468     token[2]=*src++;\r
469     token[3]=0;\r
470   }\r
471   else\r
472   {\r
473     i=0;\r
474     while (chr_table[*src] != SPECIAL)\r
475       token[i++]=*src++;\r
476     token[i]=0;\r
477   }\r
478   if (token[0]=='$') ConvHexToDec();\r
479   else if (token[0]=='\'') DoTickMarks();\r
480   else token_nvalue=atoi(token);\r
481 }\r
482 \r
483 void GetPunctuation()\r
484 { char c;\r
485 \r
486   c=*src;\r
487   switch (c)\r
488   {\r
489      case '(': token[0]='('; token[1]=0; src++; break;\r
490      case ')': token[0]=')'; token[1]=0; src++; break;\r
491      case '{': token[0]='{'; token[1]=0; src++; break;\r
492      case '}': token[0]='}'; token[1]=0; src++; break;\r
493      case '[': token[0]='['; token[1]=0; src++; break;\r
494      case ']': token[0]=']'; token[1]=0; src++; break;\r
495      case ',': token[0]=','; token[1]=0; src++; break;\r
496      case ':': token[0]=':'; token[1]=0; src++; break;\r
497      case ';': token[0]=';'; token[1]=0; src++; break;\r
498      case '/': token[0]='/'; token[1]=0; src++; break;\r
499      case '*': token[0]='*'; token[1]=0; src++; break;\r
500      case '^': token[0]='^'; token[1]=0; src++; break;\r
501      case '%': token[0]='%'; token[1]=0; src++; break;\r
502      case '\"': token[0]='\"'; token[1]=0; src++; break;\r
503      case '+' : token[0]='+';\r
504                 src++;\r
505                 if (*src=='+')\r
506                 { token[1]='+';\r
507                   src++; }\r
508                 else if (*src=='=')\r
509                 { token[1]='=';\r
510                   src++; }\r
511                 else token[1]=0;\r
512                 token[2]=0;\r
513                 break;\r
514      case '-' : token[0]='-';\r
515                 src++;\r
516                 if (*src=='-')\r
517                 { token[1]='-';\r
518                   src++; }\r
519                 else if (*src=='=')\r
520                 { token[1]='=';\r
521                   src++; }\r
522                 else token[1]=0;\r
523                 token[2]=0;\r
524                 break;\r
525      case '>' : token[0]='>';\r
526                 src++;\r
527                 if (*src=='=')\r
528                 { token[1]='=';\r
529                   token[2]=0;\r
530                   src++; break; }\r
531                 if (*src=='>')\r
532                 { token[1]='>';\r
533                   token[2]=0;\r
534                   src++; break; }\r
535                 token[1]=0;\r
536                 break;\r
537       case '<': token[0]='<';\r
538                 src++;\r
539                 if (*src=='=')\r
540                 { token[1]='=';\r
541                   token[2] = 0;\r
542                   src++; break; }\r
543                 if (*src=='<')\r
544                 { token[1]='<';\r
545                   token[2] = 0;\r
546                   src++; break; }\r
547                 token[1]=0;\r
548                 break;\r
549       case '!': token[0]='!';\r
550                 src++;\r
551                 if (*src=='=')\r
552                 { token[1]='=';\r
553                   token[2]=0;\r
554                   src++; break; }\r
555                 token[1]=0;\r
556                 break;\r
557       case '=': token[0]='=';\r
558                 src++;\r
559                 if (*src=='=')\r
560                 { token[1]=0;\r
561                   src++; }\r
562                 else token[1]=0;\r
563                 break;\r
564       case '&': token[0]='&';\r
565                 src++;\r
566                 if (*src=='&')\r
567                 { token[1]='&';\r
568                   token[2]=0;\r
569                   src++; break; }\r
570                 token[1]=0;\r
571                 break;\r
572       case '|': token[0]='|';\r
573                 src++;\r
574                 if (*src=='|')\r
575                 { token[1]='|';\r
576                   token[2]=0;\r
577                   src++; break; }\r
578                 token[1]=0;\r
579                 break;\r
580        default: src++;                   // This should be an error.\r
581   }\r
582 }\r
583 \r
584 void GetString(void)\r
585 {\r
586   int i;\r
587 \r
588   // Expects a "quoted" string. Places the contents of the string in\r
589   // token[] but does not include the quotes.\r
590 \r
591   Expect("\"");\r
592   i=0;\r
593   while (*src!='\"')\r
594   {\r
595     token[i++]=*src++;\r
596     if (i>250)\r
597       vcerr("String exceeds 250 character maximum.");\r
598   }\r
599   src++;\r
600   token[i]=0;\r
601 }\r
602 \r
603 void GetToken(void)\r
604 {\r
605   int i;\r
606 \r
607   // Simply reads in the next statement and places it in the\r
608   // token buffer.\r
609 \r
610   ParseWhitespace();\r
611   i=0;\r
612 \r
613   switch (chr_table[*src])\r
614   {\r
615     case  LETTER: { token_type = IDENTIFIER; GetIdentifier();  break; }\r
616     case   DIGIT: { token_type = DIGIT;      GetNumber();      break; }\r
617     case SPECIAL: { token_type = CONTROL;    GetPunctuation(); break; }\r
618   }\r
619 \r
620   if (!*src && inevent)\r
621     err("Unexpected end of file");\r
622 }\r
623 \r
624 void Expect(char *str)\r
625 {\r
626   GetToken();\r
627   if (TokenIs(str)) return;\r
628   vcerr("error: %s expected, %s got", str, token);\r
629 }\r
630 \r
631 int ExpectNumber()\r
632 {\r
633   GetToken();\r
634   if (token_type!=DIGIT) err("error: Numerical value expected");\r
635   return token_nvalue;\r
636 }\r
637 \r
638 void InitCompileSystem()\r
639 { int i;\r
640 \r
641   vprint("Building chr_table[].");\r
642   for (i=0; i<256; i++) chr_table[i]=SPECIAL;\r
643   for (i='0'; i<='9'; i++) chr_table[i]=DIGIT;\r
644   for (i='A'; i<='Z'; i++) chr_table[i]=LETTER;\r
645   for (i='a'; i<='z'; i++) chr_table[i]=LETTER;\r
646 \r
647   chr_table[10]=0;\r
648   chr_table[13]=0;\r
649   chr_table[' ']=0;\r
650   chr_table['_']=LETTER;\r
651   chr_table['.']=LETTER;\r
652   chr_table['$']=DIGIT;\r
653   chr_table[39]=DIGIT;\r
654 }\r
655 \r
656 char lasttoken[2048];\r
657 \r
658 int NextIs(char *str)\r
659 { char *ptr,tt,tst;\r
660   int i,nv;\r
661 \r
662   ptr=src;\r
663   tt=token_type;\r
664   tst=token_subtype;\r
665   nv=token_nvalue;\r
666   memcpy(lasttoken, token, 2048);\r
667   GetToken();\r
668   src=ptr;\r
669   token_nvalue=nv;\r
670   tst=token_subtype;\r
671   tt=token_type;\r
672   //if (!strcmp(str,token)) i=1; else i=0;\r
673   i=streq(str,token);\r
674   memcpy(token, lasttoken, 2048);\r
675   return i;\r
676 }\r