【问题标题】:Tokenizing an s-expression in C在 C 中标记一个 s 表达式
【发布时间】:2015-10-26 05:02:03
【问题描述】:

我正在尝试创建自己的 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] == '\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);
}

Output:

(
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 之前没有数据是必需的?

【问题讨论】:

    标签: c parsing lisp tokenize s-expression


    【解决方案1】:

    简单的错字。

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

    应该是

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

    str 是输入参数,startend 是输出参数。您可以将 start 设为 inout 参数,但并不是每个人都喜欢这些。

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

    【讨论】:

    • 嗯,这太尴尬了……谢谢你发现。
    猜你喜欢
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-02
    • 2016-11-20
    • 2013-03-15
    • 1970-01-01
    相关资源
    最近更新 更多