1
2
3
4
5 import sys, copy, re, string
6
7 rules = []
8 trace = 0
9 indent = ""
10
12 sys.stdout.write ("Fatal: %s\n" % mesg)
13 sys.exit(1)
14
15 -def split (l, sep, All=1) :
16 "Split l by sep but honoring () and []"
17 nest = 0
18 lsep = len(sep)
19 if l == "" : return []
20 for i in range(len(l)) :
21 c = l[i]
22 if nest <= 0 and l[i:i+lsep] == sep :
23 if All : return [l[:i]]+split(l[i+lsep:],sep)
24 else : return [l[:i],l[i+lsep:]]
25 if c in ['[','('] : nest = nest+1
26 if c in [']',')'] : nest = nest-1
27 return [l]
28
29 -def isVariable(term) : return term.args == [] and term.pred[0:1] in string.uppercase
30 -def isConstant(term) : return term.args == [] and not term.pred[0:1] in string.uppercase
31
32 infixOps = ("*is*","==","<",">","+","--","*","/")
34 for op in infixOps:
35 p = split(s,op,All=0)
36 if len(p) > 1 : return (op,p)
37 return None
38
40
43 if not args : parts = splitInfix(s)
44 if args :
45 self.pred = s
46 self.args = args
47 elif parts :
48 self.args = map(makeTerm,parts[1])
49 self.pred = parts[0]
50 elif s[-1] == ']' :
51 flds = split(s[1:-1],",")
52 fld2 = split(s[1:-1],"|")
53 if len(fld2) > 1 :
54 self.args = map(makeTerm,fld2)
55 self.pred = '.'
56 else :
57 flds.reverse()
58 l = Term('.',[])
59 for fld in flds : l = Term('.',[Term(fld),l])
60 self.pred = l.pred; self.args = l.args
61 elif s[-1] == ')' :
62 flds = split(s,'(',All=0)
63 if len(flds) != 2 : fatal("Syntax error in term: %s" % [s])
64 self.args = map(makeTerm,split(flds[1][:-1],','))
65 self.pred = flds[0]
66 else :
67 self.pred = s
68 self.args = []
69
71 if self.pred == '.' :
72 if len(self.args) == 0 : return "[]"
73 nxt = self.args[1]
74 if nxt.pred == '.' and nxt.args == [] :
75 return "[%s]" % str(self.args[0])
76 elif nxt.pred == '.' :
77 return "[%s,%s]" % (str(self.args[0]),str(self.args[1])[1:-1])
78 else :
79 return "[%s|%s]" % (str(self.args[0]),str(self.args[1]))
80 elif self.args :
81 return "<%s(%s)>" % (self.pred,string.join(map(str,self.args),","))
82 else : return self.pred
83
85 s = re.sub("#.*","",sent[:-1])
86 s = re.sub(" is ","*is*",s)
87 s = re.sub(" ", "" ,s)
88 if s[-1] in ['?','.'] : punc=s[-1]; s=s[:-1]
89 else : punc='.'
90 if punc == '?' : return search(Term(s))
91 else :
92 rules.append(Rule(s))
93
94 return []
95
99
100
103 flds = string.split(s,":-")
104 self.head = Term(flds[0])
105 self.goals = []
106 if len(flds) == 2 :
107 flds = split(flds[1],",")
108 for fld in flds : self.goals.append(Term(fld))
109
111 return "<Rule: %s :- %s>" % (self.head, self.goals)
112
114 - def __init__ (self, rule, parent=None, env={}) :
115 self.rule = rule
116 self.parent = parent
117 self.env = copy.deepcopy(env)
118 self.inx = 0
119
121 return "<Goal:%s:%d:%s>" % (self.rule,self.inx,self.env)
122
124 for file in sys.argv[1:] :
125 if file == '.' : return
126 procFile(open(file),'')
127 procFile (sys.stdin,'? ')
128
130 global rules, trace
131 env = []
132 while 1 :
133 if prompt :
134 sys.stdout.write(prompt)
135 sys.stdout.flush()
136 sent = f.readline()
137 if sent == "" : break
138 s = re.sub("#.*","",sent[:-1])
139 s = re.sub(" is ","*is*",s)
140 s = re.sub(" ", "" ,s)
141 if s == "" : continue
142
143 if s[-1] in ['?','.'] : punc=s[-1]; s=s[:-1]
144 else : punc='.'
145
146 if s == 'trace' : trace = not trace
147 elif s == 'dump' :
148 for rule in rules : print rule
149 elif punc == '?' : search(Term(s))
150 else : rules.append(Rule(s))
151
152
153
154
155
156
157
158
159 -def unify (src, srcEnv, dest, destEnv) :
160 "update dest env from src. return true if unification succeeds"
161 global trace, indent
162 if trace : print indent, "Unify", src, srcEnv, "to", dest, destEnv
163 indent = indent+" "
164 if src.pred == '_' or dest.pred == '_' : return sts(1,"Wildcard")
165
166 if isVariable(src) :
167 srcVal = eval(src, srcEnv)
168 if not srcVal : return sts(1,"Src unset")
169 else : return sts(unify(srcVal,srcEnv,dest,destEnv), "Unify to Src Value")
170
171 if isVariable(dest) :
172 destVal = eval(dest, destEnv)
173 if destVal : return sts(unify(src,srcEnv,destVal,destEnv),"Unify to Dest value")
174 else :
175 destEnv[dest.pred] = eval(src,srcEnv)
176 return sts(1,"Dest updated 1")
177
178 elif src.pred != dest.pred : return sts(0,"Diff predicates")
179 elif len(src.args) != len(dest.args) : return sts(0,"Diff # args")
180 else :
181 dde = copy.deepcopy(destEnv)
182 for i in range(len(src.args)) :
183 if not unify(src.args[i],srcEnv,dest.args[i],dde) :
184 return sts(0,"Arg doesn't unify")
185 destEnv.update(dde)
186 return sts(1,"All args unify")
187
193
195 global trace
196 res = []
197
198 goal = Goal(Rule("all(done):-x(y)"))
199 goal.rule.goals = [term]
200 queue = [goal]
201 while queue :
202 c = queue.pop()
203 if trace : print "Deque", c
204 if c.inx >= len(c.rule.goals) :
205 if c.parent == None :
206 if c.env :
207 print c.env
208 res.append(c.env)
209 else : print "Yes"
210 continue
211 parent = copy.deepcopy(c.parent)
212 unify (c.rule.head, c.env,
213 parent.rule.goals[parent.inx],parent.env)
214 parent.inx = parent.inx+1
215 queue.insert(0,parent)
216 if trace : print "Requeuing", parent
217 continue
218
219
220 term = c.rule.goals[c.inx]
221
222 pred = term.pred
223 if pred in ['*is*', 'cut','fail', 'diff', '<','=='] :
224 if pred == '*is*' :
225 ques = eval(term.args[0],c.env)
226 ans = eval(term.args[1],c.env)
227 if ques == None :
228 c.env[term.args[0].pred] = ans
229 elif ques.pred != ans.pred :
230 continue
231 elif pred == 'diff' :
232 ques = eval(term.args[0],c.env)
233 ans = eval(term.args[1],c.env)
234 if ques.pred == ans.pred :
235 continue
236 elif pred == 'cut' : queue = []
237 elif pred == 'fail': continue
238 elif not eval(term,c.env) : continue
239 c.inx = c.inx + 1
240 queue.insert(0,c)
241 continue
242
243 for rule in rules :
244 if rule.head.pred != term.pred : continue
245 if len(rule.head.args) != len(term.args) : continue
246 child = Goal(rule, c)
247 ans = unify (term, c.env, rule.head, child.env)
248 if ans :
249 queue.insert(0,child)
250 if trace : print "Queuing", child
251 return res
252
256 -def lt (a,b) : return int(a.pred) < int(b.pred)
257 -def eq (a,b) : return int(a.pred) == int(b.pred)
258
262
263 operators = {'+': add, '--':sub, '*':mul, '<':lt}
264
265 -def eval (term, env) :
266 special = operators.get(term.pred)
267 if special :
268 return special(eval(term.args[0],env),eval(term.args[1],env))
269 if isConstant(term) : return term
270 if isVariable(term) :
271 ans = env.get(term.pred)
272 if not ans : return None
273 else : return eval(ans,env)
274 args = []
275 for arg in term.args :
276 a = eval(arg,env)
277 if not a : return None
278 args.append(a)
279 return Term(term.pred, args)
280
281 if __name__ == "__main__" : main()
282