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.
int lval_read_sym(lval* v, char* s, int i) {
/* Allocate Empty String */
char* part = calloc(1,1);
/* While valid identifier characters */
while (strchr(
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789_+-*\\/=<>!&", s[i]) && s[i] != '\0') {
/* Append character to end of string */
part = realloc(part, strlen(part)+2);
part[strlen(part)+1] = '\0';
part[strlen(part)+0] = s[i];
i++;
}
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.
/* Check if Identifier looks like number */
int is_num = strchr("-0123456789", part[0]);
for (int i = 1; i < strlen(part); i++) {
if (!strchr("0123456789", part[i])) { is_num = 0; break; }
}
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.
/* Add Symbol or Number as lval */
if (is_num) {
errno = 0;
long x = strtol(part, NULL, 10);
lval_add(v, errno != ERANGE ? lval_num(x) : lval_err("Invalid Number %s", part));
} else {
lval_add(v, lval_sym(part));
}
/* Free temp string */
free(part);
/* Return updated position in input */
return i;
}
And we are done with reading symbols. Onto strings!