我正在尝试创建自己的 Lisp 解释器,但在解析 s 表达式时遇到了一些问题。我最初的想法是标记表达式并一次处理一个位。在我自己的尝试失败后,我遇到了一些代码来执行此操作,但是我对它的输出感到困惑。
int lex(const char *str, const char **start, const char **end)
{
const char *ws = " \t\r\n";
const char *delim = "() \t\r\n";
const char *prefix = "()'`";
str += strspn(str, ws);
if (str[0] == '\0') {
*start = *end = NULL;
return 1;
}
*start = str;
if (strchr(prefix, str[0]) != NULL)
*end = *start + 1;
else
*end = *start + strcspn(str, delim);
return 0;
}
用法:
const char *input = "(foo bar 17 '(a b c) 2)";
char *token;
char *p = input;
lex(p, &token, &p);
while(token != NULL)
{
printf("%.*s\n", (int)(p - input), token);
lex(p, &token, &p);
}
(
foo
bar 17 '
17 '(a b c)
'(a b c) 2)
(a b c) 2)
a b c) 2)
b c) 2)
c) 2)
) 2)
2)
)
看着代码,我已经预料到它,例如,输出17
和非17 '(a b c)
或输出2
和非2)
。是什么原因造成的,我该如何解决?如果在这种情况下标记化不是最佳解决方案,我也愿意接受建议。
第二点,像这样的参数是str
绝对必要的吗?start
和end
参数是否不够,因为之前不需要start
数据?