Exemple #1
0
static double eval_expr(const char *buf, int *pos) /* expr = term+expr | term-expr | term */
{
	double rv = 0.0, lhs, rhs;
	Token tok;
	
	DB(printf("-- eval_expr(\"%s\", &pos=%p pos=%d)\n", buf+*pos, pos, *pos));
	lhs = eval_term(buf, pos);
	if(G_eval_error)
		return rv;
	DB(printf("-- expr lhs=%f\n", lhs));
	tok = pull_token(buf, pos);
	if(G_eval_error)
		return rv;
	DB(printf("-- expr token type '%c' = ", tok.type));
	switch(tok.type)
	{
	case '\0':
		DB(printf("END OF BUFFER\n"));
		rv = lhs;
		break;
	case '+': /* addition */
		rhs = eval_expr(buf, pos);
		DB(printf("%f+%f", lhs, rhs));
		rv = lhs+rhs;
		DB(printf("=%f\n", rv));
		break;
	case '-': /* subtraction */
		rhs = eval_expr(buf, pos);
		DB(printf("%f-%f", lhs, rhs));
		rv = lhs-rhs;
		DB(printf("=%f\n", rv));
		break;
	case ')': /* end of group */
		DB(printf("end group"));
		push_token(tok);
		rv = lhs;
		DB(printf(" (rv=%f)\n", rv));
		break;
	case ',': /* argument delimiter */
		DB(printf("delimiter"));
		push_token(tok);
		rv = lhs;
		DB(printf(" (rv=%f)\n", rv));
		break;
	default:
		DB(printf("invalid expr token\n"));
		G_eval_error = EVAL_SYNTAX_ERROR;
		rv = lhs;
	}
	
	DB(printf("-- expr rv=%f\n", rv));
	return rv;
}
Exemple #2
0
static double eval_fact(const char *buf, int *pos) /* fact = item^fact | item */
{
	double rv = 0.0, lhs, rhs;
	Token tok;
	
	DB(printf("-- eval_fact(\"%s\", &pos=%p pos=%d)\n", buf+*pos, pos, *pos));
	lhs = eval_item(buf, pos);
	if(G_eval_error)
		return rv;
	DB(printf("-- fact lhs=%f\n", lhs));
	tok = pull_token(buf, pos);
	if(G_eval_error)
		return rv;
	DB(printf("-- fact token type '%c' = ", tok.type));
	switch(tok.type)
	{
	case '\0':
		DB(printf("END OF BUFFER\n"));
		rv = lhs;
		break;
	case '^': /* exponentiation */
		rhs = eval_fact(buf, pos);
		DB(printf("%f^%f", lhs, rhs));
		if(G_eval_error)
			return rv;
		rv = pow(lhs, rhs);
		DB(printf("=%f\n", rv));
		break;
	default:
		DB(printf("PUSHBACK\n"));
		push_token(tok);
		rv = lhs;
	}
	
	DB(printf("-- fact rv=%f\n", rv));
	return rv;
}
Exemple #3
0
static double eval_item(const char *buf, int *pos) /* item = -item | +item | int | var | (expr) */
{
	double rv = 0.0;
	void *data;
	int tlen, nargs, xargs;
	DB(int i);
	FunctionPtr fn;
	DB(char *fname);
	Token tok;
	
	DB(printf("-- eval_item(\"%s\", &pos=%p pos=%d)\n", buf+*pos, pos, *pos));
	tok = pull_token(buf, pos);
	if(G_eval_error)
		return rv;
	DB(printf("-- item token type '%c' = ", tok.type));
	switch(tok.type)
	{
	case '+': /* positive */
		DB(printf("positive\n"));
		rv = eval_fact(buf, pos);
		break;
	case '-': /* negative */
		DB(printf("negative\n"));
		rv = -eval_fact(buf, pos);
		break;
	case 'v': /* variable */
		DB(printf("variable name '%s'=%f\n", tok.str, tok.value));
		rv = tok.value;
		break;
	case 'f': /* function */
		DB(printf("function name '%s'=%p(%d)\n", tok.str, tok.fn, tok.args));
		tlen = tok.args;
		nargs = tok.args;
		xargs = nargs;
		data = tok.data;
		fn = tok.fn;
		DB(fname = tok.str);
		tok = pull_token(buf, pos);
		if(G_eval_error == 0)
		{
			if(tok.type != '(')
				G_eval_error = EVAL_SYNTAX_ERROR;
			else
			{
				double *targ = NULL;
				
				if(tlen > 0)
				{
					targ = (double*)lalloc(sizeof(double)*tlen);
					if(targ == NULL)
					{
						G_eval_error = EVAL_MEM_ERROR;
						break;
					}
				}else
					tlen = 0;
				if(eval_args(buf, pos, &nargs, &targ, &tlen, 0))
					break;
				DB(printf("-- item %d arguments\n", nargs));
				if(xargs < 0)
				{
					if(nargs < 1)
					{
						DB(printf("-- item too few arguments\n"));
						G_eval_error = EVAL_ARGS_ERROR;
						break;
					}
				}else if(nargs != xargs)
				{
					DB(printf("-- item bad argument count (%d) need %d\n",
						nargs, xargs));
					G_eval_error = EVAL_ARGS_ERROR;
					break;
				}
				tok = pull_token(buf, pos);
				if(tok.type != ')')
					G_eval_error = EVAL_SYNTAX_ERROR;
				else if(G_eval_error == 0)
				{
					DB(printf("-- call function [%p] with %d args [%p]\n",
						fn, nargs, targ));
					DB(printf("-- %s(%f", fname, targ[0]));
					DB(for(i=1;i<nargs;i++)printf(",%f",targ[i]));
					DB(printf(")\n"));
					if(fn(nargs, targ, &rv, data) != 0)
						G_eval_error = EVAL_FUNCTION_ERROR;
					DB(printf("-- rv = %f\n", rv));
				}
			}
		}
		break;
	case 'n': /* number */
		DB(printf("number value '%s'=%f\n", tok.str, tok.value));
		rv = tok.value;
		break;
	case '(':
		DB(printf("start grouping\n"));
		rv = eval_expr(buf, pos);
		tok = pull_token(buf, pos);
		if(tok.type != ')')
			G_eval_error = EVAL_SYNTAX_ERROR;
		break;
	default:
		DB(printf("PUSHBACK\n"));
		push_token(tok);
	}
Exemple #4
0
static double eval_term(const char *buf, int *pos) /* term = fact*term | fact/term | fact */
{
	double rv = 0.0, lhs, rhs;
	Token tok;
	
	DB(printf("-- eval_term(\"%s\", &pos=%p pos=%d)\n", buf+*pos, pos, *pos));
	lhs = eval_fact(buf, pos);
	if(G_eval_error)
		return rv;
	DB(printf("-- term lhs=%f\n", lhs));
	tok = pull_token(buf, pos);
	if(G_eval_error)
		return rv;
	DB(printf("-- term token type '%c' = ", tok.type));
	switch(tok.type)
	{
	case '\0':
		DB(printf("END OF BUFFER\n"));
		rv = lhs;
		break;
	case '*': /* multiplication */
		rhs = eval_term(buf, pos);
		DB(printf("%f*%f", lhs, rhs));
		rv = lhs*rhs;
		DB(printf("=%f\n", rv));
		break;
	case '/': /* division */
		rhs = eval_term(buf, pos);
		DB(printf("%f/%f", lhs, rhs));
		if(rhs == 0.0)
		{
			DB(printf(" DIVISION BY ZERO\n"));
			G_eval_error = EVAL_DIVIDE_BY_ZERO;
		}else
		{
			rv = lhs/rhs;
			DB(printf("=%f\n", rv));
		}
		break;
	case '\\': /* modulo division */
		rhs = eval_term(buf, pos);
		DB(printf("%f%%%f", lhs, rhs));
		if(rhs == 0.0)
		{
			DB(printf(" DIVISION BY ZERO\n"));
			G_eval_error = EVAL_DIVIDE_BY_ZERO;
		}else
		{
			rv = fmod(lhs, rhs);
			DB(printf("=%f\n", rv));
		}
		break;
	default:
		DB(printf("PUSHBACK\n"));
		push_token(tok);
		rv = lhs;
	}
	
	DB(printf("-- term rv=%f\n", rv));
	return rv;
}
Exemple #5
0
		DB(printf("number value '%s'=%f\n", tok.str, tok.value));
		rv = tok.value;
		break;
	case '(':
		DB(printf("start grouping\n"));
		rv = eval_expr(buf, pos);
		tok = pull_token(buf, pos);
		if(tok.type != ')')
			G_eval_error = EVAL_SYNTAX_ERROR;
		break;
	default:
		DB(printf("PUSHBACK\n"));
		push_token(tok);
	}
	
	tok = pull_token(buf, pos);
	while(tok.type == '%')
	{
		rv = rv/100.0;
		tok = pull_token(buf, pos);
	}
	if(tok.type != '\0')
		push_token(tok);
	
	DB(printf("-- item rv=%f\n", rv));
	return rv;
}

static int eval_args(const char *buf, int *pos, int *args, double **arg,
	int *arglen, int argpos) /* args = expr,args | expr | */
{
Exemple #6
0
/**
 * Parse the query which has been set up.
 * \param	state	Parser state we already setup with QueryParserStart
 * \return	0 on success, error codes otherwise.
 */
int
QueryParserRun(struct parser_state *state, BOOL strict_quotes)
{
	char *token;
	struct expression *current_expression = state->start;
	
	while (pull_token(&(state->query_ptr), &token) != -1) {
		if (current_expression < state->start) {
			// ran off the top of our stack, but there were still tokens
			DEBUG_MESSAGE("ERR: tokens remaining in data\n");
			return -1;
		}
		if (QueryParser_IsOp(token) == 0) {
			if (current_expression->op != NULL) {
				// check this operator will allow sub-expressions
				// TODO - this isn't quite right yet.
				//if (QueryParser_CanSubExp(current_expression->op) == 0) {
				//	DEBUG_MESSAGE("ERR: Cannot accept subexpression at this point\n");
				//	return -1;
				//}
				
				// need to find a free expr slot
				struct expression *next_expression = ++(state->last);
				
				// check we're not off the end of the array
				if (state->last > (state->start + state->entries)) {
					DEBUG_MESSAGE("ERR: ran off end of array\n");
					return -1;
				}
				
				// link the current expression to the new one
				if (current_expression->exp1 == NULL) {
					current_expression->exp1 = next_expression;
				} else if (current_expression->exp2 == NULL) {
					current_expression->exp2 = next_expression;
				} else {
					// bad expression with three args or something
					DEBUG_MESSAGE("ERR: Too many args\n");
					return -1;
				}
				// advance to the new expression
				current_expression = next_expression;
			}
			current_expression->op = token;
		} else {
			// find the next last expression with free slots
			if (rewind_expression(&current_expression, state->start)) {
				DEBUG_MESSAGE("ERR: ran off the start of the array\n");
				return -1;
			}
			if (current_expression->op == NULL) {
				// we can't set parameters before we have an operator...
				DEBUG_MESSAGE("ERR: parameters received before operator\n");
				return -1;
			}
			int type = 0;
			if (token[0] == '\'') {
				// could be a string
				if (QueryParser_IsString(token) == 0) type = 2;
			} else if (QueryParser_IsNumber(token) == 0) {
				// is a number
				type = 3;
			} else if (QueryParser_IsProperty(token) == 0) {
				type = 1;
			}
			if ((strict_quotes == TRUE) && (type == 0)) {
				DEBUG_MESSAGE("ERR: Token not correctly quoted\n");
				return -1;
			}
			if (current_expression->exp1 == NULL) {
				current_expression->exp1 = token;
				current_expression->exp1_const = 1;
				current_expression->exp1_type = type;
			} else if (current_expression->exp2 == NULL) {
				current_expression->exp2 = token;
				current_expression->exp2_const = 1;
				current_expression->exp2_type = type;
				
				// ignore errors here, since when we fill the last slot
				// we pop off top of the stack. That's not an error if 
				// there are no more tokens (see check at top of loop)
				rewind_expression(&current_expression, state->start);
			}
		}
	}
	
	if (current_expression >= state->start) {
		// we didn't fill all our slots...
		DEBUG_MESSAGE("ERR: not enough parameters received\n");
		return -1;
	}
	
	return 0;
}