Parsing 解析器DCG不具有确定性是否合适?
我正在为查询引擎编写一个解析器。我的解析器DCGParsing 解析器DCG不具有确定性是否合适?,parsing,prolog,logic,dcg,deterministic,Parsing,Prolog,Logic,Dcg,Deterministic,我正在为查询引擎编写一个解析器。我的解析器DCGquery不是确定性的 我将以关系方式使用解析器,检查和合成查询 解析器DCG不具有确定性是否合适 代码: 如果我希望能够同时使用query/2,它需要这样做吗 ?- phrase(query, [q,u,e,r,y]). true; false. 或者我应该能够获得 ?- phrase(query, [q,u,e,r,y]). true. 尽管如此,考虑到第一个片段需要我这样使用它 ?- bagof(X, phrase(query, [q,u
query
不是确定性的
我将以关系方式使用解析器,检查和合成查询
解析器DCG不具有确定性是否合适
代码:
如果我希望能够同时使用query/2,它需要这样做吗
?- phrase(query, [q,u,e,r,y]).
true;
false.
或者我应该能够获得
?- phrase(query, [q,u,e,r,y]).
true.
尽管如此,考虑到第一个片段需要我这样使用它
?- bagof(X, phrase(query, [q,u,e,r,y]), [true]).
true.
当用它来检查公式时?首先要问你自己的问题是,你的语法是确定性的,还是用语法的术语。这不是问你的DCG是否确定,而是问语法是否明确。这可以用基本的解析概念来回答,不需要使用DCG来回答这个问题。换句话说,只有一种方法可以解析有效的输入。这方面的标准书籍是“编译器:原理、技术和工具”() 现在您实际上在询问解析的三种不同用途
下面是一个语法非常简单的示例 语法只是一个中缀二进制表达式,包含一个运算符和两个可能的操作数。运算符为(+),操作数为(1)或(2) 语法是明确的,只有4个唯一的有效字符串 识别器是确定性的,只返回true或false。
解析器是确定性的,并返回唯一的AST。
生成器是半确定性的,返回所有4个有效的唯一字符串 测试用例的示例运行
?- run_tests.
% PL-Unit: expr ........... done
% All 11 tests passed
true.
对Daniel的评论进行一点扩展 正如丹尼尔所指出的
1 + 2 + 3
可以解析为
(1 + 2) + 3
或
因此,1+2+3
就是一个例子,正如您所说,是由递归DCG指定的,正如我所指出的,解决问题的一个常见方法是使用括号来启动新上下文。开始一个新的上下文的意思是,它就像让一个新的上下文重新开始一样。如果要创建AST,只需将新上下文(括号之间的项)作为新子树放在当前节点上
对于,这也很有帮助,但要注意操作符的左关联性和右关联性。看
e、 g
+
是左关联的
?- write_canonical(1+2+3).
+(+(1,2),3)
true.
?- write_canonical(2^3^4).
^(2,^(3,4))
true.
^
是右关联的
?- write_canonical(1+2+3).
+(+(1,2),3)
true.
?- write_canonical(2^3^4).
^(2,^(3,4))
true.
i、 e
添加这些信息的目的是警告你,语法设计充满了隐藏的陷阱,如果你没有一门严格的课程,并且做了一些,你可以很容易地创建一个看起来很好、效果很好的语法,然后几年后发现有严重的问题。虽然Python在AFAIK中并不含糊,但它确实存在语法问题,在创建Python3时,已经解决了很多问题。因此,Python3与Python2()不向后兼容。是的,他们已经做了一些更改和库,使Python 2代码更容易与Python 3一起使用,但关键是语法在设计时可以使用更多的分析。代码应该是非确定性的唯一原因是您的问题有多个答案。在这种情况下,您当然希望查询具有多个解决方案。然而,即使如此,如果可能的话,您也希望它在最后一个解决方案之后留下一个选择点
我的意思是:
“两个数字中较小的是什么?”
这是不错的代码,但我认为它仍然是垃圾。这就是为什么,对于两个数字中较小的一个,您会使用以下内容
类似地,假设你想问,“1到10之间的偶数是多少”;您可以编写查询:
?- between(1, 10, X), X rem 2 =:= 0.
X = 2 ;
X = 4 ;
X = 6 ;
X = 8 ;
X = 10.
。。。这很好,但是如果你要的是3的倍数,你会得到:
?- between(1, 10, X), X rem 3 =:= 0.
X = 3 ;
X = 6 ;
X = 9 ;
false. % crap...
“低挂果实”是指作为程序员,您会发现不可能存在非确定性,但由于某种原因,您的Prolog无法从您编写的代码中推断出非确定性。在大多数情况下,你可以做点什么
关于你的实际问题。如果可以,请编写代码,以便只有当您要问的问题有多个答案时,才会出现非确定性。当您使用DCG进行解析和生成时,这有时意味着您将得到两条代码路径。这感觉很笨拙,但它更容易书写、阅读、理解,而且可能更有效率。作为警告,请看一看。我不能确定这一点,但OP遇到的问题几乎肯定是由不必要的非决定论造成的。对于较大的输入,可能会出现以下情况:大量的选择点被留下,大量的内存无法回收,大量的处理时间用于簿记,巨大的解决方案树被遍历,结果(如预期)没有得到任何解决方案。。。。你明白了
对于我的意思的例子,你可以看看。注意几件事:
- 文档非常明确地说明了什么是确定性的,什么不是确定性的,以及非确定性对客户机代码的用处李>
- 在必要时使用削减,以消除无用的选择点李>
- 代码的实现
?- min_a(1, 2, Min).
Min = 1.
?- min_a(2, 1, Min).
Min = 1 ; % crap...
false.
?- min_a(2, 1, 2).
false.
?- min_a(2, 1, 1).
true ; % crap...
false.
?- between(1, 10, X), X rem 2 =:= 0.
X = 2 ;
X = 4 ;
X = 6 ;
X = 8 ;
X = 10.
?- between(1, 10, X), X rem 3 =:= 0.
X = 3 ;
X = 6 ;
X = 9 ;
false. % crap...