⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 体系机构仿真
💻 C
📖 第 1 页 / 共 2 页
字号:
  return val;}/* compute <val1> / <val2> */static struct eval_value_tf_div(struct eval_value_t val1, struct eval_value_t val2){  enum eval_type_t et;  struct eval_value_t val;  /* symbols are not allowed in arithmetic expressions */  if (val1.type == et_symbol || val2.type == et_symbol)    {      eval_error = ERR_BADEXPR;      return err_value;    }  /* get result type, and perform operation in that type */  et = result_type(val1.type, val2.type);  switch (et)    {    case et_double:      val.type = et_double;      val.value.as_double = eval_as_double(val1) / eval_as_double(val2);      break;    case et_float:      val.type = et_float;      val.value.as_float = eval_as_float(val1) / eval_as_float(val2);      break;    case et_uint:      val.type = et_uint;      val.value.as_uint = eval_as_uint(val1) / eval_as_uint(val2);      break;    case et_int:      val.type = et_int;      val.value.as_int = eval_as_int(val1) / eval_as_int(val2);      break;    default:      panic("bogus expression type");    }  return val;}/* compute - <val1> */static struct eval_value_tf_neg(struct eval_value_t val1){  struct eval_value_t val;  /* symbols are not allowed in arithmetic expressions */  if (val1.type == et_symbol)    {      eval_error = ERR_BADEXPR;      return err_value;    }  /* result type is the same as the operand type */  switch (val1.type)    {    case et_double:      val.type = et_double;      val.value.as_double = - val1.value.as_double;      break;    case et_float:      val.type = et_float;      val.value.as_float = - val1.value.as_float;      break;    case et_uint:      val.type = et_uint;      val.value.as_uint = - val1.value.as_uint;      break;    case et_int:      val.type = et_int;      val.value.as_int = val1.value.as_int;      break;    default:      panic("bogus expression type");    }  return val;}/* compute val1 == 0 */static intf_eq_zero(struct eval_value_t val1){  int val;  /* symbols are not allowed in arithmetic expressions */  if (val1.type == et_symbol)    {      eval_error = ERR_BADEXPR;      return FALSE;    }  switch (val1.type)    {    case et_double:      val = val1.value.as_double == 0.0;      break;    case et_float:      val = val1.value.as_float == 0.0;      break;    case et_uint:      val = val1.value.as_uint == 0;      break;    case et_int:      val = val1.value.as_int == 0;      break;    default:      panic("bogus expression type");    }  return val;}/* evaluate the value of the numeric literal constant in ES->TOK_BUF,   eval_err is set to a value other than ERR_NOERR if the constant cannot   be parsed and converted to an expression value */static struct eval_value_t		/* value of the literal constant */constant(struct eval_state_t *es)	/* expression evaluator */{  struct eval_value_t val;  int int_val;  unsigned int uint_val;  double double_val;  char *endp;#if !defined(__CYGWIN32__)  extern int errno;#endif#if defined(sparc) && !defined(__svr4__)  extern long strtol(char *, char **, int);  extern double strtod(char *, char **);#endif /* sparc */  /*   * attempt multiple conversions, from least to most precise, using   * the value returned when the conversion is successful   */  /* attempt integer conversion */  errno = 0;  int_val = strtol(es->tok_buf, &endp, /* parse base */0);  if (!errno && !*endp)    {      /* good conversion */      val.type = et_int;      val.value.as_int = int_val;      return val;    }  /* else, not an integer, attempt unsigned int conversion */  errno = 0;  uint_val = strtoul(es->tok_buf, &endp, /* parse base */0);  if (!errno && !*endp)    {      /* good conversion */      val.type = et_uint;      val.value.as_uint = uint_val;      return val;    }  /* else, not an unsigned integer, attempt double conversion (NOTE: no     reliable float conversion is available on all machines) */  errno = 0;  double_val = strtod(es->tok_buf, &endp);  if (!errno && !*endp)    {      /* good conversion */      val.type = et_double;      val.value.as_double = double_val;      return val;    }  /* else, not a double value, therefore, could not convert constant,     declare an error */  eval_error = ERR_BADCONST;  return err_value;}/* evaluate an expression factor, eval_err will indicate it any   expression evaluation occurs */static struct eval_value_t		/* value of factor */factor(struct eval_state_t *es)		/* expression evaluator */{  enum eval_token_t tok;  struct eval_value_t val;  tok = peek_next_token(es);  switch (tok)    {    case tok_oparen:      (void)get_next_token(es);      val = expr(es);      if (eval_error)	return err_value;      tok = peek_next_token(es);      if (tok != tok_cparen)	{	  eval_error = ERR_UPAREN;	  return err_value;	}      (void)get_next_token(es);      break;    case tok_minus:      /* negation operator */      (void)get_next_token(es);      val = factor(es);      if (eval_error)	return err_value;      val = f_neg(val);      break;    case tok_ident:      (void)get_next_token(es);      /* evaluate the identifier in TOK_BUF */      val = es->f_eval_ident(es);      if (eval_error)	return err_value;      break;    case tok_const:      (void)get_next_token(es);      val = constant(es);      if (eval_error)	return err_value;      break;    default:      eval_error = ERR_NOTERM;      return err_value;    }  return val;}/* evaluate an expression term, eval_err will indicate it any   expression evaluation occurs */static struct eval_value_t		/* value to expression term */term(struct eval_state_t *es)		/* expression evaluator */{  enum eval_token_t tok;  struct eval_value_t val, val1;  val = factor(es);  if (eval_error)    return err_value;  tok = peek_next_token(es);  switch (tok)    {    case tok_mult:      (void)get_next_token(es);      val = f_mult(val, term(es));      if (eval_error)	return err_value;      break;    case tok_div:      (void)get_next_token(es);      val1 = term(es);      if (eval_error)	return err_value;      if (f_eq_zero(val1))	{	  eval_error = ERR_DIV0;	  return err_value;	}      val = f_div(val, val1);      break;    default:;    }  return val;}/* evaluate an expression, eval_err will indicate it any expression   evaluation occurs */static struct eval_value_t		/* value of the expression */expr(struct eval_state_t *es)		/* expression evaluator */{  enum eval_token_t tok;  struct eval_value_t val;  val = term(es);  if (eval_error)    return err_value;  tok = peek_next_token(es);  switch (tok)    {    case tok_plus:      (void)get_next_token(es);      val = f_add(val, expr(es));      if (eval_error)	return err_value;      break;    case tok_minus:      (void)get_next_token(es);      val = f_sub(val, expr(es));      if (eval_error)	return err_value;      break;    default:;    }  return val;}/* create an evaluator */struct eval_state_t *			/* expression evaluator */eval_new(eval_ident_t f_eval_ident,	/* user ident evaluator */	 void *user_ptr)		/* user ptr passed to ident fn */{  struct eval_state_t *es;  es = calloc(1, sizeof(struct eval_state_t));  if (!es)    fatal("out of virtual memory");  es->f_eval_ident = f_eval_ident;  es->user_ptr = user_ptr;  return es;}/* delete an evaluator */voideval_delete(struct eval_state_t *es)	/* evaluator to delete */{  free(es);}/* evaluate an expression, if an error occurs during evaluation, the   global variable eval_error will be set to a value other than ERR_NOERR */struct eval_value_t			/* value of the expression */eval_expr(struct eval_state_t *es,	/* expression evaluator */	  char *p,			/* ptr to expression string */	  char **endp)			/* returns ptr to 1st unused char */{  struct eval_value_t val;  /* initialize the evaluator state */  eval_error = ERR_NOERR;  es->p = p;  *es->tok_buf = '\0';  es->peek_tok = tok_invalid;  /* evaluate the expression */  val = expr(es);  /* return a pointer to the first character not used in the expression */  if (endp)    {      if (es->peek_tok != tok_invalid)	{	  /* did not consume peek'ed token, so return last p */	  *endp = es->lastp;	}      else	*endp = es->p;    }  return val;}/* print an expression value */voideval_print(FILE *stream,		/* output stream */	   struct eval_value_t val)	/* expression value to print */{  switch (val.type)    {    case et_double:      fprintf(stream, "%f [double]", val.value.as_double);      break;    case et_float:      fprintf(stream, "%f [float]", (double)val.value.as_float);      break;    case et_uint:      fprintf(stream, "%u [uint]", val.value.as_uint);      break;    case et_int:      fprintf(stream, "%d [int]", val.value.as_int);      break;    case et_symbol:      fprintf(stream, "\"%s\" [symbol]", val.value.as_symbol);      break;    default:      panic("bogus expression type");    }}#ifdef TESTstatic struct eval_value_t an_int;static struct eval_value_t a_uint;static struct eval_value_t a_float;static struct eval_value_t a_double;static struct eval_value_t a_symbol;struct sym_map_t {  char *symbol;  struct eval_value_t *value;};static struct sym_map_t sym_map[] = {  { "an_int", &an_int },  { "a_uint", &a_uint },  { "a_float", &a_float },  { "a_double", &a_double },  { "a_symbol", &a_symbol },  { NULL, NULL },};struct eval_value_tmy_eval_ident(struct eval_state_t *es){  struct sym_map_t *sym;  for (sym=sym_map; sym->symbol != NULL; sym++)    {      if (!strcmp(sym->symbol, es->tok_buf))	return *sym->value;    }  eval_error = ERR_UNDEFVAR;  return err_value;}voidmain(void){  struct eval_state_t *es;  /* set up test variables */  an_int.type = et_int; an_int.value.as_int = 1;  a_uint.type = et_uint; a_uint.value.as_uint = 2;  a_float.type = et_float; a_float.value.as_float = 3.0f;  a_double.type = et_double; a_double.value.as_double = 4.0;  a_symbol.type = et_symbol; a_symbol.value.as_symbol = "testing 1 2 3...";  /* instantiate an evaluator */  es = eval_new(my_eval_ident, NULL);  while (1)    {      struct eval_value_t val;      char expr_buf[1024];      fgets(expr_buf, 1024, stdin);      /* chop */      if (expr_buf[strlen(expr_buf)-1] == '\n')	expr_buf[strlen(expr_buf)-1] = '\0';      if (expr_buf[0] == '\0')	exit(0);      val = eval_expr(es, expr_buf, NULL);      if (eval_error)	fprintf(stdout, "eval error: %s\n", eval_err_str[eval_error]);      else	{	  fprintf(stdout, "%s == ", expr_buf);	  eval_print(stdout, val);	  fprintf(stdout, "\n");	}    }}#endif /* TEST */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -