Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

240
LINES

< > BotCompany Repo | #1002817 // prolog.c - Prolog interpreter in C++

Document

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  
}

Author comment

from http://www.cl.cam.ac.uk/~am21/research/funnel/prolog.c

download  show line numbers   

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: 496 / 333
Referenced in: [show references]