tisp

tiny lisp
git clone git://edryd.org/tisp
Log | Files | Refs | LICENSE

commit 53ffeea163e349956099cdcdd4a32ff411f38a3a
parent 0639965a3936a29ec2d99a40c68bb0b0856cd589
Author: Ed van Bruggen <edvb@uw.edu>
Date:   Mon,  1 Apr 2019 18:34:44 -0700

Support implicit creation of improper lists

Diffstat:
tisp.c | 52++++++++++++++++++++++++++++++++++------------------
1 file changed, 34 insertions(+), 18 deletions(-)

diff --git a/tisp.c b/tisp.c @@ -130,6 +130,13 @@ isnum(char *str) ((*str == '-' || *str == '+') && (isdigit(str[1]) || str[1] == '.')); } +/* check if character is a symbol delimiter */ +static char +isdelim(int c) +{ + return isspace(c) || c == '(' || c == ')' || c == '"' || c == ';'; +} + /* skip over comments and white space */ void skip_ws(Str str) @@ -564,27 +571,34 @@ read_sym(Env env, Str str) return mk_sym(env, sym); } -/* return read string containing list */ +/* return read string containing a list */ static Val -read_list(Env env, Str str) +read_pair(Env env, Str str) { - int n = 0; - Val *a = emalloc(sizeof(Val)), b; - str->d++; + Val a, b; skip_ws(str); - while (*str->d != ')') { - if (!str->d[1]) - tsp_warn("reached end before closing ')'"); - a = erealloc(a, (n+1) * sizeof(Val)); /* TODO realloc less */ - if (!(a[n++] = tisp_read(env, str))) - return NULL; + if (*str->d == ')') { + str->d++; skip_ws(str); + return env->nil; } - b = mk_list(env, n, a); - free(a); - str->d++; + if (!(a = tisp_read(env, str))) + return NULL; skip_ws(str); - return b; + if (*str->d == '.' && isdelim(str->d[1])) { + str->d++; + if (!(b = tisp_read(env, str))) + return NULL; + skip_ws(str); + if (*str->d != ')') + tsp_warn("did not find closing ')'"); + str->d++; + skip_ws(str); + } else { + if (!(b = read_pair(env, str))) + return NULL; + } + return mk_pair(a, b); } /* reads given string returning its tisp value */ @@ -604,9 +618,11 @@ tisp_read(Env env, Str str) } if (issym(*str->d)) return read_sym(env, str); - if (*str->d == '(') - return read_list(env, str); - tsp_warn("could not read given input"); + if (*str->d == '(') { + str->d++; + return read_pair(env, str); + } + tsp_warnf("could not read given input '%s'", str->d); } /* return string containing contents of file name */