Beispiel #1
0
static Value* parseToken(const char** expr, parser_cb* cb) {
	Value* ret;
	
	char* token = nextToken(expr);
	if(token == NULL) {
		return ValErr(badChar(**expr));
	}
	
	trimSpaces(expr);
	if(**expr == '(') {
		(*expr)++;
		ArgList* arglist = ArgList_parse(expr, ',', ')', cb);
		if(arglist == NULL) {
			/* Parse error occurred and has already been raised */
			free(token);
			return ValErr(ignoreError());
		}
		
		ret = ValCall(FuncCall_create(token, arglist));
	}
	else {
		ret = ValVar(token);
	}
	
	free(token);
	return ret;
}
Beispiel #2
0
Value* Expression_eval(Expression* expr, Context* ctx) {
	Value* ret;
	Variable* var = expr->var;
	
	if(var->type == VAR_VALUE) {
		/* Evaluate right side */
		ret = Value_eval(var->val, ctx);
		
		/* If an error occurred, bail */
		if(ret->type == VAL_ERR)
			return ret;
		
		/* Variable assignment? */
		if(ret->type == VAL_VAR) {
			/* This means ret must be a function */
			Variable* func = Variable_get(ctx, ret->name);
			if(func == NULL) {
				Value* err = ValErr(varNotFound(ret->name));
				Value_free(ret);
				return err;
			}
			
			if(func->type == VAR_BUILTIN) {
				Value_free(ret);
				return ValErr(typeError("Cannot assign a variable to a builtin value."));
			}
			
			if(var->name != NULL) {
				Context_setGlobal(ctx, var->name, Variable_copy(func));
			}
		}
		else {
			/* This means ret must be a Value */
			Value_free(var->val);
			var->val = Value_copy(ret);
			
			/* Update ans */
			Context_setGlobal(ctx, "ans", Variable_copy(var));
			
			/* Save the newly evaluated variable */
			if(var->name != NULL)
				Context_setGlobal(ctx, var->name, Variable_copy(var));
		}
	}
	else if(var->type == VAR_FUNC) {
		ret = ValVar(var->name);
		Context_setGlobal(ctx, var->name, Variable_copy(var));
	}
	else {
		badVarType(var->type);
	}
	
	return ret;
}
Beispiel #3
0
Value* Value_copy(const Value* val) {
	Value* ret;
	
	switch(val->type) {
		case VAL_INT:
			ret = ValInt(val->ival);
			break;
		
		case VAL_REAL:
			ret = ValReal(val->rval);
			break;
		
		case VAL_FRAC:
			ret = ValFrac(Fraction_copy(val->frac));
			break;
		
		case VAL_EXPR:
			ret = ValExpr(BinOp_copy(val->expr));
			break;
		
		case VAL_CALL:
			ret = ValCall(FuncCall_copy(val->call));
			break;
		
		case VAL_UNARY:
			ret = ValUnary(UnOp_copy(val->term));
			break;
		
		case VAL_VAR:
			ret = ValVar(val->name);
			break;
		
		case VAL_VEC:
			ret = ValVec(Vector_copy(val->vec));
			break;
		
		case VAL_NEG:
			/* Shouldn't be reached, but so easy to code */
			ret = ValNeg();
			break;
		
		case VAL_ERR:
			ret = ValErr(Error_copy(val->err));
			break;
		
		default:
			typeError("Unknown value type: %d.", val->type);
			ret = NULL;
			break;
	}
	
	return ret;
}
Beispiel #4
0
Expression* Expression_parse(const char** expr) {
	Expression* ret = NULL;
	Variable* var;
	Value* val;
	
	const char* equals = strchr(*expr, '=');
	
	if(equals == NULL) {
		/* No assignment, just a plain expression. */
		return parseExpr(expr);
	}
	
	/* There is an assignment */
	/* First, parse the right side of the assignment */
	equals++;
	val = Value_parse(&equals, 0, 0);
	
	if(val->type == VAL_ERR) {
		/* A parse error occurred */
		var = VarErr(Error_copy(val->err));
		Value_free(val);
		return Expression_new(var);
	}
	
	if(val->type == VAL_END) {
		/* Empty input */
		Value_free(val);
		var = VarErr(earlyEnd());
		return Expression_new(var);
	}
	
	/* Now parse the left side */
	char* name = nextToken(expr);
	if(name == NULL) {
		Value_free(val);
		var = VarErr(syntaxError("No variable to assign to."));
		return Expression_new(var);
	}
	
	trimSpaces(expr);
	
	if(**expr == '(') {
		/* Defining a function */
		(*expr)++;
		
		/* Array of argument names */
		unsigned size = 2;
		char** args = fmalloc(size * sizeof(*args));
		unsigned len = 0;
		
		/* Add each argument name to the array */
		char* arg = nextToken(expr);
		
		if(arg == NULL && **expr != ')') {
			/* Invalid character */
			Value_free(val);
			free(args);
			free(name);
			
			var = VarErr(badChar(**expr));
			return Expression_new(var);
		}
		
		trimSpaces(expr);
		
		if(arg == NULL) {
			/* Empty parameter list means function with no args */
			free(args);
			args = NULL;
			len = 0;
		}
		else {
			/* Loop through each argument in the list */
			while(**expr == ',' || **expr == ')') {
				args[len++] = arg;
				
				if(**expr == ')')
					break;
				
				(*expr)++;
				
				/* Expand argument array if it's too small */
				if(len >= size) {
					size *= 2;
					args = frealloc(args, size * sizeof(*args));
				}
				
				arg = nextToken(expr);
				if(arg == NULL) {
					/* Invalid character */
					Value_free(val);
					free(name);
					/* Free argument names and return */
					unsigned i;
					for(i = 0; i < len; i++) {
						free(args[i]);
					}
					free(args);
					
					var = VarErr(badChar(**expr));
					return Expression_new(var);
				}
				
				trimSpaces(expr);
			}
		}
		
		if(**expr != ')') {
			/* Invalid character inside argument name list */
			Value_free(val);
			free(name);
			
			/* Free argument names and return */
			unsigned i;
			for(i = 0; i < len; i++) {
				free(args[i]);
			}
			free(args);
			
			var = VarErr(badChar(**expr));
			return Expression_new(var);
		}
		
		/* Skip closing parenthesis */
		(*expr)++;
		trimSpaces(expr);
		
		if(**expr != '=') {
			Value_free(val);
			free(name);
			
			unsigned i;
			for(i = 0; i < len; i++) {
				free(args[i]);
			}
			free(args);
			
			var = VarErr(badChar(**expr));
			return Expression_new(var);
		}
		
		/* Construct function and return it */
		Function* func = Function_new(len, args, val);
		var = VarFunc(name, func);
		free(name);
		
		ret = Expression_new(var);
	}
	else {
		/* Defining a variable */
		if(**expr != '=') {
			/* In-place manipulation */
			BINTYPE bin = BinOp_nextType(expr, 0, 0);
			
			/* Still not an equals sign means invalid character */
			if(**expr != '=') {
				Value_free(val);
				free(name);
				
				var = VarErr(badChar(**expr));
				return Expression_new(var);
			}
			
			val = ValExpr(BinOp_new(bin, ValVar(name), val));
		}
		
		var = VarValue(name, val);
		free(name);
		
		ret = Expression_new(var);
	}
	
	return ret;
}