|  |  | @ -34,17 +34,20 @@ void add_history(char* unused) {} | 
			
		
	
		
			
				
					|  |  |  | /* Declare new lval struct */ | 
			
		
	
		
			
				
					|  |  |  | typedef struct { | 
			
		
	
		
			
				
					|  |  |  | int type; | 
			
		
	
		
			
				
					|  |  |  | long num; | 
			
		
	
		
			
				
					|  |  |  | union { | 
			
		
	
		
			
				
					|  |  |  | long num; | 
			
		
	
		
			
				
					|  |  |  | double dec; | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  | int err; | 
			
		
	
		
			
				
					|  |  |  | } lval; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /* Create enumeration of possible lval types */ | 
			
		
	
		
			
				
					|  |  |  | enum {LVAL_NUM, LVAL_ERR}; | 
			
		
	
		
			
				
					|  |  |  | enum lval_types {LVAL_NUM, LVAL_DEC, LVAL_ERR}; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /* Create enumeration of possible error types */ | 
			
		
	
		
			
				
					|  |  |  | enum {LERR_DIV_ZERO, LERR_BAD_OP, LERR_BAD_NUM}; | 
			
		
	
		
			
				
					|  |  |  | enum lval_errors {LERR_DIV_ZERO, LERR_BAD_OP, LERR_BAD_NUM}; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /* Create a new number of type lval */ | 
			
		
	
	
		
			
				
					|  |  | @ -56,6 +59,15 @@ lval lval_num(long x) { | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /* Create a new decimal of type lval */ | 
			
		
	
		
			
				
					|  |  |  | lval lval_dec(double x) { | 
			
		
	
		
			
				
					|  |  |  | lval v; | 
			
		
	
		
			
				
					|  |  |  | v.type = LVAL_DEC; | 
			
		
	
		
			
				
					|  |  |  | v.dec = x; | 
			
		
	
		
			
				
					|  |  |  | return v; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /* Create a new error type lval */ | 
			
		
	
		
			
				
					|  |  |  | lval lval_err(int x) { | 
			
		
	
		
			
				
					|  |  |  | lval v; | 
			
		
	
	
		
			
				
					|  |  | @ -73,6 +85,11 @@ void lval_print(lval v) { | 
			
		
	
		
			
				
					|  |  |  | case LVAL_NUM: | 
			
		
	
		
			
				
					|  |  |  | printf("%li", v.num); | 
			
		
	
		
			
				
					|  |  |  | break; | 
			
		
	
		
			
				
					|  |  |  | /* In the case the type is a decimal print it | 
			
		
	
		
			
				
					|  |  |  | Then break out of the switch */ | 
			
		
	
		
			
				
					|  |  |  | case LVAL_DEC: | 
			
		
	
		
			
				
					|  |  |  | printf("%.2f", v.dec); | 
			
		
	
		
			
				
					|  |  |  | break; | 
			
		
	
		
			
				
					|  |  |  | /* In the case the type is an error */ | 
			
		
	
		
			
				
					|  |  |  | case LVAL_ERR: | 
			
		
	
		
			
				
					|  |  |  | /* Check what type of error it is & print it */ | 
			
		
	
	
		
			
				
					|  |  | @ -127,19 +144,37 @@ lval eval_op(lval x, char* op, lval y) { | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /* Otherwise do maths on the number values */ | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "+") == 0) {return lval_num(x.num + y.num);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "-") == 0) {return lval_num(x.num - y.num);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "*") == 0) {return lval_num(x.num * y.num);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "/") == 0) { | 
			
		
	
		
			
				
					|  |  |  | /* If second operand is zero return error */ | 
			
		
	
		
			
				
					|  |  |  | return y.num == 0 ? lval_err(LERR_DIV_ZERO) | 
			
		
	
		
			
				
					|  |  |  | : lval_num(x.num / y.num); | 
			
		
	
		
			
				
					|  |  |  | if (x.type == LVAL_NUM && y.type == LVAL_NUM) { | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "+") == 0) {return lval_num(x.num + y.num);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "-") == 0) {return lval_num(x.num - y.num);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "*") == 0) {return lval_num(x.num * y.num);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "/") == 0) { | 
			
		
	
		
			
				
					|  |  |  | /* If second operand is zero return error */ | 
			
		
	
		
			
				
					|  |  |  | return y.num == 0 ? lval_err(LERR_DIV_ZERO) | 
			
		
	
		
			
				
					|  |  |  | : lval_num(x.num / y.num); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "%") == 0) {return lval_num(x.num % y.num);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "^") == 0) {return lval_num(pow(x.num, y.num));} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "min") == 0) {return lval_num(min(x.num, y.num));} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "max") == 0) {return lval_num(max(x.num, y.num));} | 
			
		
	
		
			
				
					|  |  |  | } else { | 
			
		
	
		
			
				
					|  |  |  | /* Cast integer number into double if necessary */ | 
			
		
	
		
			
				
					|  |  |  | double a = x.type == LVAL_NUM ? (double) x.num : x.dec; | 
			
		
	
		
			
				
					|  |  |  | double b = y.type == LVAL_NUM ? (double) y.num : y.dec; | 
			
		
	
		
			
				
					|  |  |  | /* Perform all operations on double */ | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "+") == 0) {return lval_dec(a + b);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "-") == 0) {return lval_dec(a - b);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "*") == 0) {return lval_dec(a * b);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "/") == 0) { | 
			
		
	
		
			
				
					|  |  |  | /* If second operand is zero return error */ | 
			
		
	
		
			
				
					|  |  |  | return b == 0 ? lval_err(LERR_DIV_ZERO) | 
			
		
	
		
			
				
					|  |  |  | : lval_dec(a / b); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "%") == 0) {return lval_dec(fmod(a, b));} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "^") == 0) {return lval_dec(pow(a, b));} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "min") == 0) {return lval_dec(fmin(a, b));} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "max") == 0) {return lval_dec(fmax(a, b));} | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "%") == 0) {return lval_num(x.num % y.num);} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "^") == 0) {return lval_num(pow(x.num, y.num));} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "min") == 0) {return lval_num(min(x.num, y.num));} | 
			
		
	
		
			
				
					|  |  |  | if (strcmp(op, "max") == 0) {return lval_num(max(x.num, y.num));} | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | return lval_err(LERR_BAD_OP); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
	
		
			
				
					|  |  | @ -150,8 +185,14 @@ lval eval(mpc_ast_t* t) { | 
			
		
	
		
			
				
					|  |  |  | if (strstr(t->tag, "number")) { | 
			
		
	
		
			
				
					|  |  |  | /* Check if there is some error in conversion */ | 
			
		
	
		
			
				
					|  |  |  | errno = 0; | 
			
		
	
		
			
				
					|  |  |  | long x = strtol(t->contents, NULL, 10); | 
			
		
	
		
			
				
					|  |  |  | return errno != ERANGE ? lval_num(x) : lval_err(LERR_BAD_NUM); | 
			
		
	
		
			
				
					|  |  |  | /* Check for decimal or integer number */ | 
			
		
	
		
			
				
					|  |  |  | if (strstr(t->contents, ".")) { | 
			
		
	
		
			
				
					|  |  |  | double x = strtof(t->contents, NULL); | 
			
		
	
		
			
				
					|  |  |  | return errno != ERANGE ? lval_dec(x) : lval_err(LERR_BAD_NUM); | 
			
		
	
		
			
				
					|  |  |  | } else { | 
			
		
	
		
			
				
					|  |  |  | long x = strtol(t->contents, NULL, 10); | 
			
		
	
		
			
				
					|  |  |  | return errno != ERANGE ? lval_num(x) : lval_err(LERR_BAD_NUM); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /* The operator is always second child */ | 
			
		
	
	
		
			
				
					|  |  | @ -182,7 +223,7 @@ int main(int argc, char const *argv[]) { | 
			
		
	
		
			
				
					|  |  |  | /* Define them with the following language */ | 
			
		
	
		
			
				
					|  |  |  | mpca_lang(MPCA_LANG_DEFAULT, | 
			
		
	
		
			
				
					|  |  |  | "                                                       \ | 
			
		
	
		
			
				
					|  |  |  | number   : /-?[0-9]+/ ;                             \ | 
			
		
	
		
			
				
					|  |  |  | number   : /-?[0-9]+([.][0-9]*|[0-9]*)/ ;           \ | 
			
		
	
		
			
				
					|  |  |  | operator : '+' | '-' | '*' | '/' | '%' | '^' |      \ | 
			
		
	
		
			
				
					|  |  |  | \"min\" | \"max\" ;                                 \ | 
			
		
	
		
			
				
					|  |  |  | expr     : <number> | '(' <operator> <expr>+ ')' ;  \ | 
			
		
	
	
		
			
				
					|  |  | 
 |