字符串类型

当用户加载文件时,我们需要其提供一个由文件名组成的字符串。 我们的语言现在支持符号类型,但仍然不支持包含空格以及其他字符的字符串类型。 我们需要添加字符串类型的lval来指定我们所需的文件名。

像在其他章节中一样,我们通过在枚举中添加新条目并添加新的lval来表示字符串类型的数据。

  1. enum { LVAL_ERR, LVAL_NUM, LVAL_SYM, LVAL_STR,
  2. LVAL_FUN, LVAL_SEXPR, LVAL_QEXPR };
  1. /* Basic */
  2. long num;
  3. char* err;
  4. char* sym;
  5. char* str;

接下来我们添加字符串类型lval的构造函数,这与符号构造函数的实现方式非常相似。

  1. lval* lval_str(char* s) {
  2. lval* v = malloc(sizeof(lval));
  3. v->type = LVAL_STR;
  4. v->str = malloc(strlen(s) + 1);
  5. strcpy(v->str, s);
  6. return v;
  7. }

我们还需要将字符串类型lval添加到所有处理lval的函数中。

对于 删除

  1. case LVAL_STR: free(v->str); break;

对于 复制

  1. case LVAL_STR: x->str = malloc(strlen(v->str) + 1);
  2. strcpy(x->str, v->str); break;

对于 相等

  1. case LVAL_STR: return (strcmp(x->str, y->str) == 0);

对于 类型名

  1. case LVAL_STR: return "String";

在此,我们需要做一些额外工作来实现字符串打印函数。 Lispy内部存储字符串与所打印字符串有所区别。 我们希望在打印用户所输入的字符串时,会使用转义字符(如\n)来表示新行。

因此,我们需要在打印字符串之前将其转义。 幸运的是,我们可以使用mpc函数来为我们做这件事。 在打印函数中,我们添加以下内容…

  1. case LVAL_STR: lval_print_str(v); break;

以及…

  1. void lval_print_str(lval* v) {
  2. /* Make a Copy of the string */
  3. char* escaped = malloc(strlen(v->str)+1);
  4. strcpy(escaped, v->str);
  5. /* Pass it through the escape function */
  6. escaped = mpcf_escape(escaped);
  7. /* Print it between " characters */
  8. printf("\"%s\"", escaped);
  9. /* free the copied string */
  10. free(escaped);
  11. }