1 | |
2 | /* prolog.c: a simple Prolog interpreter written in C++, */ |
3 | /* including an example test run as main(). */ |
4 | /* Copyright (c) Alan Mycroft, University of Cambridge, 2000. */ |
5 | |
6 | #include <iostream> |
7 | using namespace std; |
8 | #include <string.h> |
9 | |
10 | void indent(int n) |
11 | { for (int i = 0; i<n; i++) cout << " "; |
12 | } |
13 | |
14 | class Atom { |
15 | char *atomname; |
16 | public: Atom(char *s) : atomname(s) {} |
17 | void print() { cout<<atomname; } |
18 | bool eqatom(Atom *t) { return strcmp(atomname, t->atomname) == 0; } |
19 | }; |
20 | |
21 | class TermCons; |
22 | |
23 | class Term { |
24 | public: virtual void print() = 0; |
25 | public: virtual bool unify(Term *) = 0; |
26 | public: virtual bool unify2(TermCons *) = 0; |
27 | public: virtual Term *copy() = 0; |
28 | }; |
29 | |
30 | class TermCons : public Term { |
31 | private: |
32 | int arity; |
33 | Atom *fsym; |
34 | Term **args; |
35 | public: |
36 | TermCons(Atom *f) : fsym(f), arity(0), args(NULL) |
37 | { } |
38 | TermCons(Atom *f, Term *a1) : fsym(f), arity(1), args(new Term*[1]) |
39 | { args[0]=a1; }; |
40 | TermCons(Atom *f, Term *a1, Term *a2) |
41 | : fsym(f), arity(2), args(new Term*[2]) |
42 | { args[0]=a1, args[1]=a2; }; |
43 | TermCons(Atom *f, Term *a1, Term *a2, Term *a3) |
44 | : fsym(f), arity(3), args(new Term*[3]) |
45 | { args[0]=a1, args[1]=a2, args[2]=a3; }; |
46 | void print() { fsym->print(); |
47 | if (arity>0) |
48 | { cout <<"("; |
49 | for (int i = 0; i<arity; ) |
50 | { args[i]->print(); |
51 | if (++i < arity) cout << ","; |
52 | } |
53 | cout <<")"; |
54 | } |
55 | } |
56 | bool unify(Term *t) { return t->unify2(this); } |
57 | Term *copy() { return copy2(); } |
58 | TermCons *copy2() { return new TermCons(this); } |
59 | private: |
60 | TermCons(TermCons *p) |
61 | : fsym(p->fsym), arity(p->arity), |
62 | args(p->arity==0 ? NULL : new Term*[p->arity]) |
63 | { for (int i=0; i<arity; i++) args[i] = p->args[i]->copy(); } |
64 | bool unify2(TermCons *t) { |
65 | if (!(fsym->eqatom(t->fsym) && arity == t->arity)) |
66 | return false; |
67 | for (int i = 0; i<arity; i++) |
68 | if (!args[i]->unify(t->args[i])) return false; |
69 | return true; |
70 | } |
71 | }; |
72 | |
73 | class TermVar : public Term { |
74 | private: |
75 | Term *instance; |
76 | int varno; |
77 | static int timestamp; |
78 | public: |
79 | TermVar() : instance(this), varno(++timestamp) {} |
80 | void print() { if (instance!=this) instance->print(); |
81 | else cout<<"_"<<varno; }; |
82 | bool unify(Term *t); |
83 | Term *copy(); |
84 | Term *reset() { instance = this; } |
85 | private: |
86 | bool unify2(TermCons *t) { return this->unify(t); } |
87 | }; |
88 | |
89 | int TermVar::timestamp = 0; |
90 | |
91 | class Program; |
92 | class TermVarMapping; |
93 | |
94 | class Goal { |
95 | private: |
96 | TermCons *car; |
97 | Goal *cdr; |
98 | public: |
99 | Goal(TermCons *h, Goal *t) : car(h), cdr(t) {} |
100 | Goal *copy() { return new Goal(car->copy2(), |
101 | cdr==NULL ? NULL : cdr->copy()); } |
102 | Goal *append(Goal *l) { return new Goal(car, |
103 | cdr==NULL ? NULL : cdr->append(l)); } |
104 | void print() { car->print(); |
105 | if (cdr != NULL) { cout << "; ", cdr->print(); } |
106 | } |
107 | void solve(Program *p, int level, TermVarMapping *map); |
108 | }; |
109 | |
110 | class Clause { |
111 | public: |
112 | TermCons *head; |
113 | Goal *body; |
114 | Clause(TermCons *h, Goal *t) : head(h), body(t) {} |
115 | Clause *copy() { return new Clause(head->copy2(), |
116 | body==NULL ? NULL : body->copy()); } |
117 | void print() { head->print(); |
118 | cout << " :- "; |
119 | if (body==NULL) cout << "true"; |
120 | else body->print(); |
121 | } |
122 | }; |
123 | |
124 | class Program { |
125 | public: |
126 | Clause *pcar; |
127 | Program *pcdr; |
128 | Program(Clause *h, Program *t) : pcar(h), pcdr(t) {} |
129 | }; |
130 | |
131 | class Trail { |
132 | private: |
133 | TermVar *tcar; |
134 | Trail *tcdr; |
135 | static Trail *sofar; |
136 | Trail(TermVar *h, Trail *t) : tcar(h), tcdr(t) {} |
137 | public: |
138 | static Trail *Note() { return sofar; } |
139 | static void Push(TermVar *x) { sofar = new Trail(x, sofar); } |
140 | static void Undo(Trail *whereto) |
141 | { for (; sofar != whereto; sofar = sofar->tcdr) |
142 | sofar->tcar->reset(); |
143 | } |
144 | }; |
145 | Trail *Trail::sofar = NULL; |
146 | |
147 | bool TermVar::unify(Term *t) { |
148 | if (instance!=this) return instance->unify(t); |
149 | Trail::Push(this); instance = t; return true; } |
150 | Term *TermVar::copy() { |
151 | if (instance==this) |
152 | { Trail::Push(this); instance = new TermVar(); |
153 | } |
154 | return instance; |
155 | } |
156 | |
157 | class TermVarMapping { |
158 | private: |
159 | TermVar **varvar; |
160 | char **vartext; |
161 | int size; |
162 | public: |
163 | TermVarMapping(TermVar *vv[], char *vt[], int vs) |
164 | :varvar(vv), vartext(vt), size(vs) {} |
165 | void showanswer() |
166 | { if (size == 0) cout << "yes\n"; |
167 | else |
168 | { for (int i = 0; i < size; i++) |
169 | { cout << vartext[i] << " = "; varvar[i]->print(); cout << "\n"; |
170 | } |
171 | } |
172 | } |
173 | }; |
174 | |
175 | void Goal::solve(Program *p, int level, TermVarMapping *map) |
176 | { indent(level); cout << "solve@" << level << ": "; |
177 | this->print(); cout << "\n"; |
178 | for (Program *q = p; q != NULL; q = q->pcdr) |
179 | { Trail *t = Trail::Note(); |
180 | Clause *c = q->pcar->copy(); |
181 | Trail::Undo(t); |
182 | indent(level); cout << " try:"; c->print(); cout << "\n"; |
183 | if (car->unify(c->head)) |
184 | { Goal *gdash = c->body==NULL ? cdr : c->body->append(cdr); |
185 | if (gdash == NULL) map->showanswer(); |
186 | else gdash->solve(p, level+1, map); |
187 | } |
188 | else |
189 | { indent(level); cout << " nomatch.\n"; |
190 | } |
191 | Trail::Undo(t); |
192 | } |
193 | } |
194 | |
195 | /* A sample test program: append */ |
196 | |
197 | Atom *at_app = new Atom("app"); |
198 | Atom *at_cons = new Atom("cons"); |
199 | TermCons *f_nil = new TermCons(new Atom("nil")); |
200 | TermCons *f_1 = new TermCons(new Atom("1")); |
201 | TermCons *f_2 = new TermCons(new Atom("2")); |
202 | TermCons *f_3 = new TermCons(new Atom("3")); |
203 | |
204 | Term *v_x = new TermVar(); |
205 | TermCons *lhs1 = new TermCons(at_app, f_nil, v_x, v_x); |
206 | Clause *c1 = new Clause(lhs1, NULL); |
207 | |
208 | Term *v_l = new TermVar(); |
209 | Term *v_m = new TermVar(); |
210 | Term *v_n = new TermVar(); |
211 | TermCons *rhs2 = new TermCons(at_app, v_l, v_m, v_n); |
212 | TermCons *lhs2 = new TermCons(at_app, new TermCons(at_cons, v_x, v_l), |
213 | v_m, |
214 | new TermCons(at_cons, v_x, v_n)); |
215 | Clause *c2 = new Clause(lhs2, new Goal(rhs2,NULL)); |
216 | |
217 | TermVar *v_i = new TermVar(); |
218 | TermVar *v_j = new TermVar(); |
219 | TermCons *rhs3 = new TermCons(at_app, v_i, v_j, |
220 | new TermCons(at_cons, f_1, |
221 | new TermCons(at_cons, f_2, |
222 | new TermCons(at_cons, f_3, f_nil)))); |
223 | |
224 | Goal *g1 = new Goal(rhs3, NULL); |
225 | |
226 | Program *test_p = new Program(c1, new Program(c2, NULL)); |
227 | Program *test_p2 = new Program(c2, new Program(c1, NULL)); |
228 | |
229 | TermVar *varvar[] = {v_i, v_j}; |
230 | char *varname[] = {"I", "J"}; |
231 | TermVarMapping *var_name_map = new TermVarMapping(varvar, varname, 2); |
232 | |
233 | int main(int argc, char *argv[]) |
234 | { |
235 | cout << "=======Append with normal clause order:\n"; |
236 | g1->solve(test_p, 0, var_name_map); |
237 | cout << "\n=======Append with reversed normal clause order:\n"; |
238 | g1->solve(test_p2, 0, var_name_map); |
239 | return 0; |
240 | } |
from http://www.cl.cam.ac.uk/~am21/research/funnel/prolog.c
Travelled to 12 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1002817 |
Snippet name: | prolog.c - Prolog interpreter in C++ |
Eternal ID of this version: | #1002817/1 |
Text MD5: | 6ee0df8ed021f15e27630fafd91102c6 |
Author: | stefan |
Category: | |
Type: | Document |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-02-27 02:27:43 |
Source code size: | 7593 bytes / 240 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 562 / 379 |
Referenced in: | [show references] |