在 C 中标记 s-表达式
Tokenizing an s-expression in C
我正在尝试创建自己的 Lisp 解释器,并且 运行 遇到了一些与 s 表达式解析有关的问题。我最初的想法是将表达式标记化并一次处理一位。 I came across some code to do this 在我自己的尝试失败后,但是我对它的输出感到困惑。
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] == '[=10=]') {
*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
之前的数据?
简单的错字。
printf("%.*s\n", (int)(p - input), token);
应该是
printf("%.*s\n", (int)(p - token), token);
str
是输入参数,start
和 end
是输出参数。你可以让 start
成为 inout 论点,但并不是每个人都喜欢这些。
无论如何,返回的token都是从start
开始,长度是end - start
,这就是为什么printf的长度参数需要是p - token
.
我正在尝试创建自己的 Lisp 解释器,并且 运行 遇到了一些与 s 表达式解析有关的问题。我最初的想法是将表达式标记化并一次处理一位。 I came across some code to do this 在我自己的尝试失败后,但是我对它的输出感到困惑。
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] == '[=10=]') {
*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
之前的数据?
简单的错字。
printf("%.*s\n", (int)(p - input), token);
应该是
printf("%.*s\n", (int)(p - token), token);
str
是输入参数,start
和 end
是输出参数。你可以让 start
成为 inout 论点,但并不是每个人都喜欢这些。
无论如何,返回的token都是从start
开始,长度是end - start
,这就是为什么printf的长度参数需要是p - token
.