我在过去的5天里了解了统一算法在Prolog中的工作原理。 现在,我想在Java中实现这样的算法..
我认为最好的方法是使用一些数据结构(如Stacks)操纵字符串并分解其部分。
说清楚:
假设用户输入为: a(X,c(d,X))= a(2,c(d,Y))。
我已将它作为一个字符串并将其拆分为两个字符串(Expression1和2)。 现在,我怎么知道下一个字符是变量还是常量等等。, 我可以通过嵌套来做到,但在我看来不是很好的解决方案.. 我试图使用继承但问题仍然存在(我怎么知道正在读取的字符类型?)
答案 0 :(得分:1)
首先,您需要解析输入并构建表达式树。然后应用Milner的统一算法(或其他一些统一算法)来计算变量到常量和表达式的映射。
可以在龙书中找到关于米尔纳算法的非常好的描述:Aho,Sethi和Ullman的“编译器:原理,技术和工具”。 (米尔纳斯算法也可以应对循环图的统一,而龙书则将其作为进行类型推断的一种方式)。通过它的声音,你可以从学习一些关于解析的东西中受益...这也被龙书所涵盖。
编辑:其他答案建议使用解析器生成器;例如ANTLR。这是一个很好的建议,但是(根据你的例子判断)你的语法非常简单,你也可以使用StringTokenizer和一个手写的递归下降解析器。事实上,如果你有时间(和倾向),那么有必要将解析器作为一种学习练习。
答案 1 :(得分:0)
听起来这个问题更多的是解析而不是统一。使用类似ANTLR之类的东西可能有助于将原始字符串转换为某种树形结构。
(你用“嵌套”来表达你的意思并不十分清楚,但是如果你的意思是你正在尝试阅读一个表达式,并且在遇到每个表达时再次出现“(”,那么这实际上就是正确的方法 - 这是ANTLR为您生成的代码的核心内容。)
如果你对统一事物的机制比解析更感兴趣,那么一个很好的方法是直接在代码中构造内部表示,并暂时解除解析方面。这在开发过程中会有点烦人,因为Prolog风格的语句现在是一组相当冗长的Java语句,但它可以让你一次只关注一个问题,这通常很有帮助。
(如果你用这种方式构造东西,这应该可以直接在以后插入一个合适的解析器,这将生成与你手工构建之前相同类型的树。这将让你分别攻击这两个问题以合理的方式。)
答案 2 :(得分:0)
在开始使用语言的语义之前,您必须将文本转换为易于操作的表单。此过程称为parsing,语义表示称为abstract syntax tree(AST)。
Prolog的简单递归下降解析器可能是手写的,但使用解析器工具包更常见,例如Rats!或Antlr
在Prolog的AST中,您可能有Term的类,CompoundTerm,Variable和Atom都是Term。多态性允许复合项的参数为任何Term。
然后,您的统一算法将统一任何复合词的名称,并递归地统一相应复合词的每个参数的值。