Reading Symbols


Reading in symbols is fairly straight forward. We start by allocating some empty string, and then, for each character in the input which is valid as part of a symbol we append this character to the string.

  1. int lval_read_sym(lval* v, char* s, int i) {
  2. /* Allocate Empty String */
  3. char* part = calloc(1,1);
  4. /* While valid identifier characters */
  5. while (strchr(
  6. "abcdefghijklmnopqrstuvwxyz"
  7. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  8. "0123456789_+-*\\/=<>!&", s[i]) && s[i] != '\0') {
  9. /* Append character to end of string */
  10. part = realloc(part, strlen(part)+2);
  11. part[strlen(part)+1] = '\0';
  12. part[strlen(part)+0] = s[i];
  13. i++;
  14. }

You’ll notice that we’re also reading in numbers with this code. So the next step is to check if this symbol is actually a number. To do this we just check if all of the characters are digits.

  1. /* Check if Identifier looks like number */
  2. int is_num = strchr("-0123456789", part[0]);
  3. for (int i = 1; i < strlen(part); i++) {
  4. if (!strchr("0123456789", part[i])) { is_num = 0; break; }
  5. }

Finally, if the symbol is a number we convert it with similar code to the previous code we used when we were reading from the mpc AST, or otherwise we just use it as a normal symbol. Then we free the temporary string we allocated and return the new position in the input.

  1. /* Add Symbol or Number as lval */
  2. if (is_num) {
  3. errno = 0;
  4. long x = strtol(part, NULL, 10);
  5. lval_add(v, errno != ERANGE ? lval_num(x) : lval_err("Invalid Number %s", part));
  6. } else {
  7. lval_add(v, lval_sym(part));
  8. }
  9. /* Free temp string */
  10. free(part);
  11. /* Return updated position in input */
  12. return i;
  13. }

And we are done with reading symbols. Onto strings!