school

thing1's amazing school repo
Log | Files | Refs | Submodules | README

comp.c (11251B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <stdbool.h>
      5 #include <signal.h>
      6 #include <unistd.h>
      7 
      8 #include "tokenizer.h"
      9 #include "util.h"
     10 #include "appendsnprintf.h"
     11 
     12 #define MAXOUTLEN 512
     13 
     14 // globals for memory management
     15 char *tofree[256];
     16 int freeptr = 0;
     17 bool neededmemptr = false;
     18 
     19 // globals for structs
     20 char *structname;
     21 
     22 // globals for errors
     23 pid_t pid;
     24 int linecount = 0;
     25 char *currentLine;
     26 char *errmsg;
     27 
     28 //# error handler that will be triggered by signal when there is a syntax error and will print information
     29 void errorhandle(int type){
     30 	fprintf(stderr, "err:%d (%s)\n", linecount, currentLine);
     31 	fprintf(stderr, "%s\n", errmsg); 
     32 
     33 	exit(1);
     34 }
     35 
     36 //# this function will check if the value given is null, if it is, it will cause a sig segv and set the error msg
     37 static void checkNULL(void *value, char *msg){
     38 	if (value == NULL) {
     39 		errmsg = msg;
     40 		kill(pid, SIGSEGV);
     41 	}
     42 }
     43 
     44 char *names[] = {
     45 	"defun", // takes a func name, func return type, and args // 0
     46 	"endfun", // takes no args // 1
     47 	"let", // takes a name and type, then a value (immutable) // 2
     48 	"set", // same as above but mutable values // 3
     49 	"if", // takes a condition // 4
     50 	"endif", // takes no args  // 5
     51 	"elif", // same as if, but only executes if the prev statment didnt // 6
     52 	"else", // its else! // 7
     53 	"for", // takes a iterator and type, a start point, a condition, and an increment // 8
     54 	"endfor", // takes no args // 9
     55 	"symbol", // takes a name and return type and args // 10
     56 	// arithmetic
     57 	"+", // 11
     58 	"-", // 12
     59 	"*", // 13
     60 	"/", // 14
     61 	// comparison
     62 	"=", // 15
     63 	"!=", // 16
     64 	"<", // 17
     65 	">", // 18
     66 	"<=", // 19
     67 	">=", // 20
     68 
     69 	"exit", // takes an int // 21
     70 	"return", // takes an int // 22
     71 	
     72 	"alloc", // takes a size and allocates a block of it // 23
     73 	
     74 	"struct", // takes a name for the struct // 24
     75 	"endstruct", // takes nothing // 25
     76 	
     77 	"def", // takes a name and type does not asign // 26
     78 	
     79 	"sizeof", // takes a datatype and returns its size // 27
     80 	
     81 	"defunptr" // takes the same stuff as defun but outputs it in fuction ptr form 
     82 };
     83 
     84 // function prototype for recursion of the compile function
     85 static char *compile(astNode *node);
     86 
     87 //# this function will convert the zpy style variable defintion, to the c style
     88 static char *vartypeToC(char *str, char *out){
     89 	char *name = malloc(strlen(str));
     90 	char *type = malloc(strlen(str));
     91 	
     92 	int j = 0, i = 0;
     93 
     94 	for (; i < strlen(str); i++){
     95 		if (str[i] == ':'){
     96 			break;
     97 		}
     98 		name[i] = str[i];
     99 	}
    100 	name[i] = '\0';
    101 	i++;
    102 	
    103 	if (i > strlen(str)) checkNULL(NULL, "expected var type, got nothing");
    104 
    105 	for (; i < strlen(str); i++){
    106 		if (str[i] == ':'){
    107 			break;
    108 		}
    109 		type[j] = str[i];
    110 		j++;
    111 	}
    112 	type[j] = '\0';
    113 
    114 	char *outbuf = calloc(0, 64);
    115 	outbuf = appendsnprintf(outbuf, MAXOUTLEN, "%s %s", type, name);
    116 	out = appendsnprintf(out, MAXOUTLEN, "%s", outbuf);
    117 	free(type);
    118 	free(name);
    119 	return out;
    120 }
    121 
    122 //# this function will give the user the variable name, without its type, which is useful for translation
    123 static char *getVarName(char *exp){
    124 	char *out = malloc(strlen(exp));
    125 	memcpy(out, exp, strlen(exp));
    126 	char *pos = strchr(out, ':');
    127 	if (pos == NULL) checkNULL(NULL, "expected var type, got nothing");
    128 	pos[0] = '\0';
    129 	return out;
    130 }
    131 
    132 //# this function will give the user the type, without its name, which is useful for translation
    133 static char *getVarType(char *exp){
    134 	char *out = malloc(strlen(exp));
    135 	char *pos = strchr(exp, ':')+1;
    136 	if (pos == NULL) checkNULL(NULL, "expected var type, got nothing");
    137 	memcpy(out, pos, strlen(pos) + 1);
    138 	return out;
    139 }
    140 //# this will convert mathmatical expressions, to the c style of maths
    141 static char *reversepolishToC(astNode *exp, char *out){
    142 	out = appendsnprintf(out, MAXOUTLEN, "%s ", exp->args[0]);
    143 	if (exp->func[0] == '=') out = appendsnprintf(out, MAXOUTLEN, "==");
    144 	else out = appendsnprintf(out, MAXOUTLEN, "%s", exp->func);
    145 	out = appendsnprintf(out, MAXOUTLEN, " %s", exp->args[1]);
    146 	return out;
    147 }
    148 
    149 //# this is a recursive loop that will call the compile function recursivly to flatten the tree
    150 static astNode *processChildren(astNode *node){
    151 	for (int i = 0; i < 8; i++){
    152 		if (node->children[i] != NULL){
    153 			node->args[i] = compile(node->children[i]);
    154 			node->children[i] = NULL;
    155 		}
    156 	}
    157 	return node;
    158 }
    159 
    160 //# this function will do the bulk of converting from zpy into c code
    161 static char *compile(astNode *node){
    162 	char *out = calloc(0, MAXOUTLEN);
    163 	node = processChildren(node);
    164 	if (strcmp(names[0], node->func) == 0){ // converting function definitions
    165 		checkNULL(node->args[0], "expected func name");
    166 		checkNULL(node->args[1], "expected return type");
    167 		out = appendsnprintf(out, MAXOUTLEN, "%s %s(", node->args[1], node->args[0]);
    168 		int i = 2;
    169 		while (node->args[i] != NULL){
    170 			if (i != 2) out = appendsnprintf(out, MAXOUTLEN, ",");
    171 			out = vartypeToC(node->args[i], out);
    172 			i++;
    173 		}
    174 		out = appendsnprintf(out, MAXOUTLEN, "){\n");
    175 	}
    176 	else if (strcmp(names[1], node->func) == 0){ // converting ending function definitions
    177 		out = appendsnprintf(out, MAXOUTLEN, "}\n");
    178 	}
    179 	else if (strcmp(names[2], node->func) == 0){ // converting variable declarations
    180 		checkNULL(node->args[0], "expected var name");
    181 		checkNULL(node->args[1], "expected var value");
    182 		out = vartypeToC(node->args[0], out);
    183 		out = appendsnprintf(out, MAXOUTLEN, " = %s;\n", node->args[1]);
    184 	}
    185 	else if (strcmp(names[3], node->func) == 0){ // converting vairable reasignments
    186 		checkNULL(node->args[0], "expected var name");
    187 		checkNULL(node->args[1], "expected var value");
    188 		out = appendsnprintf(out, MAXOUTLEN, "%s = %s;\n", node->args[0], node->args[1]);
    189 	}
    190 	else if (strcmp(names[4], node->func) == 0){ // converting if statments
    191 		checkNULL(node->args[0], "expected sub expression");
    192 		out = appendsnprintf(out, MAXOUTLEN, "if (%s", node->args[0]);
    193 		out = appendsnprintf(out, MAXOUTLEN, "){\n");
    194 	}
    195 	else if (strcmp(names[5], node->func) == 0){ // converting ending if statments 
    196 		out = appendsnprintf(out, MAXOUTLEN, "}\n");
    197 	}
    198 	else if (strcmp(names[6], node->func) == 0){ // converting elif (else if) statments 
    199 		checkNULL(node->args[0], "expected sub expression");
    200 		out = appendsnprintf(out, MAXOUTLEN, "}else if (%s", node->args[0]);
    201 		out = appendsnprintf(out, MAXOUTLEN, "){\n");
    202 	}
    203 	else if (strcmp(names[7], node->func) == 0){ // converting else statments
    204 		out = appendsnprintf(out, MAXOUTLEN, "}\n");
    205 		out = appendsnprintf(out, MAXOUTLEN, "else{");
    206 	} 
    207 	else if (strcmp(names[8], node->func) == 0){ // converting for loop statments
    208 		checkNULL(node->args[0], "expected iterator");
    209 		checkNULL(node->args[1], "expected iterator value");
    210 		checkNULL(node->args[2], "expected condition");
    211 		checkNULL(node->args[3], "expected iterator increment");
    212 		out = appendsnprintf(out, MAXOUTLEN, "for (");
    213 		out = vartypeToC(node->args[0], out);
    214 		out = appendsnprintf(out, MAXOUTLEN, " = %s;", node->args[1]);
    215 		out = appendsnprintf(out, MAXOUTLEN, "%s", node->args[2]);
    216 		out = appendsnprintf(out, MAXOUTLEN, "; %s+=%s){", getVarName(node->args[0]), node->args[3]);
    217 	} 
    218 	else if (strcmp(names[9], node->func) == 0){ // converting end for loop statments
    219 		out = appendsnprintf(out, MAXOUTLEN, "}\n");
    220 	}
    221 	else if (strcmp(names[10], node->func) == 0){ // converting symbol definition statments
    222 		checkNULL(node->args[0], "expected symbol type");
    223 		checkNULL(node->args[1], "expected symbol name");
    224 		out = appendsnprintf(out, MAXOUTLEN, "%s %s(", node->args[1], node->args[0]);
    225 		int i = 2;
    226 		while (node->args[i] != NULL){
    227 			if (i != 2) out = appendsnprintf(out, MAXOUTLEN, ",", node->args[i]);
    228 			out = vartypeToC(node->args[i], out);
    229 			i++;
    230 		}
    231 		out = appendsnprintf(out, MAXOUTLEN, ");\n");
    232 	}
    233 	else if (strcmp(names[21], node->func) == 0){ //converting exit statments
    234 		checkNULL(node->args[0], "expected exit code");
    235 		out = appendsnprintf(out, MAXOUTLEN, "exit(%s);\n", node->args[0]);
    236 	}	
    237 	else if (strcmp(names[22], node->func) == 0){
    238 		for (int i = 0; i < 256; i++){
    239 			if (tofree[i] != NULL){
    240 				out = appendsnprintf(out, MAXOUTLEN, "free(%s);\n", tofree[i]);
    241 			} else{
    242 				for (int j = 0; j < 256; j++){
    243 					tofree[j] = NULL;
    244 				}
    245 				freeptr = 0;
    246 				break;
    247 			}
    248 		}
    249 		checkNULL(node->args[0], "expected return value"); // converting return statments
    250 		out = appendsnprintf(out, MAXOUTLEN, "return %s;\n", node->args[0]);
    251 	}	
    252 	else if (strcmp(names[23], node->func) == 0){ // converting memory allocation statments
    253 		checkNULL(node->args[0], "expected alloc size");
    254 		out = appendsnprintf(out, MAXOUTLEN, "malloc(%s)", node->args[0]);
    255 		neededmemptr = true;
    256 	}	
    257 	else if (strcmp(names[24], node->func) == 0){ // converting struct definiton statments
    258 		checkNULL(node->args[0], "expected type name");
    259 		out = appendsnprintf(out, MAXOUTLEN, "typedef struct %s %s;\n", node->args[0], node->args[0]);
    260 		out = appendsnprintf(out, MAXOUTLEN, "typedef struct %s {", node->args[0]);
    261 		structname = node->args[0];
    262 	}	
    263 	else if (strcmp(names[25], node->func) == 0){ // converting struct end statments
    264 		out = appendsnprintf(out, MAXOUTLEN, "} %s", structname);
    265 		structname = NULL;
    266 	}	
    267 	else if (strcmp(names[26], node->func) == 0){ // converting variable definition statments 
    268 		checkNULL(node->args[0], "expected variable definition");
    269 		out = vartypeToC(node->args[0], out);
    270 	}	
    271 	else if (strcmp(names[27], node->func) == 0){ // converting sizeof statments
    272 		checkNULL(node->args[0], "expected variable type");
    273 		out = appendsnprintf(out, MAXOUTLEN, "sizeof(%s)", node->args[0]); 
    274 	}
    275 	else if (strcmp(names[28], node->func) == 0){ // converting function pointer definition staments
    276 		checkNULL(node->args[0], "expected function ptr type");
    277 		checkNULL(node->args[0], "expected function ptr name");
    278 		out = appendsnprintf(out, MAXOUTLEN, "%s (*%s)", node->args[1], node->args[0]);
    279 		int i = 2;
    280 		while (node->args[i] != NULL){
    281 			if (i != 2) out = appendsnprintf(out, MAXOUTLEN, ",");
    282 			else out = appendsnprintf(out, MAXOUTLEN, "(");
    283 			out = appendsnprintf(out, MAXOUTLEN, "%s", getVarType(node->args[i]));
    284 			i++;
    285 		}
    286 		out = appendsnprintf(out, MAXOUTLEN, ")");
    287 	}
    288 	
    289 	else { 
    290 		// arithmetic operators and comparitors
    291 		for (int i = 0; i < 9; i++){
    292 			checkNULL(node->func, "expected func name");
    293 			if (strcmp(names[11+i], node->func) == 0){
    294 				out = reversepolishToC(node, out);
    295 				goto end;
    296 			}
    297 		}
    298 
    299 		// converting user defined function calls	
    300 		checkNULL(node->func, "expected func name"); 
    301 		out = appendsnprintf(out, MAXOUTLEN, "%s(", node->func);
    302 		int i = 0;
    303 		while (node->args[i] != NULL){
    304 			if (i != 0) out = appendsnprintf(out, MAXOUTLEN, ",", node->args[i]);
    305 			out = appendsnprintf(out, MAXOUTLEN, "%s", node->args[i]);
    306 			i++;
    307 		}
    308 		out = appendsnprintf(out, MAXOUTLEN, ")");
    309 	}	
    310 end:
    311 	return out;
    312 }
    313 
    314 //# this function sets up the signal handler for the error msgs
    315 void CompilerInit(){
    316 	signal(SIGSEGV, &errorhandle);
    317 	pid = getpid();
    318 }
    319 
    320 //# the exposed compiler function that will fully process an astNode tree
    321 void Compile(astNode *line, FILE *f, char* strline){
    322 	currentLine = strline;
    323 	char *code = compile(line);
    324 	if (neededmemptr == true){
    325 		tofree[freeptr] = line->args[0];
    326 		freeptr++;
    327 		neededmemptr = false;
    328 	}
    329 	int len = strlen(code);
    330 	if (code[len-2] == ';' || code[len-2] == '{' || code[len-2] == '}')  fprintf(f, "%s", code);
    331 	else fprintf(f, "%s;\n", code);
    332 	linecount++;
    333 	free(code);
    334 }