String Type


For the user to load a file we’ll have to let them supply a string consisting of the file name. Our language supports symbols, but still doesn’t support strings, which can include spaces and other characters. We need to add this possible lval type to specify the file names we need.

We start, as in other chapters, by adding an entry to our enum and adding an entry to our lval to represent the type’s data.

  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;

Next we can add a function for constructing string lval, very similar to how we construct constructing symbols.

  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. }

We also need to add the relevant entries into our functions that deal with lval.

For Deletion

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

For Copying

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

For Equality

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

For Type Name

  1. case LVAL_STR: return "String";

For Printing we need to do a little more. The string we store internally is different to the string we want to print. We want to print a string as a user might input it, using escape characters such as \n to represent a new line.

We therefore need to escape it before we print it. Luckily we can make use of a mpc function that will do this for us.

In the printing function we add the following…

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

Where…

  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. }