我发现了这个在prolog中解析lisp的好片段(来自here):

ws --> [W], { code_type(W, space) }, ws.
ws --> [].

parse(String, Expr) :- phrase(expressions(Expr), String).

expressions([E|Es]) -->
    ws, expression(E), ws,
    !, % single solution: longest input match
    expressions(Es).
expressions([]) --> [].

% A number N is represented as n(N), a symbol S as s(S).

expression(s(A))         --> symbol(Cs), { atom_codes(A, Cs) }.
expression(n(N))         --> number(Cs), { number_codes(N, Cs) }.
expression(List)         --> "(", expressions(List), ")".
expression([s(quote),Q]) --> "'", expression(Q).

number([D|Ds]) --> digit(D), number(Ds).
number([D])    --> digit(D).

digit(D) --> [D], { code_type(D, digit) }.

symbol([A|As]) -->
    [A],
    { memberchk(A, "+/-*><=") ; code_type(A, alpha) },
    symbolr(As).

symbolr([A|As]) -->
    [A],
    { memberchk(A, "+/-*><=") ; code_type(A, alnum) },
    symbolr(As).
symbolr([]) --> [].

但是表达式使用剪切我想这是为了提高效率是否可以编写此代码以使其在不进行剪切的情况下高效工作?
也会有兴趣的答案,涉及水星的软切/承诺的选择。

最佳答案

削减不是为了提高效率,而是为了致力于第一个解决方案(请参阅旁边的评论!)!/0:“单一解决方案:最长输入匹配”)。如果你评论出来!/0,例如:

?- parse("abc", E).
E = [s(abc)] ;
E = [s(ab), s(c)] ;
E = [s(a), s(bc)] ;
E = [s(a), s(b), s(c)] ;
false.

显然,在这种情况下,只需要第一种解决方案,即由构成令牌的最长字符序列组成。鉴于上面的例子,我不同意“false”:表达式//1是不明确的,因为数字//1和符号//1是不明确的在Mercury中,可以使用决定论声明cc_nondet来承诺解决方案(如果有的话)。

09-30 17:25