1

我正在尝试创建自己的 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绝对必要的吗?startend参数是否不够,因为之前不需要start数据?

4

1 回答 1

3

简单的错字。

 printf("%.*s\n", (int)(p - input), token);

应该

 printf("%.*s\n", (int)(p - token), token);

str是输入参数,startend是输出参数。你可以提出start一个 inout 论点,但不是每个人都喜欢这些。

在任何情况下,返回的令牌都从 开始,start它的长度是end - start,这就是为什么 printf 长度参数需要是p - token

于 2015-08-03T23:32:45.390 回答