Prolog 序言错误:`character';应为,找到“”;()"';(一串)

Prolog 序言错误:`character';应为,找到“”;()"';(一串),prolog,dcg,Prolog,Dcg,我的目标是以括号表示法打印具有N个节点的所有形式的树,可以根据上下文无关语法定义如下: T→ 树是空的 T→ (T.T)具有左右子节点的节点 例如,具有3个节点的所有树将如下所示: () ()(()) ().() (.(.) ()(()) 我用Prolog编写了以下代码 form1(Prev, Next) :- string_concat("(", Prev, Inter), string_concat(Inter, ".)", Next). form2(Prev, Next

我的目标是以括号表示法打印具有N个节点的所有形式的树,可以根据上下文无关语法定义如下:

T→ 树是空的

T→ (T.T)具有左右子节点的节点

例如,具有3个节点的所有树将如下所示:

()

()(())

().()

(.(.)

()(())

我用Prolog编写了以下代码


form1(Prev, Next) :- 
    string_concat("(", Prev, Inter),
    string_concat(Inter, ".)", Next).
form2(Prev, Next) :- 
    string_concat("(.", Prev, Inter),
    string_concat(Inter, ")", Next).

tree(1, ["(.)"]) :- !.

tree(N, Strings) :-
    A is N - 1, tree(A, PrevStrings1),
    maplist(form1 , PrevStrings1, List1),
    maplist(form2 , PrevStrings1, List2),
    append(List1, List2, Result),
    Strings is Result.
但我得到了这个错误:

?- tree(2, L).
ERROR: Type error: `character' expected, found `"((.).)"' (a string)
ERROR: In:
ERROR:    [9] _3182 is ["((.).)","(.(.))"]
ERROR:    [7] <user>
?-树(2,L)。
错误:类型错误:应为'character',找到''(.)''(字符串)
错误:在:
错误:[9]_3182是[“()”,“()”]
错误:[7]

我的代码中没有引用字符。怎么了?

解决此类问题的最佳方法是首先从抽象表示开始。抽象表示所有语法细节都已删除。你真正想要的是以下形式的树

is_tree(empty).
is_tree(node(Left, Right)) :-
   is_tree(Left),
   is_tree(Right).
然后,基于此表示,您可以使用您最喜欢的语法钟声和口哨来定义一个具体表示

:- set_prolog_flag(double_quotes, chars).

tree(empty) --> "".
tree(node(Left, Right)) -->
   "(",
   tree(Left),
   ".",
   tree(Right),
   ")".

?- length(Text, N), phrase(tree(Tree), Text).
Text = [],
N = 0,
Tree = empty ;
Text = ['(','.',')'],
N = 3,
Tree = node(empty,empty) ;
Text = ['(','.','(','.',')',')'],
N = 6,
Tree = node(empty,node(empty,empty)) ;
Text = ['(','(','.',')','.',')'],
N = 6,
Tree = node(node(empty,empty),empty) ...
要提高答案的可读性,请使用[
库(双引号)
表示和

最后,您现在可以完全跳过抽象语法树,因此:

tree --> "".
tree --> "(", tree, ".", tree, ")".

?- length(Text, N), phrase(tree, Text).
Text = [],
N = 0;
Text = "(.)",
N = 3;
Text = "(.(.))",
N = 6;
Text = "((.).)",
N = 6;
Text = "(.(.(.)))",
N = 9;
Text = "(.((.).))",
N = 9 ...

乍一看,这种简洁的语法似乎更可取,但在许多情况下,它是非常不方便的。特别是,如果你正在设计一种新的语法,而你不确定你的语法是否包含歧义。在前一个版本的帮助下,证明这些事情是非常简单的。

当你你的意思是
=
is/2
严格用于算术计算,
=
用于统一。用
=
替换
is
会产生
错误:在本地堆栈外
反正你不需要那一行,只要将
树(N,字符串)
更改为
树(N,结果)
。堆栈溢出是不相关的;请使用
跟踪
对其进行调试。
tree --> "".
tree --> "(", tree, ".", tree, ")".

?- length(Text, N), phrase(tree, Text).
Text = [],
N = 0;
Text = "(.)",
N = 3;
Text = "(.(.))",
N = 6;
Text = "((.).)",
N = 6;
Text = "(.(.(.)))",
N = 9;
Text = "(.((.).))",
N = 9 ...